array( 'id' => 3, 'type' => 'text', 'placeholder' => 'What\'s the plugin\'s name?', ), 'I could not get the plugin to work' => array( 'type' => 'textarea', 'placeholder' => 'What problem are you experiencing?', 'id' => 4, ), 'I no longer need the plugin' => array( 'id' => 5, 'type' => 'textarea', 'placeholder' => 'If you could improve one thing about our product, what would it be?', ), 'It\'s a temporary deactivation. I\'m just debugging an issue.' => array( 'type' => 'textarea', 'placeholder' => 'What problem are you experiencing?', 'id' => 6, ), ); /** * Default options for theme. * * @var array $options_theme The main options list for themes. */ private $options_theme = array( 'I don\'t know how to make it look like demo' => array( 'id' => 7, ), 'It lacks options' => array( 'placeholder' => 'What option is missing?', 'type' => 'text', 'id' => 8, ), 'Is not working with a plugin that I need' => array( 'id' => 9, 'type' => 'text', 'placeholder' => 'What is the name of the plugin', ), 'I want to try a new design, I don\'t like {theme} style' => array( 'id' => 10, ), ); /** * Default other option. * * @var array $other The other option */ private $other = array( 'Other' => array( 'id' => 999, 'type' => 'textarea', 'placeholder' => 'What can we do better?', ), ); /** * Default heading for plugin. * * @var string $heading_plugin The heading of the modal */ private $heading_plugin = 'What\'s wrong?'; /** * Default heading for theme. * * @var string $heading_theme The heading of the modal */ private $heading_theme = 'What does not work for you in {theme}?'; /** * Default submit button action text. * * @var string $button_submit The text of the deactivate button */ private $button_submit = 'Submit & Deactivate'; /** * Default cancel button. * * @var string $button_cancel The text of the cancel button */ private $button_cancel = 'Skip & Deactivate'; /** * Loads the additional resources */ public function load_resources() { $screen = get_current_screen(); if ( ! $screen || ! in_array( $screen->id, array( 'theme-install', 'plugins' ) ) ) { return; } $this->add_feedback_popup_style(); if ( $this->product->get_type() === 'theme' ) { $this->add_theme_feedback_drawer_js(); $this->render_theme_feedback_popup(); return; } $this->add_plugin_feedback_popup_js(); $this->render_plugin_feedback_popup(); } /** * Render theme feedback drawer. */ private function render_theme_feedback_popup() { $heading = str_replace( '{theme}', $this->product->get_name(), $this->heading_theme ); $button_submit = apply_filters( $this->product->get_key() . '_feedback_deactivate_button_submit', 'Submit' ); $options = $this->options_theme; $options = $this->randomize_options( apply_filters( $this->product->get_key() . '_feedback_deactivate_options', $options ) ); $info_disclosure_link = '' . apply_filters( $this->product->get_slug() . '_themeisle_sdk_info_collect_cta', 'What info do we collect?' ) . ''; $options += $this->other; ?>
product->get_key(); ?> product->get_key() . '_uninstall_feedback_after_js' ); } /** * Render the options list. * * @param array $options the options for the feedback form. */ private function render_options_list( $options ) { $key = $this->product->get_key(); $inputs_row_map = [ 'text' => 1, 'textarea' => 2, ]; ?> product->get_key() . '_feedback_deactivate_button_cancel', $this->button_cancel ); $button_submit = apply_filters( $this->product->get_key() . '_feedback_deactivate_button_submit', $this->button_submit ); $options = $this->randomize_options( apply_filters( $this->product->get_key() . '_feedback_deactivate_options', $this->options_plugin ) ); $info_disclosure_link = '' . apply_filters( $this->product->get_slug() . '_themeisle_sdk_info_collect_cta', 'What info do we collect?' ) . ''; $options += $this->other; ?>
product->get_slug() . '_uninstall_feedback_popup'; $key = $this->product->get_key(); ?> product->get_key() . '_uninstall_feedback_after_js' ); } /** * Get the disclosure labels markup. * * @return string */ private function get_disclosure_labels() { $disclosure_new_labels = apply_filters( $this->product->get_slug() . '_themeisle_sdk_disclosure_content_labels', [], $this->product ); $disclosure_labels = array_merge( [ 'title' => 'Below is a detailed view of all data that ThemeIsle will receive if you fill in this survey. No email address or IP addresses are transmitted after you submit the survey.', 'items' => [ sprintf( '%s %s version %s %s %s %s', '', ucwords( $this->product->get_type() ), '', '', $this->product->get_version(), '' ), sprintf( '%sCurrent website:%s %s %s %s', '', '', '', get_site_url(), '' ), sprintf( '%sUsage time:%s %s %s%s', '', '', '', ( time() - $this->product->get_install_time() ), 's' ), sprintf( '%s Uninstall reason %s %s Selected reason from the above survey %s ', '', '', '', '' ), ], ], $disclosure_new_labels ); $info_disclosure_content = '

' . wp_kses_post( $disclosure_labels['title'] ) . '

'; return $info_disclosure_content; } /** * Randomizes the options array. * * @param array $options The options array. */ public function randomize_options( $options ) { $new = array(); $keys = array_keys( $options ); shuffle( $keys ); foreach ( $keys as $key ) { $new[ $key ] = $options[ $key ]; } return $new; } /** * Called when the deactivate button is clicked. */ public function post_deactivate() { check_ajax_referer( (string) __CLASS__, 'nonce' ); $this->post_deactivate_or_cancel(); if ( empty( $_POST['id'] ) ) { wp_send_json( [] ); return; } $this->call_api( array( 'type' => 'deactivate', 'id' => sanitize_key( $_POST['id'] ), 'comment' => isset( $_POST['msg'] ) ? sanitize_textarea_field( $_POST['msg'] ) : '', ) ); wp_send_json( [] ); } /** * Called when the deactivate/cancel button is clicked. */ private function post_deactivate_or_cancel() { if ( ! isset( $_POST['type'] ) || ! isset( $_POST['key'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing, Nonce already present in caller function. return; } if ( 'theme' !== $_POST['type'] ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing, Nonce already present in caller function. return; } set_transient( 'ti_sdk_pause_' . sanitize_text_field( $_POST['key'] ), true, self::PAUSE_DEACTIVATE_WINDOW_DAYS * DAY_IN_SECONDS );//phpcs:ignore WordPress.Security.NonceVerification.Missing, Nonce already present in caller function. } /** * Calls the API * * @param array $attributes The attributes of the post body. * * @return bool Is the request succesfull? */ protected function call_api( $attributes ) { $slug = $this->product->get_slug(); $version = $this->product->get_version(); $attributes['slug'] = $slug; $attributes['version'] = $version; $attributes['url'] = get_site_url(); $attributes['active_time'] = ( time() - $this->product->get_install_time() ); $response = wp_remote_post( self::FEEDBACK_ENDPOINT, array( 'body' => $attributes, ) ); return is_wp_error( $response ); } /** * Should we load this object?. * * @param Product $product Product object. * * @return bool Should we load the module? */ public function can_load( $product ) { if ( $this->is_from_partner( $product ) ) { return false; } if ( $product->is_theme() && ( false !== get_transient( 'ti_sdk_pause_' . $product->get_key(), false ) ) ) { return false; } if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { return true; } global $pagenow; if ( ! isset( $pagenow ) || empty( $pagenow ) ) { return false; } if ( $product->is_plugin() && 'plugins.php' !== $pagenow ) { return false; } if ( $product->is_theme() && 'theme-install.php' !== $pagenow ) { return false; } return true; } /** * Loads module hooks. * * @param Product $product Product details. * * @return Uninstall_Feedback Current module instance. */ public function load( $product ) { if ( apply_filters( $product->get_key() . '_hide_uninstall_feedback', false ) ) { return; } $this->product = $product; add_action( 'admin_head', array( $this, 'load_resources' ) ); add_action( 'wp_ajax_' . $this->product->get_key() . '_uninstall_feedback', array( $this, 'post_deactivate' ) ); return $this; } }