[WordPress] 外掛分享: Envato Toolkit

首頁外掛目錄 › Envato Toolkit
WordPress 外掛 Envato Toolkit 的封面圖片
6,000+
安裝啟用
★★☆☆☆
2.8/5 分(9 則評價)
1786 天前
最後更新
問題解決
WordPress 4.6+ PHP 5.4+ v1.4 上架:2017-06-20

內容簡介

這個外掛包含一個三個檔案的程式庫和視覺化介面,用於驗證客戶購買代碼、獲取特定 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;
}

外掛標籤

開發者團隊

⬇ 下載最新版 (v1.4) 或搜尋安裝

① 下載 ZIP → 後台「外掛 › 安裝外掛 › 上傳外掛」
② 後台搜尋「Envato Toolkit」→ 直接安裝(推薦)

原文外掛簡介

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): ?>
, Licenses:

Code: ,
License: ,
Purchased: ,
Expires: ,
Support Status:

List of all different themes you bought:
$theme): ?>
, Licenses:

Code: ,
License: ,
Purchased: ,
Expires: ,
Status:

Your summary:
Your location is , .
You've sold your items times and you have followers on Envato.

1. Your Customer's License Details
----------------------------------------------------------
Purchase Code:
Is Valid License:
Buyer Username:
License Type:
Purchased At:
Supported Until:
Support Status:

2. Details About Target Envato User -
----------------------------------------------------------
is located in , .
He sold his items times and has followers on Envato.

3. Status of Purchased Plugin ID -
----------------------------------------------------------
Plugin Name:
Plugin Update Available:
Installed Plugin Version:
Available Plugin Version:
Plugin Update Download URL:
Download newest version

4. Status of Purchased Theme ID - :
----------------------------------------------------------
Theme Name:
Theme Update Available:
Installed Theme Version:
Available Theme Version:
Theme Update Download URL:
Download newest version

5. Envato Item Id of Purchased Plugin
----------------------------------------------------------
Searched for Name:
Searched for Author:
Found Plugin Id:

6. Envato Item Id of Purchased Theme
----------------------------------------------------------
Searched for Name:
Searched for Author:
Found Theme Id:

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, '<'); // View vars $view->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, '<'); // View vars $view->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);

文章
Filter
Apply Filters
Mastodon