I've recently written a plugin that has the ability to render its output through a skinning system. While writing functionality that would allow the user to add new skins to their collection via an upload functionality (mimicking WordPress' plugin and theme upload experience) I encountered a part of the
WP_Upgrader class that could use some improvement.
- We have a custom destination directory housing all uploaded skin asset files in sub-directories. This skin directory is created upon plugin activation.
- Uploads are handled by submitting to the
/wp-admin/update.phpfile with a custom
- Upload processing is achieved by hooking into the
"update-custom_" . $actionaction at the end of the
- We have created custom child classes for
WP_Upgrader_Skinin order to utilize the same upload, validation and processing functionality used by the WordPress core for plugin and theme installation and upload handling.
The problem that revealed the need to make the WP_Upgrader class more flexible
When we modeled our structure for the
WP_Upgrader_Skin child classes off of the existing
Plugin_Installer_Skin child classes we ran into some problems when the ZIP files we were uploading for our skins were being copied to the skin directory we had created. When the
WP_Upgrader class processed the files with the
install_package() method it couldn't create a sub-directory with the
mkdir() command. After extensive debugging it was discovered that the destination directories did not include sub-directories named after the uploaded ZIP file or after the sub-directory included in the ZIP file as would normally be expected when uploading a plugin or theme. For example:
- A file name
my-skin.zipfile contains a directory named
my-skinwhich contains all assets for the skin.
- When uploaded, the desired result is that a sub-directory called
my-skinwould be created in the skins directory, but instead the destination directory according to the
install_package()method is still just the skins directory - no
my-skinsub-directory, unfortunately resulting in an error.
Upon further investigation I found that the reason themes and plugins can be uploaded with the destination directory merely specified as
/wp-content/themes is because the
install_package() method is hard-coded, statically accommodating for those specific folders (see line 210-213 of
/wp-admin/class-wp-upgrader.php since version 3.3 of WordPress).
Unfortunately we cannot just specify the destination directory for the newly uploaded skin including the skin's expected sub-directory when calling the
WP_Upgrader->run() command as it causes an error when
WP_Upgrader->fs_connect() is called since the sub-directory does not exist yet.
To circumvent this we merely overloaded the
install_package() method in our
WP_Upgrader child class and extended custom filters to allow us to re-define the
$remote_destination and $destination
values to include our skin's sub-directory. The filter we wrote merely mimics the exact path modification being done to$remote_destination
on lines 211-212 of/wp-admin/class-wp-upgrader.php` for plugins and themes.
Instead of forcing plugin developers to fork the
install_package() method by overloading it in a sub-class, add an
apply_filters() command for
$destination for easy hooking in to modify those values.