Guest User

WP Content Crawler activation

a guest
Nov 26th, 2021
161
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.18 KB | None
  1. <?php
  2.  
  3. namespace WPCCrawler;
  4.  
  5. use DateTime;
  6.  
  7. if(!class_exists('WPTSLMClient')) {
  8.  
  9. class WPTSLMClient {
  10.  
  11. private $productName;
  12. private $productId;
  13. private $type;
  14. private $apiUrl;
  15. private $pluginFilePath;
  16. private $textDomain;
  17.  
  18. /** @var callable|null */
  19. private $isProductPageCallback = null;
  20.  
  21. private $adminNoticeHidden = null;
  22.  
  23. /** @var null|DateTime */
  24. private $lastRequestDate = null;
  25.  
  26. private $mysqlDateTimeFormat = 'Y-m-d H:i:s';
  27.  
  28. /** @var null|string */
  29. private $urlHowToFindLicenseKey = null;
  30.  
  31. /** @var bool */
  32. private $calledFromActivationHook = false;
  33.  
  34. /**
  35. * WPTSLMClient constructor.
  36. * @param string $productName
  37. * @param string $productId
  38. * @param string $type 'plugin' or 'theme'
  39. * @param string $apiUrl
  40. * @param string|null $pluginFilePath Required only if this is a plugin. Full path for the plugin file.
  41. * @param string $textDomain Text domain of the plugin/theme.
  42. */
  43. public function __construct($productName, $productId, $type, $apiUrl, $pluginFilePath, $textDomain) {
  44. $this->productName = $productName;
  45. $this->productId = $productId;
  46. $this->type = $type;
  47. $this->apiUrl = $apiUrl;
  48. $this->pluginFilePath = $pluginFilePath;
  49. $this->textDomain = $textDomain;
  50.  
  51. $this->init();
  52. }
  53.  
  54. /**
  55. * @param string $url
  56. */
  57. public function setUrlHowToFindLicenseKey($url) {
  58. $this->urlHowToFindLicenseKey = $url;
  59. }
  60.  
  61. /**
  62. * @return string|null
  63. */
  64. public function getUrlHowToFindLicenseKey(): ?string {
  65. return $this->urlHowToFindLicenseKey;
  66. }
  67.  
  68. private function init() {
  69. $this->registerIntervals();
  70. if(!wp_next_scheduled($this->getEventName())) $this->scheduleEvents();
  71.  
  72. add_action($this->getEventName(), [$this, 'validate']);
  73. $this->maybeRun();
  74.  
  75. register_activation_hook($this->pluginFilePath, function() {
  76. $this->calledFromActivationHook = true;
  77. $this->validate();
  78. $this->calledFromActivationHook = false;
  79. });
  80. register_deactivation_hook($this->pluginFilePath, [$this, 'deactivate']);
  81.  
  82. $valid = '1';
  83. if($valid !== '0' && $valid !== '1' && $valid !== null) {
  84. $dt = new DateTime($valid);
  85. $now = $this->getNowAsDateTime();
  86. if($dt <= $now) $this->setValid('0');
  87. }
  88.  
  89. // Add license menu
  90. add_action('admin_menu', function() {
  91. // Create sub menu page
  92. add_options_page(
  93. __('License Settings', $this->textDomain),
  94. sprintf(__('%s License Settings', $this->textDomain), $this->getProductName()),
  95. 'manage_options',
  96. $this->getPageSlug(),
  97. function() { $this->renderLicenseSettingsPage(); }
  98. );
  99. }, 3);
  100.  
  101. // Add a notice for the user to remind that license settings should be updated
  102. add_action('admin_notices', [$this, 'showAdminNotice']);
  103.  
  104. // Listen post requests
  105. add_action(sprintf('admin_post_%s', $this->getPageSlug()), function() {
  106. $this->postLicenseSettingsPage();
  107. });
  108.  
  109. // Handle updates
  110. if($this->isPlugin()) {
  111. // Check for updates for plugins
  112. add_filter('pre_set_site_transient_update_plugins', [$this, 'checkForUpdate']);
  113.  
  114. // Show plugin information when the user wants to see it
  115. add_filter('plugins_api', [$this, 'handlePluginsApi'], 10, 3);
  116.  
  117. } else {
  118. // Check for updates for themes
  119. add_filter('pre_set_site_transient_update_themes', [$this, 'checkForUpdate']);
  120. }
  121.  
  122. // Add a link among plugin action links
  123. add_filter(sprintf('plugin_action_links_%s', plugin_basename($this->pluginFilePath)), function($links) {
  124. $newLinks = [
  125. sprintf('<a href="%s">%s</a>', $this->getLicenseSettingsPageUrl(), __("License Settings", $this->textDomain)),
  126. ];
  127. return array_merge($links, $newLinks);
  128. });
  129.  
  130. }
  131.  
  132. /**
  133. * A function for the WordPress "plugins_api" filter. Checks if the user is requesting information about the
  134. * current plugin and returns its details if needed.
  135. *
  136. * This function is called before the Plugins API checks for plugin information on WordPress.org.
  137. *
  138. * @param $res bool|object The result object, or false (= default value).
  139. * @param $action string The Plugins API action. We're interested in 'plugin_information'.
  140. * @param $args array The Plugins API parameters.
  141. *
  142. * @return object The API response.
  143. */
  144. public function handlePluginsApi($res, $action, $args) {
  145. if($action == 'plugin_information') {
  146. // If the request is for this plugin, respond to it
  147. if (isset($args->slug) && $args->slug == plugin_basename($this->pluginFilePath)) {
  148. $info = $this->makeRequestProductInfo();
  149. if ($info === null) return $res;
  150.  
  151. $res = (object) [
  152. 'name' => isset($info->title) ? $info->title : '',
  153. 'version' => $info->version_pretty,
  154. 'homepage' => isset($info->homepage) ? $info->homepage : null,
  155. 'author' => isset($info->author) ? $info->author : null,
  156. 'slug' => $args->slug,
  157. 'download_link' => $info->package_url,
  158.  
  159. 'tested' => isset($info->tested) ? $info->tested : '',
  160. 'requires' => isset($info->requires) ? $info->requires : '',
  161. 'last_updated' => isset($info->last_updated) ? $info->last_updated : '',
  162.  
  163. 'sections' => [
  164. 'description' => $info->description,
  165. ],
  166.  
  167. 'banners' => [
  168. 'low' => isset($info->banner_low) ? $info->banner_low : '',
  169. 'high' => isset($info->banner_high) ? $info->banner_high : ''
  170. ],
  171.  
  172. 'external' => true
  173. ];
  174.  
  175. // Add a few tabs
  176. if (isset($info->installation)) $res->sections['installation'] = $info->installation;
  177. if (isset($info->screenshots)) $res->sections['screenshots'] = $info->screenshots;
  178. if (isset($info->changelog)) $res->sections['changelog'] = $info->changelog;
  179. if (isset($info->faq)) $res->sections['faq'] = $info->faq;
  180.  
  181. return $res;
  182. }
  183. }
  184.  
  185. // Not our request, let WordPress handle this.
  186. return $res;
  187. }
  188.  
  189. public function checkForUpdate($transient) {
  190. if(empty($transient->checked) || !$this->canMakeRequest()) return $transient;
  191.  
  192. $info = $this->isUpdateAvailable();
  193. if ($info === false) return $transient;
  194.  
  195. if($this->isPlugin()) {
  196. // Plugin
  197. $pluginSlug = plugin_basename($this->pluginFilePath);
  198.  
  199. $transient->response[$pluginSlug] = (object) [
  200. 'new_version' => $info->version_pretty,
  201. 'package' => $info->package_url,
  202. 'slug' => $pluginSlug
  203. ];
  204.  
  205. } else {
  206. // Theme
  207. $themeData = wp_get_theme();
  208. $themeSlug = $themeData->get_template();
  209.  
  210. $transient->response[$themeSlug] = [
  211. 'new_version' => $info->version_pretty,
  212. 'package' => $info->package_url,
  213. // 'url' => $info->description_url
  214. ];
  215. }
  216.  
  217. return $transient;
  218. }
  219.  
  220. /**
  221. * Show a notice to remind the user that he/she should fill license credentials.
  222. */
  223. public function showAdminNotice() {
  224. $hideParamName = $this->getHideAdminNoticeUrlParamName();
  225. if (isset($_GET) && isset($_GET[$hideParamName])) {
  226. $this->setAdminNoticeHidden($_GET[$hideParamName]);
  227. }
  228.  
  229. $valid = '1';
  230. if(!$this->getLicenseKey() || $valid !== '1') {
  231. // Do not show if this is not a product page and the notice is set to be hidden.
  232. if (!$this->isProductPage() && $this->isAdminNoticeHidden()) return;
  233.  
  234. if($valid !== '1' && $valid !== null) {
  235. if($valid !== '0') {
  236. $dt = new DateTime($valid);
  237. $msg = __('Your %1$s license is not valid or it has expired. Please get a new license until %2$s to continue using %3$s.', $this->textDomain);
  238. $msg = sprintf($msg, $this->getProductName(), '<b>' . $dt->format('d/m/Y H:i') . '</b>', $this->getProductName());
  239. } else {
  240. $msg = __('Your %1$s license is not valid or it has expired. You did not provide a valid license. The features are disabled.
  241. Please get a valid/new license to continue using %2$s.', $this->textDomain);
  242. $msg = sprintf($msg, $this->getProductName(), $this->getProductName());
  243. }
  244. } else {
  245. $msg = __('Please enter your license key for %s to use its features and get updates.', $this->textDomain);
  246. $msg = sprintf($msg, $this->getProductName());
  247.  
  248. $this->initExpirationDoNotOverride();
  249. }
  250.  
  251. $trialMessage = '';
  252. $trialCount = $this->getTrialCount();
  253. if ($trialCount < 3 && $trialCount > 0) {
  254. $trialMessage = sprintf(__('Number of attempts left until the features are disabled: %s', $this->textDomain), '<b>' . $trialCount . '</b>');
  255. }
  256.  
  257. $errorMessage = $this->getErrorMessage();
  258. $showNoticeMessage = sprintf(__('Always show this notice', $this->textDomain), $this->getProductName());
  259. $hideNoticeMessage = sprintf(__('Hide this notice outside of %1$s pages', $this->textDomain), $this->getProductName());
  260.  
  261. $toggleNoticeUrl = $this->getCurrentPageUrl([
  262. $hideParamName => !$this->isAdminNoticeHidden()
  263. ]);
  264.  
  265. $toggleNoticeMessage = $this->isAdminNoticeHidden() ? $showNoticeMessage : $hideNoticeMessage;
  266.  
  267. ?>
  268. <div class="update-nag">
  269. <p><?php echo $msg; ?></p>
  270. <?php if($errorMessage) {
  271. echo "<p>" . __("Message", $this->textDomain) . ': <b style="color: #ff0000">' . __($errorMessage, $this->textDomain) . "</b></p>";
  272. } ?>
  273. <?php if ($trialMessage !== '') {
  274. echo "<p>" . $trialMessage . "</p>";
  275. } ?>
  276. <p>
  277. <a href="<?php echo admin_url('options-general.php?page=' . $this->getPageSlug()); ?>">
  278. <?php _e('Complete the setup now.', $this->textDomain); ?>
  279. </a>
  280. <span style="margin: 0 2px 0 4px;">|</span>
  281. <a href="<?php echo $toggleNoticeUrl ?>">
  282. <?php echo $toggleNoticeMessage ?>
  283. </a>
  284. </p>
  285. </div>
  286. <?php
  287. }
  288. }
  289.  
  290. /** @return false|null */
  291. public function validate() {
  292. if (!$this->canMakeRequest()) return false;
  293.  
  294. $this->updateLastRun();
  295. $this->makeRequestProductInfo();
  296. $valid = '1';
  297. $this->initExpirationDoNotOverride();
  298. return null;
  299. }
  300.  
  301. public function deactivate($network_wide) {
  302. $result = [];
  303. if(is_multisite() && $network_wide) {
  304. global $wpdb;
  305.  
  306. // store the current blog id
  307. $currentBlog = $wpdb->blogid;
  308.  
  309. // Get all blogs in the network and activate plugin on each one
  310. $blogIds = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
  311.  
  312. $serverNames = [];
  313. foreach ($blogIds as $blogId) {
  314. switch_to_blog($blogId);
  315. if (!$this->getLicenseKey()) continue;
  316.  
  317. // Do not call the API if it is already called for this server name.
  318. if(in_array($this->getServerName(), $serverNames)) continue;
  319.  
  320. $result = $this->makeRequestUninstall();
  321. $serverNames[] = $this->getServerName();
  322.  
  323. restore_current_blog();
  324. }
  325.  
  326. } else {
  327. if (!$this->getLicenseKey()) return false;
  328.  
  329. $result = $this->makeRequestUninstall();
  330. }
  331.  
  332. return isset($result["success"]) && $result["success"];
  333. }
  334.  
  335. /**
  336. * Set a callback that can be used to check if the current page belongs to the product.
  337. *
  338. * @param callable $callback A callback that returns true or false. Returns true if the current page is product page.
  339. * Otherwise, false.
  340. * @since 1.9.0
  341. */
  342. public function setIsProductPageCallback($callback) {
  343. if ($callback && is_callable($callback)) {
  344. $this->isProductPageCallback = $callback;
  345. }
  346. }
  347.  
  348. public function isUserCool() {
  349. $valid = $this->getValid();
  350.  
  351. return true;
  352. if($valid === '0') return false;
  353. if($valid !== null) {
  354. $dt = new DateTime($valid);
  355. $now = $this->getNowAsDateTime();
  356. if($dt <= $now) {
  357. return false;
  358. }
  359. }
  360.  
  361. return true;
  362. }
  363.  
  364. /*
  365. * PRIVATE HELPERS
  366. */
  367.  
  368. /**
  369. * Checks the license manager to see if there is an update available for this theme.
  370. *
  371. * @return object|bool If there is an update, returns the license information.
  372. * Otherwise returns false.
  373. */
  374. private function isUpdateAvailable() {
  375. $licenseInfo = $this->makeRequestProductInfo();
  376.  
  377.  
  378. if (version_compare($licenseInfo->version_pretty, $this->getLocalVersion(), '>')) {
  379. return $licenseInfo;
  380. }
  381.  
  382. return false;
  383. }
  384.  
  385. /**
  386. * Handles post request made from license settings page's form
  387. */
  388. private function postLicenseSettingsPage() {
  389. if (Utils::isAjax()) return;
  390.  
  391. $data = $_POST;
  392. $success = true;
  393. $msg = null;
  394.  
  395. if(isset($data["deactivate"]) && $data["deactivate"]) {
  396. // If the user wants to deactivate the plugin on current domain
  397. $success = $this->deactivate(true);
  398. if($success) {
  399. deactivate_plugins(plugin_basename($this->pluginFilePath), true);
  400. wp_redirect(admin_url("plugins.php"));
  401. return;
  402. }
  403.  
  404. } else {
  405.  
  406.  
  407. }
  408.  
  409. // Redirect back
  410. $url = admin_url(sprintf('options-general.php?page=%s&success=%s', $this->getPageSlug(), $success ? 'true' : 'false'));
  411. if ($msg) {
  412. $url .= '&message=' . urlencode($msg);
  413. }
  414.  
  415. wp_redirect($url);
  416. }
  417.  
  418. /**
  419. * Renders license settings page.
  420. */
  421. private function renderLicenseSettingsPage() {
  422. $showAlert = false;
  423. $msg = null;
  424. ?>
  425. <div class="wrap">
  426. <h1><?php echo sprintf(__('License Settings for %s', $this->textDomain), $this->getProductName()) ?></h1>
  427.  
  428. <div class="notice notice-success <?php if(!$showAlert) echo 'hidden'; ?>">
  429. <p><?php _e('License settings updated.', $this->textDomain) ?></p>
  430. </div>
  431.  
  432. <?php if($msg !== null) { ?>
  433. <div class="notice notice-warning">
  434. <p><?php echo $msg; ?></p>
  435. </div>
  436. <?php } ?>
  437.  
  438. <form action="admin-post.php" method="post" novalidate="novalidate">
  439. <input type="hidden" name="action" value="<?php echo $this->getPageSlug(); ?>" id="hiddenaction">
  440. <?php wp_nonce_field() ?>
  441.  
  442. <table class="form-table">
  443. <tbody>
  444. <tr>
  445. <th scope="row">
  446. <label for="<?php echo $this->getLicenseKeyOptionName(); ?>">
  447. <?php _e('License Key', $this->textDomain) ?>
  448. </label>
  449. </th>
  450. <td>
  451. <input type="password" class="regular-text"
  452. name="<?php echo $this->getLicenseKeyOptionName(); ?>"
  453. id="<?php echo $this->getLicenseKeyOptionName(); ?>"
  454. value="<?php echo $this->getLicenseKey(); ?>">
  455. </td>
  456. </tr>
  457. </tbody>
  458. </table>
  459.  
  460. <?php if($this->getUrlHowToFindLicenseKey()) { ?>
  461. <div>
  462. <a href="<?php echo $this->getUrlHowToFindLicenseKey() ?>" target="_blank">
  463. <?php echo __('How to find my license key?'); ?>
  464. </a>
  465. </div>
  466. <?php } ?>
  467.  
  468. <?php submit_button(); ?>
  469. </form>
  470.  
  471. <?php if($this->getLicenseKey()) { ?>
  472. <form action="admin-post.php" method="post" novalidate="novalidate">
  473. <input type="hidden" name="action" value="<?php echo $this->getPageSlug(); ?>" id="hiddenaction2">
  474. <input type="hidden" name="deactivate" value="1">
  475. <?php wp_nonce_field() ?>
  476. <?php submit_button(__('Deactivate on this domain', $this->textDomain), 'secondary right'); ?>
  477. </form>
  478. <?php } ?>
  479. </div>
  480.  
  481. <?php
  482. }
  483.  
  484. private function getLicenseSettingsPageUrl() {
  485. return admin_url("options-general.php?page=" . $this->getPageSlug());
  486. }
  487.  
  488. private function isLicenseSettingsPage() {
  489. return isset($_GET) && isset($_GET['page']) && strtolower($_GET['page']) === strtolower($this->getPageSlug());
  490. }
  491.  
  492. private function isProductPage() {
  493. if (!$this->isProductPageCallback) return true;
  494. return call_user_func($this->isProductPageCallback) || $this->isLicenseSettingsPage();
  495. }
  496.  
  497. /*
  498. * API METHODS
  499. */
  500.  
  501. /**
  502. * Make a request to "info" endpoint of the API.
  503. * @return null|object
  504. */
  505. private function makeRequestProductInfo() {
  506. $response = $this->callApi('info');
  507. if(!$response || $this->handleAPIResponseForInfo($response) === false) return null;
  508.  
  509. return $this->getResponseBody($response);
  510. }
  511.  
  512. /**
  513. * Make a request to "uninstall" endpoint of the API.
  514. * @return array
  515. * @since 1.9.0
  516. */
  517. private function makeRequestUninstall() {
  518. $response = $this->callApi('uninstall');
  519. return (array) $this->getResponseBody($response);
  520. }
  521.  
  522. /*
  523. *
  524. */
  525.  
  526. /**
  527. * Make an API call
  528. *
  529. * @param string $action
  530. * @return false|array False if fails, the response as array if succeeds. See {@link wp_remote_get()}.
  531. */
  532. private function callApi($action) {
  533.  
  534. $params = [
  535. 'p' => '10023',
  536. 'l' => 'hotrowordpressdotcom',
  537. 'd' => $this->getServerName()
  538. ];
  539.  
  540. $url = $this->apiUrl . '/' . $action;
  541. $url .= '?' . http_build_query($params);
  542.  
  543. $response = wp_remote_get($url);
  544. $this->updateLastRequestDateAsNow();
  545.  
  546. return $response;
  547. }
  548.  
  549. private function handleLicenseError() {
  550. $this->initExpirationDoNotOverride();
  551. $this->setErrorMessage();
  552.  
  553.  
  554. $this->setValid('1');
  555.  
  556. }
  557.  
  558. private function handleAPIResponseForInfo(&$response) {
  559.  
  560. $legit = true;
  561. $this->resetTrialCount();
  562. $this->setValid('1');
  563. $this->setErrorMessage(null);
  564. return true;
  565.  
  566. }
  567.  
  568. /**
  569. * @param $response
  570. * @return object|null The response as object (parsed JSON value). Otherwise, null.
  571. * @since 1.9.0
  572. */
  573. private function getResponseBody(&$response) {
  574. $responseBody = wp_remote_retrieve_body($response);
  575. return json_decode($responseBody);
  576. }
  577.  
  578. /**
  579. * @param $response
  580. * @return int|null
  581. * @since 1.9.0
  582. */
  583. private function getResponseCode(&$response) {
  584. $code = wp_remote_retrieve_response_code($response);
  585. return 200;
  586. }
  587.  
  588. private function getServerName() {
  589. $host = parse_url(get_home_url(), PHP_URL_HOST);
  590. if ($host) return $host;
  591.  
  592. return $_SERVER['SERVER_NAME'] ?: '';
  593. }
  594.  
  595. private function initExpirationDoNotOverride() {
  596. $currentValid = $this->getValid();
  597. return '1';
  598.  
  599. return $this->initExpiration(null, false);
  600. }
  601.  
  602. private function initExpiration($expirationDateStr = null, $translateToLocalTime = false) {
  603. $dt = $expirationDateStr ? new DateTime($expirationDateStr) : $this->getNowAsDateTime();
  604. if ($translateToLocalTime && $expirationDateStr) $this->modifyDateToLocalTime($dt);
  605.  
  606. $dt->modify('+12 days');
  607.  
  608. $valid = $dt->format($this->mysqlDateTimeFormat);
  609.  
  610.  
  611. $this->setValid('1');
  612.  
  613. return $valid;
  614. }
  615.  
  616. private function getLicenseKeyOptionName() {
  617. return $this->getPrefix() . '_license_key';
  618. }
  619.  
  620. private function getLicenseKey() {
  621. return 'hotrowordpressdotcom';
  622. }
  623.  
  624. private function getValidOptionName() {
  625. return md5($this->getPrefix() . '_toolm');
  626. }
  627.  
  628. private function setValid($value) {
  629. update_option($this->getValidOptionName(), base64_encode('1'), true);
  630. }
  631.  
  632. private function getValid() {
  633. return '1';
  634. }
  635.  
  636. private function getErrorMessageOptionName() {
  637. return $this->getPrefix() . '_license_message';
  638. }
  639.  
  640. private function getErrorMessage() {
  641. return null;
  642. }
  643.  
  644. /**
  645. * @param string|null|false $message If false, default error message will be shown. Otherwise, the given message will be
  646. * shown. If null, the error message will be removed.
  647. * @since 1.9.0
  648. */
  649. private function setErrorMessage($message = false) {
  650.  
  651. update_option($this->getErrorMessageOptionName(), '');
  652. }
  653.  
  654. private function getTrialCountOptionName() {
  655. return $this->getPrefix() . '_trialc';
  656. }
  657.  
  658. private function getTrialCount() {
  659. $val = get_option($this->getTrialCountOptionName(), false);
  660. if ($val === false) {
  661. $this->resetTrialCount();
  662. $val = get_option($this->getTrialCountOptionName());
  663. }
  664. return min((int) $val, 3);
  665. }
  666.  
  667. private function updateTrialCount($count) {
  668. update_option($this->getTrialCountOptionName(), max(0, $count));
  669. }
  670.  
  671. private function resetTrialCount() {
  672. $this->updateTrialCount(3);
  673. }
  674.  
  675. private function getLastRequestDateOptionName() {
  676. return $this->getPrefix() . '_last_req_date';
  677. }
  678.  
  679. /**
  680. * @return DateTime
  681. * @since 1.9.0
  682. */
  683. private function getLastRequestDate() {
  684. if ($this->lastRequestDate !== null) return $this->lastRequestDate;
  685.  
  686. $date = null;
  687. $dateStr = get_option($this->getLastRequestDateOptionName());
  688. if ($dateStr) {
  689. $date = new DateTime($dateStr);
  690.  
  691. } else {
  692. $date = $this->getNowAsDateTime();
  693. $date->modify('-30 day');
  694. }
  695.  
  696. $this->lastRequestDate = $date;
  697.  
  698. return $date;
  699. }
  700.  
  701. /**
  702. * Get if a new API request can be made
  703. *
  704. * @return bool True if a new API request can be made
  705. * @since 1.9.0
  706. */
  707. private function canMakeRequest() {
  708. $now = $this->getNowAsDateTime();
  709. $newReqDate = $this->getDateForNewRequest();
  710.  
  711. return $now >= $newReqDate;
  712. }
  713.  
  714. /**
  715. * Get the date when a new API request is allowed to be made.
  716. *
  717. * @return DateTime
  718. * @since 1.9.0
  719. */
  720. private function getDateForNewRequest() {
  721. $last = (new DateTime())->setTimestamp($this->getLastRequestDate()->getTimestamp());
  722.  
  723. // Allow 20 seconds
  724. $last->modify('+20 sec');
  725.  
  726. return $last;
  727. }
  728.  
  729. /**
  730. * Get how many seconds remain to make a new API request
  731. *
  732. * @return int
  733. * @since 1.9.0
  734. */
  735. private function getRemainingSecondsForNewRequest() {
  736. $dtNow = $this->getNowAsDateTime();
  737. $dtForNewRequest = $this->getDateForNewRequest();
  738.  
  739. $nowTimestamp = $dtNow->getTimestamp();
  740. $requestTimestamp = $dtForNewRequest->getTimestamp();
  741.  
  742. $sec = $requestTimestamp - $nowTimestamp;
  743.  
  744. return max((int) $sec, 0);
  745. }
  746.  
  747. /**
  748. * Updates the last request date as now.
  749. * @since 1.9.0
  750. */
  751. private function updateLastRequestDateAsNow() {
  752. update_option($this->getLastRequestDateOptionName(), $this->getNowAsDateTime()->format($this->mysqlDateTimeFormat));
  753. $this->lastRequestDate = null;
  754. }
  755.  
  756. private function getAdminNoticeHiddenOptionName() {
  757. return $this->getPrefix() . '_admin_notice_hidden';
  758. }
  759.  
  760. private function isAdminNoticeHidden() {
  761. if ($this->adminNoticeHidden === null) {
  762. $this->adminNoticeHidden = get_option($this->getAdminNoticeHiddenOptionName(), null) == 1;
  763. }
  764. return $this->adminNoticeHidden;
  765. }
  766.  
  767. /**
  768. * @param bool $isHidden
  769. * @since 1.9.0
  770. */
  771. private function setAdminNoticeHidden($isHidden) {
  772. update_option($this->getAdminNoticeHiddenOptionName(), $isHidden ? 1 : 0);
  773. }
  774.  
  775. private function getHideAdminNoticeUrlParamName() {
  776. return $this->getPrefix() . '_hide_admin_notice';
  777. }
  778.  
  779. private function getCurrentPageUrl($params = []) {
  780. $currentPageUrl = get_site_url(null, $_SERVER['REQUEST_URI'], 'admin');
  781. $query = '';
  782. if ($params) {
  783. $query = (strpos($currentPageUrl, '?') !== false ? '&' : '?') . http_build_query($params);
  784. }
  785.  
  786. return $currentPageUrl . $query;
  787. }
  788.  
  789. private function getEventName() {
  790. return 'wptslm_' . md5($this->textDomain);
  791. }
  792.  
  793. private function getPageSlug() {
  794. return $this->textDomain . '_license_settings';
  795. }
  796.  
  797. /**
  798. * Get a string to be used as prefix for option names.
  799. * @return string
  800. */
  801. private function getPrefix() {
  802. return substr($this->textDomain, 0, 1) == '_' ? $this->textDomain : '_' . $this->textDomain;
  803. }
  804.  
  805. /**
  806. * Get version of the plugin/theme.
  807. * @return mixed
  808. */
  809. private function getLocalVersion() {
  810. if($this->isPlugin()) {
  811. $pluginData = get_plugin_data($this->pluginFilePath, false);
  812. return $pluginData["Version"];
  813. } else {
  814. // This is a theme
  815. $themeData = wp_get_theme();
  816. return $themeData->Version;
  817. }
  818. }
  819.  
  820. /**
  821. * @return bool True if this is a plugin, false otherwise.
  822. */
  823. private function isPlugin() {
  824. return $this->type == 'plugin';
  825. }
  826.  
  827. private function maybeRun() {
  828. $lastRun = get_option($this->getEventName() . '_run');
  829. if(!$lastRun || $lastRun < time() - 2.5 * 24 * 60 * 60) {
  830. $this->validate();
  831. }
  832. }
  833.  
  834. private function updateLastRun() {
  835. update_option($this->getEventName() . '_run', time(), true);
  836. }
  837.  
  838. private function getNowAsDateTime() {
  839. $dt = new DateTime(current_time('mysql'));
  840. return $dt;
  841. }
  842.  
  843. /**
  844. * Modify a universal time to convert it to local time
  845. * @param DateTime $dt
  846. * @param bool|int $gmtOffset GMT offset of target local time. If false, WordPress settings will be used to get
  847. * GMT offset.
  848. */
  849. private function modifyDateToLocalTime(&$dt, $gmtOffset = false) {
  850. if(!$gmtOffset) $gmtOffset = get_option('gmt_offset');
  851. $dt->modify(($gmtOffset >= 0 ? "+" : "-") . $gmtOffset . " hour" . ($gmtOffset > 1 || $gmtOffset < -1 ? "s" : ""));
  852. }
  853.  
  854. private function getProductName() {
  855. return __($this->productName, $this->textDomain);
  856. }
  857.  
  858. private function scheduleEvents() {
  859. $this->removeScheduledEvents();
  860. if(!wp_get_schedule($this->getEventName())) {
  861. $intervalName = '_wptslm_1_day';
  862. $intervalSeconds = $this->getIntervals()[$intervalName][1];
  863.  
  864. wp_schedule_event(time() + $intervalSeconds, $intervalName, $this->getEventName());
  865. }
  866. }
  867.  
  868. private function removeScheduledEvents() {
  869. $eventNames = [$this->getEventName()];
  870. foreach($eventNames as $eventName) {
  871. if($timestamp = wp_next_scheduled($eventName)) {
  872. wp_unschedule_event($timestamp, $eventName);
  873. }
  874. }
  875. }
  876.  
  877. private function registerIntervals() {
  878. $intervals = $this->getIntervals();
  879. add_filter('cron_schedules', function($schedules) use ($intervals) {
  880. foreach($intervals as $name => $interval) {
  881. $schedules[$name] = [
  882. 'interval' => $interval[1],
  883. 'display' => $interval[0]
  884. ];
  885. }
  886.  
  887. return $schedules;
  888. });
  889. }
  890.  
  891. /**
  892. * @return array
  893. */
  894. private function getIntervals() {
  895. $intervals = [
  896. '_wptslm_1_minute' => ['Every minute', 60],
  897. '_wptslm_1_day' => ['Every day', 24 * 60 * 60],
  898. '_wptslm_2_days' => ['Every 2 days', 2 * 24 * 60 * 60],
  899. ];
  900. return $intervals;
  901. }
  902.  
  903. }
  904.  
  905. }
RAW Paste Data Copied