Skip to content

Instantly share code, notes, and snippets.

@DannyCooper
Last active February 10, 2024 18:50
Show Gist options
  • Save DannyCooper/a3fe77c34632535fa14b8f56ca13dc20 to your computer and use it in GitHub Desktop.
Save DannyCooper/a3fe77c34632535fa14b8f56ca13dc20 to your computer and use it in GitHub Desktop.
## Undocumented use of a 3rd Party or external service
You call LINK
While this is actually okay, you neglected to fully document this in your readme.
We require plugins that reach out to other services to disclose this, in clear and plain language, so users are aware of where data is being sent. This allows them to ensure that any legal issues with data transmissions are covered (like people in the EU). This is true even if YOU are the 3rd party service.
In order to do so, you must update your readme to do the following:
* clearly explain that your plugin is relying on a 3rd party as a service and under what circumstances
* provide a link to the service
* provide a link to the services’ a terms of use and/or privacy policies
Remember, this is for your own legal protection. The use of services must be upfront and well documented.
## Calling the admin URLs incorrectly
There's no need to hardcode /wp-admin/admin.php or any similar path into your plugin. WordPress has a function called admin_url() which will do this for you:
http://codex.wordpress.org/Function_Reference/admin_url
Please change your plugin to use that instead. It will be more sustainable in the long run and account for more configurations of WP.
## Registration on Installation/Activation
Registrations to your service MUST be an opt-in action taken SEPARATE of installation (and deactivation). Users often install plugins to look at them, and auto-registration is a privacy concern. You need to remove this. Either link users to your own site where they can register via an OAuth/API call or allow them to paste in API keys.
## Poorly Chosen Plugin Name
We cannot accept this plugin as is because your name needs to be fixed. Don’t worry! We can fix it, but we need your help.
The name you submitted was this: NAME
That created the slug of this: THIS
We recommend this slug instead: NEWSLUG
The reason for this is we have some requirements about plugin names, like you can’t include the word ‘plugin’ or ‘wordpress’ in them (it’s redundant after all), but also because names that are too long, or too short, or too generic are really annoying.
When a name is over 4 words, it's frustrating for users and developers alike and makes for an extremely poor experience. This is especially true of a plugin with stop words like 'a' or 'an' or 'the' or even 'by.'
Plugin names like 'cars' and 'users' aren’t permitted because their names are too generic. Try to use a better name like 'car organize' or 'user management' -- something that's more specific to the exact nature of your plugin. Generic plugin names are usually used to try and scam SEO.
Using special characters (ones that aren't [a-z][0-9]) in the name of your plugin is also a bad idea. By using characters outside the American English alphabet, you get VERY weird results on other sites, and it's just not something we support (code wise).
If you got all the way down here and forgot what to do next, just press reply to this email and tell us what slug you’d like. We can fix the plugin.
## Collecting User Data Without Consent
Per our guidelines (see section 7), we do not permit this as it's considered to be phoning home.
https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/
No unauthorized collection of user data. For example, sending the admin's email address back to your own servers without the permission of the user is not allowed; but asking the user for an email address and collecting if they choose to submit it is fine. All actions taken in this respect MUST be of the user's doing, not automatically done by the plugin.
Please remove this check from your plugin.
## Unsafe Requiring of Common Libraries
Since you're using a common library, it's important that you enqueue it safely.
Example(s):
EXAMPLE
Since that is a common library, you need to detect IF the code is already included and not re-include it, as doing so will cause conflicts if two people call the same defines and functions.
Please read these:
http://php.net/manual/en/function.class-exists.php
http://php.net/manual/en/function.function-exists.php
## Please do not imply full legal compliance
Sadly, no plugin in and of itself can provide absolute legal compliance. While a plugin can certainly assist in automating the steps on a compliance journey, or allow people to develop a workflow to solve the situation, they cannot protect a site administrator from mistakes or lack of compliance, nor can they protect site users from incorrect or incomplete legal compliance on the part of the web site.
We require you to edit your readme and make it clear that while your plugin can HELP people meet compliance requirements, they themselves must ensure that all requirements are met.
If you are providing a service that itself offers compliance, make sure it’s clear that the SERVICE is what is compliant, and not the plugin itself.
This is a requirement for your own protection and will help you reduce your personal liability for any claims or promises made by your plugin.
## Including Libraries Already In Core
Your plugin has included a copy of a library that WordPress already includes.
WordPress includes a number of useful libraries, such as jQuery, Atom Lib, SimplePie, PHPMailer, PHPass, and more. For security and stability reasons, plugins may not include those libraries in their own code, but instead must use the versions of those libraries packaged with WordPress.
While we do not YET have a decent public facing page to list all these libraries, we do have a list here: https://meta.trac.wordpress.org/browser/sites/trunk/api.wordpress.org/public_html/core/credits/wp-50.php (scroll to the bottom of the page)
## Including your own CURL code
WordPress comes with an extensive HTTP API that should be used instead of creating your own curl calls. It’s both faster and more extensive. It’ll fall back to curl if it has to, but it’ll use a lot of WordPress’ native functionality first.
https://developer.wordpress.org/plugins/http-api/
## Calling remote data
Your plugin is calling data remotely from another server that is not yours.
EXAMPLE
The exception to this rule is if your plugin is performing a service. We will permit this on a case by case basis, however since this can be confusing, we have some examples of what is not permitted:
* Inserting an iframe with a help doc - A link, or including the docs in your plugin is preferred.
* Calling images from your own domain - They should be included in your plugin.
* Calling content from Github - This creates an unnecessary dependency on another service that is not yours
Here are some examples of what we would permit:
* Calling font families from Google or their approved CDN (if GPL compatible)
* API calls back to your server to process possible spam comments (like Akismet)
* Offloading comments to your own servers (like Disqus)
* oEmbed calls to a service provider (like Twitter or YouTube)
Please remove this dependency from your plugin and, if possible, include all files within the plugin (that is not called remotely). If instead you feel you ARE providing a service, please re-write your readme.txt in a manner that explains the service, the servers being called, and if an account is needed to connect
## Errors on site when testing with WP_DEBUG
Please re-test your plugin with WP_DEBUG set to true. When we tested your plugin, it came up with numerous errors and alerts, which would cause problems for users.
We suggest you read this: http://codex.wordpress.org/WP_DEBUG
Also, you can install the WP Debug Bar on your test site - http://wordpress.org/plugins/debug-bar/ - in order to track down errors.
## Please use generic example defaults
Please use more generic defaults in your plugin. When you default to existing media or content, it often inadvertently causes people to have their sites displaying content they did not wish to show. You can have your code show http://example.com or your shortcode not display information, instead of forcing the display of content.
## Unchecked defines
You added a define in your plugin which is fine, but you've hardcoded without the ability for someone to change it. If you intend for your users to take advantage of this, you need to wrap it with a check to see if they already defined it like this:
if ( !defined( 'DEFINE_NAME' ) ) define( 'DEFINE_NAME', 'value' );
Keep in mind, defining constants should be kept to a bare minimum. They’re globals, after all.
Your code:
## Including demo folders
Your plugin is including demo folders for your third-party libraries. You really don't need to do this. The entire library isn't going to be used by your users, and having all those files included is just extra weight to a plugin. Please remove them and ONLY include the files you need.
## Please make sure your readme links to your development files
In general, we prevent plugins to include everything needed for future developers to fork and enhance the code. Realistically, this is impractical for many larger plugins, especially with the inclusion of the new Block Editor. Instead, we ask that developers make sure they link to their public development repositories, such as on Github, and provide instructions on how one might edit and build the code.
In this way, we are all good stewards of open source and encourage future developers to contribute.
## Allowing Direct File Access to plugin files
Direct file access is when someone directly queries your file. This can be done by simply entering the complete path to the file in the URL bar of the browser but can also be done by doing a POST request directly to the file. For files that only contain a PHP class the risk of something funky happening when directly accessed is pretty small. For files that contain procedural code, functions and function calls, the chance of security risks is a lot bigger.
You can avoid this by putting this code at the top of all php files:
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
## Please use wp_enqueue commands
Your plugin is using <style> and/or <link> tags to insert CSS/JS
You should be using the built-in functions for this:
https://developer.wordpress.org/reference/functions/wp_enqueue_script/
https://developer.wordpress.org/reference/functions/wp_enqueue_style/
And remember you can use this function to add inline javascript:
https://developer.wordpress.org/reference/functions/wp_add_inline_script/
If you're trying to enqueue on the admin pages you'll want to use the admin enqueues
https://developer.wordpress.org/reference/hooks/admin_enqueue_scripts/
https://developer.wordpress.org/reference/hooks/admin_print_scripts/
https://developer.wordpress.org/reference/hooks/admin_print_styles/
## Please don't mess with error reporting
While error_reporting() is a great tool in PHP (http://www.php.net/manual/en/function.error-reporting.php ) but if you set it permanently in your plugin, you mess things up for everyone who uses your code. Should they have a reason to try to debug their site which happens to use your code, they won't be able to get a clean test because you're messing with the output. It has no place in the day to day function of your plugin.
## Don’t use esc_ functions to sanitize
When sanitizing data, it’s important to use sanitization functions, not escape functions. The two work together, but are not interchangeable.
Functions like esc_attr() do NOT sanitize anything, and should never be used for that purpose.
The sole exception to this is URLs, which can use esc_url() or esc_url_raw() when being saved.
Please review this document for help finding the most appropriate sanitization functions: https://developer.wordpress.org/plugins/security/securing-input/
## Using Fancybox 2.0
It's required that all code be compatible with GPL to be included in our directory.
FancyBox v2 is not GPL compatible, as it has been licensed Creative Commons.
You may use FancyBox v1 and v3, but not v2.
If you cannot alter the code, we suggest you find alternate code that is GPL compatible and use that instead. For more information on what types of licenses are compatible with GPL, please review the following links:
http://www.gnu.org/licenses/license-list.html
http://www.gnu.org/licenses/gpl-faq.html#AllCompatibility
## Using file_get_contents on remote files
Many hosts block the use of file_get_contents on remote content. This is a security measure that we fully endorse.
Thankfully, WordPress comes with an extensive HTTP API that can be used instead. It’s fast and more extensive than most home-grown alternatives. It’ll fall back to curl if it has to, but it’ll use a lot of WordPress’ native functionality first.
https://developer.wordpress.org/plugins/http-api/
## Calling file locations poorly
The way your plugin is referencing other files is not going to work with all setups of WordPress.
When you hardcode in paths, or assume that everyone has WordPress in the root of their domain, you cause anyone using 'Giving WordPress it's own directory' (a VERY common setup) to break. In addition, WordPress allows users to change the name of wp-content, so you would break anyone who chooses to do so.
Please review http://codex.wordpress.org/Determining_Plugin_and_Content_Directories and update your plugin accordingly. And don't worry about supporting WordPress 2.x or lower. We don't encourage it nor expect you to do so, so save yourself some time and energy.
## Please use the anonymous CDN for Font Awesome
In 2016, Font Awesome introduced a new way to get their font library, via a URL like https://use.fontawesome.com/CUSTOMCODE.js
The problem with it is that it's tied to an individual's email, which means it's actually trackable. That can be a legal issue when it comes to disclosure of data and is something best avoided whenever possible. Not to mention, we don't allow tracking unless it's opt-in.
We need you to use the font-awesome anonymous CDN - https://www.bootstrapcdn.com/fontawesome/
## Your plugin is an uncredited fork for another
Despite the fact that all plugins in our directory are licensed under the GPL or compatible licenses, we do not allow direct copies of other plugins to be re-listed under somebody else's name. "Forking" is acceptable only when the resulting fork is of a substantial nature, or when the original plugin is no longer updated or supported.
While your plugin qualifies as a fork, you've stripped all credit/copyright information from the original. This is a copyright violation and we can't allow it.
Please restore the copyright information to the source files and credit the original author in your plugin's readme. In that way, you protect yourself from legal issues AND you're a good steward of the open source community.
## Your plugin has files that aren't compatible with GPL
It's required that all code be compatible with GPL to be included in our directory.
Please remove the code and alter the plugin so it is not required. If you cannot alter the code, we suggest you find alternate code that is GPL compatible and use that instead. For more information on what types of licenses are compatible with GPL, please review the following links:
http://www.gnu.org/licenses/license-list.html
http://www.gnu.org/licenses/gpl-faq.html#AllCompatibility
## Hardcoded plugin folder name
Your plugin won't work via our directory because you hardcoded in the plugin's folder. You've defined your plugin name like this:
EXAMPLE
Please read http://codex.wordpress.org/Function_Reference/plugins_url - you'll notice how we have a __FILE__ parameter used in most examples. If you change your plugin to use that, it will work no matter what the folder name is.
## There's a problem with your Plugin Headers
Without correct headers, a plugin will fail to be activated and updated properly, and can (and usually will) cause issues with other plugins.
In addition, putting plugin headers on any file other than the main plugin file will cause issues on uninstall and activation.
Please review https://developer.wordpress.org/plugins/the-basics/header-requirements/ and update your plugin accordingly, putting the headers in only the main file.
## HighCharts is not GPL compatible
It's required that all code be compatible with GPL to be included in our directory.
Highcharts and their add ons have been licensed Creative Commons.
Please remove HighCharts and alter the plugin so it is not required. If you cannot alter the code, we suggest you find alternate code that is GPL compatible and use that instead. For more information on what types of licenses are compatible with GPL, please review the following links:
http://www.gnu.org/licenses/license-list.html
http://www.gnu.org/licenses/gpl-faq.html#AllCompatibility
## Editing htaccess in a non-optimal way
Please consider using insert_with_markers() to edit .htaccess.
https://developer.wordpress.org/reference/functions/insert_with_markers/
It's more reliable.
## Don’t use variables or defines as text domain shortcuts
Please do NOT use variable names for the text domain portion of a gettext function.
For example, this is a bad shortcut: __( ‘Translate me.’ , $text_domain );
The text domain also needs to be added to the plugin header. WordPress uses it to internationalize your plugin meta-data even when the plugin is disabled. The text domain should be the same as the one used when loading the text domain.
If your plugin slug is wp-penfold-macrame, then your text domain should be the same.
You can read https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#text-domains for more information.
## Don’t use ‘if exists’ like a silver bullet
Using if (!function_exists(‘NAME ‘)) { around all your functions and classes sounds like a great idea until you realize the fatal flaw. What happens IF someone else has a function with the same name and their plugin or theme loads first?
Your plugin breaks. And that would suck. Please only use if-exists checks for SHARED libraries.
## Your admin dashboard has an iframe
Having the admin dashboard include an iframe isn't permitted.
We don't permit plugins to phone home like that (for two main reasons - security and appearance - too often people assume that they just signed into WORDPRESS and not your plugin). Please change your code to use an API or just link back to your site so they can configure things there.
## Calling images remotely
Offloading images to your own server is disallowed.
Please include all the images needed for your plugin locally.
## Installing another plugin/app
We currently do not permit plugins to install other plugins or 3rd party apps. The code has to be included in your plugin. It's fine to recommend another plugin be installed, but you can't do it for them.
## Isotope pre version 2.2 isn't GPL compatible
You've included Isotope, which has a commercial license that is not compatible with the GPL. The GPL stresses there are to be no further limitations on the use of the code, but Isotope requires users to pay for a commercial license. In addition, we cannot possibly enforce that requirement, and as such would be violating THEIR terms of use.
You can use version 2.2 and up of Isotope, however. Please change to that version.
## Including (or calling) javascript files included in WP core
Your plugin has included (or called it remotely, probably from Google or jquery.com) your own copy of a javascript file that WordPress already includes.
WordPress includes many common javascript files. In order to provide the best compatibility and experience for users, we do not permit the inclusion of those files in your plugin. Instead, we require you use the versions that come with WordPress.
To reiterate:
* DO NOT include your own copy of javascript files that are already included in WordPress Core
* DO NOT make remote calls to javascript files that are already included in WordPress Core
Please review the following link to understand how to properly include javascript, learn what files we provide out of the box, and update your plugin accordingly:
https://developer.wordpress.org/reference/functions/wp_enqueue_script/
It’s fine to locally include add-ons that are not in core, but please ONLY add those additional files. You do not need the whole jquery UI library for one file.
If your code doesn't work with the built-in versions of jQuery, it's most likely a noConflict issue.
## Hardcoded your public and/or private keys
You shouldn't do that. For security, those keys MUST be per-user. Otherwise, you have access to their data, and that's not okay.
Your public key is actually a username. It is an alphanumeric text string that uniquely identifies the user who owns the account. No two accounts can have the same Public (aka Access) Key.
Your SECRET key plays the role of a password. It's called secret because it is assumed to be known by the owner only. That's why, when you type it in the given box on Amazon or Dropbox, it's displayed as asterisk or dots. A Password with Access Key forms a secure information set that confirms the user's identity. App APIs tell you to keep your Secret Key in a safe place.
Please change those codes to something the user is required to enter themselves, and not default to your own keys. If the vendor requires you use specific keys, please provide documentation (links to their website are best) to explain this.
## Making license checks
We do not permit plugins to phone home for license validation unless the plugin is providing a service that cannot be completed on the user's server.
For example, a plugin like Akismet is processing spam on their own servers and passing the data back to the users via an API. This is a service.
On the other hand, a plugin that simply validates a license and 'unlocks' functionality that's already in the plugin is not a service.
This is explained in more detail in our guidelines - https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/ - under “5. Trialware is not allowed in the directory.”
Please remove the license check from your plugin. Alternately, you may provide more information as to how you are providing a service. Remember. The service needs to be running from an external server.
## No Line Breaks
For some reason, your code came to us all as one line. We need you to use line breaks for readability in your code. We feel that to make your code human-unreadable is in violation of the directory guidelines, found at: https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/
In specific, the fourth guideline, which reads: "4. No obfuscated code."
Please use Linux friendly line breaks in your code.
## Hidden/Shortened 3rd party Links
While we permit plugins to link back to pro versions, required plugins, or affiliates, we require that all such links be obvious. By this we mean don’t use URL shorteners like bit.ly
In addition, don’t track users by using your own URLs like example.com/jetpack that would pass through your server. Doing that is a violation of our guidelines. Please use the direct links to any and all affiliates.
The exception to this is if you’re linking to your own services via your own shorteners. In all cases, the use of tinyurl, bit.ly, and similar services is to be avoided.
## Calling core loading files directly
Including wp-config.php, wp-blog-header.php, wp-load.php, or pretty much any other WordPress core file that you have to call directly via an include is not permitted.
These calls are prone to failure as not all WordPress installs have the exact same file structure. In addition it opens your plugin to security issues, as WordPress can be easily tricked into running code in an unauthenticated manner.
Your code should always exist in functions and be called by action hooks. This is true even if you need code to exist outside of WordPress. Code should only be accessible to people who are logged in and authorized, if it needs that kind of access. Your plugin's pages should be called via the dashboard like all the other settings panels, and in that way, they'll always have access to WordPress functions.
If you need to have a ‘page’ accessed directly by an external service, you should use query_vars and/or rewrite rules to create a virtual page which calls a function.
Please consult the Plugins API reference for more information: http://codex.wordpress.org/Plugin_API
If you're trying to use AJAX, please read this: http://codex.wordpress.org/AJAX_in_Plugins
For other possibilities, or to better understand why we disallow this, read this: http://ottopress.com/2010/dont-include-wp-load-please/
## Your plugin is still calling localhost related information
It looks like you may have forgotten to clean up some test information, as your plugin is still referring to local information. Please make sure you clean that up so the plugin will work for everyone.
## Missing files
Your plugin is missing files called for in the code. This may be from Github (which has a habit of not including submodules in its downloadable zips). Please double check the file you sent us and make sure it's got all the content.
## Using mkdir and chmod
Instead of using mkdir and chmod, which won’t exist on non-unix systems and are fraught with security concerns, please use wp_mkdir_p(), which will create a folder AND set permissions properly.
https://developer.wordpress.org/reference/functions/wp_mkdir_p/
## We cannot accept your plugin with this name
Your autogenerated plugin slug was this: XXXX
Since you don’t appear to legally represent that group, we need to change the plugin slug.
We recommend the following: XXXXXX
You also need to change the display name to not BEGIN with that term.
We're no longer accepting plugins that begin with (or are in total) a trademarked product name or term as the name or slug of a plugin (ex: Facebook or google-maps-bathrooms). Nor are we accepting plugins that include the name of another plugin at the beginning of the name/slug (eg: contact-form-7-music), unless you LEGALLY represent that service/plugin/theme/etc.
Please reply to this email with what slug you’d like. We’ll edit it slug for you.
You DO NOT need to edit your code for this review (although you will want to correct the text-domain for our translation service to function properly). ALL we need is to be on the same page for the plugin slug :)
If we’re wrong and you DO work for the company, we either need you either prove this or provide an OFFICIAL company account to own this plugin.
Keep in mind, if you were hired as a freelance developer or a consultant by the company to create this plugin, then they must own the plugin. This is for their legal protection as well as yours. They can give your account access, but anything official MUST be owned by the company, not a temp-employee.
If you got all the way down here and forgot what to do next, just reply to this email and tell us what slug you’d like, or if you need to transfer the plugin to a different account. We can fix the plugin.
DO NOT resubmit this plugin as a new account, though, you’ll just make everything messier.
Some helpful links:
* https://developer.wordpress.org/plugins/wordpress-org/plugin-developer-faq/#what-if-i-submitted-the-plugin-with-the-wrong-user-id
## Renaming JS files
Generally when you include a JS library, like Fancybox or Jquery UI add-ons, you should not combine and rename them.
Renaming files, or enqueuing them with your own unique names (like ‘myplugin-jquery-ui’), may cause WordPress to download the same javascript file multiple times when a user visits a site running your plugin. This makes sites slower, caching less effective, and is generally a worse experience for people.
Please, don’t rename or combine javascript files. If your code requires multiple files, then use wp_enqueue_scripts() and flag things as dependencies. That will ensure users have an optimum experience with your plugin.
## Running submission checks outside a function
Your plugin is checking for post submission outside of functions. This is a bad idea, as it means the check runs on every single load of the plugin, which generally is every page. This makes your code slow and unwieldy for users on any high-traffic site, and can cause instability and crashes.
Please properly used the settings API - https://developer.wordpress.org/plugins/settings/settings-api/ - whenever possible, and if you cannot, please protect your code within a function that checks for and validates user permissions and nonces.
## Not using Nonces and/or checking permissions
Please add a nonce to your POST calls to prevent unauthorized access.
Keep in mind, check_admin_referer alone is NOT bulletproof security. Do not rely on nonces for authorization purposes. Use current_user_can() in order to prevent users without the right permissions from accessing things.
https://developer.wordpress.org/plugins/security/nonces/
## Calling files remotely
Offloading images, js, css, cgi, and other scripts to Google (or jquery.com or anywhere else frankly) is disallowed because you're introducing an unnecessary dependency on another site. If the file you're trying to use isn't a part of WordPress Core, then you should include it -locally- in your plugin, not remotely. If the file IS included in WordPress core, please call that instead.
The one exception to this rule is if your plugin is performing a service. We will permit this on a case by case basis, however since this can be confusing, we have some examples of what are not permitted:
* Offloading jquery CSS files to Google - You should include the CSS in your plugin.
* Inserting an iframe with a help doc - A link, or including the docs in your plugin is preferred.
* Calling images from your own domain - They should be included in your plugin.
Here are some examples of what we would permit:
* Calling font families from Google or their approved CDN (if GPL compatible)
* API calls back to your server to process possible spam comments (like Akismet)
* Offloading comments to your own servers (like Disqus)
* oEmbed calls to a service provider (like Twitter or YouTube)
Please remove this dependency from your plugin and, if possible, include all files within the plugin (that is not called remotely). If instead you feel you ARE providing a service, please re-write your readme.txt in a manner that explains the service, the servers being called, and if an account is needed to connect.
## You're using an out of date library
One of the 3rd party libraries you're using is out of date. Please upgrade to the latest version for supportability and security.
## Encrypted code
Using encryption methods like base64() or p,a,c,k,e,r to hide your code or otherwise make it human-unreadable is in violation of the directory guidelines, found at: https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/
In specific, the fourth guideline, which reads: "4. No obfuscated code."
This also includes using phar to compress your PHP and making all your PHP mashed into one line.
It's fine to compress your code and minify, but it's not okay to hide it. All code must be human readable for inclusion in this directory.
## Phoning Home
We do not permit plugins to phone home to your own server unless they're acting as a service.
For example, a plugin like Akismet is processing spam on their own servers, and passing the data back to the users via an API. This is a service.
On the other hand, a plugin that simply validates a license and 'unlocks' functionality that's already in the plugin is not a service.
Similarly, if you have your plugin send an email or message to your own servers when the plugin is installed and/or uninstalled, this is patently nor permitted.
This is explained in more detail in our guidelines ( https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/ ) under "Serviceware"
Please remove any calls back to your own server from the plugin. Alternately, you may provide more information as to how you are providing a service. Remember. The service needs to be running from an external server.
## Using Placeholders
Using placeholder services like placehold.it or placekitten.com in your plugin is generally a bad idea unless that's the point of the plugin. Introducing an unnecessary dependency on an external service can have adverse impact on your plugin. Should the service be unavailable, you will cause the site to be slower. Instead, you should include the images locally.
This is especially true of any images used on wp-admin. They should always be local.
## Powered By / credit links
We do not permit plugins to insert Powered By attribution in plugins on any front-facing aspect of the site, without the user's express permission. This includes credits, be they links or not, powered by attribution, css-hidden links, or any other advertising whatsoever.
You are permitted to have an HTML comment, or to have the attribution be opt-in, however we're serious about Opt IN. This means the user must check a box to indicate that yes, they want to show the credit on their site. Under no circumstances are you permitted to display the attribution without permission.
The sole exception to this rule is service ware (such as Twitter, Disqus, or YouTube), which includes the attribution on their own site, not in the plugin.
## Generic function (and/or define) names
All plugins must have unique function names, namespaces, defines, and classnames. This prevents your plugin from conflicting with other plugins or themes. We need you to update your plugin to use more unique and distinct names.
A good way to do this is with a prefix. For example, if your plugin is called "Easy Custom Post Types" then you could use names like these:
function ecpt_save_post()
define( ‘ECPT_LICENSE’, true );
class ECPT_Admin{}
namespace EasyCustomPostTypes;
Don't try to use two-letter slugs anymore. We have over 60 THOUSAND plugins on WordPress.org alone, you’re going to run into conflicts.
Similarly, don't use __ (double underscores), wp_ , or _ (single underscore) as a prefix. Those are reserved for WordPress itself. You can use them inside your classes, but not as stand-alone function.
Remember: Good names are unique and distinct. This will help you and the next person in debugging, as well as prevent conflicts.
Some examples from your plugin:
## No Frameworks Accepted
At this time, we are no longer accepting frameworks, boilerplates, and libraries as stand-alone plugins.
Yes, we used to.
We’re not deleting all the existing ones so we don’t break people’s sites, but we aren’t accepting any NEW ones. This has nothing to do with the quality or purpose of your code. Most of us on the team are fans of libraries and frameworks.
We do generally require that plugins be useful in and of themselves (even if only being a portal to an external service). And while there are many benefits to frameworks and libraries, we lack any plugin dependency support in core or the directory.
In short, if your plugin has to require other plugins or themes to edit themselves in order to use your plugin, it's a library. If your plugin is a template for which more code can be built, it's a framework or boilerplate.
The parade of likely support issues:
* Not recognizing the need for the plugin, and thus deleting it (causing others to break)
* Not recognizing the plugin and thinking they’ve been hacked
* Updating the plugin separately from the dependent plugins, leading to breakage
* Updating a dependent plugin without updating yours, leading to breakage
* Different plugins requiring different versions of your plugin
And bearing in mind that the framework and plugin developers are different people, that’s another level of coordination/compatibility issues.
We feel that frameworks and libraries should be packaged with each plugin (hopefully in a way that doesn’t conflict with other plugins using the framework or libraries). At least until core supports plugin dependencies.
If you feel this was in error, please reply to this email with your plugin attached as a zip and explain why you feel your plugin should be an exception.
## Generic Rejection
At this time, we are not accepting plugins of this nature.
Plugins that reproduce features that are already included in WordPress, without any perceivable additions, such as (but not limited to) duplication of existing shortcodes ([embed] and [gallery]), widgets (RSS feed display), or functionality (adding users), will not be accepted.
We do not permit plugins that we feel to be unethical, such as black or grey hat SEO (including plugins that auto post content). Any plugin related to claims like 'Our plugin will help you earn thousands of dollars' will be rejected, as that behavior is scummy and unwelcome.
Plugins with obfuscated (i.e. hidden or encrypted) code will never be accepted.
While the directory is open for all secure, GPLv2 (or later) compatible plugins, we reserve the right to reject any plugin on any grounds we feel are reasonable, whether or not they are explicitly noted in the guidelines.
If you feel this was in error, please reply to this email with your plugin attached as a zip and explain why you feel your plugin should be an exception.
## We require you to include or link to your developer libraries
In order to comply with our guidelines of human-readable code, we require you to include a link to the non-compressed, developer libraries you’ve included in your plugin. This may be in your source code, however we recommend having it in your readme.
https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/#4-code-must-be-mostly-human-readable
We strongly feel that one of the strengths of open source is the ability to review, observe, and adapt the code. By maintaining a public directory of freely available code, we encourage and welcome future developers to engage with WordPress and push it forward.
However with the advent of larger and larger plugins using more complex libraries, people are making proper use of build tools (such as npm) to generate their distributed production code. In order to balance the need to keep plugin sizes smaller while still encouraging open source development, we will be requiring plugins to make the source code to any compressed files available.
For example, if you’ve made a Gutenberg plugin and used npm and webpack to compress and minify it, you must either include the source code within the published plugin or provide access to a public maintained source that can be reviewed, studied, and yes, forked.
We strongly recommend you include directions on the use of any build tools to encourage future developers.
## Incomplete Readme
Plugins that send data to other servers, call js from other servers, and/or require passwords and APIs to function are required to have a full and complete Readme so we can make sure you're providing the users with all the information they need before they install your plugin. Our goal with this is to make sure everyone knows what they're installing and what they need to do before they install it. No surprises.
This is especially important if your plugin is making calls back to your own servers. For the most part, we do not permit the offloading of images or code, however in the case where you are providing a service (like Disqus or Akismet or Twitter), we permit it. The catch is you have to actually explain this to the layman in your read me, so they know where data is going.
Your readme MUST validate per http://wordpress.org/plugins/about/validator/ or we will reject it. Keep in mind, we don't want to see a readme.MD. Among other things, the formatting for markup is different, and the filetype isn't read by our system. (And if you're thinking "Hey, I did submit a read me!" then it's likely we felt it wasn't informative enough.)
Please create your readme one based on this: https://wordpress.org/plugins/readme.txt
Please send a link so that the completed plugin can be downloaded. Alternately you can reply to this and send a .zip file. Note: We would like you to send the whole plugin, not just the read me, as we will re-review your entire code as a whole.
## Please sanitize, escape, and validate your POST calls
When you include POST/GET/REQUEST/FILE calls in your plugin, it's important to sanitize, validate, and escape them. The goal here is to prevent a user from accidentally sending trash data through the system, as well as protecting them from potential security issues.
SANITIZE: Data that is input (either by a user or automatically) must be sanitized. This lessens the possibility of XSS vulnerabilities and MITM attacks where posted data is subverted.
VALIDATE: All data should be validated as much as possible. Even when you sanitize, remember that you don’t want someone putting in ‘dog’ when the only valid values are numbers.
ESCAPE: Data that is output must be escaped properly, so it can't hijack admin screens. There are many esc_*() functions you can use to make sure you don't show people the wrong data.
To help you with this, WordPress comes with a number of sanitization and escaping functions. You can read about those here:
* https://developer.wordpress.org/plugins/security/securing-input/
* https://developer.wordpress.org/plugins/security/securing-output/
Remember: You must use the MOST appropriate functions for the context. If you’re sanitizing email, use sanitize_email(), if you’re outputting HTML, use esc_html(), and so on.
Clean everything, check everything, escape everything, and never trust the users to always have input sane data.
Some examples from your plugin:
## Forcing PHP Sessions on all pages
Using session_start() or ob_start() in your plugin without having it encapsulated in a function means that it will run on every single page load when your plugin is active. Sadly the way PHP Sessions work is they indicate the visitor using sessions is unique and should have a non-cached view of the website.
That means the use of sessions breaks server-based caching such as nginx and Varnish. Those types of services are heavily used by managed WordPress hosts, which means your plugin may wind up prohibited on those hosts.
We would greatly prefer that not to happen for you, as it could be detrimental to your plugin’s adoption and user base.
Please remove this from your plugin, or put it only in the function that absolutely must have it.
If you cannot remove it, then you are required to document that use of your plugin may conflict with server-based cache services, and you cannot support its use on those servers.
This is for your own protection.
## PHP Short Tags
The primary issue with PHP's short tags is that PHP managed to choose a tag (<?) that was used by another syntax, XML.
With the option enabled, you weren't able to raw output the xml declaration without getting syntax errors:
<?xml version="1.0" encoding="UTF-8" ?>
This is a big issue when you consider how common XML parsing and management is.
While as of PHP 5.4, <?= ... ?> tags are supported everywhere, regardless of short tags settings. This should mean they're safe to use in portable code but that does mean there's then a dependency on PHP 5.4+. If you want to support pre-5.4 and can't guarantee short tags, you'll still need to use <?php echo ... ?>.
At this time, we ask that no plugin use PHP short tags, for sanity.
## Unsafe SQL calls
When making database calls, it's highly important to protect your code from SQL injection vulnerabilities. You need to update your code to use prepare() with your queries to protect them.
Please review the following:
* http://codex.wordpress.org/Class_Reference/wpdb#Protect_Queries_Against_SQL_Injection_Attacks
* http://codex.wordpress.org/Data_Validation#Database
* http://make.wordpress.org/core/2012/12/12/php-warning-missing-argument-2-for-wpdb-prepare/
* http://ottopress.com/2013/better-know-a-vulnerability-sql-injection/<
## Improper use of tags
Plugins are not permitted to use more than 12 tags in their readme. In addition, they are not to include the tags of their competition. In doing so, you're seen as trying to game the system.
Remove any 'common misspellings' from your tag list as well as any duplicates. They do not help your results in our search engine.
Also please remove any tags that relate to your competition. That’s not what tags are for. Tag what your plugin DOES and IS, not what it isn’t.
Make the readme for people, not for machines, and it will help you rank higher in the search results.
## Text domain and slug do not match
Text domain: XXXX
Plugin Slug: XXXX
In order for your plugin to work properly with WordPress’ translation system, your text domain AND the plugin slug have to match.
https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#text-domains
We can change your slug for you, but there are limits to what we can use for your plugin slug. You need to tell us if the slug should be changed, otherwise it will remain as is, and you should correct your code before uploading to SVN.
## Including unit tests
Your plugin is including the unit test folders for your code. While it's awesome you're testing, you must remove those when you submit your plugin (and not include them when you upload to wordpress.org) because they're not something that users need. Also many of them call wp-load directly, which is not secure for public code.
## Including the default ThemeForest license
You’ve included the default license from ThemeForest. The problem is that the license is a split-license. It allows you to release a plugin as GPL and NON-GPL. That’s what this statement means:
&gt; (2) All other parts, but not limited to the CSS code, images,
&gt; and design are licensed according to the terms of your purchased
&gt; license.
Please remove that license file, as well as any code included in your plugin which is NOT GPLv2 or later compatible.
## Including files called from a theme directory
You should never call files from a specific theme directory, nor from the get_template_directory_uri() as the files may not exist in the theme. Instead, please call all files locally from within the plugin itself.
## Setting a default timezone
This is rarely a good idea. People should be able to define their own timezones in WordPress.
Also WordPress explicitly sets and expects the default timezone to be UTC (in settings.php) and the date/time functions sometimes rely on the fact that the default timezone is UTC. For instance if you do date_default_timezone_set(get_option('timezone_string')) and then later try to get a GMT timestamp from get_post_time() or get_post_modified_time(), it will fail to give you the right date.<
## Using TimThumb is not permitted
We no longer accept using TimThumb in the directory.
TimThumb is no longer supported or maintained. You can read the reasons why at http://www.binarymoon.co.uk/2014/09/timthumb-end-life/
Please consider other options.
## Tracking Users
We do not permit plugins to track users of their code without the tracking being 100% optional, and turned OFF by default. We feel strongly about the privacy of plugin users, and by that standard, they should not have their actions recorded.
Read https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/ to be fully praised of our guidelines.
Please either remove the code for tracking or change to be an opt-in feature of your code.
## Trialware is not permitted
Trialware is not allowed in the directory.
It's perfectly fine to attempt to upsell the user on other products and features, but a) not in an annoying manner and b) not by disabling functionality after some time period. Similarly, you cannot "cripple" functionality in the plugin and then ask for payment or provide a code to unlock the functionality.
All code hosted by WordPress.org servers must be free and fully-functional. If you want to sell advanced features for a plugin (such as a "pro" version), then you must sell and serve that code from your own site, we will not host it on our servers.
This means you also cannot have a license that checks if someone is using your plugin and, after X days, disable it for non-purchasing. That does not make you a service, and violates both the trialware and license check guidelines found here: https://wordpress.org/plugins/about/guidelines/
## Not calling uninstall safely
Please secure your uninstall code. Please review the following links and make sure you're not letting unauthorized users access the uninstall command, and that you're allowing it to be called on an actual uninstall.
* https://developer.wordpress.org/reference/functions/register_uninstall_hook/
* https://developer.wordpress.org/plugins/the-basics/uninstall-methods/
## Including your own update checker
Please remove the checks you have in your plugin to provide for updates.
We do not permit plugins to phone home to other servers for updates, as we are providing that service for you with WordPress.org hosting. One of our guidelines is that you actually use our hosting, so we need you to remove that code.
## Using Uploadify
Your plugin calls Uploadify which we no longer permit due to license issues, security problems, and a lack of support.
We recommend you use the built-in WordPress media functionality for uploading files.
https://developer.wordpress.org/reference/functions/wp_handle_upload/
## Use of a trademark in your domain
Did you know that trademarks extend to URLs as well?
It's a trademark violation to include 'google' or 'paypal' or even 'wordpress' in your TLD. It's fine as a subdomain, but the use of a trademark in your TLD is only permitted in specific cases like satire, parody, criticism, news gathering &amp; social commentary value, etc.
Regarding 'wordpress' specifically: http://wordpress.org/about/domains/
We need you to do the following:
1) Change your domain name
2) Update the plugin files (including readme) with the new URL
3) Update your user account (including email) to use the new domain
## Not checking for user permissions
Use current_user_can() in order to prevent users without the right permissions from accessing things. Please make sure your plugin does not allow people who should not be accessing settings (i.e. non-admins) from being able to do so.
## Including full vendor folders
Your plugin includes the vendor folders (like Bower or Node folders). You really don't need to do this. The entire library isn't going to be used by your users, and having all those files included is just extra weight to a plugin. Please remove them and ONLY include the files you need.
## Including another plugin
We cannot accept a plugin that includes an entire other plugin, wholesale, inside it UNLESS the plugin has been specifically written to be used AS an included framework.
While we understand the use of framework (or boilerplate) plugins, and encourage the use of common libraries, full-blown plugins should never be included inside another, as it causes multiple potential issues, such as function/attribute conflicts, and also opens your code up for issues should the included plugin be closed for a security hole.
If the plugin exists in WordPress.org already then the proper way to include another plugin would be to require it in your own. You can use the hook is_plugin_active() to check to see if the plugin is, indeed, installed and active: https://codex.wordpress.org/Function_Reference/is_plugin_active
Some libraries (like Titan Framework) have cleverly included their own requirement checker. Other libraries (like CMB2) have an alternate install version that checks for the presence of an updated version of their full plugin. Sadly there isn't a one PERFECT answer for including a library that happens to be a plugin.
If the included plugin does NOT check for its own existence, you need to detect IF the code is already included and not re-include it, as doing so will cause conflicts if two people call the same defines and functions. Please review the following links:
* http://php.net/manual/en/function.class-exists.php
* http://php.net/manual/en/function.function-exists.php
Keep in mind, including another plugin means you MUST remove their plugin headers. Period. Failing to do so causes issues on uninstall and activation.
Either way, an entire copy of a plugin that already exists in the directory is not permitted.
## Calling Woo 'scripts' needlessly
Anytime your plugin includes a call to something like this:
if (!function_exists('woothemes_queue_update'))
require_once('woo-includes/woo-functions.php');
And those woo functions include calls to woothemes_queue_update or woothemes_updater_install, you've followed the wrong directions on how to PROPERLY verify if woo is installed and active.
Please review https://docs.woocommerce.com/document/create-a-plugin/ which explains how to correctly check for that
## Asks users to edit/writes to plugin
We cannot accept a plugin that forces (or tells) users to edit the plugin files in order to function, or saves data in the plugin folder.
Plugin folders are deleted when upgraded, so using them to store any data is problematic.
Please change your plugin to save those files outside of the plugins folder (in wp-content/pluginname perhaps or wp-content/uploads/pluginname - which would make it work well with multisite, making sure you read http://codex.wordpress.org/Determining_Plugin_and_Content_Directories to understand where the folders are and how best to call them), or if possible, save data to the wp_options tables.
## You're the 3rd Party
Actually, you are the 3rd party service.
See the first party is the user. The second party is WordPress. The 3rd party is any service your plugin calls. So even when you’re the service you STILL have to document this clearly for your own protection. We don’t want someone to sue you, after all.
## Including a zip file
We do not permit plugins to include zip files.
Yours includes EXAMPLE
This was probably an oversight, but please remove it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment