Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/playground/blueprints/src/lib/steps/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ export type LoginStep = {
/**
* Logs in to Playground.
* Under the hood, this function sets the `PLAYGROUND_AUTO_LOGIN_AS_USER` constant.
* The `0-auto-login.php` mu-plugin uses that constant to log in the user on the first load.
* The `1-auto-login.php` mu-plugin uses that constant to log in the user on the first load.
* This step depends on the `@wp-playground/wordpress` package because
* the plugin is located in and loaded automatically by the `@wp-playground/wordpress` package.
*
* In the CLI, the `--login` flag injects this constant at boot time via
* `mergeDefinedConstants` so every worker has it before the server starts.
*/
export const login: StepHandler<LoginStep> = async (
playground,
Expand All @@ -39,6 +42,5 @@ export const login: StepHandler<LoginStep> = async (
) => {
progress?.tracker.setCaption(progress?.initialCaption || 'Logging in');

// TODO: Make defineConstant apply to all workers
playground.defineConstant('PLAYGROUND_AUTO_LOGIN_AS_USER', username);
};
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ export class BlueprintsV1Handler {
withXdebug: !!this.args.xdebug,
nativeInternalDirPath,
pathAliases: this.args.pathAliases,
constants: mergeDefinedConstants(this.args),
});
await playground.isReady();
return playground;
Expand Down Expand Up @@ -237,7 +238,7 @@ export class BlueprintsV1Handler {
return isBlueprintBundle(resolvedBlueprint)
? resolvedBlueprint
: {
login: this.args.login,
login: this.getEffectiveLogin(),
...(resolvedBlueprint || {}),
preferredVersions: {
php:
Expand All @@ -252,4 +253,20 @@ export class BlueprintsV1Handler {
},
};
}

/**
* When the user explicitly sets PLAYGROUND_AUTO_LOGIN_AS_USER via
* --define, skip the blueprint login step — the boot-time constant
* from mergeDefinedConstants already handles auto-login and the
* blueprint step would overwrite the custom username with 'admin'.
*/
private getEffectiveLogin(): boolean {
if (!this.args.login) {
return false;
}
if (this.args.define?.['PLAYGROUND_AUTO_LOGIN_AS_USER']) {
return false;
}
return true;
}
}
2 changes: 2 additions & 0 deletions packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ interface WorkerBootRequestHandlerOptions {
withMemcached?: boolean;
withXdebug?: boolean;
pathAliases?: PathAlias[];
constants?: Record<string, string | number | boolean>;
}

/**
Expand Down Expand Up @@ -162,6 +163,7 @@ export class PlaygroundCliBlueprintV1Worker extends PHPWorker {
const requestHandler = await bootRequestHandler({
siteUrl: options.siteUrl,
maxPhpInstances: 1,
constants: options.constants,
createPhpRuntime: createPhpRuntimeFactory(
options,
this.fileLockManager!
Expand Down
13 changes: 12 additions & 1 deletion packages/playground/cli/src/defines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,17 +172,28 @@ function mergeConstants(
/**
* Merge all constants from CLI arguments.
*
* When `login` is true, `PLAYGROUND_AUTO_LOGIN_AS_USER` is injected so that
* every PHP worker defines the constant at boot time — not just the single
* worker that would run the blueprint `login` step via the pool proxy.
*
* @param args - CLI arguments
* @returns Merged constants
*/
export function mergeDefinedConstants(args: {
define?: Record<string, string>;
'define-bool'?: Record<string, boolean>;
'define-number'?: Record<string, number>;
login?: boolean;
}): Record<string, string | number | boolean> {
return mergeConstants(
const merged = mergeConstants(
args['define'],
args['define-bool'],
args['define-number']
);

if (args.login && !Object.hasOwn(merged, 'PLAYGROUND_AUTO_LOGIN_AS_USER')) {
Comment thread
ashfame marked this conversation as resolved.
merged['PLAYGROUND_AUTO_LOGIN_AS_USER'] = 'admin';
}
Comment thread
ashfame marked this conversation as resolved.

return merged;
}
61 changes: 61 additions & 0 deletions packages/playground/cli/tests/merge-defined-constants.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { mergeDefinedConstants } from '../src/defines';

describe('mergeDefinedConstants', () => {
it('should merge string, boolean, and number constants', () => {
const result = mergeDefinedConstants({
define: { API_KEY: 'secret' },
'define-bool': { WP_DEBUG: true },
'define-number': { LIMIT: 100 },
});
expect(result).toEqual({
API_KEY: 'secret',
WP_DEBUG: true,
LIMIT: 100,
});
});

it('should return empty object when no constants are provided', () => {
const result = mergeDefinedConstants({});
expect(result).toEqual({});
});

it('should inject PLAYGROUND_AUTO_LOGIN_AS_USER when login is true', () => {
const result = mergeDefinedConstants({ login: true });
expect(result).toEqual({
PLAYGROUND_AUTO_LOGIN_AS_USER: 'admin',
});
});

it('should not inject login constant when login is false', () => {
const result = mergeDefinedConstants({ login: false });
expect(result).toEqual({});
});

it('should not inject login constant when login is undefined', () => {
const result = mergeDefinedConstants({});
expect(result).toEqual({});
});

it('should not override explicit PLAYGROUND_AUTO_LOGIN_AS_USER from --define', () => {
const result = mergeDefinedConstants({
define: { PLAYGROUND_AUTO_LOGIN_AS_USER: 'editor' },
login: true,
});
expect(result).toEqual({
PLAYGROUND_AUTO_LOGIN_AS_USER: 'editor',
});
});

it('should preserve other constants alongside the injected login constant', () => {
const result = mergeDefinedConstants({
define: { API_KEY: 'secret' },
'define-bool': { WP_DEBUG: true },
login: true,
});
expect(result).toEqual({
API_KEY: 'secret',
WP_DEBUG: true,
PLAYGROUND_AUTO_LOGIN_AS_USER: 'admin',
});
});
});
Loading