I work on a plugin that has WDS-Shortcodes as a dependency. Attempting to run composer install
on this plugin will fail with the error message:
[RuntimeException] Could not scan for classes inside "/public_html/wp-content/plugins/lqd-messages/vendor/webdevstudios/wds-shortcodes/vendor/tgmpa/tgm-plugin-activation/class-tgm-plugin-activation.php" which does not appear to be a file nor a folder
This is because the WDS-Shortcodes on packagist has the following in its composer.json
:
"autoload": {
"classmap": [ "includes", "vendor/tgmpa/tgm-plugin-activation/class-tgm-plugin-activation.php" ],
...
}
The problem is that this file doesn’t yet exist. Once this failure has occurred it can be remedied by going to: vendor/webdevstudios/wds-shortcodes/
and running composer install
. After that you can go back up to the main project directory and run composer install
again and it should succeed.
The patch for this has been made on the github repository, unfortunately it hasn’t made its way to packagist. So lets try using the repository code directly by adding the repo as a repository to our composer.json
like so:
"repositories": [
{
"type": "vcs",
"url": "https://github.com/webdevstudios/wds-shortcodes"
}
],
We’ll then update our require in composer.json
to point to dev-master
. The line "webdevstudios/wds-shortcodes": "^1.0.7",
has the version number swapped out for dev-master
. For kicks and giggles lets delete our vendor
directory, composer.lock
, and run composer clear-cache
.
This time everything installs without issue (huzzah!). We pull up a page on our dev site and it crashes. Looking at the debug.log
again we see:
PHP Warning: require(/public_html/wp-content/plugins/lqd-messages/vendor/composer/../webdevstudios/wds-shortcodes/vendor/jtsternberg/shortcode-button/shortcode-button.php): failed to open stream: No such file or directory in /public_html/wp-content/plugins/lqd-messages/vendor/composer/autoload_real.php on line 69
This issue arises because WDS-Shortcodes is attempting to load the shortcode-button dependency from within its own vendor folder, which doesn’t exist. The shortcode-button dependency does exist in the main plugin’s vendor folder but the composer.json
for WDS-Shortcodes is hard coded to use its own vendor directory.
Okay, this is an easy fix. Run composer install
from within the WDS-Shortcodes folder. Refresh our page and we are still crashing. What now?
PHP Fatal error: Class 'WDS_Shortcodes' not found in /public_html/wp-content/plugins/lqd-messages/includes/shortcodes/class-shortcodes-run-base.php on line 7
Here the problem is that Composer when it creates the autoload files doesn’t add any autoloading of WDS-Shortcodes’ files. Why not? Because WDS-Shortcodes doesn’t have any autoloading setup in its composer.json
. There are two ways we can resolve this. One is to edit WDS-Shortcode’s composer.json
and add to the "files"
portion of "autoload"
: wds-shortcodes.php
. But, for whatever reason, this won’t be picked up by Composer even if we do a composer dump-autoload -o
, manually delete the autoload files, and run composer dump-autoload -o
again. So lets leave this option for the moment.
The other way we can handle this is by editing our main plugin’s composer.json
to include the autoloading specifications. This involves adding "vendor/webdevstudios/wds-shortcodes/wds-shortcodes.php"
under the "files"
section of "autoload"
.
Welp, that doesn’t work either. Lets try instead adding this file and all the files in /includes to the classmapping:
"autoload": {
"classmap": [
"gc-sermons.php",
"includes/",
"vendor/webdevstudios/wds-shortcodes/wds-shortcodes.php",
"vendor/webdevstudios/wds-shortcodes/includes"
],
"files": [
]
},
Huzzah! That works! But there was a lot of manual work to get things going. Lets try removing the path specification for shortcode-button in WDS-Shortcodes composer.json to see if we can simplify things a bit (we already have shortcode-button installed as a dependency of the main plugin). After making this edit we run composer dump-autoload -o
and get an error:
PHP Parse error: syntax error, unexpected ''4cfe55868654b2ea9298a46af9d2b' (T_ENCASULATED_AND_WHITESPACE), expecting end of file in /public_html/wp-content/plugins/lqd-messages/vendor/webdevstudios/wds-shortcoes/vendor/composer/autoload_files.php in line 11
If someone wants to clue me in on exactly why this happens, I’d appreciate it. The quick way around this issue is to manually delete the composer autoload files. Once this is done one can rerun composer dump-autoload -o
and composer will complete without error.
If we refresh our page that seems to have gone okay. But what if we try to actually remove the vendor/jtsternberg/shortcode_button
in wds-shortcodes
? I’m a glutton for punishment, let’s find out. Reloading the page seems to work!
What if we forked our own version of WDS-Shortcodes and attempted to make the changes we’ve made above to composer.json
and see if we can’t avoid all this manual work? I’m game.
We update our main composer.json to point to our new repo instead of WDS’:
"repositories": [
{
"type": "vcs",
"url": "https://github.com/liquidchurch/wds-shortcodes"
}
],
We’ll also delete our composer.lock
and vendor
files/directories and run composer clear-cache
. Then, with fingers crossed, composer install
. The install goes smoothly, reloading the page not as much.
PHP Fatal error: Class 'Shortcode_Button' not found in /public_html/wp-content/plugins/lqd-messages/vendor/webdevstudios/wds-shortcodes/includes/shortcode-admin.php on line 3
Ahh, that’s right, I need to add the shortcode_button as a dependency to the main composer.json
file, under "require"
I add: "jtsternberg/shortcode_button": "^1.0.7",
just like it was in WDS-Shortcode’s composer.json
previously. I go through my regular rigamarole (delete composer related files, run clear-cache) and do composer install
again. Its successful but I’m still getting the same error as above.
Ahh, that’s right. I need to tell Composer to autoload the shortcode-button code, so I add the same "autoload"
"files"
statement from WDS-Shortcode’s composer.json
(okay, so I did try adding the statement to "classmap"
first, but it didn’t work, so…): "vendor/jtsternberg/shortcode-button/shortcode-button.php"
.
Regular rigamarole, refresh, and the page loads! So this is better but still not perfect. Ideally I wouldn’t need to manually add short-button as a dependency to my plugin or tell composer to autoload the files…but for the moment, it works.