Skip to content

Resolve issues reported by WPORG plugin review #110

@jeffpaul

Description

@jeffpaul

Description

The below items have been flagged during the plugin review, let's look to get those resolved or identify a response to the WPORG Plugin Team on why we view them a non-issue. I've amended some of the feedback to remove some specific, personal references but have left all necessary feedback items we need to work through.

Once we resolve all issues, we'll also want to:

  • Test the updated plugin on a clean WordPress installation with WP_DEBUG set to true.
  • Go to "Add your plugin" and upload the updated version.
  • @jeffpaul to reply to the WPORG Plugin Team email with concise clarifications or important context that the team needs to know.

Step-by-step reproduction instructions

Review: Missing permission_callback in REST API Route

When using register_rest_route() or wp_register_ability() to define custom REST API endpoints, it is crucial to include a proper permission_callback.

🔒 This callback function ensures that only authorized users can access or modify data through your endpoint.

Code example, checking that the user can change options:

register_rest_route( 'ai/v1', '/my-endpoint', array(
    'methods' => 'GET',
    'callback' => 'ai_callback_function',
    'permission_callback' => function() {
        return current_user_can( 'manage_options' );
    }
) );

Please check the register_rest_route() documentation and the current_user_can() documentation.

✅ When a permission_callback is NOT Required:

There are valid use cases for public endpoints, such as publicly available data (e.g., posts, public metadata) or endpoints designed for unauthenticated access (e.g., fetching public stats or information).

In these cases, you should use __return_true as the permission_callback to indicate that the endpoint is intentionally public.

🔒 When a permission_callback IS Required:

For endpoints that involve sensitive data or actions (e.g., getting not public data, creating, updating, or deleting content).

In these cases, you should always implement proper permission checks.

Possible cases found on this plugin's code:

includes/Experiments/Title_Generation/Title_Generation.php:54 wp_register_ability('ai/' . $this->get_id(), array('label' => $this->get_label(), 'description' => $this->get_description(), 'ability_class' => Title_Generation_Ability::class));

Note: This check with wp_register_ability() was just added today, we are one of the first seeing it.
Its assumed that it should work as in register_rest_route but that should be tested to confirm before re-submitting.

Generic function/class/define/namespace/option names

All plugins must have unique function names, namespaces, defines, class and option names. 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 "AI Experiments" then you could use names like these:
function aiex_save_post(){ ... }
class AIEX_Admin { ... }
update_option( 'aiex_options', $options );
register_setting( 'aiex_settings', 'aiex_user_id', ... );
define( 'AIEX_PLUGIN_DIR', plugin_dir_path( FILE ) );
global $aiex_options;
add_action('wp_ajax_aiex_save_data', ... );
namespace jeffpaul\ai;

Disclaimer: These are just examples that may have been self-generated from your plugin name, we trust you can find better options. If you have a good alternative, please use it instead, this is just an example.

The prefix should be at least four (4) characters long (don't try to use two- or three-letter prefixes anymore). We host almost 100,000 plugins on WordPress.org alone. There are tens of thousands more outside our servers. Believe us, you're likely to encounter conflicts.

You also need to avoid the use of __ (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.

Please remember, if you're using _n() or __() for translation, that's fine. We're only talking about functions you've created for your plugin, not the core functions from WordPress. In fact, those core features are why you need to not use those prefixes in your own plugin! You don't want to break WordPress for your users.

Related to this, using if (!function_exists('NAME')) { around all your functions and classes sounds like a great idea until you realize the fatal flaw. If something else has a function with the same name and their code loads first, your plugin will break. Using if-exists should be reserved for shared libraries only.

Remember: Good prefix names are unique and distinct to your plugin. This will help you and the next person in debugging, as well as prevent conflicts.

Analysis result:

# This plugin is using the prefix "ai" for 18 element(s).
# This plugin is using the prefix "wordpress_ai" for 9 element(s).

# Using the common word "ai" as a prefix.
includes/bootstrap.php:26 define('AI_VERSION', '0.1.0');
includes/bootstrap.php:29 define('AI_PLUGIN_FILE', defined('WP_AI_DIR') ? WP_AI_DIR . 'ai.php' : '');
includes/bootstrap.php:32 define('AI_PLUGIN_DIR', defined('WP_AI_DIR') ? WP_AI_DIR : '');
includes/bootstrap.php:35 define('AI_PLUGIN_URL', plugin_dir_url(AI_PLUGIN_FILE));
includes/bootstrap.php:38 define('AI_MIN_PHP_VERSION', '7.4');
includes/bootstrap.php:41 define('AI_MIN_WP_VERSION', '6.8');
includes/bootstrap.php:44 define('AI_DEFAULT_ABILITY_CATEGORY', 'ai-experiments');
# Using the common word "wp" as a prefix.
ai.php:32 define('WP_AI_DIR', plugin_dir_path(__FILE__));

Regarding this issue I totally get that this plugin could be allowed with this prefix as it's a "special" one, but bear in mind that there might be other plugins trying to use that prefix when they shouldn't. Also this can set a example for other developers that is not among what's expected from them.

Therefore this is a case of "it's going to be their fault, but better safe than sorry" so it will be better if you can set a more complex prefix to avoid that kind of issues.

In any case the actions, filters and options may be able to stay with the ai_ prefix in the case that code here gets merged at some point to WordPress core.

How can we check the functionality of this plugin?

During our reviews, we check the functionality of the plugin.

We also check that the plugin functionality is sufficiently explained in the readme file and/or through messages that help the user configure and use the plugin.

We encountered difficulties when trying to test the functionality of this plugin, either we could not find details on how to make it work, or it did not work.

Please add instructions on how to configure and use this plugin to the readme file if you have not already done so.

Please also make sure that the functionality of your plugin works properly and that anyone can configure and use it, even if it is installed from scratch.

After activating the plugin:

Your installation of the AI plugin is incomplete. Please run composer install.

The composer.json is not there, anyway it's best if you include the final release with the production libraries included.

@jeffpaul note: I downloaded the ZIP from the 0.1.0 release on GitHub to submit, so perhaps we need to similarly resolve #109 to ensure the ZIP file Is one that can be used for WPORG submission as well as non-technical users coming to the repo and downloading a release ZIP.

Screenshots, screen recording, code snippet

No response

Environment info

No response

Please confirm that you have searched existing issues in the repo.

  • Yes

Please confirm that you have tested with all plugins deactivated except AI Experiments plugin.

  • Yes

Please confirm which theme type you used for testing.

  • Block
  • Classic
  • Hybrid (e.g. classic with theme.json)
  • Not sure

Metadata

Metadata

Labels

[Type] BugSomething isn't working

Type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions