johnpbloch / wordpress

A fork of WordPress with Composer support added. Branches, tags, and trunk synced from upstream every 15 minutes.
https://packagist.org/packages/johnpbloch/wordpress
602 stars 102 forks source link

Installer should respect custom package types (for the core themes and plugins) #40

Closed eyalroth closed 5 years ago

eyalroth commented 5 years ago

Imagine a situation where one desires to keep the wp-content directory separate from the core wordpress files, much like described in this blog post / guide.

The directory structure would look something like so:

/
|
|-- public/
|   |-- wp-content/
|   |-- wp-core/
|   |-- .htaccess
|   |-- index.php
|   `-- wp-config.php
|
|-- .gitignore
|-- composer.json
`-- local-config.php

(There's no actual need for the additional nesting under the public directory, it's just an extra security measurement to make sure the sensitive configuration in local-config.php is not under the public domain of the web server)

The composer.json for this example looks something like this:

{
    "repositories": [
        {
            "type": "composer",
            "url": "http://wpackagist.org"
        }
    ],
    "require": {
        "php": ">=5.4",
        "composer/installers": "1.*",
        "johnpbloch/wordpress": "4.3.*"
    },
    "extra": {
        "wordpress-install-dir": "public/wp-core",
        "installer-paths": {
            "public/wp-content/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
            "public/wp-content/plugins/{$name}/": ["type:wordpress-plugin"],
            "public/wp-content/themes/{$name}/": ["type:wordpress-theme"]
        }
    }
}

(versions in the example are a bit old but it doesn't matter)

The problem is that the "core" installation of wordpress does not respect the custom types (such as wordpress-theme), resulting in all of the "core" plugins and themes installed in the public/wp-core/wp-content directory instead of the public/wp-content one. Any project relying on these core plugins and themes will fail unless the owner manually moves them (which is against the whole point of automation).

This issue is very similar to #14, only that the proposed solution is not to avoid installing the default themes and plugins, but to "annotate" them as a different type of package.

For anyone interested in a workaround, one could do this for each of the plugins / themes / mu-plugins directories:

// add this to the end of the root composer.json (and don't forget a comma after the previous section)
    "scripts": {
        "post-update-cmd": [
            "for i in $(find public/wp-core/wp-content/themes/ -maxdepth 1 -mindepth 1 -type d -printf '%f\n'); do rm -rf public/wp-content/$i; done",
            "mkdir --parents public/wp-content/themes/",
            "for i in $(find public/wp-core/wp-content/themes/ -maxdepth 1 -mindepth 1 -type d); do cp -r $i public/wp-content/themes/; done"
        ]
    }

This will the following steps after each composer install or composer update:

  1. Delete the core themes from the actually used wp-content folder (if they exist).
  2. Create the themes directory in the actually used wp-content folder (if it doesn't exist).
  3. Copy the core themes from the core wp-content directory to the actually used one.
johnpbloch commented 5 years ago

Thanks for stopping by. It would be a significant backwards-compatibility break to strip out the core themes/plugins, so that's not happening in the wordpress-core repository or in this repository's composer.json manifest. Also, considering those themes and plugins aren't actually installed directly by composer, it doesn't seem appropriate to try to manage their installation location separately with Composer.

If you want to make sure the core themes are installed in the composer/installers location, the correct way to do that is to use wpackagist and add wpackagist-theme/twentyseventeen (for example) to your site's composer.json manifest.

If you want to make sure any given core themes that ship with core also show up in your themes page, you could register the core location as an extra theme location, which is what I do in my site package. You just need to be pretty careful with that approach, because core has been known to drop themes from the package, which could break your site on upgrade. Personally, I'd just stick with the wpackagist option.

eyalroth commented 5 years ago

@johnpbloch Well my problem is mostly that wordpress is being installed this way in an unstable state. I don't really mind about the default themes, so the second option looks good to me. Thanks 😃

eyalroth commented 5 years ago

@johnpbloch FYI your example MU plugin doesn't work properly - the core themes appear on the theme list in wp-admin, but they will not function properly - complaining about the theme not being found when trying to customize them or load any page with any of them activated.

This seems to stem from the get_raw_theme_root method which is used by wp_get_theme; for some reason, the method ignores the registered theme directories ($wp_theme_directories) if there's less than 2 entries in it.

So the solution is simply to register two directories in the register-theme-directory.php:

<?php

register_theme_directory( 'themes' );
register_theme_directory( ABSPATH . 'wp-content/themes' );

Also, on a clean install without any custom themes, one should create the themes directory inside the directory denoted by WP_CONTENT_DIR (and if you want to commit it to git just create an empty index.php file in it).