[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fyNIyhPqF_JdKzqx6e3fkHXEi2ZMXQcDvyXyim1kMJss":3},{"slug":4,"name":5,"version":6,"author":7,"author_profile":8,"description":9,"short_description":10,"active_installs":11,"downloaded":12,"rating":13,"num_ratings":14,"last_updated":15,"tested_up_to":16,"requires_at_least":17,"requires_php":18,"tags":19,"homepage":25,"download_link":26,"security_score":27,"vuln_count":28,"unpatched_count":28,"last_vuln_date":29,"fetched_at":30,"vulnerabilities":31,"developer":32,"crawl_stats":29,"alternatives":39,"analysis":147,"fingerprints":376},"toolkit-for-envato","Envato Toolkit","1.4","KestutisIT","https:\u002F\u002Fprofiles.wordpress.org\u002Fkestutisit\u002F","\u003Cp>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.\u003C\u002Fp>\n\u003Cp>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 \u002F author, have been looking for months.\u003C\u002Fp>\n\u003Cp>If you are looking for the library-only version to integrate into your plugin \u002F theme, it’s on GitHub:\u003Cbr \u002F>\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FKestutisIT\u002FEnvatoToolkit\" title=\"Envato Toolkit (Standalone)\" rel=\"nofollow ugc\">Envato Toolkit (Standalone)\u003C\u002Fa>\u003C\u002Fp>\n\u003Cp>The main purpose of this plugin is to help you to start much easier without having a headache trying to understand \u003Ccode>WordPress - Envato Market\u003C\u002Fcode> 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).\u003C\u002Fp>\n\u003Cp>When I tried to create plugin’s \u003Ccode>[Check for Update]\u003C\u002Fcode> and \u003Ccode>[Validate Purchase Code]\u003C\u002Fcode> feature-buttons in the plugin myself, and I saw the code of the \u003Ccode>WordPress - Envato Market\u003C\u002Fcode> plugin, I was shocked how badly it is written and how you should not to code.\u003C\u002Fp>\n\u003Cp>For example – you would like to give an error message, if Envato user token is empty, which is a required string, i.e. – \u003Ccode>pAA0aBCdeFGhiJKlmNOpqRStuVWxyZ44\u003C\u002Fcode>. 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:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$token = get_user_meta(get_current_user_id(), 'envato_token', TRUE);\nif($token == \"\")\n{\n    return new \\WP_Error('api_token_error', __('An API token is required.', 'envato-toolkit'));\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Now lets see how the same task traceback looks like in \u003Ccode>WordPress - Envato Market\u003C\u002Fcode> plugin:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Ccode>[Api.php -> request(..)]\u003C\u002Fcode> Check if the token is empty:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>if ( empty( $token ) )\n{\n    return new WP_Error( 'api_token_error', __( 'An API token is required.', 'envato-market' ) );\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ccode>[Api.php -> request(..)]\u003C\u002Fcode> Parse it from another string:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$token = trim( str_replace( 'Bearer', '', $args['headers']['Authorization'] ) );\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ccode>[Api.php -> request(..)]\u003C\u002Fcode> Parse it one more time – this time from arguments array:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>public function request( $url, $args = array() ) {\n    $defaults = array(\n        'timeout' => 20,\n    );\n    $args = wp_parse_args( $args, $defaults );\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ccode>[Api.php -> download(..)]\u003C\u002Fcode> Transfer the token variable one more time – this time via params:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>class Envato_Market_API {\n    public function download( $id, $args = array() ) {\n        $url = 'https:\u002F\u002Fapi.envato.com\u002Fv2\u002Fmarket\u002Fbuyer\u002Fdownload?item_id=' . $id . '&shorten_url=true';\n        return $this->request( $url, $args );\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ccode>[admin.php -> maybe_deferred_download(..)]\u003C\u002Fcode> Pass it again – this time get it to args array from another method call:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>function maybe_deferred_download( $options ) {\n    $args = $this->set_bearer_args();\n    $options['package'] = envato_market()->api()->download( $vars['item_id'], $args );\n    return $options;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ccode>[admin.php -> set_bearer_args(..)]\u003C\u002Fcode> Wrap the token into multi-dimensional string array:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$args = array(\n    'headers' => array(\n        'Authorization' => 'Bearer ' . $token,\n    ),\n);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ccode>[admin.php -> set_bearer_args(..)]\u003C\u002Fcode> Pass the wrapped token one more time – this time get it from get_option:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>foreach ( envato_market()->get_option( 'items', array() ) as $item ) {\n    if ( $item['id'] === $id ) {\n        $token = $item['token'];\n        break;\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ccode>[admin.php -> get_option(..)]\u003C\u002Fcode> So what’s in this \u003Ccode>get_option\u003C\u002Fcode>? – Correct, another call to another method – \u003Ccode>get_options()\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>public function get_option( $name, $default = '' ) {\n    $options = self::get_options();\n    $name = self::sanitize_key( $name );\n    return isset( $options[ $name ] ) ? $options[ $name ] : $default;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ccode>[admin.php -> get_options()]\u003C\u002Fcode> Finally, after almost 10 steps in the tree, we are finally getting the original\u003Cbr \u002F>\nWordPress method call, but now I’m getting confused again – what is that \u003Ccode>option_name\u003C\u002Fcode> variable here:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>public function get_options() {\n    return get_option( $this->option_name, array() );\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ccode>[envato-market.php -> init_globals()]\u003C\u002Fcode> Here is it is – the \u003Ccode>option name\u003C\u002Fcode> key name is… Oh wait…\u003Cbr \u002F>\nNo it is not here it. It is equals to another variable, who is is put\u003Cbr \u002F>\nin another clean-up function – look like I’m keep seeing this for the 2 time in the tree – the sanitization of sanitization:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$this->option_name = self::sanitize_key( $this->slug );\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ccode>[envato-market.php -> init_globals()]\u003C\u002Fcode> So the \u003Ccode>option name\u003C\u002Fcode> key name is the name of \u003Ccode>$this->slug\u003C\u002Fcode>.\u003Cbr \u002F>\nNow lets see what is the value of \u003Ccode>$this->slug\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$this->slug        = 'envato-market';\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>So it takes \u003Cstrong>eleven (!)\u003C\u002Fstrong> 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.\u003C\u002Fp>\n\u003Cp>And, I believe, that many other developers had the same issue when tried to create update check feature for their plugins or themes.\u003C\u002Fp>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cp>Finally – the code is poetry – \u003Cstrong>the better is the plugin, the happier is the world\u003C\u002Fstrong>.\u003C\u002Fp>\n\u003Cp>The pseudo-code of example output of the plugin is this:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>Details about you:\n----------------------------------------------------------\nList of all different plugins you bought:\n\u003C?php foreach($plugins AS $pluginId => $plugin): ?>\n    \u003C?='Plugin Id: '.$pluginId.', Name: '.$plugin['name'];?>, Licenses:\n    \u003C?php foreach($plugin['licenses'] AS $license): ?>\n        Code: \u003C?=$license['purchase_code'];?>,\n        License: \u003C?=$license['license'];?>,\n        Purchased: \u003C?=$license['license_purchase_date'];?> \u003C?=$license['license_purchase_time'];?>,\n        Expires: \u003C?=$license['support_expiration_date'];?> \u003C?=$license['support_expiration_time'];?>,\n        Support Status: \u003C?=$license['support_active'];?>\n    \u003C?php endforeach; ?>\n\u003C?php endforeach; ?>\n\nList of all different themes you bought:\n\u003C?php foreach($themes AS $themeId => $theme): ?>\n    \u003C?='Theme Id: '.$themeId.', Name: '.$theme['name'];?>, Licenses:\n    \u003C?php foreach($theme['licenses'] AS $license): ?>\n        Code: \u003C?=$license['purchase_code'];?>,\n        License: \u003C?=$license['license'];?>,\n        Purchased: \u003C?=$license['license_purchase_date'];?> \u003C?=$license['license_purchase_time'];?>,\n        Expires: \u003C?=$license['support_expiration_date'];?> \u003C?=$license['support_expiration_time'];?>,\n        Status: \u003C?=$license['support_active'] == 1 ? \"Supported\" : \"Support Expired\";?>\n    \u003C?php endforeach; ?>\n\u003C?php endforeach; ?>\n\nYour summary:\nYour location is \u003C?=$authorCity;?>, \u003C?=$authorCountry;?>.\nYou've sold your items \u003C?=$authorSales;?> times and you have \u003C?=$authorFollowers;?> followers on Envato.\n\n1. Your Customer's License Details\n----------------------------------------------------------\nPurchase Code: \u003C?=$targetPurchaseCode;?>\nIs Valid License: \u003C?=$isValidTargetLicense ? 'Yes' : 'No';?>\nBuyer Username: \u003C?=$targetLicenseBuyer;?>\nLicense Type: \u003C?=$targetLicenseType;?>\nPurchased At: \u003C?=$targetLicensePurchasedAt;?>\nSupported Until: \u003C?=$targetLicenseSupportedUntil;?>\nSupport Status: \u003C?=$targetLicenseSupportActive == 1 ? \"Supported\" : \"Support Expired\";?>\n\n2. Details About Target Envato User - \u003C?=$targetUsername;?>\n----------------------------------------------------------\n\u003C?=$targetUsername;?> is located in \u003C?=$targetUserCity;?>, \u003C?=$targetUserCountry;?>.\nHe sold his items \u003C?=$targetUserSales;?> times and has \u003C?=$targetUserFollowers;?> followers on Envato.\n\n3. Status of Purchased Plugin ID - \u003C?=$targetPluginId;?>\n----------------------------------------------------------\nPlugin Name: \u003C?=$nameOfTargetPluginId;?>\nPlugin Update Available: \u003C?=$pluginUpdateAvailable ? 'Yes' : 'No';?>\nInstalled Plugin Version: \u003C?=$installedPluginVersion;?>\nAvailable Plugin Version: \u003C?=$availablePluginVersion;?>\nPlugin Update Download URL:\n\u003Ca href=\"\u003C?=$pluginUpdateDownloadUrl;?>\" target=\"_blank\" title=\"Download newest version\">Download newest version\u003C\u002Fa>\n\n4. Status of Purchased Theme ID - \u003C?=$targetThemeId;?>:\n----------------------------------------------------------\nTheme Name: \u003C?=$nameOfTargetThemeId;?>\nTheme Update Available: \u003C?=$themeUpdateAvailable ? 'Yes' : 'No';?>\nInstalled Theme Version: \u003C?=$installedThemeVersion;?>\nAvailable Theme Version: \u003C?=$availableThemeVersion;?>\nTheme Update Download URL:\n\u003Ca href=\"\u003C?=$themeUpdateDownloadUrl;?>\" target=\"_blank\" title=\"Download newest version\">Download newest version\u003C\u002Fa>\n\n5. Envato Item Id of Purchased Plugin\n----------------------------------------------------------\nSearched for Name: \u003C?=$targetPluginName;?>\nSearched for Author: \u003C?=$targetPluginAuthor;?>\nFound Plugin Id: \u003C?=$foundPluginId;?>\n\n6. Envato Item Id of Purchased Theme\n----------------------------------------------------------\nSearched for Name: \u003C?=$targetThemeName;?>\nSearched for Author: \u003C?=$targetThemeAuthor;?>\nFound Theme Id: \u003C?=$foundThemeId;?>\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>And the example input of the output above, it this:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$objToolkit = new EnvatoAPIManager($toolkitSettings);\n\n\u002F\u002F Details about you\n$purchasedPlugins = $objToolkit->getPurchasedPluginsWithDetails();\n$plugins = array();\nforeach($purchasedPlugins AS $pluginId => $purchasedPlugin)\n{\n    $purchasedPlugin['licenses'] = $objToolkit->getLicensesByItemId($pluginId);\n    $plugins[$pluginId] = $purchasedPlugin;\n}\n\n$purchasedThemes = $objToolkit->getPurchasedThemesWithDetails();\n$themes = array();\nforeach($purchasedThemes AS $themeId => $purchasedTheme)\n{\n    $purchasedTheme['licenses'] = $objToolkit->getLicensesByItemId($themeId);\n    $themes[$themeId] = $purchasedTheme;\n}\n\n$authorDetails = $objToolkit->getUserDetails($sanitizedEnvatoUsername);\n\u002F\u002F View vars\n$view->plugins = $plugins;\n$view->themes = $themes;\nif($authorDetails != FALSE)\n{\n    $view->authorCity = $authorDetails['city'];\n    $view->authorCountry = $authorDetails['country'];\n    $view->authorSales = $authorDetails['sales'];\n    $view->authorFollowers = $authorDetails['followers'];\n} else\n{\n    $view->authorCity = '';\n    $view->authorCountry = '';\n    $view->authorSales = 0;\n    $view->authorFollowers = 0;\n}\n\n\u002F\u002F 1. Details About Target Purchase Code\n$targetLicenseDetails = $objToolkit->getLicenseDetails($sanitizedTargetPurchaseCode);\n\u002F\u002F View vars\n$view->targetPurchaseCode = esc_html($sanitizedTargetPurchaseCode); \u002F\u002F Ready for print\n$view->isValidTargetLicense = $objToolkit->isValidLicense($sanitizedTargetPurchaseCode);\n$view->targetLicenseBuyer = $targetLicenseDetails['buyer_username'];\n$view->targetLicense = $targetLicenseDetails['license'];\n$view->targetLicensePurchasedAt = $targetLicenseDetails['license_purchase_date'].' '.$targetLicenseDetails['license_purchase_time'];\n$view->targetLicenseSupportedUntil = $targetLicenseDetails['support_expiration_date'].' '.$targetLicenseDetails['support_expiration_time'];\n$view->targetLicenseSupportActive = $targetLicenseDetails['support_active'];\n\n\u002F\u002F 2. Details About Target Envato User\n$targetUserDetails = $objToolkit->getUserDetails($sanitizedTargetUsername);\n\u002F\u002F View vars\n$view->targetUsername = esc_html($sanitizedTargetUsername); \u002F\u002F Ready for print\n$view->targetUserCity = $targetUserDetails['city'];\n$view->targetUserCountry = $targetUserDetails['country'];\n$view->targetUserSales = $targetUserDetails['sales'];\n$view->targetUserFollowers = $targetUserDetails['followers'];\n\n\u002F\u002F 3. Status of Purchased Plugin ID\n$availablePluginVersion = $objToolkit->getAvailableVersion($sanitizedTargetPluginId);\n$pluginUpdateAvailable = version_compare($sanitizedInstalledPluginVersion, $availablePluginVersion, '\u003C');\n\u002F\u002F View vars\n$view->targetPluginId = intval($sanitizedTargetPluginId); \u002F\u002F Ready for print\n$view->installedPluginVersion = esc_html($sanitizedInstalledPluginVersion); \u002F\u002F Ready for print\n$view->nameOfTargetPluginId = esc_html($objToolkit->getItemName($sanitizedTargetPluginId));\n$view->availablePluginVersion = $availablePluginVersion;\n$view->pluginUpdateAvailable = $pluginUpdateAvailable;\n$view->pluginUpdateDownloadUrl = $pluginUpdateAvailable ? $objToolkit->getDownloadUrlIfPurchased($sanitizedTargetPluginId) : '';\n\n\u002F\u002F 4. Status of Purchased Theme ID\n$availableThemeVersion = $objToolkit->getAvailableVersion($sanitizedTargetThemeId);\n$themeUpdateAvailable = version_compare($sanitizedInstalledThemeVersion, $availableThemeVersion, '\u003C');\n\u002F\u002F View vars\n$view->targetThemeId = intval($sanitizedTargetThemeId); \u002F\u002F Ready for print\n$view->installedThemeVersion = esc_html($sanitizedInstalledThemeVersion); \u002F\u002F Ready for print\n$view->nameOfTargetThemeId = esc_html($objToolkit->getItemName($sanitizedTargetThemeId));\n$view->availableThemeVersion = $availableThemeVersion;\n$view->themeUpdateAvailable = $themeUpdateAvailable;\n$view->themeUpdateDownloadUrl = $themeUpdateAvailable ? $objToolkit->getDownloadUrlIfPurchased($sanitizedTargetThemeId) : '';\n\n\u002F\u002F 5. Envato Item Id of Purchased Plugin\n$view->targetPluginName = esc_html($sanitizedTargetPluginName); \u002F\u002F Ready for print\n$view->targetPluginAuthor = esc_html($sanitizedTargetPluginAuthor); \u002F\u002F Ready for print\n$view->foundPluginId = $objToolkit->getItemIdByPluginAndAuthorIfPurchased($sanitizedTargetPluginName, $sanitizedTargetPluginAuthor);\n\n\u002F\u002F 6. Envato Item Id of Purchased Theme\n$view->targetThemeName = esc_html($sanitizedTargetThemeName); \u002F\u002F Ready for print\n$view->targetThemeAuthor = esc_html($sanitizedTargetThemeAuthor); \u002F\u002F Ready for print\n$view->foundThemeId = $objToolkit->getItemIdByThemeAndAuthorIfPurchased($sanitizedTargetThemeName, $sanitizedTargetThemeAuthor);\n\u003C\u002Fcode>\u003C\u002Fpre>\n","Validate purchase code, check for item update & support expiration, download newest version, lookup for user details, search for Envato item id & more",6000,126000,56,9,"2021-04-26T18:00:00.000Z","5.7.15","4.6","5.4",[20,21,22,23,24],"api","envato","license","purchase-validator","update-checker","https:\u002F\u002Fwordpress.org\u002Fplugins\u002Ftoolkit-for-envato\u002F","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftoolkit-for-envato.zip",85,0,null,"2026-03-15T15:16:48.613Z",[],{"slug":33,"display_name":7,"profile_url":8,"plugin_count":34,"total_installs":35,"avg_security_score":27,"avg_patch_time_days":36,"trust_score":37,"computed_at":38},"kestutisit",4,6070,30,84,"2026-04-04T10:38:30.542Z",[40,63,82,101,122],{"slug":41,"name":42,"version":43,"author":44,"author_profile":45,"description":46,"short_description":47,"active_installs":48,"downloaded":49,"rating":28,"num_ratings":28,"last_updated":50,"tested_up_to":51,"requires_at_least":52,"requires_php":53,"tags":54,"homepage":58,"download_link":59,"security_score":60,"vuln_count":61,"unpatched_count":28,"last_vuln_date":62,"fetched_at":30},"license-envato","License For Envato","1.1.0","Ashraful Sarkar Naiem","https:\u002F\u002Fprofiles.wordpress.org\u002Fashrafulsarkar\u002F","\u003Cp>Are you a theme or plugin developer and selling your product in the Envato market? Can’t manage your product license? If all questions are yes. This plugin help you. Now you can manage all Envato licenses with this plugin.\u003C\u002Fp>\n\u003Ch3>⚡ Features\u003C\u002Fh3>\n\u003Cul>\n\u003Cli>Easy installation\u003C\u002Fli>\n\u003Cli>License management\u003C\u002Fli>\n\u003Cli>Search with purchasecode\u003C\u002Fli>\n\u003Cli>Lightweight and fast\u003C\u002Fli>\n\u003C\u002Ful>\n","\"License For Envato\" is a Envato theme & plugin license management Software.",8000,60465,"2025-12-17T06:33:00.000Z","6.9.4","6.0","7.2",[55,22,41,56,57],"envato-license","license-manager","plugin-license","https:\u002F\u002Fgithub.com\u002Fashrafulsarkar\u002Fenvato-licenser","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flicense-envato.1.1.0.zip",94,2,"2025-04-21 00:00:00",{"slug":64,"name":65,"version":66,"author":67,"author_profile":68,"description":69,"short_description":70,"active_installs":71,"downloaded":72,"rating":28,"num_ratings":28,"last_updated":73,"tested_up_to":74,"requires_at_least":75,"requires_php":18,"tags":76,"homepage":80,"download_link":81,"security_score":27,"vuln_count":28,"unpatched_count":28,"last_vuln_date":29,"fetched_at":30},"vatomi","Vatomi","1.0.3","nK","https:\u002F\u002Fprofiles.wordpress.org\u002Fnko\u002F","\u003Ch3>Features\u003C\u002Fh3>\n\u003Cul>\n\u003Cli>Envato oAuth button in registration form\u003C\u002Fli>\n\u003Cli>AwesomeSupport integration for Envato products\u003C\u002Fli>\n\u003Cli>Activation API for themes and plugins developers\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Activation themes\u002Fplugins for developers\u003C\u002Fh3>\n\u003Col>\n\u003Cli>Fill settings in \u003Cstrong>wp_admin > Vatomi > Settings > Envato Settings\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli>Create Licenses page in \u003Cstrong>wp_admin > Vatomi > Settings > Licenses\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli>\n\u003Cp>Use these links to let users activate your theme\u002Fplugin:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\n\u003Cp>Activate\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u003Ca href=\"\u003C?php echo esc_attr( 'https:\u002F\u002F{YOUR_SITE}\u002Flicenses\u002F?vatomi_item_id={ITEM_ID}&vatomi_action=activate&vatomi_site=' . urlencode( home_url( '\u002F' ) ) . '&vatomi_redirect=' . urlencode( admin_url( 'admin.php?page={YOUR_THEME_PAGE}' ) ) ); ?>\" class=\"button button-primary\">Activate\u003C\u002Fa>\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>After button clicked, user will be redirected back to their site on the page \u003Ccode>admin_url( 'admin.php?page={YOUR_THEME_PAGE}' )\u003C\u002Fcode> with available GET variables, that you can use:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>vatomi_action\u003C\u002Fstrong> (activate, deactivate)\u003C\u002Fli>\n\u003Cli>\u003Cstrong>vatomi_item_id\u003C\u002Fstrong> (item ID)\u003C\u002Fli>\n\u003Cli>\u003Cstrong>vatomi_license_code\u003C\u002Fstrong> (Envato purchase code)\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>Deactivate\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u003Ca href=\"\u003C?php echo esc_attr( 'https:\u002F\u002F{YOUR_SITE}\u002Flicenses\u002F?vatomi_item_id={ITEM_ID}&vatomi_action=deactivate&vatomi_license={PURCHASE_CODE}&vatomi_redirect=' . urlencode( admin_url( 'admin.php?page={YOUR_THEME_PAGE}' ) ) ); ?>\" class=\"button button-primary\">Deactivate\u003C\u002Fa>\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>After button clicked, user will be redirected back to their site on the page \u003Ccode>admin_url( 'admin.php?page={YOUR_THEME_PAGE}' )\u003C\u002Fcode> with available GET variables, that you can use:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>vatomi_action (activate, deactivate)\u003C\u002Fli>\n\u003Cli>vatomi_item_id (item ID)\u003C\u002Fli>\n\u003Cli>vatomi_license_code (Envato purchase code)\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>After theme\u002Fplugin activated, you will be able to use Vatomi API:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\n\u003Cp>Get URL to ZIP file:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>https:\u002F\u002F{YOUR_SITE}\u002Fwp-json\u002Fvatomi\u002Fv1\u002Fenvato\u002Fitem_wp_url\u002F{ITEM_ID}?license={PURCHASE_CODE}&site={ACTIVATED_SITE_ADDRESS}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>Get item current version number:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>https:\u002F\u002F{YOUR_SITE}\u002Fwp-json\u002Fvatomi\u002Fv1\u002Fenvato\u002Fitem_version\u002F{ITEM_ID}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>Check valid purchase code (if user purchased item from you):\u003C\u002Fp>\n\u003Cpre>\u003Ccode>https:\u002F\u002F{YOUR_SITE}\u002Fwp-json\u002Fvatomi\u002Fv1\u002Fenvato\u002Fcheck_license\u002F{PURCHASE_CODE}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fli>\n\u003C\u002Ful>\n","Envato oAuth registration. Support Envato customers users with AwesomeSupport plugin.",10,1441,"2019-11-02T22:26:00.000Z","5.3.21","4.8.0",[77,21,22,78,79],"activation","oauth","support","","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fvatomi.1.0.3.zip",{"slug":83,"name":84,"version":85,"author":86,"author_profile":87,"description":88,"short_description":89,"active_installs":71,"downloaded":90,"rating":28,"num_ratings":28,"last_updated":91,"tested_up_to":92,"requires_at_least":18,"requires_php":53,"tags":93,"homepage":99,"download_link":100,"security_score":27,"vuln_count":28,"unpatched_count":28,"last_vuln_date":29,"fetched_at":30},"verify-customers-licenses-gumroad","Verify Customers Licenses for Gumroad","1.0.0","unistudio","https:\u002F\u002Fprofiles.wordpress.org\u002Funistudio\u002F","\u003Cp>Are you a seller of licensing digital products on Gumroad? And do you need to verify the licenses of your customers when they request technical support from you or something else?\u003Cbr \u002F>\nThis plugin was specially developed for this matter as it relies on the Gumroad API and is easy to install and use.\u003C\u002Fp>\n\u003Ch4>How it works\u003C\u002Fh4>\n\u003Cp>STEP 1:\u003Cbr \u002F>\n1. Create a \u003Ca href=\"https:\u002F\u002Fgumroad.com\u002Fsettings\u002Fadvanced#application-form\" title=\"Gumroad App\" rel=\"nofollow ugc\">Gumroad\u003C\u002Fa> on your profile settings.\u003Cbr \u002F>\n2. Click on Generate your access token.\u003Cbr \u002F>\n3. Copy\u002FPaste the generated access token on the plugin API Authentication field.\u003Cbr \u002F>\n4. Save changes!\u003C\u002Fp>\n\u003Cp>STEP 2:\u003Cbr \u002F>\n1. Copy\u002FPaste this shortcode \u003Ccode>[vclg_form]\u003C\u002Fcode> on whatever place you want the verify licenses form to show up.\u003C\u002Fp>\n\u003Cp>That’s it!! Well done.\u003C\u002Fp>\n","Verify your Gumroad's customers licenses right within WordPress.",2988,"2020-11-05T21:54:00.000Z","5.5.18",[94,95,96,97,98],"digial-products","gumroad","gumroad-api","license-verify","verify-licenses","https:\u002F\u002Funistudio.co\u002Fcollections\u002Fapps\u002Fvl-gumroad\u002F","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fverify-customers-licenses-gumroad.1.0.zip",{"slug":102,"name":103,"version":104,"author":105,"author_profile":106,"description":107,"short_description":108,"active_installs":28,"downloaded":109,"rating":28,"num_ratings":28,"last_updated":110,"tested_up_to":111,"requires_at_least":112,"requires_php":113,"tags":114,"homepage":119,"download_link":120,"security_score":121,"vuln_count":28,"unpatched_count":28,"last_vuln_date":29,"fetched_at":30},"eacsoftwareregistry-distribution-sdk","{eac}SoftwareRegistry Distribution SDK","1.1.3","Kevin Burkholder","https:\u002F\u002Fprofiles.wordpress.org\u002Fkevinburkholder\u002F","\u003Cp>\u003Cstrong>{eac}SoftwareRegistry Distribution SDK\u003C\u002Fstrong> is an extension plugin to \u003Ca href=\"https:\u002F\u002Fswregistry.earthasylum.com\u002Fsoftware-registration-server\u002F\" rel=\"nofollow ugc\">{eac}SoftwareRegistry Software Registration Server\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>The Software Registry Distribution SDK is used to generate a custom PHP package that you can include in your software project to register your product with your registration server and manage that registration.\u003C\u002Fp>\n\u003Cp>\u003Cem>A custom version of this document is included in the generated SDK package.\u003C\u002Fem>\u003C\u002Fp>\n\u003Cp>The SDK provides most of the PHP code you will need to implement the Application Program Interface with your Software Registration Server.\u003C\u002Fp>\n\u003Cp>Included with the Software Registration SDK package…\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Ccode>(your_productid)_registration.(wordpress_or_filebased).trait.php\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Ccode>(your_productid)_registration.includes.php\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Ccode>(your_productid)_registration.interface.php\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Ccode>(your_productid)_registration.interface.trait.php\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Ccode>(your_productid)_registration.refresh.php\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Ccode>(your_productid)_registration.readme.md\u003C\u002Fcode>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch4>Software Registry Implementation\u003C\u002Fh4>\n\u003Cp>After extracting the \u003Ccode>(your_productid)_registration.zip\u003C\u002Fcode> file, move the \u003Ccode>(your_productid)_registration\u003C\u002Fcode> folder to your project.\u003C\u002Fp>\n\u003Cp>In your project or class file, include \u003Ccode>(your_productid)_registration\u002F(your_productid)_registration.includes.php\u003C\u002Fcode> to load the required interface and traits.\u003C\u002Fp>\n\u003Cp>Your class file must then:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>implement \u003Ccode>\\(your_namespace)\\Interfaces\\(your_productid)_registration\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>use \u003Ccode>\\(your_namespace)\\Traits\\(your_productid)_registration_(wordpress_or_filebased)\u003C\u002Fcode>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Example:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>include \"(your_productid)_registration\u002F(your_productid)_registration.includes.php\";\n\nclass \u003Cyour_classname> implements \\(your_namespace)\\Interfaces\\(your_productid)_registration\n{\n    use \\(your_namespace)\\Traits\\(your_productid)_registration_(wordpress_or_filebased);\n        ...\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>(your_productid)_registration.interface.php will have your product and registration server API constants.\u003C\u002Fp>\n\u003Cpre>\u003Ccode>const SOFTWARE_REGISTRY_PRODUCTID   = '{your_software_registry_productid}';\nconst SOFTWARE_REGISTRY_HOST_URL    = '{your_software_registry_host_url}';\nconst SOFTWARE_REGISTRY_CREATE_KEY  = '{your_software_registry_create_key}';\nconst SOFTWARE_REGISTRY_UPDATE_KEY  = '{your_software_registry_update_key}';\nconst SOFTWARE_REGISTRY_READ_KEY    = '{your_software_registry_read_key}';\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch4>Using The API\u003C\u002Fh4>\n\u003Cp>\u003Cstrong>API Parameters\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>API parameters are passed as an array:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$apiParams =\n[\n    'registry_key'          => 'unique ID',                     \u002F\u002F * registration key (assigned by registry server)\n    'registry_name'         => 'Firstname Lastname',            \u002F\u002F   registrant's full name\n    'registry_email'        => 'email@domain.com',              \u002F\u002F * registrant's email address\n    'registry_company'      => 'Comapny\u002FOrganization Name',     \u002F\u002F   registrant's company name\n    'registry_address'      => 'Street\\n City St Zip',          \u002F\u002F   registrant's full address (textarea)\n    'registry_phone'        => 'nnnnnnnnnn',                    \u002F\u002F   registrant's phone\n    'registry_product'      => 'productId',                     \u002F\u002F * your product name\u002Fid ((your_productid))\n    'registry_title'        => 'Product Title',                 \u002F\u002F   your product title\n    'registry_description'  => 'Product Description',           \u002F\u002F   your product description\n    'registry_version'      => 'M.m.p',                         \u002F\u002F   your product version\n    'registry_license'      => 'Lx',                            \u002F\u002F   'L1'(Lite), 'L2'(Basic), 'L3'(Standard), 'L4'(Professional), 'L5'(Enterprise), 'LD'(Developer), 'LU'(Unlimited)\n    'registry_count'        => int,                             \u002F\u002F   Number of licenses (users\u002Fseats\u002Fdevices)\n    'registry_variations'   => array('name'=>'value',...),      \u002F\u002F   array of name\u002Fvalue pairs\n    'registry_options'      => array('value',...),              \u002F\u002F   array of registry options\n    'registry_domains'      => array('domain',...),             \u002F\u002F   array of valid\u002Fregistered domains\n    'registry_sites'        => array('url',...),                \u002F\u002F   array of valid\u002Fregistered sites\u002Furis\n    'registry_transid'      => '',                              \u002F\u002F   external transaction id\n    'registry_timezone'     => '',                              \u002F\u002F   standard timezone string (client timezone)\n    'registry_locale'       => '',                              \u002F\u002F   standard locale\u002Flanguage code\n];\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>* \u003Cem>Required values (registry_key not required when creating a new registration).\u003C\u002Fem>\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>If setting registry_transid, the recommended (not required) format is \u003Ccode>{id}|{source}|{suffix}\u003C\u002Fcode> where {id} is the transaction id, {source} indicates the source of the transaction, and {suffix} may be used as needed.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>Any additional fields passed wil be saved as custom fields.\u003C\u002Fp>\n\u003Cp>Although typically set by the Software Registry server, with the proper option setting, the API \u003Cem>may\u003C\u002Fem> override:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>[\n    'registry_status'       => 'status',                        \u002F\u002F 'pending', 'trial', 'active', 'inactive', 'expired', 'terminated'\n    'registry_effective'    => 'DD-MMM-YYYY',                   \u002F\u002F Effective date\n    'registry_expires'      => 'DD-MMM-YYYY',                   \u002F\u002F Expiration date or term ('30 days', '1 year',... added to effective date)\n];\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Payment information may be posted with:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>[\n    'registry_paydue'       => float,                           \u002F\u002F amount to be paid\u002Fbilled,\n    'registry_payamount'    => float,                           \u002F\u002F amount paid,\n    'registry_paydate'      => 'DD-MMM-YYYY',                   \u002F\u002F date paid\n    'registry_payid'        => 'payment id'                     \u002F\u002F transaction id\u002Fcheck #, etc.\n    'registry_nextpay'      => 'DD-MMM-YYYY',                   \u002F\u002F next payment\u002Frenewal date\n];\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>API Requests\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>Create\u002Frequest a new registration…\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$response = $this->registryApiRequest('create',$apiParams);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Activate an existing registration…\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$response = $this->registryApiRequest('activate',['registry_key' => '\u003CregistrationKeyValue>']);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Activate and Update an existing registration…\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$response = $this->registryApiRequest('activate',$apiParams);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Deactivate an existing registration…\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$response = $this->registryApiRequest('deactivate',['registry_key' => '\u003CregistrationKeyValue>']);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Verify or Refresh an existing registration…\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$response = $this->registryApiRequest('verify',['registry_key' => '\u003CregistrationKeyValue>']);\n$response = $this->registryApiRequest('refresh',$apiParams);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Revise an existing registration…\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$response = $this->registryApiRequest('revise',$apiParams);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>API Response\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>The API response is a standard object. status->code is an http status, 200 indicating success.\u003C\u002Fp>\n\u003Cpre>\u003Ccode>status      ->\n(\n    code                  -> 200,             \u002F\u002F HTTP status code\n    message               -> '(action) ok'    \u002F\u002F (action) = 'create', 'activate', 'deactivate', 'verify', 'revise'\n),\nregistration ->\n(\n    registry_key          -> string           \u002F\u002F UUID,\n    registry_status       -> string,          \u002F\u002F 'pending', 'trial', 'active', 'inactive', 'expired', 'terminated', 'invalid'\n    registry_effective    -> string,          \u002F\u002F DD-MMM-YYYY effective date\n    registry_expires      -> string,          \u002F\u002F DD-MMM-YYYY expiration date\n    registry_name         -> string,\n    registry_email        -> string,\n    registry_company      -> string,\n    registry_address      -> string,\n    registry_phone        -> string,\n    registry_product      -> string,\n    registry_title        -> string,\n    registry_description  -> string,\n    registry_version      -> string,\n    registry_license      -> string,\n    registry_count        -> int,\n    registry_variations   -> array,\n    registry_options      -> array,\n    registry_domains      -> array,\n    registry_sites        -> array,\n    registry_transid      -> string,\n    registry_timezone     -> string,\n    registry_locale       -> string,\n    registry_valid        -> bool,\n),\nregistrar ->\n(\n    contact               -> object(\n        name              -> string           \u002F\u002F Registrar Name\n        email             -> string           \u002F\u002F Registrar Support Email\n        phone             -> string           \u002F\u002F Registrar Telephone\n        web               -> string           \u002F\u002F Registrar Web Address\n    ),\n    timezone              -> string,          \u002F\u002F standard timezone string\n    locale                -> string,          \u002F\u002F WordPress locale\n    cacheTime             -> int,             \u002F\u002F in seconds, time to cache the registration response (Default Cache Time)\n    refreshInterval       -> int,             \u002F\u002F in seconds, time before refreshing the registration (Default Refresh Time)\n    refreshSchedule       -> string,          \u002F\u002F 'hourly', 'twicedaily', 'daily', 'twiceweekly', 'weekly',  'twicemonthly', 'monthly' - corresponding to refreshInterval\n    options               -> array(           \u002F\u002F from settings page, registrar_options (Allow API to...)\n        'allow_set_key',\n        'allow_set_status',\n        'allow_set_effective',\n        'allow_set_expiration',\n        'allow_activation_update'\n    ),\n    licenseCodes          -> object(          \u002F\u002F may be changed by filter on registration server\n        L1                -> 'Lite'\n        L2                -> 'Basic'\n        L3                -> 'Standard'\n        L4                -> 'Professional'\n        L5                -> 'Enterprise'\n        LD                -> 'Developer'\n        LU                -> 'Unlimited'\n    ),\n    notices               -> object(\n        info              -> string,          \u002F\u002F information message text\n        warning           -> string,          \u002F\u002F warning message text\n        error             -> string,          \u002F\u002F error message text\n        success           -> string,          \u002F\u002F success message text\n    ),\n    message               -> string,          \u002F\u002F html message\n),\nregistryHtml              -> string,          \u002F\u002F html (table) of human-readable registration values\nsupplemental              -> mixed,           \u002F\u002F supplemental data\u002Fhtml assigned via filters (developer's discretion).\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>On a successful response (status->code = 200), the SDK will automatically cache the registration data and schedule the next refresh event (you do not have to do this).\u003C\u002Fp>\n\u003Cp>\u003Cem>notices\u003C\u002Fem> may be set (according to severity) to indicate an expiration or pending expiration and should be displayed to the user. Typically, only one notice will be set but they can be set via the \u003Ccode>eacSoftwareRegistry_api_registration_notices\u003C\u002Fcode> filter.\u003C\u002Fp>\n\u003Cp>\u003Cem>message\u003C\u002Fem> is set via the \u003Ccode>eacSoftwareRegistry_api_registration_message\u003C\u002Fcode> filter.\u003C\u002Fp>\n\u003Cp>\u003Cem>supplemental\u003C\u002Fem> is set via the \u003Ccode>eacSoftwareRegistry_api_registration_supplemental\u003C\u002Fcode> filter.\u003C\u002Fp>\n\u003Cp>On an error response, an additional element is included:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>error      ->\n(\n    code                  -> 'error_code',\n    message               -> 'error message'\n),\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>error->message may be more informative than status->message.\u003Cbr \u002F>\nErrors may be handled with something like:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>if ($this->is_api_error($response))\n{\n    echo \"\u003Cdiv class='notice notice-error'>\u003Ch4>Error \".$response->error->code.\" : \".$response->error->message.\"\u003C\u002Fh4>\u003C\u002Fdiv>\";\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch4>Methods, Hooks, and Callbacks\u003C\u002Fh4>\n\u003Cp>Useful methods built into the SDK…\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$this->isValidRegistration();\n    \u002F\u002F Returns boolean\n    if ( $this->isValidRegistration() ) {...}\n\n$this->getRegistrationKey();\n    \u002F\u002F Returns the current registration key\n    $registrationKey = $this->getRegistrationKey();\n\n$this->getCurrentRegistration();\n    \u002F\u002F Returns the current registration object (above response object)\n    $currentRegistration = $this->getCurrentRegistration();\n\n$this->isRegistryValue($keyName);\n    \u002F\u002F Returns the value of a specific registry key\n    $regStatus = $this->isRegistryValue( 'status ');\n\n$this->isRegistryValue($keyName, $value, $test);\n    \u002F\u002F Returns boolean comparison of the value of a registry key ($test is '=|eq' (default), '\u003C|lt', '>|gt', '\u003C=|le', '>=|ge')\n    if ( $this->isRegistryValue('license', 'L3', '>=') ) {...}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Several hooks are available to customize or react to registration events.\u003Cbr \u002F>\nIn WordPresss, there are several actions and filters, for file based projects there are corresponding callback methods…\u003C\u002Fp>\n\u003Cpre>\u003Ccode> filter\u002Fcallback: (your_productid)_api_remote_request( $request, $endpoint )\n    @param  array $request ['method'=>, 'timeout'=>, 'redirection'=>, 'sslverify'=>, 'headers'=>, 'body'=>]\n    @param  string $endpoint create, activate, deactivate, verify, refresh, revise\n    @return array request body\n\n action\u002Fcallback: (your_productid)_api_remote_response( $body, $request, $endpoint )\n    @param  array $body response body\n    @param  array $request ['method'=>, 'timeout'=>, 'redirection'=>, 'sslverify'=>, 'headers'=>, 'body'=>]\n    @param  string $endpoint create, activate, deactivate, verify, refresh, revise\n\n action\u002Fcallback: (your_productid)_api_remote_$endpoint( $body, $request, $endpoint )\n    @param  array $body response body\n    @param  array $request ['method'=>, 'timeout'=>, 'redirection'=>, 'sslverify'=>, 'headers'=>, 'body'=>]\n    @param  string $endpoint create, activate, deactivate, verify, refresh, revise\n\n action\u002Fcallback: (your_productid)_api_remote_error( $error, $request, $endpoint )\n    @param  object $error {status:{}, error: {}}\n    @param  array $request ['method'=>, 'timeout'=>, 'redirection'=>, 'sslverify'=>, 'headers'=>, 'body'=>]\n    @param  string $endpoint create, activate, deactivate, verify, refresh, revise\n\n action\u002Fcallback: (your_productid)_update_registration($registration)\n    @param  array $registration registration object\n\n action\u002Fcallback: (your_productid)_purge_registration()\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch4>What You Need To Do\u003C\u002Fh4>\n\u003Cp>\u003Cstrong>For WordPress Projects\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>In your class constructor\u002Finitialization, add an action to fulfill the registration refresh scheduled by the \u003Ccode>scheduleRegistryRefresh()\u003C\u002Fcode> method in \u003Ccode>(your_productid).wordpress.trait.php\u003C\u002Fcode>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\\add_action( '(your_productid)_registry_refresh', array($this, 'refreshRegistration') );\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>You can add this and other hooks with:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$this->addSoftwareRegistryHooks();\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>The \u003Ccode>addSoftwareRegistryHooks()\u003C\u002Fcode> method adds:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\\add_action( '(your_productid)_registry_refresh',     array($this, 'refreshRegistration') );\n\\add_filter( '(your_productid)_is_registered',        array($this, 'isValidRegistration') );\n\\add_filter( '(your_productid)_registration_key',     array($this, 'getRegistrationKey') );\n\\add_filter( '(your_productid)_registration',         array($this, 'getCurrentRegistration') );\n\\add_filter( '(your_productid)_registry_value',       array($this, 'isRegistryValue'), 10, 4 );\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Example:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>include \"(your_productid)_registration\u002F(your_productid)_registration.includes.php\";\n\nclass \u003Cyour_classname> implements \\(your_namespace)\\Interfaces\\(your_productid)_registration\n{\n    use \\(your_namespace)\\Traits\\(your_productid)_registration_wordpress;\n        ...\n    public function __construct()\n    {\n        $this->addSoftwareRegistryHooks();\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Note:\u003C\u002Fp>\n\u003Cp>If your primary plugin file name is not the same as the product id, edit your \u003Ccode>(your_productid).interface.tpl\u003C\u002Fcode> file and change the \u003Ccode>SOFTWARE_REGISTRY_FILENAME\u003C\u002Fcode> constant.\u003C\u002Fp>\n\u003Cpre>\u003Ccode>    const SOFTWARE_REGISTRY_FILENAME    = 'myPluginName';\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>For Other File Based Projects\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>The \u003Ccode>scheduleRegistryRefresh()\u003C\u002Fcode> method in \u003Ccode>(your_productid)_registration.filebased.trait.php\u003C\u002Fcode> is called to schedule the next registration refresh. This method can be modified to schedule a cron event to execute the refresh at a future time. The scheduled event may run \u003Ccode>(your_productid)_registration.refresh.php \u003CregistrationKeyValue>\u003C\u002Fcode> from the command line to refresh the registration.\u003C\u002Fp>\n\u003Cp>When left as is, the \u003Ccode>checkRegistryRefreshEvent()\u003C\u002Fcode> method uses the key file to check for a needed registration refresh.\u003C\u002Fp>\n\u003Cp>In your class constructor or destructor add:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$this->checkRegistryRefreshEvent();\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>to trigger the refresh check.\u003C\u002Fp>\n\u003Cp>Example:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>include \"(your_productid)_registration\u002F(your_productid)_registration.includes.php\";\n\nclass \u003Cyour_classname> implements \\(your_namespace)\\Interfaces\\(your_productid)_registration\n{\n    use \\(your_namespace)\\Traits\\(your_productid)_registration_filebased;\n        ...\n    public function __destruct()\n    {\n        \u002F* if necessary, set HOME\u002FUSERPROFILE and\u002For TMP\u002FTMPDIR\u002FTEMP directories *\u002F\n        \u002F\u002F putenv('HOME={your home directory}');   \u002F\u002F where the registration key is stored, otherwise use $_SERVER['DOCUMENT_ROOT']\n        \u002F\u002F putenv('TMP={your temp directory}');    \u002F\u002F where the registration data is stored, otherwise use sys_get_temp_dir()\n        $this->checkRegistryRefreshEvent();\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch4>User Interface\u003C\u002Fh4>\n\u003Cp>Of course, the user interface is up to you, the developer, but you may look at (and maybe use) the registration UI trait included  with \u003Cem>{eac}Doojigger\u003C\u002Fem> and used by \u003Cem>{eac}SoftwareRegistry\u003C\u002Fem> as an example.\u003C\u002Fp>\n\u003Cp>see:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>…\u002FTraits\u002FswRegistrationUI.trait.php in the eacDoojigger folder.\u003C\u002Fli>\n\u003Cli>…\u002FExtensions\u002Fclass.eacSoftwareRegistry_registration.extension.php in the eacSoftwareRegistry folder.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch4>See Also\u003C\u002Fh4>\n\u003Cul>\n\u003Cli>\n\u003Cp>\u003Ca href=\"https:\u002F\u002Fswregistry.earthasylum.com\u002Fsoftware-registration-server\u002F\" rel=\"nofollow ugc\">{eac}SoftwareRegistry – Software Registration Server\u003C\u002Fa>\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Ca href=\"https:\u002F\u002Fswregistry.earthasylum.com\u002Fsoftware-registry-hooks\u002F\" rel=\"nofollow ugc\">{eac}SoftwareRegistry Custom Hooks\u003C\u002Fa>\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Copyright\u003C\u002Fh3>\n\u003Ch4>Copyright © 2019-2025, EarthAsylum Consulting, distributed under the terms of the GNU GPL.\u003C\u002Fh4>\n\u003Cp>This program is free software: you can redistribute it and\u002For modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\u003C\u002Fp>\n\u003Cp>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\u003C\u002Fp>\n\u003Cp>You should receive a copy of the GNU General Public License along with this program. If not, see \u003Ca href=\"https:\u002F\u002Fwww.gnu.org\u002Flicenses\u002F\" rel=\"nofollow ugc\">https:\u002F\u002Fwww.gnu.org\u002Flicenses\u002F\u003C\u002Fa>.\u003C\u002Fp>\n","{eac}SoftwareRegistry Distribution SDK for the Software Registration Server - Implementing the Software Registry SDK Package.",2388,"2025-07-25T15:37:00.000Z","6.8.5","5.8","7.4",[56,115,116,117,118],"registration-api","software-license","software-registration","software-registry","https:\u002F\u002Fswregistry.earthasylum.com\u002Fsoftware-registry-sdk\u002F","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Feacsoftwareregistry-distribution-sdk.1.1.3.zip",100,{"slug":123,"name":124,"version":125,"author":126,"author_profile":127,"description":128,"short_description":129,"active_installs":130,"downloaded":131,"rating":132,"num_ratings":133,"last_updated":134,"tested_up_to":51,"requires_at_least":135,"requires_php":113,"tags":136,"homepage":142,"download_link":143,"security_score":144,"vuln_count":145,"unpatched_count":28,"last_vuln_date":146,"fetched_at":30},"facebook-for-woocommerce","Meta for WooCommerce","3.6.0","Facebook","https:\u002F\u002Fprofiles.wordpress.org\u002Ffacebook\u002F","\u003Cp>This is the official Meta for WooCommerce plugin that connects your WooCommerce website to Facebook, Instagram and WhatsApp. With this plugin, you can install the Facebook pixel, upload your online store catalog, enabling you to easily run dynamic ads and connect your WhatsApp Business account to automatically update customers about their orders.\u003C\u002Fp>\n\u003Cp>Marketing on Meta platforms helps your business build lasting relationships with people, find new customers, and increase sales for your online store. With this Facebook ad extension, reaching the people who matter most to your business is simple. This extension will track the results of your advertising across devices. It will also help you:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Maximize your campaign performance. By setting up the Facebook pixel and building your audience, you will optimize your ads for people likely to buy your products, and reach people with relevant ads on Facebook after they’ve visited your website.\u003C\u002Fli>\n\u003Cli>Find more customers. Connecting your product catalog automatically creates carousel ads that showcase the products you sell and attract more shoppers to your website.\u003C\u002Fli>\n\u003Cli>Generate sales among your website visitors. When you set up the Facebook pixel and connect your product catalog, you can use dynamic ads to reach shoppers when they’re on Facebook with ads for the products they viewed on your website. This will be included in a future release of Meta for WooCommerce.\u003C\u002Fli>\n\u003Cli>Engage with customers on WhatsApp by updating your customers about their orders at every step, freeing up more time for you to focus on your business.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Support\u003C\u002Fh3>\n\u003Cp>Before raising a question with Meta Support, please first take a look at the Meta \u003Ca href=\"https:\u002F\u002Fwww.facebook.com\u002Fbusiness\u002Fhelp\" rel=\"nofollow ugc\">helpcenter docs\u003C\u002Fa>, by searching for keywords like ‘WooCommerce’ here. If you didn’t find what you were looking for, you can go to \u003Ca href=\"https:\u002F\u002Fwww.facebook.com\u002Fbusiness-support-home\" rel=\"nofollow ugc\">Meta Direct Support\u003C\u002Fa> and ask your question.\u003C\u002Fp>\n\u003Cp>When reporting an issue on Meta Direct Support, please give us as many details as possible.\u003Cbr \u002F>\n* Symptoms of your problem\u003Cbr \u002F>\n* Screenshot, if possible\u003Cbr \u002F>\n* Your Facebook page URL\u003Cbr \u002F>\n* Your website URL\u003Cbr \u002F>\n* Current version of Facebook-for-WooCommerce, WooCommerce, WordPress, PHP\u003C\u002Fp>\n\u003Cp>To suggest technical improvements, you can raise an issue on our \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ffacebook\u002Ffacebook-for-woocommerce\u002Fissues\" rel=\"nofollow ugc\">Github repository\u003C\u002Fa>.\u003C\u002Fp>\n","Get the Official Meta for WooCommerce plugin for powerful ways to help grow your business.",500000,48379215,44,474,"2026-03-12T09:56:00.000Z","5.6",[137,138,139,140,141],"catalog-sync","conversions-api","facebook","meta","whatsapp","https:\u002F\u002Fgithub.com\u002Fwoocommerce\u002Ffacebook-for-woocommerce\u002F","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ffacebook-for-woocommerce.3.6.0.zip",93,3,"2025-10-29 00:00:00",{"attackSurface":148,"codeSignals":176,"taintFlows":332,"riskAssessment":366,"analyzedAt":375},{"hooks":149,"ajaxHandlers":172,"restRoutes":173,"shortcodes":174,"cronEvents":175,"entryPointCount":28,"unprotectedCount":28},[150,156,159,162,165,169],{"type":151,"name":152,"callback":153,"file":154,"line":155},"action","admin_notices","displayCloningIsForbiddenNotice","Controllers\\class.MainController.php",64,{"type":151,"name":152,"callback":157,"file":154,"line":158},"displayUnserializingIsForbiddenNotice",77,{"type":151,"name":152,"callback":160,"file":154,"line":161},"displayPhpVersionRequirementNotice",178,{"type":151,"name":152,"callback":163,"file":154,"line":164},"displayWPVersionRequirementNotice",187,{"type":151,"name":166,"callback":167,"file":154,"line":168},"admin_menu","loadAdmin",214,{"type":151,"name":152,"callback":170,"file":154,"line":171},"displaySessionsAreDisabledInServerNotice",263,[],[],[],[],{"dangerousFunctions":177,"sqlUsage":178,"outputEscaping":180,"fileOperations":28,"externalRequests":61,"nonceChecks":28,"capabilityChecks":28,"bundledLibraries":331},[],{"prepared":28,"raw":28,"locations":179},[],{"escaped":181,"rawEcho":182,"locations":183},68,78,[184,187,189,191,193,195,198,200,203,205,207,209,211,214,216,218,221,223,225,227,229,231,233,235,237,239,240,241,243,245,247,249,251,253,255,256,258,259,261,263,265,267,268,270,271,273,274,276,278,280,281,283,285,286,288,289,290,292,293,295,297,299,301,303,304,306,308,310,312,313,315,317,319,321,323,325,327,330],{"file":154,"line":185,"context":186},88,"raw output",{"file":154,"line":188,"context":186},103,{"file":154,"line":190,"context":186},118,{"file":154,"line":192,"context":186},130,{"file":154,"line":194,"context":186},138,{"file":196,"line":197,"context":186},"Controllers\\class.SearchController.php",192,{"file":196,"line":199,"context":186},237,{"file":201,"line":202,"context":186},"Models\\class.AutoLoad.php",46,{"file":201,"line":204,"context":186},47,{"file":201,"line":206,"context":186},110,{"file":201,"line":208,"context":186},111,{"file":201,"line":210,"context":186},112,{"file":212,"line":213,"context":186},"Models\\class.EnvatoEdgeAPI.php",114,{"file":215,"line":190,"context":186},"Models\\class.EnvatoMarketAPI.php",{"file":215,"line":217,"context":186},329,{"file":219,"line":220,"context":186},"Templates\\template.SearchInput.php",12,{"file":219,"line":222,"context":186},20,{"file":219,"line":224,"context":186},32,{"file":219,"line":226,"context":186},49,{"file":219,"line":228,"context":186},58,{"file":219,"line":230,"context":186},67,{"file":219,"line":232,"context":186},72,{"file":219,"line":234,"context":186},81,{"file":219,"line":236,"context":186},86,{"file":219,"line":238,"context":186},95,{"file":219,"line":121,"context":186},{"file":219,"line":208,"context":186},{"file":219,"line":242,"context":186},116,{"file":244,"line":14,"context":186},"Templates\\template.SearchResults.php",{"file":244,"line":246,"context":186},11,{"file":244,"line":248,"context":186},18,{"file":244,"line":250,"context":186},21,{"file":244,"line":252,"context":186},22,{"file":244,"line":254,"context":186},23,{"file":244,"line":254,"context":186},{"file":244,"line":257,"context":186},24,{"file":244,"line":257,"context":186},{"file":244,"line":260,"context":186},35,{"file":244,"line":262,"context":186},38,{"file":244,"line":264,"context":186},39,{"file":244,"line":266,"context":186},40,{"file":244,"line":266,"context":186},{"file":244,"line":269,"context":186},41,{"file":244,"line":269,"context":186},{"file":244,"line":272,"context":186},51,{"file":244,"line":272,"context":186},{"file":244,"line":275,"context":186},52,{"file":244,"line":277,"context":186},53,{"file":244,"line":279,"context":186},62,{"file":244,"line":155,"context":186},{"file":244,"line":282,"context":186},65,{"file":244,"line":284,"context":186},66,{"file":244,"line":230,"context":186},{"file":244,"line":287,"context":186},76,{"file":244,"line":182,"context":186},{"file":244,"line":182,"context":186},{"file":244,"line":291,"context":186},79,{"file":244,"line":291,"context":186},{"file":244,"line":294,"context":186},80,{"file":244,"line":296,"context":186},87,{"file":244,"line":298,"context":186},89,{"file":244,"line":300,"context":186},91,{"file":244,"line":302,"context":186},92,{"file":244,"line":238,"context":186},{"file":244,"line":305,"context":186},104,{"file":244,"line":307,"context":186},106,{"file":244,"line":309,"context":186},108,{"file":244,"line":311,"context":186},109,{"file":244,"line":210,"context":186},{"file":244,"line":314,"context":186},123,{"file":244,"line":316,"context":186},124,{"file":244,"line":318,"context":186},125,{"file":244,"line":320,"context":186},134,{"file":244,"line":322,"context":186},135,{"file":244,"line":324,"context":186},136,{"file":244,"line":326,"context":186},141,{"file":328,"line":329,"context":186},"Views\\class.PageView.php",37,{"file":328,"line":282,"context":186},[],[333,356],{"entryPoint":334,"graph":335,"unsanitizedCount":354,"severity":355},"printContent (Controllers\\class.SearchController.php:26)",{"nodes":336,"edges":350},[337,341,345],{"id":338,"type":339,"label":340,"file":196,"line":206},"n0","source","$_POST",{"id":342,"type":343,"label":344,"file":196,"line":206},"n1","transform","→ getLicenseDetails()",{"id":346,"type":347,"label":348,"file":212,"line":213,"wp_function":349},"n2","sink","echo() [XSS]","echo",[351,353],{"from":338,"to":342,"sanitized":352},false,{"from":342,"to":346,"sanitized":352},1,"medium",{"entryPoint":357,"graph":358,"unsanitizedCount":354,"severity":355},"\u003Cclass.SearchController> (Controllers\\class.SearchController.php:0)",{"nodes":359,"edges":363},[360,361,362],{"id":338,"type":339,"label":340,"file":196,"line":206},{"id":342,"type":343,"label":344,"file":196,"line":206},{"id":346,"type":347,"label":348,"file":212,"line":213,"wp_function":349},[364,365],{"from":338,"to":342,"sanitized":352},{"from":342,"to":346,"sanitized":352},{"summary":367,"deductions":368},"The 'toolkit-for-envato' plugin v1.4 exhibits a generally positive security posture with no reported vulnerabilities (CVEs) and a seemingly limited attack surface. The static analysis shows no directly exploitable entry points like AJAX handlers, REST API routes, shortcodes, or cron events that are unprotected. Furthermore, the code does not utilize dangerous functions, performs file operations safely, and all identified SQL queries are properly prepared, which are strong indicators of secure coding practices. The absence of external HTTP requests is also a good sign, as these can often be points of exploitation. However, a significant concern arises from the taint analysis, which revealed two flows with unsanitized paths. While classified as low severity, unsanitized paths can lead to path traversal or file inclusion vulnerabilities if not handled carefully in the context of how these paths are used. Additionally, the output escaping is only properly handled in 47% of cases, suggesting a potential for Cross-Site Scripting (XSS) vulnerabilities if user-controlled data is outputted without sufficient sanitization.",[369,372],{"reason":370,"points":371},"Unsanitized paths in taint flows",6,{"reason":373,"points":374},"Low percentage of properly escaped output",7,"2026-03-16T18:05:00.244Z",{"wat":377,"direct":394},{"assetPaths":378,"generatorPatterns":385,"scriptPaths":386,"versionParams":387},[379,380,381,382,383,384],"\u002Fwp-content\u002Fplugins\u002Ftoolkit-for-envato\u002Fassets\u002Fcss\u002Fbootstrap.min.css","\u002Fwp-content\u002Fplugins\u002Ftoolkit-for-envato\u002Fassets\u002Fcss\u002Fenvato-toolkit-admin.css","\u002Fwp-content\u002Fplugins\u002Ftoolkit-for-envato\u002Fassets\u002Fjs\u002Fbootstrap.min.js","\u002Fwp-content\u002Fplugins\u002Ftoolkit-for-envato\u002Fassets\u002Fjs\u002Fenvato-toolkit-admin.js","\u002Fwp-content\u002Fplugins\u002Ftoolkit-for-envato\u002Fassets\u002Fjs\u002Fjquery.min.js","\u002Fwp-content\u002Fplugins\u002Ftoolkit-for-envato\u002Fassets\u002Fjs\u002Fjquery.validate.min.js",[],[382,384],[388,389,390,391,392,393],"toolkit-for-envato\u002Fassets\u002Fcss\u002Fbootstrap.min.css?ver=","toolkit-for-envato\u002Fassets\u002Fcss\u002Fenvato-toolkit-admin.css?ver=","toolkit-for-envato\u002Fassets\u002Fjs\u002Fbootstrap.min.js?ver=","toolkit-for-envato\u002Fassets\u002Fjs\u002Fenvato-toolkit-admin.js?ver=","toolkit-for-envato\u002Fassets\u002Fjs\u002Fjquery.min.js?ver=","toolkit-for-envato\u002Fassets\u002Fjs\u002Fjquery.validate.min.js?ver=",{"cssClasses":395,"htmlComments":398,"htmlAttributes":400,"restEndpoints":414,"jsGlobals":415,"shortcodeOutput":417},[396,397],"envato-toolkit-wrapper","envato-form",[399],"\u003C!-- ---------------------------------------------------------- -->",[401,402,403,404,405,406,407,408,409,410,411,412,413],"data-envato-username","data-envato-api-key","data-envato-personal-token","data-target-purchase-code","data-target-username","data-target-plugin-id","data-installed-plugin-version","data-target-theme-id","data-installed-theme-version","data-target-plugin-name","data-target-plugin-author","data-target-theme-name","data-target-theme-author",[],[416],"window.envatoToolkitAdmin",[]]