WordPress.org

Making WordPress.org

#3692 closed enhancement (wontfix)

Add CamelCase support from plugin names as per PSR-4 Autoloaders standard

Reported by: KestutisIT Owned by:
Milestone: Priority: normal
Component: Plugin Directory Keywords: close
Cc:

Description

PROLOG:

WP Core team lead Dion (@dd32) showed me at WordCamp Europe 2018 via his laptop screen and send me via e-mail, and it appears I can see the code of "class-upload-handled.php" (at least today it is not [YET / ANYMORE] closed source)

GOAL & MOTIVATION:

The goal is to add support for plugins that are created in S.O.L.I.D. MVC - way. They are based on cross-plaftorm / cross-CMS coding standards like PSR-2 and PSR-4 Autoloaders, which is actually not just PHP coding standard, but it is almost a full match to coding standards used by majority of JAVA & C# developers, that are fully object-oriented languages.
S.O.L.I.D. MVC-based plugin use Camel-cased plugin folder names instead of lowercased & dash-separated plugin folder name, that is default.

Last year I have successfully tested S.O.L.I.D. MVC plugin development in Vilnius University's (World's TOP 500 University) Master Degree's Software Engineering Field studies for "Software Architecture & Design Patterns" course, that was mostly in JAVA for last 8 years, and for last year it was in C#. And I was able to process this task via WordPress plugin in PHP language, as I was able to port C# OOP code straight to WordPress plugin with some small modification, as it was enough to follow the PSR coding standards and have a basic wrapper of main initializer controller for WordPress hooks and filters and class autoloader model.

And that is not just that. Last month, I needed to update one of PHP-Fusion CMS Website's ReCaptcha and I just ditched the existing code and instead of that I just took my existing S.O.L.I.D. MVC plugin for ReCaptcha for WordPress and it WORKED AS WELL. And it took me to do this only one day. So as Ma.tt says that now everything is not just about WordPress, not even PHP - as Guttenberg goes beyond that and can be used pretty much in any CMS for PHP or EVEN ANY OTHER OOP CODING LANGUAGE (!). So this is a perfect model to convert other CMSes plugin developers, the C# and JAVA OOP developers to WordPress plugin developers without ANY NEED to learn any new coding standard - S.O.L.I.D. MVC is enough for that.

But as everyone know from Jordan Belford's ("Wolf of Wall Street") book "The way of the wolf" we have 4 seconds to make our new developer to believe in WordPress and if we fail, it will take at least additional 8 long meetings to make him believe. And if we have to start from the sentence that MVC / Camelcased namespaces will work everywhere in the plugin, but EXCEPT for the plugin folder, and you will have to use the HACK there, he get that 4 seconds negative impact, and that is enough for at least University Students to NOT choose to do their course task in WordPress plugin via S.O.L.I.D. MVC and they would rather go with C# and ASP.NET. And that is a lost believer of WordPress. So we need to fix that, and add a support for S.O.L.I.D. MVC in w.org plugins directory, or at least to add a check that it would not reset the plugin's folder name to dash-separated after update, as this is like a broken backbone of the skyscraper - S.O.L.I.D. MVC + Templates allows you to make plugins for WordPress (i.e. Booking), then each plugin may have different extensions (i.e. Hotel, Villa) and each extension can have dozens of themes that each can have a full visual overriding of the VIEW, as in S.O.L.I.D. MVC the visual part (HTML templates with .php extension, JavaScript files & all assets - Images, CSS files with CSS4 Variables, Icons) is fully separated from the plugin's logic (Models, Controllers & 3rd Party Libraries).

Also even if you use a HACK this may look as resolvable with "/EnvatoTookit/" <=> "/envato-toolkit/" folder, but with "/SOLID_MVC/" it would get a tragic folder name of "/s-o-l-i-d---m-v-c/". And the S.O.L.I.D. MVC allows you to have a separate units tests with PHPUnit via "_Tests" plugin (to make the plugin lightweight and not to include the tests code into plugin's folder", so for "/SOLID_MVC_Tests/" the HACK code would loose it's head to "/s-o-l-i-d---m-v-c---tests/". While it should allow to have me "/solid-mvc/" and "/solid-mvc-tests/" URL's for the plugin in w.org, but allow me to download the plugins as "SOLID_MVC.zip" and "SOLID_MVC_Tests.zip", as well as with the first example "EnvatoToolkit.zip". And will keep that name for the folder name as well. The folder name can be taken from the ZIP's archive name, or via additional "Namespace" plugin header's META parameter.

CURRENT STATUS:

Currently you can create a S.O.L.I.D. MVC plugin and publish in into web-app stores like Envato's CodeCanyon, or you can have it hosted on GitHub, but it gets issues if you want to host the plugin on W.org, which is a 'default' repository. Additionally, even it the plugin got downloaded from other repository, that supports camelcased plugin names, and it has the update link in plugins META header to w.org, after you will click "Update the plugin" button, it will RESET the plugins folder name from i.e. "/wp-content/plugins/EnvatoToolkit/" to "/wp-content/plugins/envato-toolkit/"

THINGS THAT NEEDS TO GET DONE:

  1. Edit the code of "class-upload-handled.php" - https://meta.trac.wordpress.org/browser/sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload-handler.php?marks=87-91#L84 )
  2. Add these 32 (if it is based on upload folder name) or 23 (if "Namespace" META header param would be allowed) additional lines of code to w.org plugins directory at the point where plugin name is assigned.
  • 32 lines version (based on uploaded plugin folder name):
    <?php
    // Retrieve uploaded plugin folder name
    $tmp_plugin_dir = "";
    foreach ( $plugin_files as $plugin_file ) {
            $plugin_data = get_plugin_data( $plugin_file, false, false ); // No markup/translation needed.
            if ( ! empty( $plugin_data['Name'] ) ) {
                    $tmp_plugin_dir = basename( $plugin_file )); // I.e. "EnvatoToolkit"
            }
    }
    
    // Determine the plugin slug based on the name of the plugin in the main plugin file.
    $this->plugin_slug = remove_accents( $this->plugin['Name'] );
    $this->plugin_slug = preg_replace( '/[^a-z0-9 _.-]/i', '', $this->plugin_slug );
    $this->plugin_slug = str_replace( '_', '-', $this->plugin_slug );
    // TODO: I have no idea why this function is used here if the three lines above already did the work
    $this->plugin_slug = sanitize_title_with_dashes( $this->plugin_slug );
    
    $this->plugin_folder_name = "";
    if (strtolower($tmp_plugin_dir) != $tmp_plugin_dir)
    {
            // --- Upper-case letters found in $tmp_plugin_dir ---
            // Determine the final plugin folder name based on the plugin folder name
            $this->plugin_folder_name = remove_accents( $tmp_plugin_dir );
            $this->plugin_folder_name = preg_replace( '/[^a-zA-Z0-9]/', '', $tmp_plugin_dir );
            // Upper-case the first letter
            $this->plugin_folder_name = ucfirst($this->plugin_folder_name);
    } else
    {
            // --- No upper-case letters found - use the existing way
            // Determine the final plugin folder name based on plugin slug
            $this->plugin_folder_name = $this->plugin_slug;
    }
    
  • 23 lines version (based on "Namespace" META plugin header).
    <?php
    // Determine the plugin slug based on the name of the plugin in the main plugin file.
    $this->plugin_slug = remove_accents( $this->plugin['Name'] );
    $this->plugin_slug = preg_replace( '/[^a-z0-9 _.-]/i', '', $this->plugin_slug );
    $this->plugin_slug = str_replace( '_', '-', $this->plugin_slug );
    // TODO: I have no idea why this function is used here if the three lines above already did the work
    $this->plugin_slug = sanitize_title_with_dashes( $this->plugin_slug );
    
    $this->plugin_folder_name = "";
    if (strtolower($tmp_plugin_dir) != $tmp_plugin_dir)
    {
            // --- Upper-case letters found in $tmp_plugin_dir ---
            // Determine the final plugin folder name based on the plugin folder name
            $this->plugin_folder_name = remove_accents( $this->plugin['Namespace'] );
            $this->plugin_folder_name = preg_replace( '/[^a-zA-Z0-9]/', '', $this->plugin_folder_name );
            // Upper-case the first letter
            $this->plugin_folder_name = ucfirst($this->plugin_folder_name);
    } else
    {
            // --- No upper-case letters found - use the existing way
            // Determine the final plugin folder name based on plugin slug
            $this->plugin_folder_name = $this->plugin_slug;
    }
    
    

NOTES:

  1. Dion (@dd32) said that this code depends on two plugin repositories:

https://meta.trac.wordpress.org/browser/sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory
https://meta.trac.wordpress.org/browser/sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins

  1. Initial slug creation code:

https://meta.trac.wordpress.org/browser/sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload-handler.php?marks=87-91#L84

  1. I'm totally confused where to created ticket as in "META TRAC" I can select a component of "PLUGIN DIRECTORY", but there is also separate "PLUGINS TRAC" that looks like forgot-one as there are very few tickets in recent years:

https://plugins.trac.wordpress.org/report/1?sort=created&asc=0&page=1

Change History (11)

#1 @audrasjb
16 months ago

  • Keywords has-patch needs-testing removed
  • Priority changed from high to normal

Hi and thanks for this ticket,

I am removing has-patch workflow keyword since there is no patch file for the moment.

You should have a look on Meta Handbook to propose a real patch for this request: https://make.wordpress.org/meta/handbook/ :-)

Also, I guess the priority is not high since it has to be discussed before: we are following PHPCS and especially WordPress Coding Standards for filenames. See related handbook page: https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#naming-conventions

Cheers,

Jb

#2 follow-up: @Otto42
16 months ago

I'm sorry, I read through all this and I still don't understand what the goal is here.

If the goal is to have capital letters in the plugin slug, then I'm going to have to say no, and close the ticket with a wontfix.

Plugin slugs are all lowercase, they are used for the URL of the plugin in our directory, they are used as the foldername for the plugin itself, and they are unique entities in the system.

Adding support for non-lowercase letters would also require additional code to prevent issues where somebody makes "exampleslug" vs "ExampleSlug", which would work on a unix based hosting, but not a Windows based one.

If you want to code your plugin code to a specific standard, then you can do so if you wish. But having it located in a folder using lowercase letters only is not really a very large burden to bear.

#3 in reply to: ↑ 2 @KestutisIT
16 months ago

Replying to Otto42:

I'm sorry, I read through all this and I still don't understand what the goal is here.

If the goal is to have capital letters in the plugin slug, then I'm going to have to say no, and close the ticket with a wontfix.

Plugin slugs are all lowercase, they are used for the URL of the plugin in our directory, they are used as the foldername for the plugin itself, and they are unique entities in the system.

Adding support for non-lowercase letters would also require additional code to prevent issues where somebody makes "exampleslug" vs "ExampleSlug", which would work on a unix based hosting, but not a Windows based one.

If you want to code your plugin code to a specific standard, then you can do so if you wish. But having it located in a folder using lowercase letters only is not really a very large burden to bear.

It is NOT for the slug, not for SEO (the URL with SOLID MVC will still remain the same, i.e. "w.org/plugins/demo-mvc/" while the folder name will be "/wp-content/plugins/DemoMVC/". It is for the FOLDER NAME ONLY.
Well, as mentioned before this small-feature-lack is like a backbone for very high scyscraper, and it impacts (the reset of namespace back to dash separated after plugin’s update) thousands of plugin authors in the whole tree stack (S.O.L.I.D. MVC -> Some plugin, i.e. Booking -> Some extension for the plugin, i.e. “Villa” or “Hotel” -> Some of 100’s themes for that plugin extension -> And that exact theme overriding plugin view (i.e. /themes/AmazingWorld/Extensions/SomeCamelCasedPluginName/) name folder), not even talking about the fact that as per Wolf of Wall Street’s Jordan’s Belford’s book “Way of The Wolf” we have 4 seconds to make this believe for a developer starting his masters course in University to choose WordPress plugin for his course task and not C# and ASP.NET, and that would never make him believe if we have to start a talk with “well, you will have to make a HACK for plugin’s folder name”, and it would take then 8 additional long meetings to make him believe in WordPress again, and as Guttenberg is not just WordPress anymore, the greatest idea to start is to say that to make a solid WordPress plugin you don’t have to learn any new coding standards, you can just port your C# code library with small changes straight to WordPress in a day due to S.O.L.I.D. MVC + Templates that follows all these PSR-2 & PSR-4 Autoloader coding standards that is pretty much a status-quo in JAVA an C# OOP world for a decade already.
The first question you need to ask if you do believe that WordPress in just just WordPress anymore, as Matt said, and do you want to convert thousands of C# and JAVA developers to WP plugin devs or not, as this will also pay-off the reputation of WordPress A LOT, as if you start to talk with C# dev or some University lecturer that you have to start from the HACK then it will never sell. I'm saying that we need just to add support for this, not to ditch the existing dash-lowercase separation, just this is just an addition that helps 10,000 of plugin author at Envato that uses EnvatoToolkit plugin concepts of SOLID MVC, as well as devs from other CMS'es like Php-Fusion, and other languages. Because autoloaders and namespaces will then won't work who prefer to follow the default global-use coding standards. And EVEN the HACK won't work well, as for "/GreatMVC_Tests/" it will give you the "great-m-v-c---tests" URL in W.ORG instead of "great-mvc-tests" URL that we want. And this can be solved with just one line of support for "Namespace" META header for plugins, and can have the SAME SLUG for URL's and translations. Meaning we need to allow this only for the folder names to follow the correct PSR-4 Autoloaders standard, so that everything, even PHPStorm IDE with have it defaults to work well without additional renames for everyfile, especially if you have a TREE-REFACTORING.

Last edited 16 months ago by KestutisIT (previous) (diff)

#4 follow-up: @swissspidy
16 months ago

Because autoloaders and namespaces will then won't work who prefer to follow the default global-use coding standards.
Meaning we need to allow this only for the folder names to follow the correct PSR-4 Autoloaders standard

If you want to use PSR-4 autoloaders and namespaces in your plugin, you can already do so just fine. The capitalization of the plugin folder doesn't matter for that.

#5 in reply to: ↑ 4 @KestutisIT
16 months ago

Replying to swissspidy:

Because autoloaders and namespaces will then won't work who prefer to follow the default global-use coding standards.
Meaning we need to allow this only for the folder names to follow the correct PSR-4 Autoloaders standard

If you want to use PSR-4 autoloaders and namespaces in your plugin, you can already do so just fine. The capitalization of the plugin folder doesn't matter for that.

No, you can't.
By following SOLID MVC, PSR-2 & PSR-4, you have to have:

For the file, name as "/wp-content/plugins/GreatMVC/Models/Item/ItemsObserver.php", you have to have a starting line of:

<?php
namespace GreatMVC/Models/Item;

final class ItemsObserver
{
....
}

And when you do have Interfaces, Traits, Inherited classes, and you do run a REFACTOR in PHPStorm IDE, it will rename all the files correctly and automatically if this will follow this pattern. Otherwise it will break. Also the HACK won't work if you parse a namespace from "solid-mvc-tests" to "S-O-L-I-D---M-V-C---TESTS" as it sould be "SOLID_MVC_Tests", so the hack would have issues as well, and would work for simple names, and you CAN'T MAKE a pattern with IF ELSE if exact plugin names, as that sould be independent autoloader class file.
And DASHES are NOT ALLOWED by PHP in namespaces.
Regarding the CamelCase, again it has to follow the standard, and by the standart, it shoud have classes like:
AbstractElement.php for abstract class AbstractElement
ElementIterface.php for interface Element
DailyPricingTrait.php for trait DailyPricing
Item.php for final class Item.
So everything is connected, and everything works and there is 10,000+ plugins made already on S.O.L.I.D. MVC in Envato and GitHub and elsewhere where your download will be i.e. "EnvatoToolkit.zip" and not "envato-toolkit.zip". Also if the theme overrides extension view (html templates and assets) it has to match the plugin folder name, so if it matched in the begging with '/ThemeX/Extensions/GreatMVC/Templates/Admin/Item/AddEditItemForm.php' then it will BREAK working (the view will get back to default) after the plugin update if the plugin URL is in w.org, as it will reset the folder name of plugins to "great-m-v-c" and that is not a match of theme folder overridden extension folder name of "GreatMVC".

Last edited 16 months ago by KestutisIT (previous) (diff)

#6 follow-up: @Otto42
16 months ago

  • Milestone Plugin Directory v3.0 deleted
  • Resolution set to wontfix
  • Status changed from new to closed

At this time, folder name and slug must be identical. The WordPress core code itself uses the folder name to check for updates and to match plugins against our slugs.

Until the WordPress core code itself no longer does this, and uses a different method for determining updates, this is a wontfix. If that changes in the future, then this may be reconsidered.

#7 in reply to: ↑ 6 @KestutisIT
16 months ago

  • Keywords 2nd-opinion added
  • Resolution wontfix deleted
  • Status changed from closed to reopened

Replying to Otto42:

At this time, folder name and slug must be identical. The WordPress core code itself uses the folder name to check for updates and to match plugins against our slugs.

Until the WordPress core code itself no longer does this, and uses a different method for determining updates, this is a wontfix. If that changes in the future, then this may be reconsidered.

Otto42, I disagree with you that is HAS to match it. I don't see why the suggested code lines cannot be added to the uploader file, as you can check for update by the slug, but when you create a folder you can use "Namespace" meta parameter name, as it will work and solve this issue. I want that release lead of WordPress would give his opinion, and I disagree that issue would be deleted. Also, as I wrote to Matt, and he said that this ticket should be here, I want Matt's input here, at least a feedback is the proposed core changes may happen in one of upcoming versions. Also the XWP team (mostly by Josiah Wold) I met on WordCamp said that they will help to make this more public issue, so they may still endorse this, and it there would be "Upvoting" feature for the ticket, I believe it would collect more upvotes.

So this has to:

  1. Get 2nd opnion from release lead.
  2. This ticket should stay, and should not be deleted, as there is A NEED from AT LEAST 10.000 plugin developers from Envato with active installations (that use my EnvatoToolkit with SolidMVC pattern) and GitHub, who don't use yet w.org, so the customers who uses their plugins can be even over 1M+ and that is more than strong argument to consider giving this priority.
  3. As Ma.tt said on WordCamp that this has to be discussed and I should create a ticket here, I do hope to get his feedback on this ticket as well.

#8 follow-up: @Otto42
16 months ago

  • Keywords 2nd-opinion removed

You're misunderstanding. The WordPress code sends the folder name of the plugin, and we match it against the slug. That's how the update API works.

So, before we even entertain the notion of allowing the folder name to not be the same as the slug of the plugin, then the WordPress core needs to have that concept built into it. It currently does not.

So, this type of ticket is dependent upon the core code itself changing what it sends for update checks. It's not something we can just shove into the meta code, the WordPress core itself must act differently, and that would be something that belongs in core.trac.

#9 in reply to: ↑ 8 @KestutisIT
16 months ago

Replying to Otto42:

You're misunderstanding. The WordPress code sends the folder name of the plugin, and we match it against the slug. That's how the update API works.

So, before we even entertain the notion of allowing the folder name to not be the same as the slug of the plugin, then the WordPress core needs to have that concept built into it. It currently does not.

So, this type of ticket is dependent upon the core code itself changing what it sends for update checks. It's not something we can just shove into the meta code, the WordPress core itself must act differently, and that would be something that belongs in core.trac.

So let's the do this - I will create this ticket on core.track first with your notes added. Then it will go over the core.trac, get's into the core first, and then this ticket will be a next thing to proceed. So it still has not to be removed, just should not have the exact version yet, as we need to make a patch first for the core. And for the core I will also need a comment from you to list EXACT files where it (the update code for the slug check where I can add a check for "Namespace" meta header as and additional check option not just the "Text Domain" meta header, as what I understand this is from where you take the 'slug' value, right?). If you can, please write these related files and code lines like DION (@dd32) did with this plugin directory file, so that my ticket on core.track would be more exact and specific, and that I could propose a patch to save teams time on code writing. Thanks. I will also ask them Matt's and team lead's input there on that ticket in core.track.

Last edited 16 months ago by KestutisIT (previous) (diff)

#10 @dd32
16 months ago

  • Keywords close added

As said at the WCEU Contributor day by myself:

  • The plugin directory internally relies upon the WordPress "slugification" process in many ways, and is an integral part of how the directory operates. This is relied upon by Core Updates, SVN Interactions, linking of plugin posts & svn directories, and a huge number of other random things behind the scenes.
  • WordPress has hooks and filters in place to allow plugins/3rd parties to change how slugs operate. The Plugin Directory will not be leveraging those to allow CamelCase (or other) formats to work for hosted plugins. Hosted plugins come with rules, restrictions, and expectations of authors.
  • The plugin directory expects slugs to be in a standard WordPress 'slug format', and won't be changing that. Changing it has implications far exceeding the intended effect, and would cause unintended consequences.

As some background to slug generation in WordPress:

  • Any request to change how WordPress itself generates slugs should be directed to the Core Team. You can dig up the code references yourself, it's all open-source (as is all the plugin directory).
  • WordPress slugification exists as it is to provide a "clean" url-safe string. There are no plans to change how that operates - other than make it more strict and remove any further edge-cases that exist (Historically, multibyte characters fall into that category)
  • WordPress does have filters in place to allow a plugin or 3rd party to modify how slugs are generated. The Plugin Directory has no intention to utilise them though.

To go back to one of your examples as suggested why this change should be made:

For the file, name as "/wp-content/plugins/GreatMVC/Models/Item/ItemsObserver.php", you have to have a starting line of:
<?php
namespace GreatMVC/Models/Item;
  • There's nothing preventing you from doing that in your own code.
  • If you want to release it publicly, you need to expect that your plugin directory can and will be changed by others
  • If you want to release it within the WordPress.org plugin directory, you need to accept it's limitations and one of those is directory slugs
  • Lots of plugins use PSR-* in their code, there's no reason you can't either.
  • To use PSR4 classes, you simply need to namespace it to your plugin. ie. GreatMVC/Models/Item/ItemsObserver exists within the file relative to the loader of plugins/great-mvc/Models/Item/ItemsObserver.php or even plugins/great-mvc/GreatMVC/Models/Item/ItemsObserver.php (if you really need the full path) or plugins/great-mvc/vendor/GreatMVC/Models/Item/ItemsObserver.php (as many other plugins do).

In general plugins & themes should not expect to know the file path to other plugins, or need to know what folder they're being loaded from. Plugins and Themes may not always live where you expect, and as a result every plugin and theme should be self-contained with no inter-plugin dependancies. As a result, what the slug of your plugin or theme is, should be completely irrelevant to your code and PSR coding notions.
Themes could be loaded from wp-content/themes/, wp-content/common/themes/pub/ or even wp-content/plugins/some-plugin/included-themes/
Plugins can be loaded from wp-content/plugins/, wp-content/mu-plugins/ or even wp-content-common/sites/plugins/.

I'm not closing this ticket (despite firmly believing this is a wontfix), as I don't want to get into a close-reopen war with you.
This is also my final (And only) comment on this issue, as this is all my opinion, and it won't be changing.

Consider taking a step back and looking at how you can make your coding style and preferences fit within the WordPress ecosystem. I'll freely admit WordPress has some limitations, but those limitations cause standardisation and wider code acceptance, many developers may initially hate it (or love it) but have been able to adapt from other languages or platforms without significant barriers, while still maintaining their previous coding standards (good or bad).

#11 @Otto42
16 months ago

  • Resolution set to wontfix
  • Status changed from reopened to closed
Note: See TracTickets for help on using tickets.