Initial commit: Atomaste website
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,236 @@
|
||||
/* Base CSS to normalize the default. */
|
||||
.uds-feedback-form--wrapper h2,
|
||||
.uds-feedback-form--wrapper p,
|
||||
.uds-feedback-form--wrapper input[type="radio"] {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.uds-feedback-form--wrapper .show {
|
||||
display: block;
|
||||
}
|
||||
.uds-feedback-form--wrapper .hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.uds-feedback-form--wrapper {
|
||||
align-items: center;
|
||||
background-color: rgba( 0, 0, 0, 0.75 );
|
||||
bottom: 0;
|
||||
display: none;
|
||||
justify-content: center;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
user-select: none;
|
||||
z-index: -9999;
|
||||
}
|
||||
|
||||
.uds-feedback-form--wrapper.show_popup {
|
||||
display: flex !important;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.uds-feedback-form--wrapper .uds-feedback-form--container {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 4px 4px 24px rgba( 0, 0, 0, 0.25 );
|
||||
max-width: 90%;
|
||||
width: 540px;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-header--wrapper {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 16px 20px 0;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-title--icon-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-title--icon-wrapper .uds-icon,
|
||||
.uds-feedback-form--container .uds-form-header--wrapper .uds-close {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-title--icon-wrapper .uds-title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-header--wrapper .uds-close {
|
||||
color: #9ca3af;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-header--wrapper .uds-close:hover {
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content {
|
||||
padding: 20px 20px 0 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content .uds-form-description {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .reason {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-options-feedback {
|
||||
color: #6b7280;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
padding: 9px 13px;
|
||||
border-radius: 6px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #e5e7eb;
|
||||
box-shadow: 0 1px 2px 0 #0000000d;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-options-feedback:hover,
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-options-feedback:focus,
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-options-feedback:active {
|
||||
border-color: #d1d5db;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-option-feedback-cta {
|
||||
color: #4b5563;
|
||||
margin-top: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-option-feedback-cta a {
|
||||
text-decoration: none;
|
||||
color: #006ba1;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-options-feedback::placeholder {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content .uds-feedback-form-sumbit--actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 20px;
|
||||
background-color: #f6f7f7;
|
||||
border-top: 1px solid #e1e1e1;
|
||||
margin: 40px -20px 0;
|
||||
border-bottom-left-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content .uds-feedback-form-sumbit--actions .button {
|
||||
padding: 7px 13px;
|
||||
border-radius: 3px;
|
||||
border-width: 1px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
border-style: solid;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content .uds-feedback-form-sumbit--actions .button:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.uds-feedback-form--container .uds-form-body--content .uds-feedback-form-sumbit--actions .button.processing {
|
||||
pointer-events: none;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.uds-feedback-form--container .uds-form-body--content .uds-feedback-form-sumbit--actions .button.processing::before {
|
||||
content: "\f463";
|
||||
animation: spin 2s linear infinite;
|
||||
font-family: dashicons, sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form .uds-reason-label {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form input[type="radio"] {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 50%;
|
||||
line-height: 0;
|
||||
box-shadow: inset 0 1px 2px rgb( 0 0 0 / 10% );
|
||||
transition: 0.05s border-color ease-in-out;
|
||||
-webkit-appearance: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form input[type="radio"]:checked {
|
||||
vertical-align: middle;
|
||||
background-color: #006ba1;
|
||||
}
|
||||
|
||||
.uds-feedback-form--container .uds-form-body--content #uds-feedback-form input[type="radio"]:checked::before {
|
||||
background-color: #fff !important;
|
||||
border-radius: 50px;
|
||||
content: "\2022";
|
||||
font-size: 24px;
|
||||
height: 6px;
|
||||
line-height: 13px;
|
||||
margin: 5px;
|
||||
text-indent: -9999px;
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate( 0deg );
|
||||
}
|
||||
100% {
|
||||
transform: rotate( 360deg );
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,237 @@
|
||||
( function ( $ ) {
|
||||
const UserDeactivationPopup = {
|
||||
slug: '',
|
||||
skipButton: '',
|
||||
formWrapper: '',
|
||||
radioButton: '',
|
||||
closeButton: '',
|
||||
buttonAction: '',
|
||||
feedbackForm: '',
|
||||
feedbackInput: '',
|
||||
deactivateUrl: '',
|
||||
buttonTrigger: '',
|
||||
deactivateButton: '',
|
||||
submitDeactivate: '',
|
||||
|
||||
/**
|
||||
* Caches elements for later use.
|
||||
*/
|
||||
_cacheElements() {
|
||||
this.slug = udsVars?._plugin_slug || '';
|
||||
this.skipButton = $( '.uds-feedback-skip' );
|
||||
this.submitDeactivate = $( '.uds-feedback-submit' );
|
||||
this.deactivateButton = $( '#the-list' ).find(
|
||||
`.row-actions span.deactivate a`
|
||||
);
|
||||
this.feedbackForm = $( '.uds-feedback-form' ); // Feedback Form.
|
||||
this.feedbackInput = $( '.uds-options-feedback' ); // Feedback Textarea.
|
||||
this.formWrapper = $( '.uds-feedback-form--wrapper' );
|
||||
this.closeButton = $( '.uds-feedback-form--wrapper .uds-close' );
|
||||
this.radioButton = $( '.uds-reason-input' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the feedback popup by adding the 'show' class to the form wrapper.
|
||||
*
|
||||
* @param {string} slug - The slug of the plugin.
|
||||
*/
|
||||
_showPopup( slug ) {
|
||||
$( `#deactivation-survey-${ slug }` ).addClass( 'show_popup' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides the feedback popup by removing the 'show' class from the form wrapper.
|
||||
*/
|
||||
_hidePopup() {
|
||||
this.formWrapper.removeClass( 'show_popup' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Redirects to the deactivate URL if it exists, otherwise reloads the current page.
|
||||
*/
|
||||
_redirectOrReload() {
|
||||
if ( this.deactivateUrl ) {
|
||||
window.location.href = this.deactivateUrl;
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the visibility of the feedback form and CTA based on the event target's attributes.
|
||||
*
|
||||
* @param {Event} event - The event that triggered this function.
|
||||
*/
|
||||
_hideShowFeedbackAndCTA( event ) {
|
||||
const acceptFeedback =
|
||||
$( event.target ).attr( 'data-accept_feedback' ) === 'true';
|
||||
const showCta =
|
||||
$( event.target ).attr( 'data-show_cta' ) === 'true';
|
||||
|
||||
$( event.target )
|
||||
.closest( this.formWrapper )
|
||||
.find( '.uds-options-feedback' )
|
||||
.removeClass( 'hide' )
|
||||
.addClass( acceptFeedback ? 'show' : 'hide' );
|
||||
$( event.target )
|
||||
.closest( this.formWrapper )
|
||||
.find( '.uds-option-feedback-cta' )
|
||||
.removeClass( 'hide' )
|
||||
.addClass( showCta ? 'show' : 'hide' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Changes the placeholder text of the feedback input based on the event target's attribute.
|
||||
*
|
||||
* @param {Event} event - The event that triggered this function.
|
||||
*/
|
||||
_changePlaceholderText( event ) {
|
||||
const radioButtonPlaceholder =
|
||||
event.target.getAttribute( 'data-placeholder' );
|
||||
|
||||
$( event.target )
|
||||
.closest( this.formWrapper )
|
||||
.find( this.feedbackInput )
|
||||
.attr( 'placeholder', radioButtonPlaceholder || '' );
|
||||
|
||||
this._hideShowFeedbackAndCTA( event );
|
||||
},
|
||||
|
||||
/**
|
||||
* Submits the feedback form and handles the response.
|
||||
*
|
||||
* @param {Event} event - The event that triggered this function.
|
||||
* @param {Object} self - A reference to the current object.
|
||||
*/
|
||||
_submitFeedback( event, self ) {
|
||||
event.preventDefault();
|
||||
|
||||
const currentForm = $( event.target );
|
||||
const closestForm = currentForm.closest( this.feedbackForm ); // Cache the closest form
|
||||
|
||||
// Gather form data.
|
||||
const formData = {
|
||||
action: 'uds_plugin_deactivate_feedback',
|
||||
security: udsVars?._ajax_nonce || '',
|
||||
reason:
|
||||
closestForm
|
||||
.find( this.radioButton.filter( ':checked' ) )
|
||||
.val() || '', // Get the selected radio button value from the current form.
|
||||
source: closestForm.find( 'input[name="source"]' ).val() || '',
|
||||
referer:
|
||||
closestForm.find( 'input[name="referer"]' ).val() || '',
|
||||
version:
|
||||
closestForm.find( 'input[name="version"]' ).val() || '',
|
||||
feedback: closestForm.find( this.feedbackInput ).val() || '', // Get the feedback input value from the current form.
|
||||
};
|
||||
|
||||
currentForm
|
||||
.find( '.uds-feedback-' + this.buttonAction )
|
||||
.text( 'Deactivating.' )
|
||||
.addClass( 'processing' );
|
||||
|
||||
// Prepare AJAX call.
|
||||
$.ajax( {
|
||||
url: udsVars?.ajaxurl, // URL to send the request to.
|
||||
type: 'POST', // HTTP method.
|
||||
data: formData, // Data to be sent.
|
||||
success( response ) {
|
||||
if ( response.success ) {
|
||||
self._redirectOrReload();
|
||||
}
|
||||
self._hidePopup();
|
||||
},
|
||||
/* eslint-disable */
|
||||
error( xhr, status, error ) {
|
||||
/* eslint-disable */
|
||||
self._redirectOrReload();
|
||||
},
|
||||
} );
|
||||
},
|
||||
|
||||
_handleClick( e ) {
|
||||
// Close feedback form or show/hide popup if clicked outside and add a click on a Activate button of Theme.
|
||||
if (
|
||||
e.target.classList.contains( 'show_popup' ) &&
|
||||
e.target.closest( '.uds-feedback-form--wrapper' )
|
||||
) {
|
||||
this._hidePopup();
|
||||
} else if ( e.target.classList.contains( 'activate' ) ) {
|
||||
this.deactivateUrl = e.target.href;
|
||||
|
||||
// Don't show for Child Themes.
|
||||
if (
|
||||
-1 !==
|
||||
this.deactivateUrl.indexOf(
|
||||
`stylesheet=${ udsVars?._current_theme }-child`
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
this._showPopup( udsVars?._current_theme );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes the feedback popup by caching elements and binding events.
|
||||
*/
|
||||
_init() {
|
||||
this._cacheElements();
|
||||
this._bind();
|
||||
},
|
||||
|
||||
/**
|
||||
* Binds event listeners to various elements to handle user interactions.
|
||||
*/
|
||||
_bind() {
|
||||
const self = this; // Store reference to the current object.
|
||||
|
||||
// Open the popup when clicked on the deactivate button.
|
||||
this.deactivateButton.on( 'click', function ( event ) {
|
||||
let closestTr = $( event.target ).closest( 'tr' );
|
||||
let slug = closestTr.data( 'slug' );
|
||||
|
||||
if ( self.slug.includes( slug ) ) {
|
||||
event.preventDefault();
|
||||
// Set the deactivation URL.
|
||||
self.deactivateUrl = $( event.target ).attr( 'href' );
|
||||
self._showPopup( slug );
|
||||
}
|
||||
} );
|
||||
|
||||
// Close the popup on a click of Close button.
|
||||
this.closeButton.on( 'click', function ( event ) {
|
||||
event.preventDefault();
|
||||
self._hidePopup(); // Use self to refer to the UserDeactivationPopup instance.
|
||||
} );
|
||||
|
||||
// Click event on radio button to change the placeholder of textarea.
|
||||
this.radioButton.on( 'click', function ( event ) {
|
||||
self._changePlaceholderText( event );
|
||||
} );
|
||||
|
||||
// Combined submit and skip button actions.
|
||||
this.submitDeactivate
|
||||
.add( this.skipButton )
|
||||
.on( 'click', function ( event ) {
|
||||
event.preventDefault(); // Prevent default button action.
|
||||
self.buttonAction = $( event.target ).attr( 'data-action' );
|
||||
$( event.target ).closest( self.feedbackForm ).submit();
|
||||
} );
|
||||
|
||||
this.feedbackForm.on( 'submit', function ( event ) {
|
||||
self._submitFeedback( event, self );
|
||||
} );
|
||||
|
||||
document.addEventListener( 'click', function ( e ) {
|
||||
self._handleClick( e );
|
||||
} );
|
||||
},
|
||||
};
|
||||
|
||||
$( function () {
|
||||
UserDeactivationPopup._init();
|
||||
} );
|
||||
} )( jQuery );
|
||||
@@ -0,0 +1 @@
|
||||
(i=>{let t={slug:"",skipButton:"",formWrapper:"",radioButton:"",closeButton:"",buttonAction:"",feedbackForm:"",feedbackInput:"",deactivateUrl:"",buttonTrigger:"",deactivateButton:"",submitDeactivate:"",_cacheElements(){this.slug=udsVars?._plugin_slug||"",this.skipButton=i(".uds-feedback-skip"),this.submitDeactivate=i(".uds-feedback-submit"),this.deactivateButton=i("#the-list").find(".row-actions span.deactivate a"),this.feedbackForm=i(".uds-feedback-form"),this.feedbackInput=i(".uds-options-feedback"),this.formWrapper=i(".uds-feedback-form--wrapper"),this.closeButton=i(".uds-feedback-form--wrapper .uds-close"),this.radioButton=i(".uds-reason-input")},_showPopup(t){i("#deactivation-survey-"+t).addClass("show_popup")},_hidePopup(){this.formWrapper.removeClass("show_popup")},_redirectOrReload(){this.deactivateUrl?window.location.href=this.deactivateUrl:location.reload()},_hideShowFeedbackAndCTA(t){var e="true"===i(t.target).attr("data-accept_feedback"),a="true"===i(t.target).attr("data-show_cta");i(t.target).closest(this.formWrapper).find(".uds-options-feedback").removeClass("hide").addClass(e?"show":"hide"),i(t.target).closest(this.formWrapper).find(".uds-option-feedback-cta").removeClass("hide").addClass(a?"show":"hide")},_changePlaceholderText(t){var e=t.target.getAttribute("data-placeholder");i(t.target).closest(this.formWrapper).find(this.feedbackInput).attr("placeholder",e||""),this._hideShowFeedbackAndCTA(t)},_submitFeedback(t,s){t.preventDefault();var t=i(t.target),e=t.closest(this.feedbackForm),e={action:"uds_plugin_deactivate_feedback",security:udsVars?._ajax_nonce||"",reason:e.find(this.radioButton.filter(":checked")).val()||"",source:e.find('input[name="source"]').val()||"",referer:e.find('input[name="referer"]').val()||"",version:e.find('input[name="version"]').val()||"",feedback:e.find(this.feedbackInput).val()||""};t.find(".uds-feedback-"+this.buttonAction).text("Deactivating.").addClass("processing"),i.ajax({url:udsVars?.ajaxurl,type:"POST",data:e,success(t){t.success&&s._redirectOrReload(),s._hidePopup()},error(t,e,a){s._redirectOrReload()}})},_handleClick(t){t.target.classList.contains("show_popup")&&t.target.closest(".uds-feedback-form--wrapper")?this._hidePopup():t.target.classList.contains("activate")&&(this.deactivateUrl=t.target.href,-1===this.deactivateUrl.indexOf(`stylesheet=${udsVars?._current_theme}-child`))&&(t.preventDefault(),this._showPopup(udsVars?._current_theme))},_init(){this._cacheElements(),this._bind()},_bind(){let a=this;this.deactivateButton.on("click",function(t){var e=i(t.target).closest("tr").data("slug");a.slug.includes(e)&&(t.preventDefault(),a.deactivateUrl=i(t.target).attr("href"),a._showPopup(e))}),this.closeButton.on("click",function(t){t.preventDefault(),a._hidePopup()}),this.radioButton.on("click",function(t){a._changePlaceholderText(t)}),this.submitDeactivate.add(this.skipButton).on("click",function(t){t.preventDefault(),a.buttonAction=i(t.target).attr("data-action"),i(t.target).closest(a.feedbackForm).submit()}),this.feedbackForm.on("submit",function(t){a._submitFeedback(t,a)}),document.addEventListener("click",function(t){a._handleClick(t)})}};i(function(){t._init()})})(jQuery);
|
||||
@@ -0,0 +1,319 @@
|
||||
<?php
|
||||
/**
|
||||
* Deactivation Survey Feedback.
|
||||
*
|
||||
* @package bsf-analytics
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Deactivation_Survey_Feedback' ) ) {
|
||||
|
||||
/**
|
||||
* Class Deactivation_Survey_Feedback.
|
||||
*/
|
||||
class Deactivation_Survey_Feedback {
|
||||
|
||||
/**
|
||||
* Feedback URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $feedback_api_endpoint = 'api/plugin-deactivate';
|
||||
|
||||
/**
|
||||
* Instance
|
||||
*
|
||||
* @access private
|
||||
* @var object Class object.
|
||||
* @since 1.1.6
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* Initiator
|
||||
*
|
||||
* @since 1.1.6
|
||||
* @return object initialized object of class.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( ! isset( self::$instance ) ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'load_form_styles' ) );
|
||||
add_action( 'wp_ajax_uds_plugin_deactivate_feedback', array( $this, 'send_plugin_deactivate_feedback' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render feedback HTML on plugins.php admin page only.
|
||||
*
|
||||
* This function renders the feedback form HTML on the plugins.php admin page.
|
||||
* It takes an optional string parameter $id for the form wrapper ID and an optional array parameter $args for customizing the form.
|
||||
*
|
||||
* @since 1.1.6
|
||||
* @param array $args Optional. Custom arguments for the form. Defaults to an empty array.
|
||||
* @return void
|
||||
*/
|
||||
public static function show_feedback_form( array $args = array() ) {
|
||||
|
||||
// Return if not in admin.
|
||||
if ( ! is_admin() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set default arguments for the feedback form.
|
||||
$defaults = array(
|
||||
'source' => 'User Deactivation Survey',
|
||||
'popup_logo' => '',
|
||||
'plugin_slug' => 'user-deactivation-survey',
|
||||
'plugin_version' => '',
|
||||
'popup_title' => __( 'Quick Feedback', 'astra-sites' ),
|
||||
'support_url' => 'https://brainstormforce.com/contact/',
|
||||
'popup_reasons' => self::get_default_reasons(),
|
||||
'popup_description' => __( 'If you have a moment, please share why you are deactivating the plugin.', 'astra-sites' ),
|
||||
'show_on_screens' => array( 'plugins' ),
|
||||
);
|
||||
|
||||
// Parse the arguments with defaults.
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
$id = '';
|
||||
|
||||
// Set a default ID if none is provided.
|
||||
if ( empty( $args['id'] ) ) {
|
||||
$id = 'uds-feedback-form--wrapper';
|
||||
}
|
||||
|
||||
$id = sanitize_text_field( $args['id'] );
|
||||
|
||||
// Return if not on the allowed screen.
|
||||
if ( ! BSF_Analytics_Helper::is_allowed_screen() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<div id="<?php echo esc_attr( $id ); ?>" class="uds-feedback-form--wrapper" style="display: none">
|
||||
<div class="uds-feedback-form--container">
|
||||
<div class="uds-form-header--wrapper">
|
||||
<div class="uds-form-title--icon-wrapper">
|
||||
<?php if ( ! empty( $args['popup_logo'] ) ) { ?>
|
||||
<img class="uds-icon" src="<?php echo esc_url( $args['popup_logo'] ); ?>" title="<?php echo esc_attr( $args['plugin_slug'] ); ?> <?php echo esc_attr( __( 'Icon', 'astra-sites' ) ); ?>" />
|
||||
<?php } ?>
|
||||
<h2 class="uds-title"><?php echo esc_html( $args['popup_title'] ); ?></h2>
|
||||
</div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="uds-close">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="uds-form-body--content">
|
||||
|
||||
<?php if ( ! empty( $args['popup_description'] ) ) { ?>
|
||||
<p class="uds-form-description"><?php echo esc_html( $args['popup_description'] ); ?></p>
|
||||
<?php } ?>
|
||||
|
||||
<form class="uds-feedback-form" id="uds-feedback-form" method="post">
|
||||
<?php foreach ( $args['popup_reasons'] as $key => $value ) { ?>
|
||||
<fieldset>
|
||||
<div class="reason">
|
||||
<input type="radio" class="uds-reason-input" name="uds_reason_input" id="uds_reason_input_<?php echo esc_attr( $key ); ?>" value="<?php echo esc_attr( $key ); ?>" data-placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>" data-show_cta="<?php echo esc_attr( $value['show_cta'] ); ?>" data-accept_feedback="<?php echo esc_attr( $value['accept_feedback'] ); ?>">
|
||||
<label class="uds-reason-label" for="uds_reason_input_<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $value['label'] ); ?></label>
|
||||
</div>
|
||||
</fieldset>
|
||||
<?php } ?>
|
||||
|
||||
<fieldset>
|
||||
<textarea class="uds-options-feedback hide" id="uds-options-feedback" rows="3" name="uds_options_feedback" placeholder="<?php echo esc_attr( __( 'Please tell us more details.', 'astra-sites' ) ); ?>"></textarea>
|
||||
<?php
|
||||
if ( ! empty( $args['support_url'] ) ) {
|
||||
?>
|
||||
<p class="uds-option-feedback-cta hide">
|
||||
<?php
|
||||
echo wp_kses_post(
|
||||
sprintf(
|
||||
/* translators: %1$s: link html start, %2$s: link html end*/
|
||||
__( 'Need help from our experts? %1$sClick here to contact us.%2$s', 'astra-sites' ),
|
||||
'<a href="' . esc_url( $args['support_url'] ) . '" target="_blank">',
|
||||
'</a>'
|
||||
)
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php } ?>
|
||||
</fieldset>
|
||||
|
||||
<div class="uds-feedback-form-sumbit--actions">
|
||||
<button class="button button-primary uds-feedback-submit" data-action="submit"><?php esc_html_e( 'Submit & Deactivate', 'astra-sites' ); ?></button>
|
||||
<button class="button button-secondary uds-feedback-skip" data-action="skip"><?php esc_html_e( 'Skip & Deactivate', 'astra-sites' ); ?></button>
|
||||
<input type="hidden" name="referer" value="<?php echo esc_url( get_site_url() ); ?>">
|
||||
<input type="hidden" name="version" value="<?php echo esc_attr( $args['plugin_version'] ); ?>">
|
||||
<input type="hidden" name="source" value="<?php echo esc_attr( $args['plugin_slug'] ); ?>">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Load form styles.
|
||||
*
|
||||
* This function loads the necessary styles for the feedback form.
|
||||
*
|
||||
* @since 1.1.6
|
||||
* @return void
|
||||
*/
|
||||
public static function load_form_styles() {
|
||||
|
||||
if ( ! BSF_Analytics_Helper::is_allowed_screen() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dir_path = BSF_ANALYTICS_URI . '/modules/deactivation-survey/';
|
||||
$file_ext = ! SCRIPT_DEBUG ? '.min' : '';
|
||||
|
||||
wp_enqueue_script(
|
||||
'uds-feedback-script',
|
||||
$dir_path . 'assets/js/feedback' . $file_ext . '.js',
|
||||
array( 'jquery' ),
|
||||
BSF_ANALYTICS_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
$data = apply_filters(
|
||||
'uds_survey_vars',
|
||||
array(
|
||||
'ajaxurl' => esc_url( admin_url( 'admin-ajax.php' ) ),
|
||||
'_ajax_nonce' => wp_create_nonce( 'uds_plugin_deactivate_feedback' ),
|
||||
'_current_theme' => function_exists( 'wp_get_theme' ) ? wp_get_theme()->get_template() : '',
|
||||
'_plugin_slug' => array(),
|
||||
)
|
||||
);
|
||||
|
||||
// Add localize JS.
|
||||
wp_localize_script(
|
||||
'uds-feedback-script',
|
||||
'udsVars',
|
||||
$data
|
||||
);
|
||||
|
||||
wp_enqueue_style( 'uds-feedback-style', $dir_path . 'assets/css/feedback' . $file_ext . '.css', array(), BSF_ANALYTICS_VERSION );
|
||||
wp_style_add_data( 'uds-feedback-style', 'rtl', 'replace' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends plugin deactivation feedback to the server.
|
||||
*
|
||||
* This function checks the user's permission and verifies the nonce for the request.
|
||||
* If the checks pass, it sends the feedback data to the server for processing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function send_plugin_deactivate_feedback() {
|
||||
|
||||
$response_data = array( 'message' => __( 'Sorry, you are not allowed to do this operation.', 'astra-sites' ) );
|
||||
|
||||
/**
|
||||
* Check permission
|
||||
*/
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
wp_send_json_error( $response_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Nonce verification
|
||||
*/
|
||||
if ( ! check_ajax_referer( 'uds_plugin_deactivate_feedback', 'security', false ) ) {
|
||||
$response_data = array( 'message' => __( 'Nonce validation failed', 'astra-sites' ) );
|
||||
wp_send_json_error( $response_data );
|
||||
}
|
||||
|
||||
$feedback_data = array(
|
||||
'reason' => isset( $_POST['reason'] ) ? sanitize_text_field( wp_unslash( $_POST['reason'] ) ) : '',
|
||||
'feedback' => isset( $_POST['feedback'] ) ? sanitize_text_field( wp_unslash( $_POST['feedback'] ) ) : '',
|
||||
'domain_name' => isset( $_POST['referer'] ) ? sanitize_text_field( wp_unslash( $_POST['referer'] ) ) : '',
|
||||
'version' => isset( $_POST['version'] ) ? sanitize_text_field( wp_unslash( $_POST['version'] ) ) : '',
|
||||
'plugin' => isset( $_POST['source'] ) ? sanitize_text_field( wp_unslash( $_POST['source'] ) ) : '',
|
||||
);
|
||||
|
||||
$api_args = array(
|
||||
'body' => wp_json_encode( $feedback_data ),
|
||||
'headers' => BSF_Analytics_Helper::get_api_headers(),
|
||||
'timeout' => 90, //phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout
|
||||
);
|
||||
|
||||
$target_url = BSF_Analytics_Helper::get_api_url() . self::$feedback_api_endpoint;
|
||||
|
||||
$response = wp_safe_remote_post( $target_url, $api_args );
|
||||
|
||||
$has_errors = BSF_Analytics_Helper::is_api_error( $response );
|
||||
|
||||
if ( $has_errors['error'] ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'success' => false,
|
||||
'message' => $has_errors['error_message'],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array of default reasons.
|
||||
*
|
||||
* @return array Default reasons.
|
||||
*/
|
||||
public static function get_default_reasons() {
|
||||
|
||||
return apply_filters(
|
||||
'uds_default_deactivation_reasons',
|
||||
array(
|
||||
'temporary_deactivation' => array(
|
||||
'label' => esc_html__( 'This is a temporary deactivation for testing.', 'astra-sites' ),
|
||||
'placeholder' => esc_html__( 'How can we assist you?', 'astra-sites' ),
|
||||
'show_cta' => 'false',
|
||||
'accept_feedback' => 'false',
|
||||
),
|
||||
'plugin_not_working' => array(
|
||||
'label' => esc_html__( 'The plugin isn\'t working properly.', 'astra-sites' ),
|
||||
'placeholder' => esc_html__( 'Please tell us more about what went wrong?', 'astra-sites' ),
|
||||
'show_cta' => 'true',
|
||||
'accept_feedback' => 'true',
|
||||
),
|
||||
'found_better_plugin' => array(
|
||||
'label' => esc_html__( 'I found a better alternative plugin.', 'astra-sites' ),
|
||||
'placeholder' => esc_html__( 'Could you please specify which plugin?', 'astra-sites' ),
|
||||
'show_cta' => 'false',
|
||||
'accept_feedback' => 'true',
|
||||
),
|
||||
'missing_a_feature' => array(
|
||||
'label' => esc_html__( 'It\'s missing a specific feature.', 'astra-sites' ),
|
||||
'placeholder' => esc_html__( 'Please tell us more about the feature.', 'astra-sites' ),
|
||||
'show_cta' => 'false',
|
||||
'accept_feedback' => 'true',
|
||||
),
|
||||
'other' => array(
|
||||
'label' => esc_html__( 'Other', 'astra-sites' ),
|
||||
'placeholder' => esc_html__( 'Please tell us more details.', 'astra-sites' ),
|
||||
'show_cta' => 'false',
|
||||
'accept_feedback' => 'true',
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Deactivation_Survey_Feedback::get_instance();
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
/**
|
||||
* UTM Analytics class
|
||||
*
|
||||
* @package bsf-analytics
|
||||
*/
|
||||
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'BSF_UTM_Analytics' ) ) {
|
||||
|
||||
|
||||
if ( ! defined( 'BSF_UTM_ANALYTICS_REFERER' ) ) {
|
||||
define( 'BSF_UTM_ANALYTICS_REFERER', 'bsf_product_referers' );
|
||||
}
|
||||
|
||||
/**
|
||||
* UTM Analytics class
|
||||
*
|
||||
* @since 1.1.10
|
||||
*/
|
||||
class BSF_UTM_Analytics {
|
||||
|
||||
/**
|
||||
* List of slugs of all the bsf products that will be referer, referring another product.
|
||||
*
|
||||
* @var array<string>
|
||||
* @since 1.1.10
|
||||
*/
|
||||
private static $bsf_product_slugs = [
|
||||
'all-in-one-schemaorg-rich-snippets',
|
||||
'astra',
|
||||
'astra-portfolio',
|
||||
'astra-sites',
|
||||
'bb-ultimate-addon',
|
||||
'cartflows',
|
||||
'checkout-paypal-woo',
|
||||
'checkout-plugins-stripe-woo',
|
||||
'convertpro',
|
||||
'header-footer-elementor',
|
||||
'latepoint',
|
||||
'presto-player',
|
||||
'surecart',
|
||||
'sureforms',
|
||||
'suremails',
|
||||
'suretriggers',
|
||||
'ultimate-addons-for-beaver-builder-lite',
|
||||
'ultimate-addons-for-gutenberg',
|
||||
'ultimate-elementor',
|
||||
'variation-swatches-woo',
|
||||
'woo-cart-abandonment-recovery',
|
||||
'wp-schema-pro',
|
||||
'zipwp',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* This function will help to determine if provided slug is a valid bsf product or not,
|
||||
* This way we will maintain consistency through out all our products.
|
||||
*
|
||||
* @param string $slug unique slug of the product which can be used for referer, product.
|
||||
* @since 1.1.10
|
||||
* @return boolean
|
||||
*/
|
||||
public static function is_valid_bsf_product_slug( $slug ) {
|
||||
if ( empty( $slug ) || ! is_string( $slug ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array( $slug, self::$bsf_product_slugs, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* This function updates value of referer and product in option
|
||||
* bsf_product_referer in form of key value pair as 'product' => 'referer'
|
||||
*
|
||||
* @param string $referer slug of the product which is refering another product.
|
||||
* @param string $product slug of the product which is refered.
|
||||
* @since 1.1.10
|
||||
* @return void
|
||||
*/
|
||||
public static function update_referer( $referer, $product ) {
|
||||
|
||||
$slugs = [
|
||||
'referer' => $referer,
|
||||
'product' => $product,
|
||||
];
|
||||
$error_count = 0;
|
||||
|
||||
foreach ( $slugs as $type => $slug ) {
|
||||
if ( ! self::is_valid_bsf_product_slug( $slug ) ) {
|
||||
error_log( sprintf( 'Invalid %1$s slug provided "%2$s", does not match bsf_product_slugs', $type, $slug ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- adding logs in case of failure will help in debugging.
|
||||
$error_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $error_count > 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$slugs = array_map( 'sanitize_text_field', $slugs );
|
||||
|
||||
$bsf_product_referers = get_option( BSF_UTM_ANALYTICS_REFERER, [] );
|
||||
if ( ! is_array( $bsf_product_referers ) ) {
|
||||
$bsf_product_referers = [];
|
||||
}
|
||||
|
||||
$bsf_product_referers[ $slugs['product'] ] = $slugs['referer'];
|
||||
|
||||
update_option( BSF_UTM_ANALYTICS_REFERER, $bsf_product_referers );
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will add utm_args to pro link or purchase link
|
||||
* added utm_source by default additional utm_args such as utm_medium etc can be provided to generate location specific links
|
||||
*
|
||||
* @param string $link Ideally this should be product site link where utm_params can be tracked.
|
||||
* @param string $product Product slug whose utm_link need to be created.
|
||||
* @param mixed $utm_args additional args to be passed ex: [ 'utm_medium' => 'dashboard'].
|
||||
* @since 1.1.10
|
||||
* @return string
|
||||
*/
|
||||
public static function get_utm_ready_link( $link, $product, $utm_args = [] ) {
|
||||
|
||||
if ( false === wp_http_validate_url( $link ) ) {
|
||||
error_log( 'Invalid url passed to get_utm_ready_link function' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- adding logs in case of failure will help in debugging.
|
||||
return $link;
|
||||
}
|
||||
|
||||
if ( empty( $product ) || ! is_string( $product ) || ! self::is_valid_bsf_product_slug( $product ) ) {
|
||||
error_log( sprintf( 'Invalid product slug provided "%1$s", does not match bsf_product_slugs', $product ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- adding logs in case of failure will help in debugging.
|
||||
return $link;
|
||||
}
|
||||
|
||||
$bsf_product_referers = get_option( BSF_UTM_ANALYTICS_REFERER, [] );
|
||||
|
||||
if ( ! is_array( $bsf_product_referers ) || empty( $bsf_product_referers[ $product ] ) ) {
|
||||
return $link;
|
||||
}
|
||||
|
||||
if ( ! self::is_valid_bsf_product_slug( $bsf_product_referers[ $product ] ) ) {
|
||||
return $link;
|
||||
}
|
||||
|
||||
if ( ! is_array( $utm_args ) ) {
|
||||
$utm_args = [];
|
||||
}
|
||||
|
||||
$utm_args['utm_source'] = $bsf_product_referers[ $product ];
|
||||
|
||||
$link = add_query_arg(
|
||||
$utm_args,
|
||||
$link
|
||||
);
|
||||
|
||||
return $link;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user