-
Notifications
You must be signed in to change notification settings - Fork 346
Safely auto-configure wp-config.php
when some configuration is missing
#2539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Conversation
What is the |
Also, note Playground defines more constants than just DB_NAME, e.g. WP_HOME and WP_SITEURL . It could be useful to either make the define behavior configurable via |
@adamziel There are multiple nuances here at play, I guess. First, currently, when the The second part is when this behavior should occur. We discussed throwing an exception when some required constant is missing and adding the
Yeah, I think there's an opportunity to unify the behavior of all of these now. Let us know what you think! |
Yeah I think it would solve for a number of use-cases, maybe for most of them. My only concern is it would make misconfigured environments harder to debug by hiding the "constant already defined" warning. That may be a good trade-off and I think we can wrap the defines in an For that further discussion – Some environments predefine the constant, others don't. Some sites come with the constant defined, others don't. Some developers would rather see an explicit warning when their environment is misconfigured over getting a constant with a different value. Some runtimes are fine with modifying the config files, others are not. There's a lot of combinations. I keep thinking why does the
|
It seems like we can’t have everything so we’re just choosing a set of trade-offs. When we’re importing site with no DB_NAME defined, we can:
Some of those upsides and downsides don’t matter as much from Studio perspective, but they are relevant from Playground CLI perspective. Note that wp-config.php may still need some rewriting if we are importing a site where DB_NAME is already defined (alongside other MySQL credentials). (edited) Perhaps instead of a hook, we could use a config option after all. It would not solve for everything, only allow the consumer to choose their set of tradeoffs:
Every runtime would choose the most appropriate set of trade-offs. Any importing-related pre-processing of the files, e.g. removing any pre-existing constants, would be up to the runtime. |
@adamziel Funny enough, I went into this issue thinking that we need a new config option, but after discussing and thinking it through, I think it may not be needed, and we could keep it simple and transparent. I'll try to explain why. I'll start with two ideas that I find important:
Considering the reasoning above, we'd be left with two options:
Both of these variants have the advantage that they are "the WP way," and they are clear, transparent, and explanatory about what Playground is doing with the configuration. They will work with For both of these options, we can inject clear and explanatory comments. We can also wrap them in a BEGIN/END comment block (as in the PR description) that could be automatically removed when the user defines the constant manually (it's the current PR behavior). In the case of option 2, we can either inject it always or only when it's missing. All of these are just optimizations that can make the experience even better; it would work without them as well. Now the question is, what is the difference between the two? I'll look at each of these closer, but I'd like to state an important factor beforehand—I suspect we might be ruling out option 1 because Studio wasn't eager to sanitize I think the variants 1 and 2 are both good solutions, and they are very close. Here's how I perceive them: 1. Add a
|
@JanJakes Thank you for your thorough argument. I'm on board. Let's proceed with a conditional |
* @param wpConfigPath The path to the "wp-config.php" file. | ||
* @param constants The constants defaults to use. | ||
*/ | ||
export async function autoConfigureWpConfig( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about the naming – we now have ensureWpConfig
that defines some constants and autoConfigureWpConfig
that also defines some constants. Let's use this opportunity to consolidate all the constants-related logic and come up with a good, descriptive name.
ae65f96
to
e72ff9d
Compare
@adamziel This should be ready for review. I will also check it once again with a fresh mind, but I think it should cover all that we need at the moment. |
11b6fe7
to
01dcb23
Compare
01dcb23
to
b44e409
Compare
const defaults = { | ||
DB_NAME: 'database_name_here', | ||
DB_USER: 'username_here', | ||
DB_PASSWORD: 'password_here', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these good defaults? Someone was complaining that it was ugly (which I kind of agree with), but if we want to use different defaults, I think we'd need to do that also for new installs (where we only copy the wp-config-sample.php
without any modifications at the moment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think we're good to change these for new installs as long as we don't break any existing sites.
AUTH_SALT: 'put your unique phrase here', | ||
SECURE_AUTH_SALT: 'put your unique phrase here', | ||
LOGGED_IN_SALT: 'put your unique phrase here', | ||
NONCE_SALT: 'put your unique phrase here', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These could also get random values by default (Is manual WP install doing something like that? 🤔).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question! AFAIR Playground was doing that up until this point – even if we got a wp-config file with these default values. Let's confirm what's the WordPress behavior and make it consistent.
One thing to be careful about – AFAIR if we change password salt on a running website, noone will be able to log in as the result of sha1($user_input . $salt)
will change.
20c28df
to
75d0346
Compare
* This is needed, because some WordPress backups and exports may not include | ||
* definitions for some of the necessary constants. | ||
*/ | ||
await ensureWpConfig( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a good chance the WordPress site doesn't exist at this point. We'll need to run this at the right time during the Blueprint v2 lifecycle, e.g. after resolving the site. We could use this ensureWpConfig()
call ATM or inject an initial Blueprint step.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamziel I think that all of this logic makes sense only with the apply-to-existing-site
mode, right? For a new site, we always seem to copy the wp-config-sample.php
file. If none of wp-config.php
and wp-config-sample.php
exists, this will be a noop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced – the comment above this method call even says:
This is needed, because some WordPress backups and exports may not include
definitions for some of the necessary constants.
Which suggests we'll see data structures looking like existing sites that don't have these constants defined. Although, in those cases, I suppose the database won't be configured so they're not going to boot anyway. Hm. 🤔 Perhaps you're right and that only matters for new sites, after all?
Even then, we need to do it at the right time of the Blueprint v2 lifecycle – we'll typically download an unzip a WordPress release as a part of await this.runBlueprintV2(args);
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps you're right and that only matters for new sites, after all?
Actually, what I want to say is that ensureWpConfig
matters only for existing sites (--mode=apply-to-existing-site
). That is—you have a site dump in your directory, and maybe the wp-config.php
doesn't have some required configuration. This dump is not specified by Blueprint (v2), we can only apply some Blueprint to it.
Even then, we need to do it at the right time of the Blueprint v2 lifecycle – we'll typically download an unzip a WordPress release as a part of await this.runBlueprintV2(args);.
I guess the question is whether the ensureWpConfig
should be a Playground feature, or a Blueprint v2 feature. My thinking at the moment is that it is a runtime (Playground) feature. If a Blueprint v2 references or creates an invalid wp-config.php
, then it would be an invalid Blueprint.
With both v1 and v2, this can also happen:
- You have some constants missing in your existing site dump (e.g., Studio).
- We add the missing constants; a DB is provided (e.g., by Studio).
- Blueprint v1 or v2 is applied to an existing site.
- If the Blueprint messed up the config, we won't try to fix it at this stage.
When you create a new site from a Blueprint (even from a ZIP with missing config constants), then it wouldn't touch it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ensureWpConfig
matters only for existing sites
I'd like to learn more about the types of import you had in mind in here.
My thinking is we're talking about two separate data structures:
site
– a WordPress directory structure configured so that it's ready to run viaphp -S
site export
– a WordPress directory structure that requires processing before it can run
I'd say ensureWpConfig
is not needed for a site
at all. We're either running that site or making a change to it, e.g. by installing a plugin. For an site export
, however, we need to do some processing before we're able to run it. I assume most site exports were produced by an export tool that has an accompanying import tool.
We can process exports compatible with the Blueprint v2 bundle format, but I don't think there's any generalized way we can process an arbitrarily mangled site export – perhaps we should just bale out on it. Are we doing that now? Or would that be a change that would also break Studio?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamziel All of this makes me wonder if the most "correct" solution for Playground may indeed be to only throw an error and do nothing else when a constant is missing, just like php -S
would do.
Maybe this is not on the table now, and it would surely mean moving this logic to Studio, but I do wonder if there are other use cases where auto-backfilling missing constants is needed, or whether we've just gotten here due to some historic behaviors in wp-now
or somewhere. Originally, the fallbacks were done at runtime via an MU plugin, but now, when the config is processed statically, the logic could maybe live in Studio as well. I guess ultimately, the question is whether this is needed in Playground in a broader sense.
Otherwise, as for the next steps, I agree with your suggestions 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need something like this for new sites, too, but I guess the existing blueprint runners take care of that.
@adamziel As for this part, I think we currently only copy wp-config-sample.php
for new sites. Maybe we should update it to use some more reasonable defaults (e.g., for the salts and stuff).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah perhaps that's just a historic wp-now issue. It seems like we're really processing a site import, aren't we? Perhaps we could export a repair function for Studio to call on their own if needed. Or just move it there entirely by proposing a Studio PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamziel I agree. If we don't see any other use cases, maybe we really should consider contributing this to Studio. Thinking this through:
The WP_Config_Transformer logic will be needed in Blueprints v2 (and v1 runner as well, while it's around). If we move it to PHP toolkit, is there a way to reuse it from there in Studio and Blueprints v1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we move it to PHP toolkit, is there a way to reuse it from there in Studio and Blueprints v1?
There probably is, but let's not overcomplicate it for now and just do a copy&paste until we set up some infrastructure for reusing PHP toolkit.
} | ||
|
||
// Ensure required constants are defined. | ||
const js = phpVars({ wpConfigPath, constants: defaults }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We never need to do that now – you can pass these values via env:
php.run({
code: `<?php echo getenv("VALUE"); `,
env: { VALUE: 'yay!' }
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamziel Ah, nice! Will that preserve types and work with arrays, etc.?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, you need to json-serialize it
$transformer = Wp_Config_Transformer::from_file($wp_config_path); | ||
$transformer->define_constants(${js.constants}); | ||
$transformer->to_file($wp_config_path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great API
? { | ||
...args, | ||
'experimental-blueprints-v2-runner': true, | ||
mode: 'create-new-site', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused why this test passes given my comment above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamziel Calling ensureWpConfig
with a new site (no existing wp-config.php
nor wp-config-sample.php
) will be a noop, so this passes and creates a new wp-config.php
.
Motivation for the change, related issues
When a required WordPress configuration is missing, such as the
DB_NAME
constant, it will be added towp-config.php
on Playground boot in the following form:When such a block already exists, it will be first deleted and then injected again, if needed. This also means that when the block is no longer needed (a user defined the required constants), it will be removed.
The default constant values can be configured via
--wp-config-default-constants
.Resolves #2530.
Implementation details
Editing WP config for different reasons (default constants,
defineWpConfigConsts
Blueprint step) has been consolidated into a singleWp_Config_Transformer
class.Testing Instructions (or ideally a Blueprint)
./test-site/wp-config.php
file and remove some constants (e.g.,DB_NAME
).npx nx unbuilt-jspi playground-cli server --mount-before-install ./existing-site:/wordpress --skip-wordpress-setup --blueprint empty-blueprint.json --wp-config-default-constants='{"DB_NAME":"my-db-name"}'
./test-site/wp-config.php
. It should included the injected config.Then you can also put the originally removed constant back and rerun step 3. The injected block should disappear again.