PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 1.4.9
Backup Migration v1.4.9
2.1.6 2.1.5.2 trunk 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.6.1 1.4.7 1.4.8 1.4.9 1.4.9.1 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.5.1
backup-backup / analyst / src / Account / Account.php
backup-backup / analyst / src / Account Last commit date
Account.php 11 months ago AccountData.php 11 months ago AccountDataFactory.php 11 months ago
Account.php
630 lines
1 <?php
2
3 namespace Account;
4
5 use Analyst\Analyst;
6 use Analyst\ApiRequestor;
7 use Analyst\Cache\DatabaseCache;
8 use Analyst\Collector;
9 use Analyst\Http\Requests\ActivateRequest;
10 use Analyst\Http\Requests\DeactivateRequest;
11 use Analyst\Http\Requests\InstallRequest;
12 use Analyst\Http\Requests\OptInRequest;
13 use Analyst\Http\Requests\OptOutRequest;
14 use Analyst\Http\Requests\UninstallRequest;
15 use Analyst\Notices\Notice;
16 use Analyst\Notices\NoticeFactory;
17 use Analyst\Contracts\TrackerContract;
18 use Analyst\Contracts\RequestorContract;
19
20 /**
21 * Class Account
22 *
23 * This is plugin's account object
24 */
25 class Account implements TrackerContract
26 {
27 /**
28 * Account id
29 *
30 * @var string
31 */
32 protected $id;
33
34 /**
35 * Basename of plugin
36 *
37 * @var string
38 */
39 protected $path;
40
41 /**
42 * Whether plugin is active or not
43 *
44 * @var bool
45 */
46 protected $isInstalled = false;
47
48 /**
49 * Is user sign in for data tracking
50 *
51 * @var bool
52 */
53 protected $isOptedIn = false;
54
55 /**
56 * Is user accepted permissions grant
57 * for collection site data
58 *
59 * @var bool
60 */
61 protected $isSigned = false;
62
63 /**
64 * Is user ever resolved install modal window?
65 *
66 * @var bool
67 */
68 protected $isInstallResolved = false;
69
70 /**
71 * Public secret code
72 *
73 * @var string
74 */
75 protected $clientSecret;
76
77 /**
78 * @var AccountData
79 */
80 protected $data;
81
82 /**
83 * Base plugin path
84 *
85 * @var string
86 */
87 protected $basePluginPath;
88
89 /**
90 * @var RequestorContract
91 */
92 protected $requestor;
93
94 /**
95 * @var Collector
96 */
97 protected $collector;
98
99 /**
100 * Account constructor.
101 * @param $id
102 * @param $secret
103 * @param $baseDir
104 */
105 public function __construct($id, $secret, $baseDir)
106 {
107 $this->id = $id;
108 $this->clientSecret = $secret;
109
110 $this->path = $baseDir;
111
112 $this->basePluginPath = plugin_basename($baseDir);
113 }
114
115 /**
116 * @return string
117 */
118 public function getPath()
119 {
120 return $this->path;
121 }
122
123 /**
124 * @param string $path
125 */
126 public function setPath($path)
127 {
128 $this->data->setPath($path);
129
130 $this->path = $path;
131 }
132
133 /**
134 * @return bool
135 */
136 public function isOptedIn()
137 {
138 return $this->isOptedIn;
139 }
140
141 /**
142 * @param bool $isOptedIn
143 */
144 public function setIsOptedIn($isOptedIn)
145 {
146 $this->data->setIsOptedIn($isOptedIn);
147
148 $this->isOptedIn = $isOptedIn;
149 }
150
151 /**
152 * Whether plugin is active
153 *
154 * @return bool
155 */
156 public function isActive()
157 {
158 return is_plugin_active($this->path);
159 }
160
161 /**
162 * @param string $id
163 */
164 public function setId($id)
165 {
166 $this->id = $id;
167 }
168
169 /**
170 * @return string
171 */
172 public function getId()
173 {
174 return $this->id;
175 }
176
177 /**
178 * @return bool
179 */
180 public function isInstalled()
181 {
182 return $this->isInstalled;
183 }
184
185 /**
186 * @param bool $isInstalled
187 */
188 public function setIsInstalled($isInstalled)
189 {
190 $this->data->setIsInstalled($isInstalled);
191
192 $this->isInstalled = $isInstalled;
193 }
194
195 protected function verifyNonceAndPerms() {
196
197 $capabilities = [
198 'activate_plugins',
199 'edit_plugins',
200 'install_plugins',
201 'update_plugins',
202 'delete_plugins',
203 'manage_network_plugins',
204 'upload_plugins'
205 ];
206
207 // Allow if has any of above permissions
208 $hasPerms = false;
209 foreach ($capabilities as $i => $cap) {
210 if (current_user_can($cap)) {
211 $hasPerms = true;
212 break;
213 }
214 }
215
216 if ($hasPerms == false) {
217 wp_send_json_error(['message' => 'no_permissions']);
218 die;
219 }
220
221 if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field($_POST['nonce']), 'analyst_opt_ajax_nonce')) {
222 wp_send_json_error(['message' => 'invalid_nonce']);
223 die;
224 }
225
226 }
227
228 /**
229 * Should register activation and deactivation
230 * event hooks
231 *
232 * @return void
233 */
234 public function registerHooks()
235 {
236 register_activation_hook($this->basePluginPath, [&$this, 'onActivePluginListener']);
237 register_uninstall_hook($this->basePluginPath, ['Account\Account', 'onUninstallPluginListener']);
238
239 $this->addFilter('plugin_action_links', [&$this, 'onRenderActionLinksHook']);
240
241 $this->addAjax('analyst_opt_in', [&$this, 'onOptInListener']);
242 $this->addAjax('analyst_opt_out', [&$this, 'onOptOutListener']);
243 $this->addAjax('analyst_plugin_deactivate', [&$this, 'onDeactivatePluginListener']);
244 $this->addAjax('analyst_install', [&$this, 'onInstallListener']);
245 $this->addAjax('analyst_skip_install', [&$this, 'onSkipInstallListener']);
246 $this->addAjax('analyst_install_verified', [&$this, 'onInstallVerifiedListener']);
247 }
248
249 /**
250 * Will fire when admin activates plugin
251 *
252 * @return void
253 */
254 public function onActivePluginListener()
255 {
256 if (!$this->isInstallResolved()) {
257 DatabaseCache::getInstance()->put('plugin_to_install', $this->id);
258 }
259
260 if (!$this->isAllowingLogging()) return;
261
262 ActivateRequest::make($this->collector, $this->id, $this->path)
263 ->execute($this->requestor);
264
265 $this->setIsInstalled(true);
266
267 AccountDataFactory::syncData();
268 }
269
270 /**
271 * Will fire when admin deactivates plugin
272 *
273 * @return void
274 */
275 public function onDeactivatePluginListener()
276 {
277 $this->verifyNonceAndPerms();
278
279 if (!$this->isAllowingLogging()) return;
280
281 $question = isset($_POST['question']) ? sanitize_text_field(stripslashes($_POST['question'])) : null;
282 $reason = isset($_POST['reason']) ? sanitize_text_field(stripslashes($_POST['reason'])) : null;
283
284 DeactivateRequest::make($this->collector, $this->id, $this->path, $question, $reason)
285 ->execute($this->requestor);
286
287 $this->setIsInstalled(false);
288
289 AccountDataFactory::syncData();
290
291 wp_send_json_success();
292 }
293
294 /**
295 * Will fire when user opted in
296 *
297 * @return void
298 */
299 public function onOptInListener()
300 {
301 $this->verifyNonceAndPerms();
302
303 OptInRequest::make($this->collector, $this->id, $this->path)->execute($this->requestor);
304
305 $this->setIsOptedIn(true);
306
307 AccountDataFactory::syncData();
308
309 wp_die();
310 }
311
312 /**
313 * Will fire when user opted out
314 *
315 * @return void
316 */
317 public function onOptOutListener()
318 {
319 $this->verifyNonceAndPerms();
320
321 OptOutRequest::make($this->collector, $this->id, $this->path)->execute($this->requestor);
322
323 $this->setIsOptedIn(false);
324
325 AccountDataFactory::syncData();
326
327 wp_send_json_success();
328 }
329
330 /**
331 * Will fire when user accept opt-in
332 * at first time
333 *
334 * @return void
335 */
336 public function onInstallListener()
337 {
338 $this->verifyNonceAndPerms();
339
340 $cache = DatabaseCache::getInstance();
341
342 // Set flag to true which indicates that install is resolved
343 // also remove install plugin id from cache
344 $this->setIsInstallResolved(true);
345 $cache->delete('plugin_to_install');
346
347 InstallRequest::make($this->collector, $this->id, $this->path)->execute($this->requestor);
348
349 $this->setIsSigned(true);
350
351 $this->setIsOptedIn(true);
352
353 $factory = NoticeFactory::instance();
354
355 $message = sprintf('Please confirm your email by clicking on the link we sent to %s. This makes sure you’re not a bot.', $this->collector->getGeneralEmailAddress());
356
357 $notificationId = uniqid();
358
359 $notice = Notice::make(
360 $notificationId,
361 $this->getId(),
362 $message,
363 $this->collector->getPluginName($this->path)
364 );
365
366 $factory->addNotice($notice);
367
368 AccountDataFactory::syncData();
369
370 // Set email confirmation notification id to cache
371 // se we can extract and remove it when user confirmed email
372 $cache->put(
373 sprintf('account_email_confirmation_%s', $this->getId()),
374 $notificationId
375 );
376
377 wp_send_json_success();
378 }
379
380 /**
381 * Will fire when user skipped installation
382 *
383 * @return void
384 */
385 public function onSkipInstallListener()
386 {
387 $this->verifyNonceAndPerms();
388
389 // Set flag to true which indicates that install is resolved
390 // also remove install plugin id from cache
391 $this->setIsInstallResolved(true);
392 DatabaseCache::getInstance()->delete('plugin_to_install');
393 }
394
395 /**
396 * Will fire when user delete plugin through admin panel.
397 * This action will happen if admin at least once
398 * activated the plugin.
399 *
400 * @return void
401 * @throws \Exception
402 */
403 public static function onUninstallPluginListener()
404 {
405 $factory = AccountDataFactory::instance();
406
407 $pluginFile = substr(current_filter(), strlen( 'uninstall_' ));
408
409 $account = $factory->getAccountDataByBasePath($pluginFile);
410
411 // If account somehow is not found, exit the execution
412 if (!$account) return;
413
414 $analyst = Analyst::getInstance();
415
416 $collector = new Collector($analyst);
417
418 $requestor = new ApiRequestor($account->getId(), $account->getSecret(), $analyst->getApiBase());
419
420 // Just send request to log uninstall event not caring about response
421 UninstallRequest::make($collector, $account->getId(), $account->getPath())->execute($requestor);
422
423 $factory->sync();
424 }
425
426 /**
427 * Fires when used verified his account
428 */
429 public function onInstallVerifiedListener()
430 {
431 $this->verifyNonceAndPerms();
432
433 $factory = NoticeFactory::instance();
434
435 $notice = Notice::make(
436 uniqid(),
437 $this->getId(),
438 'Thank you for confirming your email.',
439 $this->collector->getPluginName($this->path)
440 );
441
442 $factory->addNotice($notice);
443
444 // Remove confirmation notification
445 $confirmationNotificationId = DatabaseCache::getInstance()->pop(sprintf('account_email_confirmation_%s', $this->getId()));
446 $factory->remove($confirmationNotificationId);
447
448 AccountDataFactory::syncData();
449
450 wp_send_json_success();
451 }
452
453 /**
454 * Will fire when wp renders plugin
455 * action buttons
456 *
457 * @param $defaultLinks
458 * @return array
459 */
460 public function onRenderActionLinksHook($defaultLinks)
461 {
462 $customLinks = [];
463
464 $customLinks[] = $this->isOptedIn()
465 ? '<a class="analyst-action-opt analyst-opt-out" analyst-plugin-id="' . $this->getId() . '" analyst-plugin-signed="' . (int) $this->isSigned() . '">Opt Out</a>'
466 : '<a class="analyst-action-opt analyst-opt-in" analyst-plugin-id="' . $this->getId() . '" analyst-plugin-signed="' . (int) $this->isSigned() . '">Opt In</a>';
467
468 // Append anchor to find specific deactivation link
469 if (isset($defaultLinks['deactivate'])) {
470 $defaultLinks['deactivate'] .= '<span analyst-plugin-id="' . $this->getId() . '" analyst-plugin-opted-in="' . (int) $this->isOptedIn() . '"></span>';
471 }
472
473 return array_merge($customLinks, $defaultLinks);
474 }
475
476 /**
477 * @return AccountData
478 */
479 public function getData()
480 {
481 return $this->data;
482 }
483
484 /**
485 * @param AccountData $data
486 */
487 public function setData(AccountData $data)
488 {
489 $this->data = $data;
490
491 $this->setIsOptedIn($data->isOptedIn());
492 $this->setIsInstalled($data->isInstalled());
493 $this->setIsSigned($data->isSigned());
494 $this->setIsInstallResolved($data->isInstallResolved());
495 }
496
497 /**
498 * Resolves valid action name
499 * based on client id
500 *
501 * @param $action
502 * @return string
503 */
504 private function resolveActionName($action)
505 {
506 return sprintf('%s_%s', $action, $this->id);
507 }
508
509 /**
510 * Register action for current plugin
511 *
512 * @param $action
513 * @param $callback
514 */
515 private function addFilter($action, $callback)
516 {
517 $validAction = sprintf('%s_%s', $action, $this->basePluginPath);
518
519 add_filter($validAction, $callback, 10);
520 }
521
522 /**
523 * Add ajax action for current plugin
524 *
525 * @param $action
526 * @param $callback
527 * @param bool $raw Format action ??
528 */
529 private function addAjax($action, $callback, $raw = false)
530 {
531 $validAction = $raw ? $action : sprintf('%s%s', 'wp_ajax_', $this->resolveActionName($action));
532
533 add_action($validAction, $callback);
534 }
535
536 /**
537 * @return bool
538 */
539 public function isSigned()
540 {
541 return $this->isSigned;
542 }
543
544 /**
545 * @param bool $isSigned
546 */
547 public function setIsSigned($isSigned)
548 {
549 $this->data->setIsSigned($isSigned);
550
551 $this->isSigned = $isSigned;
552 }
553
554 /**
555 * @return RequestorContract
556 */
557 public function getRequestor()
558 {
559 return $this->requestor;
560 }
561
562 /**
563 * @param RequestorContract $requestor
564 */
565 public function setRequestor(RequestorContract $requestor)
566 {
567 $this->requestor = $requestor;
568 }
569
570 /**
571 * @return string
572 */
573 public function getClientSecret()
574 {
575 return $this->clientSecret;
576 }
577
578 /**
579 * @return Collector
580 */
581 public function getCollector()
582 {
583 return $this->collector;
584 }
585
586 /**
587 * @param Collector $collector
588 */
589 public function setCollector(Collector $collector)
590 {
591 $this->collector = $collector;
592 }
593
594 /**
595 * Do we allowing logging
596 *
597 * @return bool
598 */
599 public function isAllowingLogging()
600 {
601 return $this->isOptedIn;
602 }
603
604 /**
605 * @return string
606 */
607 public function getBasePluginPath()
608 {
609 return $this->basePluginPath;
610 }
611
612 /**
613 * @return bool
614 */
615 public function isInstallResolved()
616 {
617 return $this->isInstallResolved;
618 }
619
620 /**
621 * @param bool $isInstallResolved
622 */
623 public function setIsInstallResolved($isInstallResolved)
624 {
625 $this->data->setIsInstallResolved($isInstallResolved);
626
627 $this->isInstallResolved = $isInstallResolved;
628 }
629 }
630