[WordPress] 外掛分享: Envato Toolkit

WordPress 外掛 Envato Toolkit 的封面圖片。

前言介紹

  • 這款 WordPress 外掛「Envato Toolkit」是 2017-06-20 上架。
  • 目前有 7000 個安裝啟用數。
  • 上一次更新是 2021-04-26,距離現在已有 1467 天。超過一年沒更新,安裝要確認版本是否可用。以及後續維護問題!
  • 外掛最低要求 WordPress 4.6 以上版本才可以安裝。
  • 外掛要求網站主機運作至少需要 PHP 版本 5.4 以上。
  • 有 9 人給過評分。
  • 還沒有人在論壇上發問,可能目前使用數不多,還沒有什麼大問題。

外掛協作開發者

kestutisit |

外掛標籤

api | envato | license | update checker | purchase validator |

內容簡介

這個外掛包含一個三個檔案的程式庫和視覺化介面,用於驗證客戶購買代碼、獲取特定 Envato 用戶的詳細信息(國家、城市、總追隨者數量、總銷量、頭像),獲取他的許可證購買和支援到期日期、他購買的許可證類型,檢查已購買的外掛和佈景主題的更新以及獲取它們的下載鏈接。

此外,這個程式庫還提供了按照外掛或佈景主題名稱和作者提供 Envato 產品 ID 搜索的功能。這是你身為開發人員/作者的工具,這是你已經尋找了幾個月的東西。

如果你正在尋找庫–only 的版本並將其集成到你的外掛/佈景主題中,可以在 GitHub 上找到:
Envato Toolkit (Standalone)

這個外掛的主要目的是幫助你更輕鬆地開始,而不必頭疼著試圖理解 Envato - WordPress Market 插件的代碼,因為那是 Envato 唯一構建的插件,代碼混亂且不清晰,從中你永遠不會明白它是如何工作的(請參見以下示例)。

當我嘗試自己創建外掛的 “檢查更新” 和 “驗證授權碼” 功能按鈕時,看到 WordPress - Envato Market 插件的代碼時,我對它的編寫情況感到震驚,這是你不應該編寫代碼的教材。

例如,如果 Envato 用戶令牌為空,則您想發送錯誤消息,該令牌是必需的字符串,即 pAA0aBCdeFGhiJKlmNOpqRStuVWxyZ44。如果您喜歡 K.I.S.S.、PSR-2、D.R.Y.、乾淨的代碼編寫標準和範式,您可能只會寫下以下五行代碼,使每個開發人員都可以理解:

$token = get_user_meta(get_current_user_id(), 'envato_token', TRUE);
if($token == "")
{
return new \WP_Error('api_token_error', __('An API token is required.', 'envato-toolkit'));
}

現在讓我們看看相同任務的 WordPress - Envato Market 插件的代碼回溯是如何的:

[Api.php -> request(..)] 檢查令牌是否為空:

if ( empty( $token ) )
{
return new WP_Error( 'api_token_error', __( 'An API token is required.', 'envato-market' ) );
}

[Api.php -> request(..)] 從另一個字符串中進行解析:

$token = trim( str_replace( 'Bearer', '', $args['headers']['Authorization'] ) );

[Api.php -> request(..)] 再次進行解析,這一次從參數數組中進行解析:

public function request( $url, $args = array() ) {
$defaults = array(
'timeout' => 20,
);
$args = wp_parse_args( $args, $defaults );
}

[Api.php -> download(..)] 再次傳遞變量 - 這一次通過參數:

class Envato_Market_API {
public function download( $id, $args = array() ) {
$url = 'https://api.envato.com/v2/market/buyer/download?item_id=' . $id . '&shorten_url=true';
return $this->request( $url, $args );
}
}

[admin.php -> maybe_deferred_download(..)] 再次進行傳遞 - 這一次從另一個方法呼叫的 args 數組中獲取:

function maybe_deferred_download( $options ) {
$args = $this->set_bearer_args();
$options['package'] = envato_market()->api()->download( $vars['item_id'], $args );
return $options;
}

原文外掛簡介

It is a 3 files library + Visual UI, to validate the purchase codes of your customers, get details about specific Envato user (country, city, total followers, total sales, avatar), get his license purchase and support expiration dates, license type he bought, check for updates of purchased plugins and themes and get the download links for them.
Plus – this library has Envato Item Id search feature by providing plugin’s or theme’s name and author. So – yes, this is a tool you, as a developer / author, have been looking for months.
If you are looking for the library-only version to integrate into your plugin / theme, it’s on GitHub:
Envato Toolkit (Standalone)
The main purpose of this plugin is to help you to start much easier without having a headache trying to understand WordPress - Envato Market plugins code, that is the only one built by Envato, and has so complicated and unclear code, that you never get how it works (see example below).
When I tried to create plugin’s [Check for Update] and [Validate Purchase Code] feature-buttons in the plugin myself, and I saw the code of the WordPress - Envato Market plugin, I was shocked how badly it is written and how you should not to code.
For example – you would like to give an error message, if Envato user token is empty, which is a required string, i.e. – pAA0aBCdeFGhiJKlmNOpqRStuVWxyZ44. If you like K.I.S.S., PSR-2, D.R.Y., clean code coding standards and paradigms, you’d probably just have these five lines of code, so that every developer would get it:
$token = get_user_meta(get_current_user_id(), 'envato_token', TRUE);
if($token == "")
{
return new \WP_Error('api_token_error', __('An API token is required.', 'envato-toolkit'));
}

Now lets see how the same task traceback looks like in WordPress - Envato Market plugin:

[Api.php -> request(..)] Check if the token is empty:
if ( empty( $token ) )
{
return new WP_Error( 'api_token_error', __( 'An API token is required.', 'envato-market' ) );
}

[Api.php -> request(..)] Parse it from another string:
$token = trim( str_replace( 'Bearer', '', $args['headers']['Authorization'] ) );

[Api.php -> request(..)] Parse it one more time – this time from arguments array:
public function request( $url, $args = array() ) {
$defaults = array(
'timeout' => 20,
);
$args = wp_parse_args( $args, $defaults );
}

[Api.php -> download(..)] Transfer the token variable one more time – this time via params:
class Envato_Market_API {
public function download( $id, $args = array() ) {
$url = 'https://api.envato.com/v2/market/buyer/download?item_id=' . $id . '&shorten_url=true';
return $this->request( $url, $args );
}
}

[admin.php -> maybe_deferred_download(..)] Pass it again – this time get it to args array from another method call:
function maybe_deferred_download( $options ) {
$args = $this->set_bearer_args();
$options['package'] = envato_market()->api()->download( $vars['item_id'], $args );
return $options;
}

[admin.php -> set_bearer_args(..)] Wrap the token into multi-dimensional string array:
$args = array(
'headers' => array(
'Authorization' => 'Bearer ' . $token,
),
);

[admin.php -> set_bearer_args(..)] Pass the wrapped token one more time – this time get it from get_option:
foreach ( envato_market()->get_option( 'items', array() ) as $item ) {
if ( $item['id'] === $id ) {
$token = $item['token'];
break;
}
}

[admin.php -> get_option(..)] So what’s in this get_option? – Correct, another call to another method – get_options():
public function get_option( $name, $default = '' ) {
$options = self::get_options();
$name = self::sanitize_key( $name );
return isset( $options[ $name ] ) ? $options[ $name ] : $default;
}

[admin.php -> get_options()] Finally, after almost 10 steps in the tree, we are finally getting the original
WordPress method call, but now I’m getting confused again – what is that option_name variable here:
public function get_options() {
return get_option( $this->option_name, array() );
}

[envato-market.php -> init_globals()] Here is it is – the option name key name is… Oh wait…
No it is not here it. It is equals to another variable, who is is put
in another clean-up function – look like I’m keep seeing this for the 2 time in the tree – the sanitization of sanitization:
$this->option_name = self::sanitize_key( $this->slug );

[envato-market.php -> init_globals()] So the option name key name is the name of $this->slug.
Now lets see what is the value of $this->slug:
$this->slug = 'envato-market';

So it takes eleven (!) steps to understand one variable. And the whole code of that plugin is like that. The example above was the headache I had, until I realized that I must write a new Envato API Management Toolkit, instead of trying to use what Envato is giving, because otherwise I won’t get anything working ever.
And, I believe, that many other developers had the same issue when tried to create update check feature for their plugins or themes.
So instead of using that library for myself, I decided that I want to help all these developers to save their time, and I’m sharing this code with you. I’m releasing it under MIT license, which allows you to use this code in your plugin without any restrictions for both – free and commercial use.
Plus – I’m giving a promise to you, that this plugin is and will always be 100% free, without any ads, ‘Subscribe’, ‘Follow us’, ‘Check our page’, ‘Get Pro Version’ or similar links.
If you created in hi-quality code a valuable additional functionality to the library and you want to share it with everyone – I’m open here to support your efforts, and add your code to the plugin’s library, so that we all together make this plugin better for authors – the better is the plugin, the better plugins authors will make for their customers. The better quality products we will have on the internet, the happier people will be all over the world.
Finally – the code is poetry – the better is the plugin, the happier is the world.
The pseudo-code of example output of the plugin is this:
Details about you:
----------------------------------------------------------
List of all different plugins you bought:
$plugin): ?>
='Plugin Id: '.$pluginId.', Name: '.$plugin['name'];?>, Licenses:

Code: =$license['purchase_code'];?>,
License: =$license['license'];?>,
Purchased: =$license['license_purchase_date'];?> =$license['license_purchase_time'];?>,
Expires: =$license['support_expiration_date'];?> =$license['support_expiration_time'];?>,
Support Status: =$license['support_active'];?>

List of all different themes you bought:
$theme): ?>
='Theme Id: '.$themeId.', Name: '.$theme['name'];?>, Licenses:

Code: =$license['purchase_code'];?>,
License: =$license['license'];?>,
Purchased: =$license['license_purchase_date'];?> =$license['license_purchase_time'];?>,
Expires: =$license['support_expiration_date'];?> =$license['support_expiration_time'];?>,
Status: =$license['support_active'] == 1 ? "Supported" : "Support Expired";?>

Your summary:
Your location is =$authorCity;?>, =$authorCountry;?>.
You've sold your items =$authorSales;?> times and you have =$authorFollowers;?> followers on Envato.

1. Your Customer's License Details
----------------------------------------------------------
Purchase Code: =$targetPurchaseCode;?>
Is Valid License: =$isValidTargetLicense ? 'Yes' : 'No';?>
Buyer Username: =$targetLicenseBuyer;?>
License Type: =$targetLicenseType;?>
Purchased At: =$targetLicensePurchasedAt;?>
Supported Until: =$targetLicenseSupportedUntil;?>
Support Status: =$targetLicenseSupportActive == 1 ? "Supported" : "Support Expired";?>

2. Details About Target Envato User - =$targetUsername;?>
----------------------------------------------------------
=$targetUsername;?> is located in =$targetUserCity;?>, =$targetUserCountry;?>.
He sold his items =$targetUserSales;?> times and has =$targetUserFollowers;?> followers on Envato.

3. Status of Purchased Plugin ID - =$targetPluginId;?>
----------------------------------------------------------
Plugin Name: =$nameOfTargetPluginId;?>
Plugin Update Available: =$pluginUpdateAvailable ? 'Yes' : 'No';?>
Installed Plugin Version: =$installedPluginVersion;?>
Available Plugin Version: =$availablePluginVersion;?>
Plugin Update Download URL:
Download newest version

4. Status of Purchased Theme ID - =$targetThemeId;?>:
----------------------------------------------------------
Theme Name: =$nameOfTargetThemeId;?>
Theme Update Available: =$themeUpdateAvailable ? 'Yes' : 'No';?>
Installed Theme Version: =$installedThemeVersion;?>
Available Theme Version: =$availableThemeVersion;?>
Theme Update Download URL:
Download newest version

5. Envato Item Id of Purchased Plugin
----------------------------------------------------------
Searched for Name: =$targetPluginName;?>
Searched for Author: =$targetPluginAuthor;?>
Found Plugin Id: =$foundPluginId;?>

6. Envato Item Id of Purchased Theme
----------------------------------------------------------
Searched for Name: =$targetThemeName;?>
Searched for Author: =$targetThemeAuthor;?>
Found Theme Id: =$foundThemeId;?>

And the example input of the output above, it this:
$objToolkit = new EnvatoAPIManager($toolkitSettings);

// Details about you
$purchasedPlugins = $objToolkit->getPurchasedPluginsWithDetails();
$plugins = array();
foreach($purchasedPlugins AS $pluginId => $purchasedPlugin)
{
$purchasedPlugin['licenses'] = $objToolkit->getLicensesByItemId($pluginId);
$plugins[$pluginId] = $purchasedPlugin;
}

$purchasedThemes = $objToolkit->getPurchasedThemesWithDetails();
$themes = array();
foreach($purchasedThemes AS $themeId => $purchasedTheme)
{
$purchasedTheme['licenses'] = $objToolkit->getLicensesByItemId($themeId);
$themes[$themeId] = $purchasedTheme;
}

$authorDetails = $objToolkit->getUserDetails($sanitizedEnvatoUsername);
// View vars
$view->plugins = $plugins;
$view->themes = $themes;
if($authorDetails != FALSE)
{
$view->authorCity = $authorDetails['city'];
$view->authorCountry = $authorDetails['country'];
$view->authorSales = $authorDetails['sales'];
$view->authorFollowers = $authorDetails['followers'];
} else
{
$view->authorCity = '';
$view->authorCountry = '';
$view->authorSales = 0;
$view->authorFollowers = 0;
}

// 1. Details About Target Purchase Code
$targetLicenseDetails = $objToolkit->getLicenseDetails($sanitizedTargetPurchaseCode);
// View vars
$view->targetPurchaseCode = esc_html($sanitizedTargetPurchaseCode); // Ready for print
$view->isValidTargetLicense = $objToolkit->isValidLicense($sanitizedTargetPurchaseCode);
$view->targetLicenseBuyer = $targetLicenseDetails['buyer_username'];
$view->targetLicense = $targetLicenseDetails['license'];
$view->targetLicensePurchasedAt = $targetLicenseDetails['license_purchase_date'].' '.$targetLicenseDetails['license_purchase_time'];
$view->targetLicenseSupportedUntil = $targetLicenseDetails['support_expiration_date'].' '.$targetLicenseDetails['support_expiration_time'];
$view->targetLicenseSupportActive = $targetLicenseDetails['support_active'];

// 2. Details About Target Envato User
$targetUserDetails = $objToolkit->getUserDetails($sanitizedTargetUsername);
// View vars
$view->targetUsername = esc_html($sanitizedTargetUsername); // Ready for print
$view->targetUserCity = $targetUserDetails['city'];
$view->targetUserCountry = $targetUserDetails['country'];
$view->targetUserSales = $targetUserDetails['sales'];
$view->targetUserFollowers = $targetUserDetails['followers'];

// 3. Status of Purchased Plugin ID
$availablePluginVersion = $objToolkit->getAvailableVersion($sanitizedTargetPluginId);
$pluginUpdateAvailable = version_compare($sanitizedInstalledPluginVersion, $availablePluginVersion, 'targetPluginId = intval($sanitizedTargetPluginId); // Ready for print
$view->installedPluginVersion = esc_html($sanitizedInstalledPluginVersion); // Ready for print
$view->nameOfTargetPluginId = esc_html($objToolkit->getItemName($sanitizedTargetPluginId));
$view->availablePluginVersion = $availablePluginVersion;
$view->pluginUpdateAvailable = $pluginUpdateAvailable;
$view->pluginUpdateDownloadUrl = $pluginUpdateAvailable ? $objToolkit->getDownloadUrlIfPurchased($sanitizedTargetPluginId) : '';

// 4. Status of Purchased Theme ID
$availableThemeVersion = $objToolkit->getAvailableVersion($sanitizedTargetThemeId);
$themeUpdateAvailable = version_compare($sanitizedInstalledThemeVersion, $availableThemeVersion, 'targetThemeId = intval($sanitizedTargetThemeId); // Ready for print
$view->installedThemeVersion = esc_html($sanitizedInstalledThemeVersion); // Ready for print
$view->nameOfTargetThemeId = esc_html($objToolkit->getItemName($sanitizedTargetThemeId));
$view->availableThemeVersion = $availableThemeVersion;
$view->themeUpdateAvailable = $themeUpdateAvailable;
$view->themeUpdateDownloadUrl = $themeUpdateAvailable ? $objToolkit->getDownloadUrlIfPurchased($sanitizedTargetThemeId) : '';

// 5. Envato Item Id of Purchased Plugin
$view->targetPluginName = esc_html($sanitizedTargetPluginName); // Ready for print
$view->targetPluginAuthor = esc_html($sanitizedTargetPluginAuthor); // Ready for print
$view->foundPluginId = $objToolkit->getItemIdByPluginAndAuthorIfPurchased($sanitizedTargetPluginName, $sanitizedTargetPluginAuthor);

// 6. Envato Item Id of Purchased Theme
$view->targetThemeName = esc_html($sanitizedTargetThemeName); // Ready for print
$view->targetThemeAuthor = esc_html($sanitizedTargetThemeAuthor); // Ready for print
$view->foundThemeId = $objToolkit->getItemIdByThemeAndAuthorIfPurchased($sanitizedTargetThemeName, $sanitizedTargetThemeAuthor);

各版本下載點

  • 方法一:點下方版本號的連結下載 ZIP 檔案後,登入網站後台左側選單「外掛」的「安裝外掛」,然後選擇上方的「上傳外掛」,把下載回去的 ZIP 外掛打包檔案上傳上去安裝與啟用。
  • 方法二:透過「安裝外掛」的畫面右方搜尋功能,搜尋外掛名稱「Envato Toolkit」來進行安裝。

(建議使用方法二,確保安裝的版本符合當前運作的 WordPress 環境。


最新版本

延伸相關外掛(你可能也想知道)

  • License Manager for WooCommerce 》WooCommerce 授權管理外掛可讓您輕鬆銷售和管理所有數字授權金鑰。憑藉批量導入器、自動交付、自動庫存管理和數據庫加密等功能,您的商店現在運行起來比以往...。
  • License For Envato 》您是一位 WordPress 主題或外掛開發者,同時在 Envato 市場上銷售您的產品嗎?管理產品許可證困難嗎?如果上述問題的回答都是肯定的,則此外掛可以幫助您。現...。
  • WC Serial Numbers – Ultimate License Manager for Selling, Licensing & Securely Delivering Digital Content with WooCommerce 》oduct: Choose the product you want to generate a license key for., 2. Set The Quantity: Specify how many license keys you want to create at once., ...。
  • Software License Manager 》這款外掛是針對網路應用程式(如 WordPress 外掛、佈景主題、基於 PHP 的會員專用腳本等)而設計的軟體授權管理方案。, 透過 API,這款外掛非常實用,您可以...。
  • Creative Commons 》這個「Creative Commons WordPress 外掛」讓作者可以使用 Creative Commons 許可證來授權內容 (選擇一個許可證 )。使用這個外掛,您可以:, , 為您的部落格(...。
  • Elite Licenser addon-lite for WooCommerce 》此外掛是Elite Licenser和WooCommerce的附加功能,因此您必須使用主要應用程式(Elite Licenser)才能使用它。, , , 這是WooCommerce的附加功能,也是Elite L...。
  • WC Key Manager – Effortlessly sell license keys, game keys, pin codes, gift cards, and more with WooCommerce 》, , , ,

    總結:

    ,
      ,
    • WC Key Manager 是一個 WooCommerce 擴充功能...。
    • Elite Licenser Lite – Software License Key Manager 》Elite Licenser 是一個 WordPress 外掛程式,可用於任何產品授權,同時管理產品更新、自动生成授權碼、内建 Envato 授权验证系統、完整授權控制等功能,並具...。
    • Terms Before Download 》「下載前條款」 (Terms Before Download) 外掛程式新增了一個短代碼,可替代 HTML 錨點來連結可下載的檔案。如果點擊此類連結,將會顯示彈出式對話框,顯示必...。
    • Software License Manager for WooCommerce 》發放授權密鑰, , 將Software License Manager發放的授權密鑰新增到WooCommerce銷售的產品中。, 要啟用授權密鑰,需要在客戶端代碼中輸入。, , 與其他插件的合...。
    • EDD License Key Template 》這款外掛可以讓你定義 Easy Digital Downloads 軟體授權金鑰的結構。, 例如:CWP-####-********-**##-** 可以生成 CWP-2827-HS982KSI-A281-09, 這是由 Calder...。
    • WP License Manager 》WP License Manager 是一款易於使用的外掛,可將您的 WordPress 網站轉換為授權管理器,用於 WordPress 主題、外掛和其他可下載產品。, 可下載的文件存儲在 A...。
    • Easy CC License 》Easy CC License 創建了一個 WordPress 短代碼,可以為您的文章添加Creative Commons許可證信息。您只需要在任何文章中使用短代碼[ezcc],插件便會處理其餘部...。
    • Comment License 》Comment License 外掛會在您的評論表單中顯示一個授權條款。您可以在選項頁面中編輯您的授權條款。。
    • Asura Connector 》Asura 連接器 v4:一個配套外掛,可存取由 Asura v4.x 外掛管理的設計集。, 您應該在自己的 WordPress 網站上安裝 Asura 連接器外掛,以從賣家處存取設計集。...。

文章
Filter
Apply Filters
Mastodon