A few days ago, I happened upon an interesting post on the ManageWP blog discussing ways to improve the WordPress plugin repository. One of the suggestions was to add a “related plugins” feature:
Both Lester Chan, with over 7 million plugin downloads to his name, and Duane Storey, a co-founder of Brave New Code, suggested that a “related plugins” area would be useful for end users. Logic dictates that if you are interested in one plugin, you might be interested in another with similar (or complimentary) functionality. Why not address that fact by showcasing related plugins?
– How to Improve the WordPress Plugins Repository
Why not, indeed? It sounded like it could be a fun project, so I went ahead and created a small web app that lets you find similar plugins. Try it yourself here.
Here’s a screenshot:
The way it works is simple: just enter a plugin slug (e.g. “all-in-one-seo-pack”) or a WordPress.org plugin directory URL (e.g. “http://wordpress.org/extend/plugins/all-in-one-seo-pack/”) in the search form, and the app will give you a list of related plugins. You can then refine the search further by filtering the results by the number of downloads, average rating, last update time and supported WordPress version.
- WordPress.org Plugin Information API
- Requests for PHP – a clean and simple HTTP client library.
- RedBeanPHP – a zero-configuration ORM. Used to store and query plugin metadata.
- Cache_Lite – a simple file-based caching library. Used to cache the results of slow SQL queries.
- MySQL probably needs no introduction. Used for its FULLTEXT indexing capabilities.
How It Works
At its core, this application is very similar to related posts plugins like Yet Another Related Posts Plugin. It matches all plugins in the database against the reference plugin and calculates a relevance score for each one, then displays the results with the highest score. The score is a weighted sum of several factors:
- Plugin name.
- Short description.
- Long description.
- The number of tags in common.
For the first three components, it extracts the most common keywords from the corresponding database fields and does a normal FULLTEXT match against each one, then sums the partial scores together. Then it adds the keyword score on top of that and filters the results based on the selected search refinements.
The actual SQL query looks something like this:
SELECT plugin.id AS plugin_id, ( matches.keyword_score + (COUNT(DISTINCT IF( plugin_tag.tag_id IN (1,2,3), plugin_tag.tag_id, NULL )) * :tag_weight) ) AS score FROM plugin JOIN ( SELECT readme.plugin_id, (0 + (MATCH (`readme`.`name`) AGAINST (:name_keywords)) * :name_weight + (MATCH (`readme`.`short_description`) AGAINST (:short_description_keywords)) * :short_description_weight + (MATCH (`readme`.`description`) AGAINST (:description_keywords)) * :description_weight) AS keyword_score FROM readme WHERE ( MATCH(readme.name, readme.short_description, readme.description) AGAINST(:all_keywords) ) HAVING keyword_score >= :min_score ) AS matches ON plugin.id = matches.plugin_id LEFT JOIN plugin_tag ON plugin.id = plugin_tag.plugin_id WHERE downloaded >= :min_downloads AND rating >= :min_rating AND updated >= :last_updated AND plugin.slug <> :reference_slug GROUP BY plugin.id ORDER BY score DESC LIMIT :limit
This query is fairly slow, so we cache the results.
If you have any questions or feedback, leave a comment below.Related posts :