Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ff8d81c
Temp commit
truongwp Aug 6, 2024
b075d52
Temp commit
truongwp Aug 9, 2024
1da5aca
Handled submission deactivation feedback
truongwp Aug 12, 2024
e0a0958
Make script run
truongwp Aug 14, 2024
ca8c7bd
Improve styling
truongwp Aug 15, 2024
3aa0c04
Remove debug code
truongwp Aug 15, 2024
a4341f7
Update event selector
truongwp Aug 15, 2024
b8077b7
Fix JS error
truongwp Aug 15, 2024
578792c
Add dismiss link
truongwp Aug 15, 2024
9b5df2e
Update feedback form URL
truongwp Aug 16, 2024
c75691b
Add site data for feedback form
truongwp Aug 16, 2024
2393ba1
Fix phpcs
truongwp Aug 21, 2024
9b60825
Use existing logo for deactivation modal
truongwp Aug 21, 2024
bac7762
Update styling
truongwp Aug 21, 2024
47d9b96
Fix phpcs
truongwp Aug 21, 2024
e0e9048
Only show feedback form once in 6 months
truongwp Aug 23, 2024
c902eaa
Temporary change feedback expired time period
truongwp Aug 23, 2024
bc775d1
Hide feedback modal icon when success
truongwp Aug 23, 2024
8d6dc76
Update temp feedback expired time
truongwp Aug 26, 2024
06e997e
Fix phpcs
truongwp Aug 26, 2024
823607d
Temporary change version
truongwp Aug 28, 2024
c735237
Merge branch 'master' into collect-feedback-deactivation
truongwp Aug 28, 2024
f6b8381
Merge branch 'master' into collect-feedback-deactivation
Crabcyborg Sep 10, 2024
028896c
Move deactivation feedback CSS to external file
truongwp Sep 11, 2024
e83be1b
Merge branch 'master' into collect-feedback-deactivation
Crabcyborg Oct 1, 2024
66df33f
Add abspath check
Crabcyborg Oct 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions classes/controllers/FrmDeactivationFeedbackController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php
/**
* Deactivation feedback controller
*
* @package Formidable
* @since x.x
*/

if ( ! defined( 'ABSPATH' ) ) {
die( 'You are not allowed to call this page directly.' );
}

/**
* Class FrmDeactivationFeedbackController
*/
class FrmDeactivationFeedbackController {

/**
* Checks if is plugins page.
*
* @return bool
*/
private static function is_plugins_page() {
return 'plugins' === get_current_screen()->id;
}
Comment thread
Crabcyborg marked this conversation as resolved.

/**
* Checks if feedback is expired.
*
* @return bool
*/
private static function feedback_is_expired() {
$feedback_expired = get_option( 'frm_feedback_expired' );
if ( ! $feedback_expired ) {
return true;
}

$expired_date = strtotime( $feedback_expired );
if ( ! $expired_date ) {
return true;
}

return $expired_date < time();
}

/**
* Sets feedback expired date.
*
* @param string $plugin Path to the plugin file relative to the plugins directory.
*
* @return void
*/
public static function set_feedback_expired_date( $plugin ) {
if ( empty( $_GET['frm_feedback_submitted'] ) ) {
return;
}
if ( ! strpos( $plugin, 'formidable.php' ) && ! strpos( $plugin, 'formidable-pro.php' ) ) {
return;
}
Comment thread
Crabcyborg marked this conversation as resolved.
update_option( 'frm_feedback_expired', gmdate( 'Y-m-d', strtotime( '+ 1 day' ) ) );
}

/**
* Enqueues assets.
*
* @return void
*/
public static function enqueue_assets() {
if ( ! self::is_plugins_page() || ! self::feedback_is_expired() ) {
return;
}

wp_enqueue_script(
'frm-deactivation-feedback',
FrmAppHelper::plugin_url() . '/js/admin/deactivation-feedback.js',
array( 'formidable', 'formidable_dom', 'jquery' ),
FrmAppHelper::plugin_version(),
true
);

wp_enqueue_style( 'formidable-admin' );

wp_enqueue_style(
'frm-deactivation-feedback',
FrmAppHelper::plugin_url() . '/css/admin/deactivation-feedback.css',
array( 'formidable-admin' ),
FrmAppHelper::plugin_version()
);

FrmAppHelper::localize_script( 'front' );

wp_localize_script(
'frm-deactivation-feedback',
'FrmDeactivationFeedbackI18n',
array(
'skip_text' => __( 'Skip & Deactivate', 'formidable' ),
)
);
}

/**
* Prints footer HTML.
*
* @return void
*/
public static function footer_html() {
if ( ! self::is_plugins_page() || ! self::feedback_is_expired() ) {
return;
}
?>
<div id="frm-deactivation-modal" class="">
<div class="metabox-holder">
<div class="postbox">
<a class="frm-modal-close dismiss" title="<?php esc_attr_e( 'Close', 'formidable' ); ?>">
<svg class="frmsvg" id="frm_close_icon" viewBox="0 0 20 20" width="18px" height="18px" aria-label="<?php esc_attr_e( 'Close', 'formidable' ); ?>">
<path d="M16.8 4.5l-1.3-1.3L10 8.6 4.5 3.2 3.2 4.5 8.6 10l-5.4 5.5 1.3 1.3 5.5-5.4 5.5 5.4 1.3-1.3-5.4-5.5 5.4-5.5z"/>
</svg>
</a>

<div class="inside">
<img id="frm-deactivation-modal-icon" class="frmsvg" src="<?php echo esc_url( FrmAppHelper::plugin_url() . '/images/logo.svg' ); ?>" alt="" />
<div id="frm-deactivation-form-wrapper" class="frmapi-form">
<span class="frm-wait frm_visible_spinner"></span>
</div>
</div>
</div>
</div>
</div><!-- End #frm-deactivation-popup -->
<?php
}
}
5 changes: 5 additions & 0 deletions classes/controllers/FrmHooksController.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ public static function load_admin_hooks() {
// Cronjob.
add_action( 'admin_init', 'FrmCronController::schedule_events' );

// Deactivation feedback.
add_action( 'admin_enqueue_scripts', 'FrmDeactivationFeedbackController::enqueue_assets' );
add_action( 'admin_footer', 'FrmDeactivationFeedbackController::footer_html' );
add_action( 'deactivated_plugin', 'FrmDeactivationFeedbackController::set_feedback_expired_date' );

FrmDashboardController::load_admin_hooks();
FrmTransLiteHooksController::load_admin_hooks();
FrmStrpLiteHooksController::load_admin_hooks();
Expand Down
91 changes: 91 additions & 0 deletions css/admin/deactivation-feedback.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#frm-deactivation-modal {
--padding: 24px;
}
.frm_screen_reader {
border: 0;
clip: rect(1px, 1px, 1px, 1px);
-webkit-clip-path: inset(50%);
clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
word-wrap: normal !important; /* many screen reader and browser combinations announce broken words as they would appear visually */
}
#frm-deactivation-modal-icon {
position: absolute;
top: calc(var(--padding) - 1px);
left: var(--padding);
width: 20px;
height: 20px;
}
#frm-deactivation-modal .frm-modal-close {
position: absolute;
top: 20px;
right: var(--padding);
z-index: 1000;
}
#frm-deactivation-modal .frm_form_title {
padding: 20px var(--padding) 12px calc(28px + var(--padding));
margin-top: 0;
border-bottom: 1px solid #f2f4f7;
font-weight: 400;
font-size: 14px;
line-height: 26px;
}
#frm-deactivation-modal .frm_description,
#frm-deactivation-modal .frm_form_field {
padding-left: var(--padding);
padding-right: var(--padding);
}
#frm-deactivation-modal .frm_description p {
font-size: 12px;
margin-top: 16px;
margin-bottom: 16px;
color: #667085;
}
#frm-deactivation-modal .inside {
padding-left: 0;
padding-right: 0;
}
#frm-deactivation-modal .frm_radio { margin-bottom: 15px; }
#frm-deactivation-modal .frm_radio .frm_form_field {
padding-left: 0;
padding-right: 0;
margin-bottom: -5px;
}
#frm-deactivation-modal .frm_radio .frm_form_field textarea {
margin-top: 5px;
height: 65px;
border-radius: 8px;
padding: 5px 12px;
font-size: 14px;
}
#frm-deactivation-modal .frm_radio .frm_form_field textarea:focus { border-color: #4199FD; box-shadow: none; }
#frm-deactivation-modal .frm_radio .frm_form_field textarea::placeholder { color: #98A2B3; }
#frm-deactivation-modal .frm_radio .frm_html_container {
padding: 6px;
background-color: #F9FAFB;
margin-top: 8px;
margin-bottom: 15px;
border-radius: 8px;
}
#frm-deactivation-modal .frm_radio .frm_html_container p {
margin: 0;
font-size: 14px;
line-height: 20px;
color: #667085;
}
#frm-deactivation-modal input[name="item_key"] + div,
#frm-deactivation-modal .frm_primary_label { display: none; }
#frm-deactivation-modal .frm_submit { text-align: right; margin-top: 38px; }
#frm-deactivation-modal .frm_button_submit { margin-right: 0; }
#frm-deactivation-modal .frm-skip-link {
color: #98A2B3;
display: inline-block;
font-size: 14px;
line-height: 40px;
padding: 0 13px;
}
114 changes: 114 additions & 0 deletions js/admin/deactivation-feedback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
( function() {
'use strict';
Comment thread
Crabcyborg marked this conversation as resolved.

const selectors = 'tr[data-slug="formidable"] .deactivate a, tr[data-slug="formidable-pro"] .deactivate a, tr[data-slug="formidable-forms-pro"] .deactivate a';

let deactivationModal, deactivationUrl;

const Modal = {
init: function( id, width ) {
const $info = jQuery( id );
const self = this;

if ( ! $info.length ) {
return false;
}

if ( typeof width === 'undefined' ) {
width = '550px';
}

const dialogArgs = {
dialogClass: 'frm-dialog',
modal: true,
autoOpen: false,
closeOnEscape: true,
width: width,
resizable: false,
draggable: false,
open: function() {
jQuery( '.ui-dialog-titlebar' ).addClass( 'frm_hidden' ).removeClass( 'ui-helper-clearfix' );
jQuery( '#wpwrap' ).addClass( 'frm_overlay' );
jQuery( '.frm-dialog' ).removeClass( 'ui-widget ui-widget-content ui-corner-all' );
$info.removeClass( 'ui-dialog-content ui-widget-content' );
self.bindClickForDialogClose( $info );
},
close: function() {
jQuery( '#wpwrap' ).removeClass( 'frm_overlay' );
jQuery( '.spinner' ).css( 'visibility', 'hidden' );

this.removeAttribute( 'data-option-type' );
const optionType = document.getElementById( 'bulk-option-type' );
if ( optionType ) {
optionType.value = '';
}
}
};

$info.dialog( dialogArgs );

return $info;
},

bindClickForDialogClose: function( $modal ) {
const closeModal = function() {
$modal.dialog( 'close' );
};
jQuery( '.ui-widget-overlay' ).on( 'click', closeModal );
$modal.on( 'click', 'a.dismiss', closeModal );
}
Comment thread
Crabcyborg marked this conversation as resolved.
};

const addSkipBtn = formEl => {
const btn = frmDom.a( {
text: FrmDeactivationFeedbackI18n.skip_text,
href: deactivationUrl,
className: 'frm-skip-link'
});

formEl.querySelector( '.frm_submit' ).prepend( btn );
};

const onClickDeactivate = event => {
event.preventDefault();

if ( ! deactivationModal ) {
deactivationModal = Modal.init(
'#frm-deactivation-modal',
'440px'
);
}

deactivationUrl = event.target.href + '&frm_feedback_submitted=1';

const pluginSlug = event.target.closest( 'tr' ).dataset.slug;

const url = 'https://feedback.strategy11.com/wp-json/frm/v2/forms/deactivation-feedback?plugin_slug=' + pluginSlug + '&site=' + window.location.host + '&return=html&exclude_script=jquery&exclude_style=formidable-css';
Comment thread
Crabcyborg marked this conversation as resolved.

const response = fetch( url, {
method: 'GET'
});

response
.then( response => response.json() )
.then( response => {
const wrapper = document.getElementById( 'frm-deactivation-form-wrapper' );
const form = response.renderedHtml.replace( /<link\b[^>]*(formidableforms.css|action=frmpro_css)[^>]*>/gi, '' );

jQuery( wrapper ).html( form );
wrapper.setAttribute( 'data-slug', pluginSlug );
addSkipBtn( wrapper );
deactivationModal.dialog( 'open' );
})
.catch( error => {
console.error( error );
});
};

frmDom.util.documentOn( 'click', selectors, onClickDeactivate );

document.addEventListener( 'frmFormCompleteBeforeReplace', function( event ) {
document.getElementById( 'frm-deactivation-modal-icon' ).remove();
window.location.href = deactivationUrl;
});
}() );