Skip to content

Commit 8da6782

Browse files
committed
initialize 🔥
0 parents  commit 8da6782

File tree

12 files changed

+1555
-0
lines changed

12 files changed

+1555
-0
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/tests export-ignore
2+
/phpunit.xml export-ignore

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
vendor/
2+
composer.lock
3+
.phpunit.result.cache
4+
/phpunit.xml

LICENSE

Lines changed: 339 additions & 0 deletions
Large diffs are not rendered by default.

composer.json

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"name": "bitapps/wp-telemetry",
3+
"description": "Collect diagnostic data and deactivation reason for a WordPress plugin",
4+
"type": "library",
5+
"homepage": "https://bitapps.pro",
6+
"license": "GPL-2.0-or-later",
7+
"version": "0.0.1",
8+
"keywords": [
9+
"diagnostic",
10+
"data",
11+
"collect",
12+
"deactivation",
13+
"reason"
14+
],
15+
"support": {
16+
"issues": "https://github.com/Bit-Apps-Pro/wp-telemetry/issues",
17+
"source": "https://github.com/Bit-Apps-Pro/wp-telemetry"
18+
},
19+
"authors": [
20+
{
21+
"email": "developer@bitcode.pro",
22+
"name": "BitApps"
23+
}
24+
],
25+
"autoload": {
26+
"psr-4": {
27+
"BitApps\\WPTelemetry\\": "src/"
28+
}
29+
},
30+
"autoload-dev": {
31+
"psr-4": {
32+
"BitApps\\WPTelemetry\\Tests\\": [
33+
"tests/"
34+
]
35+
}
36+
},
37+
"scripts": {
38+
"test:unit": "./vendor/bin/pest --testdox --colors=always tests/ --exclude-group db",
39+
"compat": "./vendor/bin/phpcs -p ./src --standard=PHPCompatibility --runtime-set testVersion 5.6-",
40+
"post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility",
41+
"post-update-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility"
42+
},
43+
"require": {
44+
"php": ">=5.6"
45+
},
46+
"require-dev": {
47+
"pestphp/pest": "3.x-dev",
48+
"squizlabs/php_codesniffer": "*",
49+
"phpcompatibility/php-compatibility": "*"
50+
},
51+
"minimum-stability": "dev",
52+
"config": {
53+
"allow-plugins": {
54+
"pestphp/pest-plugin": true,
55+
"dealerdirect/phpcodesniffer-composer-installer": true
56+
}
57+
}
58+
}

readme.md

Whitespace-only changes.

src/Telemetry/Client.php

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
namespace BitApps\WPTelemetry\Telemetry;
4+
5+
use BitApps\WPTelemetry\Telemetry\Feedback\Feedback;
6+
use BitApps\WPTelemetry\Telemetry\Report\Report;
7+
8+
class Client
9+
{
10+
public $report;
11+
12+
public $feedback;
13+
14+
public $title;
15+
16+
public $slug;
17+
18+
public $prefix;
19+
20+
public $version;
21+
22+
public $logo;
23+
24+
public $telemetryVersion = '0.1.0';
25+
26+
public $termsUrl = 'https://bitapps.pro/terms';
27+
28+
public $policyUrl = 'https://bitapps.pro/privacy-policy';
29+
30+
public $apiBaseUrl = 'https://wp-api.bitapps.pro/public/';
31+
32+
public function __construct($title, $slug, $prefix, $version)
33+
{
34+
$this->title = $title;
35+
36+
$this->slug = $slug;
37+
38+
$this->prefix = $prefix;
39+
40+
$this->version = $version;
41+
}
42+
43+
public function report()
44+
{
45+
if (!$this->report) {
46+
$this->report = new Report($this);
47+
}
48+
49+
return $this->report;
50+
}
51+
52+
public function feedback()
53+
{
54+
if (!$this->feedback) {
55+
$this->feedback = new Feedback($this);
56+
}
57+
58+
return $this->feedback;
59+
}
60+
61+
public function setLogo($logo)
62+
{
63+
$this->logo = $logo;
64+
}
65+
66+
public function setTermsUrl($url)
67+
{
68+
$this->termsUrl = $url;
69+
}
70+
71+
public function setPolicyUrl($url)
72+
{
73+
$this->policyUrl = $url;
74+
}
75+
76+
public function setServerUrl($url)
77+
{
78+
$this->apiBaseUrl = trailingslashit($url);
79+
}
80+
81+
public function view($fileName, $args)
82+
{
83+
load_template(\dirname(\dirname(__DIR__)) . '/src/views/' . $fileName . '.php', false, $args);
84+
}
85+
86+
public function sendReport($route, $data, $blocking = false)
87+
{
88+
$apiUrl = $this->apiBaseUrl . $route;
89+
90+
$headers = [
91+
'host-user' => 'BitApps/' . md5(esc_url(home_url())),
92+
'Content-Type' => 'application/json',
93+
];
94+
95+
return wp_remote_post(
96+
$apiUrl,
97+
[
98+
'method' => 'POST',
99+
'timeout' => 30,
100+
'redirection' => 5,
101+
'httpversion' => '1.0',
102+
'blocking' => $blocking,
103+
'headers' => $headers,
104+
'body' => wp_json_encode(array_merge($data, ['wp_telemetry' => $this->telemetryVersion])),
105+
'cookies' => [],
106+
]
107+
);
108+
}
109+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
<?php
2+
3+
namespace BitApps\WPTelemetry\Telemetry\Feedback;
4+
5+
use BitApps\WPTelemetry\Telemetry\Client;
6+
7+
class Feedback
8+
{
9+
private $client;
10+
11+
public function __construct(Client $client)
12+
{
13+
$this->client = $client;
14+
15+
$this->init();
16+
}
17+
18+
public function init()
19+
{
20+
add_action('wp_ajax_' . $this->client->prefix . 'deactivate_feedback', [$this, 'handleDeactivateFeedback']);
21+
22+
add_action('current_screen', [$this, 'loadAllScripts']);
23+
}
24+
25+
public function loadAllScripts()
26+
{
27+
if (!$this->is_plugins_screen()) {
28+
return;
29+
}
30+
31+
add_action('admin_enqueue_scripts', [$this, 'enqueueFeedbackDialogScripts']);
32+
}
33+
34+
/**
35+
* Enqueue feedback dialog scripts.
36+
*
37+
* Registers the feedback dialog scripts and enqueues them.
38+
*
39+
* @since 0.0.1
40+
*/
41+
public function enqueueFeedbackDialogScripts()
42+
{
43+
add_action('admin_footer', [$this, 'printDeactivateFeedbackDialog']);
44+
45+
$cssFilePath = $this->getAssetPath() . 'resources/css/deactivateModalStyle.css';
46+
wp_register_style($this->client->prefix . 'deactivate_modal', $cssFilePath, [], $this->client->version);
47+
wp_enqueue_style($this->client->prefix . 'deactivate_modal');
48+
}
49+
50+
public static function getAssetPath()
51+
{
52+
return plugin_dir_url(\dirname(__DIR__));
53+
}
54+
55+
/**
56+
* Print deactivate feedback dialog.
57+
*
58+
* Display a dialog box to ask the user why he deactivated this plugin.
59+
*
60+
* @since 0.0.1
61+
*/
62+
public function printDeactivateFeedbackDialog()
63+
{
64+
$this->client->view('deactivateModal', [
65+
'slug' => $this->client->slug,
66+
'prefix' => $this->client->prefix,
67+
'title' => $this->client->title,
68+
'logo' => $this->client->logo,
69+
'reasons' => $this->getDeactivateReasons(),
70+
]);
71+
}
72+
73+
public function getDeactivateReasons()
74+
{
75+
$reasons = [
76+
'found_a_better_plugin' => [
77+
'title' => esc_html__('Found a better plugin', $this->client->slug),
78+
'placeholder' => esc_html__('Which plugin?', $this->client->slug),
79+
],
80+
'missing_specific_feature' => [
81+
'title' => esc_html__('Missing a specific featureMissing a specific featureMissing a specific feature featureMissing a specific feature', $this->client->slug),
82+
'placeholder' => esc_html__('Could you tell us more about that feature?', $this->client->slug),
83+
],
84+
'not_working' => [
85+
'title' => esc_html__('Not working', $this->client->slug),
86+
'placeholder' => esc_html__('Could you tell us what is not working?', $this->client->slug),
87+
],
88+
'not_working_as_expected' => [
89+
'title' => esc_html__('Not working as expected', $this->client->slug),
90+
'placeholder' => esc_html__('Could you tell us what do you expect?', $this->client->slug),
91+
],
92+
'temporary_deactivation' => [
93+
'title' => esc_html__('It\'s a temporary deactivation', $this->client->slug),
94+
'placeholder' => '',
95+
],
96+
$this->client->prefix . 'pro' => [
97+
'title' => esc_html__('I have ' . $this->client->title . ' Pro', $this->client->slug),
98+
'placeholder' => '',
99+
'alert' => esc_html__('Wait! Don\'t deactivate ' . $this->client->title . '. You have to activate both ' . $this->client->title . ' and ' . $this->client->title . ' Pro in order to work the plugin.', $this->client->slug),
100+
],
101+
'other' => [
102+
'title' => esc_html__('Other', $this->client->slug),
103+
'placeholder' => esc_html__('Please share the reason', $this->client->slug),
104+
],
105+
];
106+
107+
return apply_filters($this->client->prefix . 'deactivate_reasons', $reasons, $this->client);
108+
}
109+
110+
/**
111+
* Ajax plugin deactivate feedback.
112+
*
113+
* Send the user feedback when plugin is deactivated.
114+
*
115+
* @since 0.0.1
116+
*/
117+
public function handleDeactivateFeedback()
118+
{
119+
if (!isset($_POST['_ajax_nonce'])) {
120+
return;
121+
}
122+
123+
if (!wp_verify_nonce(sanitize_key(wp_unslash($_POST['_ajax_nonce'])), $this->client->prefix . 'nonce')) {
124+
wp_send_json_error('Nonce verification failed');
125+
}
126+
127+
if (!current_user_can('activate_plugins')) {
128+
wp_send_json_error('Permission denied');
129+
}
130+
131+
$report = $this->client->report->getTrackingData();
132+
$report['site_lang'] = get_bloginfo('language');
133+
$report['feedback_key'] = sanitize_text_field(wp_unslash($_POST['reason_key'])) ?: null;
134+
$report['feedback'] = sanitize_text_field(wp_unslash($_POST["reason_{$report['feedback_key']}"])) ?: null;
135+
136+
$this->client->sendReport('deactivate-reason', $report);
137+
138+
wp_send_json_success();
139+
}
140+
141+
/**
142+
* @since 0.0.1
143+
*/
144+
private function is_plugins_screen()
145+
{
146+
return \in_array(get_current_screen()->id, ['plugins', 'plugins-network']);
147+
}
148+
}

0 commit comments

Comments
 (0)