PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / trunk
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! vtrunk
3.8.0 3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 All 112 releases
templately / modules / deactivation-survey / REST / Survey.php

Survey.php in Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! trunk, at modules/deactivation-survey/REST/Survey.php

124 lines 3.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Templately\Modules\DeactivationSurvey\REST;
4
5 use Templately\API\API;
6 use Templately\Utils\Helper;
7 use WP_REST_Request;
8
9 /**
10 * POST /templately/v1/deactivation-feedback — the optional "why are you leaving?"
11 * submission from the plugins screen.
12 *
13 * REST rather than the `wp_ajax_templately_deactivation_feedback` action the
14 * original carried on `latest`. New endpoints on this branch are REST by
15 * convention (Constitution III / the PRD §9 migration), and unlike the
16 * post-import-feedback migration there is nothing to keep a shim for: this
17 * feature has never shipped from this branch, so no cached bundle anywhere is
18 * calling the old action name.
19 *
20 * The request is fire-and-forget from the client — it is sent with `keepalive`
21 * and never awaited, because it must not delay or block the deactivation the
22 * user actually asked for. That shapes the contract here: this endpoint has no
23 * meaningful failure the UI will ever read.
24 */
25 class Survey extends API {
26
27 private $endpoint = 'deactivation-feedback';
28
29 /**
30 * Reason codes offered in the survey dropdown.
31 *
32 * Keep in sync with CommonConstant::DEACTIVATION_REASONS on the backend — the
33 * cloud rejects a code it does not know, and the whole submission is discarded
34 * rather than partially stored.
35 *
36 * @var string[]
37 */
38 const REASONS = [
39 'temporary' => 'It\'s a temporary deactivation',
40 'no_longer_need' => 'I no longer need the plugin',
41 'found_better' => 'I found a better plugin',
42 'not_working' => 'It\'s not working / broke my site',
43 'couldnt_configure' => 'I couldn\'t get the plugin to work',
44 'missing_feature' => 'Missing a feature I need',
45 'other' => 'Other',
46 ];
47
48 /**
49 * Deactivating is the act being surveyed, so it is also the capability.
50 *
51 * Deliberately NOT the base class's `delete_posts`: an author who can delete a
52 * post has no business filing a deactivation reason, and deliberately not a
53 * connected-account check either — someone deactivating over a broken or
54 * expired connection is exactly the feedback worth having.
55 *
56 * @param WP_REST_Request $request
57 * @return bool
58 */
59 public function permission_check( WP_REST_Request $request ) {
60 $this->request = $request;
61
62 return current_user_can( 'deactivate_plugins' );
63 }
64
65 public function register_routes() {
66 $this->post( $this->endpoint, [ $this, 'submit' ] );
67 }
68
69 /**
70 * The reason list, shaped for the JS dropdown.
71 *
72 * @return array<int, array{value:string,label:string}>
73 */
74 public static function get_reasons_for_js() {
75 $reasons = [];
76
77 foreach ( self::REASONS as $value => $label ) {
78 $reasons[] = [
79 'value' => $value,
80 // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteral -- constant-fed, one entry per REASONS key.
81 'label' => __( $label, 'templately' ),
82 ];
83 }
84
85 return $reasons;
86 }
87
88 /**
89 * Forward the reason to the cloud.
90 */
91 public function submit() {
92 $reason = $this->get_param( 'reason', '', 'sanitize_key' );
93
94 if ( ! array_key_exists( $reason, self::REASONS ) ) {
95 return $this->error(
96 'invalid_reason',
97 __( 'Unknown deactivation reason.', 'templately' ),
98 $this->endpoint,
99 400
100 );
101 }
102
103 // sanitize_textarea_field, not the base sanitize_text_field: this is the one
104 // free-text field in the payload and newlines are the whole point of it.
105 $message = $this->get_param( 'message', '', 'sanitize_textarea_field' );
106
107 $response = Helper::make_api_post_request( 'v2/deactivation-feedback', [
108 'reason' => $reason,
109 'message' => $message,
110 ] );
111
112 if ( is_wp_error( $response ) ) {
113 return $this->error(
114 'api_error',
115 $response->get_error_message(),
116 $this->endpoint,
117 500
118 );
119 }
120
121 return $this->success( [] );
122 }
123 }
124