diff --git a/assets/js/src/RedirectionForCF7/index.js b/assets/js/src/RedirectionForCF7/index.js
new file mode 100644
index 00000000..45e94ec4
--- /dev/null
+++ b/assets/js/src/RedirectionForCF7/index.js
@@ -0,0 +1,141 @@
+import {useState} from '@wordpress/element';
+import {Button} from '@wordpress/components';
+
+import './style.scss';
+import {activatePlugin, installPluginOrTheme} from "../common/utils";
+import useSettings from "../common/useSettings";
+
+export default function RedirectionForCF7({stacked = false, noImage = false, type, onDismiss, onSuccess, initialStatus = null }) {
+ const {
+ assets,
+ title,
+ email: initialEmail,
+ option,
+ optionKey,
+ labels,
+ rfCF7ActivationUrl,
+ cf7Dash,
+ } = window.themeisleSDKPromotions;
+
+ const [showStatus, setShowStatus] = useState(false);
+ const [email, setEmail] = useState(initialEmail || '');
+ const [dismissed, setDismissed] = useState(false);
+ const [progress, setProgress] = useState( initialStatus );
+ const [getOption, updateOption] = useSettings();
+
+ const dismissNotice = async () => {
+ setDismissed(true);
+ const newValue = {...option};
+ newValue[type] = new Date().getTime() / 1000 | 0;
+ window.themeisleSDKPromotions.option = newValue;
+ await updateOption(optionKey, JSON.stringify(newValue));
+
+ if (onDismiss) {
+ onDismiss();
+ }
+ };
+
+ const installPluginRequest = async (e) => {
+ e.preventDefault();
+ setShowStatus(true);
+ setProgress('installing');
+ await installPluginOrTheme('wpcf7-redirect');
+
+ setProgress('activating');
+ await activatePlugin(rfCF7ActivationUrl);
+
+ updateOption('themeisle_sdk_promotions_redirection_cf7_installed', !Boolean(getOption('themeisle_sdk_promotions_redirection_cf7_installed')));
+
+ setProgress('done');
+
+ }
+
+ if (dismissed) {
+ return null;
+ }
+
+ const installPluginRequestStatus = () => {
+ if (progress === 'done') {
+ return (
+
+
{labels.redirectionCF7.all_set}
+
+
+ );
+ }
+
+ if (progress) {
+ return (
+
+
+
+ {progress === 'installing' && labels.redirectionCF7.installing}
+ {progress === 'activating' && labels.redirectionCF7.activating}
+ …
+
+
+ );
+ }
+ };
+
+ const dismissButton = () => (
+
+ );
+
+
+ if (stacked) {
+ return (
+
+
+ {dismissButton()}
+
{labels.redirectionCF7.heading}
+
+
{labels.redirectionCF7.message}
+
+ {( !showStatus && 'done' !== progress ) && (
+
+ )}
+ {( showStatus || 'done' === progress ) && installPluginRequestStatus()}
+
+
{title}
+
+
+ );
+ }
+
+ return (
+ <>
+ {dismissButton()}
+
+
+
{title}
+
{labels.redirectionCF7.message}
+ {!showStatus && (
+
+
+
+
+ )}
+ {showStatus && (
+
+ {installPluginRequestStatus()}
+
+ )}
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/assets/js/src/RedirectionForCF7/style.scss b/assets/js/src/RedirectionForCF7/style.scss
new file mode 100644
index 00000000..9603ca06
--- /dev/null
+++ b/assets/js/src/RedirectionForCF7/style.scss
@@ -0,0 +1,303 @@
+.ti-redirection-cf7-notice {
+ --wp-admin-theme-color: #3858E9;
+ --wp-admin-theme-color-darker-10: #2e47ba;
+ position: relative;
+ padding: 0;
+ border-left-color: #3858E9;
+
+ .content {
+ background: rgba(255, 255, 255, 0.75);
+ display: flex;
+ align-items: center;
+ padding: 15px 20px;
+ }
+
+ img {
+ max-width: 100px;
+ margin-right: 20px;
+ display: none;
+ }
+
+ .description {
+ font-size: 14px;
+ margin-bottom: 20px;
+ color: #000;
+ }
+
+ .actions {
+ margin-top: auto;
+ display: flex;
+ margin-bottom: 0;
+ gap: 20px;
+ }
+
+ form {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ }
+
+ .form-wrap {
+ display: grid;
+
+ span:not(.dashicons) {
+ margin-bottom: 5px;
+ font-weight: 500;
+ }
+ }
+
+ input {
+ border-radius: 0;
+ min-width: 250px;
+ }
+
+ a.components-button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .is-link {
+ text-decoration: none;
+ display: flex;
+ align-items: center;
+
+ span {
+ line-height: normal;
+ }
+ }
+
+ .dashicons {
+ margin-right: 2px;
+ text-decoration: none;
+ }
+
+ .done {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+
+ a {
+ width: auto;
+ }
+ }
+}
+
+@media screen and (min-width: 768px) {
+ .ti-sdk-rf-cf7-notice {
+ img {
+ display: block;
+ }
+ }
+}
+
+.compat-field-optimole {
+ th {
+ display: none !important;
+ }
+
+ td {
+ width: 100% !important;
+ }
+
+ .ti-sdk-rf-cf7-notice {
+ margin: 0;
+ }
+}
+
+.rf-cf7-notice-dismiss {
+ right: 10px;
+ top: 10px;
+ text-decoration: none !important;
+ position: absolute;
+
+ &:before {
+ content: none;
+ }
+}
+
+.ti-rf-cf7-stack-wrap {
+ .rf-cf7-stack-notice {
+ --wp-admin-theme-color: #3858E9;
+ --wp-admin-theme-color-darker-10: #2e47ba;
+
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ position: relative;
+ text-align: center;
+ padding: 20px 10px;
+
+ > span {
+ display: none;
+ }
+
+ img {
+ max-width: 90px !important;
+ }
+
+ h2 {
+ font-size: 18px;
+ margin: 30px auto 10px;
+ font-weight: 600;
+ }
+
+ p {
+ font-size: 13px;
+ max-width: 250px;
+ margin: 0 auto;
+ line-height: 17px;
+ }
+
+ i {
+ margin-top: 10px;
+ font-size: 12px;
+ color: #757575;
+ }
+
+ .cta {
+ margin: 20px auto 0;
+ padding: 10px 25px !important;
+ }
+
+ .rf-cf7-notice-dismiss {
+ color: inherit;
+ }
+
+ input {
+ border-radius: 0;
+ }
+
+ form {
+ place-items: center;
+ width: 75%;
+ display: grid;
+ margin-top: 10px;
+ gap: 10px;
+ }
+
+ .done {
+ margin-top: 15px;
+ display: grid;
+ gap: 10px;
+
+ p {
+ font-size: 15px;
+ font-weight: 500;
+ }
+ }
+
+ .rf-cf7-progress {
+ margin: 20px 0;
+ }
+ }
+}
+
+.block-editor-block-inspector {
+ .ti-rf-cf7-stack-wrap {
+ border-top: 1px solid #e0e0e0;
+ }
+}
+
+
+.rf-cf7-progress {
+ gap: 5px;
+ font-size: 14px;
+ display: flex;
+ align-items: center;
+
+ .spin {
+ animation: rf-cf7-rotation 2s infinite linear;
+ }
+}
+
+@keyframes rf-cf7-rotation {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(359deg);
+ }
+}
+
+.ti-sdk-rf-cf7-promo.hidden {
+ display: none;
+}
+
+.media-sidebar {
+ .ti-sdk-rf-cf7-notice {
+ input {
+ min-width: unset;
+ flex-grow: 1;
+ }
+
+ .description {
+ margin-bottom: 10px;
+ }
+
+ .content {
+ padding: 15px 10px;
+ }
+
+ .actions {
+ gap: 10px;
+ }
+
+ form {
+ flex-wrap: wrap;
+ justify-content: center;
+ }
+ }
+}
+
+.attachment-info {
+ .ti-sdk-rf-cf7-notice {
+ input {
+ min-width: unset;
+ flex-grow: 1;
+ }
+ form {
+ flex-wrap: wrap;
+ justify-content: center;
+
+ @media screen and (min-width: 1200px) {
+ flex-wrap: unset;
+ }
+ }
+ }
+}
+
+.ti-sdk-rop-notice {
+ position: relative;
+ padding: 10px;
+
+ .rop-notice-actions {
+ display: flex;
+ gap: 10px;
+ }
+
+ p {
+ padding: 0 10px 0 0;
+ }
+}
+.ti-sdk-neve-fse-notice {
+ position: relative;
+ padding: 10px;
+
+ .neve-fse-notice-actions {
+ display: flex;
+ gap: 10px;
+
+ a {
+ text-decoration: none;
+ span:not(.dashicons) {
+ text-decoration: underline;
+ }
+ }
+ }
+
+ p {
+ padding: 0 10px 0 0;
+ font-size: 14px;
+ }
+}
diff --git a/assets/js/src/index.js b/assets/js/src/index.js
index d0b4309c..024b74bd 100644
--- a/assets/js/src/index.js
+++ b/assets/js/src/index.js
@@ -2,3 +2,4 @@ import './otter.js';
import './optimole.js';
import './rop.js';
import './neve-fse.js';
+import './redirection-for-cf7.js';
diff --git a/assets/js/src/redirection-for-cf7.js b/assets/js/src/redirection-for-cf7.js
new file mode 100644
index 00000000..c6970d34
--- /dev/null
+++ b/assets/js/src/redirection-for-cf7.js
@@ -0,0 +1,43 @@
+import {Fragment, render, unmountComponentAtNode, useState} from '@wordpress/element';
+import {registerPlugin,} from '@wordpress/plugins';
+import {PluginPostPublishPanel} from '@wordpress/edit-post';
+import {useSelect} from '@wordpress/data';
+import {createHigherOrderComponent} from '@wordpress/compose';
+import {addFilter} from '@wordpress/hooks';
+import {InspectorControls} from '@wordpress/block-editor';
+
+import {getBlocksByType} from "./common/utils";
+import RedirectionForCF7 from "./RedirectionForCF7";
+
+class RedirectionForCF7Notice {
+ constructor() {
+ const {showPromotion, debug} = window.themeisleSDKPromotions;
+ this.promo = showPromotion;
+ this.debug = debug === '1';
+ this.domRef = null;
+
+ this.run();
+ }
+
+ run() {
+ if (window.themeisleSDKPromotions.option['redirection-cf7']) {
+ return;
+ }
+
+ const root = document.querySelector('#ti-redirection-cf7-notice');
+
+ if (!root) {
+ return;
+ }
+
+ render(
+ {
+ root.style.opacity = 0;
+ }}
+ />, root);
+ }
+}
+
+new RedirectionForCF7Notice();
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 3efa502c..fdae78a6 100644
--- a/composer.json
+++ b/composer.json
@@ -19,8 +19,8 @@
"codeinwp/phpcs-ruleset": "dev-main"
},
"scripts": {
- "format": "phpcbf --standard=phpcs.xml --report-summary --report-source -s --runtime-set testVersion 5.6- ",
- "phpcs": "phpcs --standard=phpcs.xml -s --runtime-set testVersion 5.6-",
+ "format": "phpcbf --standard=phpcs.xml --report-summary --report-source -s --runtime-set testVersion 7.2- ",
+ "phpcs": "phpcs --standard=phpcs.xml -s --runtime-set testVersion 7.2-",
"lint": "composer run-script phpcs"
},
"support": {
diff --git a/src/Loader.php b/src/Loader.php
index f83d924c..a5eabc8b 100644
--- a/src/Loader.php
+++ b/src/Loader.php
@@ -114,8 +114,8 @@ final class Loader {
'no_activations' => 'No more activations left for %s. You need to upgrade your plan in order to use %s on more websites. If you need assistance, please get in touch with %s staff.',
],
'promotions' => [
- 'recommended' => 'Recommended by %s',
- 'woo' => [
+ 'recommended' => 'Recommended by %s',
+ 'woo' => [
'title' => 'More extensions from Themeisle',
'title2' => 'Recommended extensions',
'cta_install' => 'Install',
@@ -130,7 +130,7 @@ final class Loader {
'spark_desc2' => 'Add a top notification bar on your website to highlight the latest products, offers, or upcoming events.',
'spark_desc3' => 'Enable an advanced review section, enlarging the basic review options with lots of capabilities.',
],
- 'optimole' => [
+ 'optimole' => [
'all_set' => 'Awesome! You are all set!',
'gotodash' => 'Go to Optimole dashboard',
'installing' => 'Installing',
@@ -147,6 +147,16 @@ final class Loader {
'message2' => 'Leverage Optimole\'s full integration with Elementor to automatically lazyload, resize, compress to AVIF/WebP and deliver from 400 locations around the globe!',
'email_placeholder' => 'Email address',
],
+ 'redirection_cf7' => [
+ 'all_set' => 'Awesome! You are all set!',
+ 'gotodash' => 'Go to Contact Forms',
+ 'installing' => 'Installing',
+ 'activating' => 'Activating',
+ 'dismisscta' => 'Dismiss this notice.',
+ 'gst' => 'Get Started Free',
+ 'learnmore' => 'Learn more',
+ 'message' => 'Add URL redirects, spam protection, execute JavaScript after submissions, and more with the Redirection for CF7 free plugin.',
+ ],
],
'welcome' => [
'ctan' => 'No, thanks.',
diff --git a/src/Modules/Promotions.php b/src/Modules/Promotions.php
index 08802a68..d58e2ddc 100644
--- a/src/Modules/Promotions.php
+++ b/src/Modules/Promotions.php
@@ -77,6 +77,13 @@ class Promotions extends Abstract_Module {
*/
private $option_neve_fse = 'themeisle_sdk_promotions_neve_fse_installed';
+ /**
+ * Option key for Redirection for CF7.
+ *
+ * @var string
+ */
+ private $option_redirection_cf7 = 'themeisle_sdk_promotions_redirection_cf7_installed';
+
/**
* Loaded promotion.
*
@@ -120,6 +127,9 @@ public function can_load( $product ) {
$promotions_to_load[] = 'rop';
$promotions_to_load[] = 'woo_plugins';
$promotions_to_load[] = 'neve-fse';
+ $promotions_to_load[] = 'redirection-cf7';
+
+ $promotions_to_load = array_unique( $promotions_to_load );
$promotions_to_load = array_unique( $promotions_to_load );
@@ -274,6 +284,16 @@ public function register_settings() {
'default' => false,
)
);
+ register_setting(
+ 'themeisle_sdk_settings',
+ $this->option_redirection_cf7,
+ array(
+ 'type' => 'boolean',
+ 'sanitize_callback' => 'rest_sanitize_boolean',
+ 'show_in_rest' => true,
+ 'default' => false,
+ )
+ );
}
/**
@@ -316,24 +336,26 @@ private function has_conflicts() {
* @return array
*/
private function get_promotions() {
- $has_otter = defined( 'OTTER_BLOCKS_VERSION' ) || $this->is_plugin_installed( 'otter-blocks' );
- $had_otter_from_promo = get_option( $this->option_otter, false );
- $has_optimole = defined( 'OPTIMOLE_VERSION' ) || $this->is_plugin_installed( 'optimole-wp' );
- $had_optimole_from_promo = get_option( $this->option_optimole, false );
- $has_rop = defined( 'ROP_LITE_VERSION' ) || $this->is_plugin_installed( 'tweet-old-post' );
- $had_rop_from_promo = get_option( $this->option_rop, false );
- $has_woocommerce = class_exists( 'WooCommerce' );
- $has_sparks = defined( 'SPARKS_WC_VERSION' ) || $this->is_plugin_installed( 'sparks-for-woocommerce' );
- $has_ppom = defined( 'PPOM_VERSION' ) || $this->is_plugin_installed( 'woocommerce-product-addon' );
- $is_min_req_v = version_compare( get_bloginfo( 'version' ), '5.8', '>=' );
- $is_min_fse_v = version_compare( get_bloginfo( 'version' ), '6.2', '>=' );
- $current_theme = wp_get_theme();
- $has_neve_fse = $current_theme->template === 'neve-fse' || $current_theme->parent() === 'neve-fse';
- $has_enough_attachments = $this->has_min_media_attachments();
- $has_enough_old_posts = $this->has_old_posts();
+ $has_otter = defined( 'OTTER_BLOCKS_VERSION' ) || $this->is_plugin_installed( 'otter-blocks' );
+ $had_otter_from_promo = get_option( $this->option_otter, false );
+ $has_optimole = defined( 'OPTIMOLE_VERSION' ) || $this->is_plugin_installed( 'optimole-wp' );
+ $had_optimole_from_promo = get_option( $this->option_optimole, false );
+ $has_rop = defined( 'ROP_LITE_VERSION' ) || $this->is_plugin_installed( 'tweet-old-post' );
+ $had_rop_from_promo = get_option( $this->option_rop, false );
+ $has_woocommerce = class_exists( 'WooCommerce' );
+ $has_sparks = defined( 'SPARKS_WC_VERSION' ) || $this->is_plugin_installed( 'sparks-for-woocommerce' );
+ $has_ppom = defined( 'PPOM_VERSION' ) || $this->is_plugin_installed( 'woocommerce-product-addon' );
+ $has_redirection_cf7 = defined( 'OPTIMOLE_VERSION' ) || $this->is_plugin_installed( 'optimole-wp' );
+ $had_redirection_cf7_promo = get_option( $this->option_optimole, false );
+ $is_min_req_v = version_compare( get_bloginfo( 'version' ), '5.8', '>=' );
+ $is_min_fse_v = version_compare( get_bloginfo( 'version' ), '6.2', '>=' );
+ $current_theme = wp_get_theme();
+ $has_neve_fse = $current_theme->template === 'neve-fse' || $current_theme->parent() === 'neve-fse';
+ $has_enough_attachments = $this->has_min_media_attachments();
+ $has_enough_old_posts = $this->has_old_posts();
$all = [
- 'optimole' => [
+ 'optimole' => [
'om-editor' => [
'env' => ! $has_optimole && $is_min_req_v && ! $had_optimole_from_promo,
'screen' => 'editor',
@@ -355,7 +377,7 @@ private function get_promotions() {
'screen' => 'elementor',
],
],
- 'otter' => [
+ 'otter' => [
'blocks-css' => [
'env' => ! $has_otter && $is_min_req_v && ! $had_otter_from_promo,
'screen' => 'editor',
@@ -369,13 +391,13 @@ private function get_promotions() {
'screen' => 'editor',
],
],
- 'rop' => [
+ 'rop' => [
'rop-posts' => [
'env' => ! $has_rop && ! $had_rop_from_promo && $has_enough_old_posts,
'screen' => 'edit-post',
],
],
- 'woo_plugins' => [
+ 'woo_plugins' => [
'ppom' => [
'env' => ! $has_ppom && $has_woocommerce,
'screen' => 'edit-product',
@@ -393,12 +415,18 @@ private function get_promotions() {
'screen' => 'edit-product',
],
],
- 'neve-fse' => [
+ 'neve-fse' => [
'neve-fse-themes-popular' => [
'env' => ! $has_neve_fse && $is_min_fse_v,
'screen' => 'themes-install-popular',
],
],
+ 'redirection-cf7' => [
+ 'wpcf7' => [
+ 'env' => ! $has_redirection_cf7 && ! $had_redirection_cf7_promo,
+ 'screen' => 'wpcf7',
+ ],
+ ],
];
foreach ( $all as $slug => $data ) {
@@ -473,6 +501,7 @@ private function filter_by_screen_and_merge() {
$is_editor = method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor();
$is_theme_install = isset( $current_screen->id ) && ( $current_screen->id === 'theme-install' || $current_screen->id === 'themes' );
$is_product = isset( $current_screen->id ) && $current_screen->id === 'product';
+ $is_cf7_install = isset( $current_screen->id ) && function_exists( 'str_contains' ) ? str_contains( $current_screen->id, 'page_wpcf7' ) : false;
$return = [];
@@ -514,6 +543,11 @@ private function filter_by_screen_and_merge() {
unset( $this->promotions[ $slug ][ $key ] );
}
break;
+ case 'wpcf7':
+ if ( ! $is_cf7_install ) {
+ unset( $this->promotions[ $slug ][ $key ] );
+ }
+ break;
}
}
@@ -551,6 +585,9 @@ private function load_promotion( $slug ) {
if ( $this->get_upsells_dismiss_time( 'neve-fse-themes-popular' ) === false ) {
add_action( 'admin_notices', [ $this, 'render_neve_fse_themes_notice' ] );
}
+ if ( $this->get_upsells_dismiss_time( 'redirection-cf7' ) === false ) {
+ add_action( 'admin_notices', [ $this, 'render_redirection_cf7_notice' ] );
+ }
$this->load_woo_promos();
@@ -598,6 +635,10 @@ private function load_promotion( $slug ) {
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
add_action( 'admin_notices', [ $this, 'render_neve_fse_themes_notice' ] );
break;
+ case 'wpcf7':
+ add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
+ add_action( 'admin_notices', [ $this, 'render_redirection_cf7_notice' ] );
+ break;
}
}
@@ -633,7 +674,8 @@ public function enqueue() {
[
'debug' => $this->debug,
'labels' => [
- 'optimole' => Loader::$labels['promotions']['optimole'],
+ 'optimole' => Loader::$labels['promotions']['optimole'],
+ 'redirectionCF7' => Loader::$labels['promotions']['redirection_cf7'],
],
'email' => $user->user_email,
'showPromotion' => $this->loaded_promo,
@@ -651,6 +693,9 @@ public function enqueue() {
'neveFSEMoreUrl' => tsdk_utmify( 'https://themeisle.com/themes/neve-fse/', 'neve-fse-themes-popular', 'theme-install' ),
// translators: %s is the product name.
'title' => esc_html( sprintf( Loader::$labels['promotions']['recommended'], $this->product->get_name() ) ),
+ 'redirectionCF7MoreUrl' => tsdk_utmify( 'https://docs.themeisle.com/collection/2014-redirection-for-contact-form-7', 'redirection-for-contact-form-7', 'plugin-install' ),
+ 'rfCF7ActivationUrl' => $this->get_plugin_activation_link( 'wpcf7-redirect' ),
+ 'cf7Dash' => esc_url( add_query_arg( [ 'page' => 'wpcf7-new' ], admin_url( 'admin.php' ) ) ),
]
);
wp_enqueue_script( $handle );
@@ -677,6 +722,13 @@ public function render_neve_fse_themes_notice() {
echo '';
}
+ /**
+ * Render Redirection for CF7 notice.
+ */
+ public function render_redirection_cf7_notice() {
+ echo '';
+ }
+
/**
* Add promo to attachment modal.
*