77use QIT_CLI \Environment \EnvironmentMonitor ;
88use QIT_CLI \Environment \Environments \E2E \E2EEnvironment ;
99use QIT_CLI \Environment \Environments \E2E \E2EEnvInfo ;
10- use QIT_CLI \Environment \Environments \EnvInfo ;
11- use QIT_CLI \LocalTests \ Performance \Environment \ PerformanceEnvironment ;
12- use QIT_CLI \LocalTests \ Performance \ Environment \PerformanceEnvInfo ;
10+ use QIT_CLI \Environment \Environments \Performance \ PerformanceEnvironment ;
11+ use QIT_CLI \Environment \ Environments \ Performance \PerformanceEnvInfo ;
12+ use QIT_CLI \Environment \Environments \ QITEnvInfo ;
1313use QIT_CLI \QITInput ;
1414use QIT_CLI \Tunnel \TunnelRunner ;
1515use Symfony \Component \Console \Command \Command ;
@@ -268,9 +268,10 @@ protected function doExecute( QITInput $input, OutputInterface $output ): int {
268268 }
269269
270270 /* ─ 1. Build the *final* env config (config‑file ⊕ CLI) ─ */
271- $ env_name = $ input ->getOption ( 'environment ' ) ?? 'default ' ;
272- $ env_config = $ this ->get_environment_config ( $ env_name );
273- $ env_config = $ this ->applyCliOverrides ( $ env_config , $ input );
271+ $ env_name = $ input ->getOption ( 'environment ' ) ?? 'default ' ;
272+ $ environment_type = $ input ->getOption ( 'environment_type ' ) ?? 'e2e ' ;
273+ $ env_config = $ this ->get_environment_config ( $ env_name );
274+ $ env_config = $ this ->applyCliOverrides ( $ env_config , $ input , $ environment_type );
274275
275276 /* ─ 1.1. Add SUT as a plugin/theme if defined in qit.json ─ */
276277 $ sut = $ this ->get_resolved_sut ();
@@ -315,7 +316,7 @@ protected function doExecute( QITInput $input, OutputInterface $output ): int {
315316 $ this ->process_test_package_requirements ( $ env_config , $ input , $ output );
316317
317318 /* ─ 2. Resolve extensions using the merged config (includes CLI overrides) ─ */
318- $ resolved_ext = $ this ->download_extensions_from_config ( $ env_config );
319+ $ resolved_ext = $ this ->download_extensions_from_config ( $ env_config, $ environment_type );
319320
320321 /* ─ 3. Use the fully-resolved extension lists ─ */
321322 $ final_plugins = $ resolved_ext ->get_plugins ();
@@ -574,12 +575,15 @@ protected function doExecute( QITInput $input, OutputInterface $output ): int {
574575 }
575576
576577 /*
577- ─ 4. Materialise E2EEnvInfo DTO ─
578+ ─ 4. Materialise EnvInfo DTO ─
578579 */
579580
580- /** @var E2EEnvInfo $env_info */ $ env_info = E2EEnvInfo::from_array ( [
581+ $ env_info_class = $ this ->get_env_info_class ( $ environment_type );
582+
583+ /** @var E2EEnvInfo|PerformanceEnvInfo $env_info */
584+ $ env_info = $ env_info_class ::from_array ( [
581585 'env_id ' => 'qitenv ' . bin2hex ( random_bytes ( 8 ) ),
582- 'environment ' => ' e2e ' ,
586+ 'environment ' => $ environment_type ,
583587 'php ' => $ env_config ['php ' ] ?? '8.2 ' ,
584588 'wp ' => $ env_config ['wp ' ] ?? 'stable ' ,
585589 'woo ' => $ env_config ['woo ' ] ?? '' ,
@@ -615,8 +619,7 @@ protected function doExecute( QITInput $input, OutputInterface $output ): int {
615619 }
616620
617621 /* ─ 8. Bring the environment up ─ */
618- $ environment_type = $ input ->getOption ( 'environment_type ' ) ?? 'e2e ' ;
619- $ environment = $ this ->get_environment ( $ environment_type );
622+ $ environment = $ this ->get_environment ( $ environment_type );
620623 $ environment ->init ( $ env_info );
621624 $ environment ->up ();
622625
@@ -696,10 +699,11 @@ protected function get_environment( string $environment_type ): \QIT_CLI\Environ
696699 * This method processes the merged config that includes CLI overrides.
697700 *
698701 * @param array<string,mixed> $env_config
702+ * @param string $environment_type
699703 *
700704 * @return \QIT_CLI\PreCommand\Extensions\ResolvedExtensions
701705 */
702- private function download_extensions_from_config ( array $ env_config ): \QIT_CLI \PreCommand \Extensions \ResolvedExtensions {
706+ private function download_extensions_from_config ( array $ env_config, string $ environment_type = ' e2e ' ): \QIT_CLI \PreCommand \Extensions \ResolvedExtensions {
703707 $ extensions = [];
704708
705709 // Create Extension objects from plugins in the merged config
@@ -800,9 +804,12 @@ private function download_extensions_from_config( array $env_config ): \QIT_CLI\
800804 $ extensions = array_values ( $ unique );
801805
802806 // Resolve/download them using ExtensionResolver
803- $ env_info = \QIT_CLI \Environment \Environments \E2E \E2EEnvInfo::from_array ( [
807+ $ env_info_class = $ this ->get_env_info_class ( $ environment_type );
808+
809+ /** @var E2EEnvInfo|PerformanceEnvInfo $env_info */
810+ $ env_info = $ env_info_class ::from_array ( [
804811 'env_id ' => 'temp_ ' . bin2hex ( random_bytes ( 4 ) ),
805- 'environment ' => ' e2e ' ,
812+ 'environment ' => $ environment_type ,
806813 ] );
807814 $ resolver = \QIT_CLI \App::make ( \QIT_CLI \PreCommand \Extensions \ExtensionResolver::class );
808815
@@ -819,7 +826,7 @@ private function download_extensions_from_config( array $env_config ): \QIT_CLI\
819826 * @param InputInterface $input
820827 * @return array<string,mixed>
821828 */
822- private function applyCliOverrides ( array $ config , InputInterface $ input ): array {
829+ private function applyCliOverrides ( array $ config , InputInterface $ input, string $ environment_type ): array {
823830 // $input is actually a QITInput instance when called from our commands
824831
825832 /* ─ Scalars ─ */
@@ -848,7 +855,7 @@ private function applyCliOverrides( array $config, InputInterface $input ): arra
848855 }
849856
850857 /* ─ Resolve special versions and add plugins explicitly ─ */
851- $ config = $ this ->resolve_woo ( $ config , $ input );
858+ $ config = $ this ->resolve_woo ( $ config , $ input, $ environment_type );
852859 $ config = $ this ->resolve_wp ( $ config , $ input );
853860 if ( $ input ->hasOption ( 'object_cache ' ) ) {
854861 $ config ['object_cache ' ] = (bool ) $ input ->getOption ( 'object_cache ' );
@@ -940,19 +947,26 @@ private function applyCliOverrides( array $config, InputInterface $input ): arra
940947 /**
941948 * Resolve --woo option explicitly.
942949 * Adds WooCommerce plugin with the specified version.
950+ * For performance environments, defaults to 'latest' if not specified.
943951 *
944952 * @param array<string,mixed> $config
945953 * @param InputInterface $input
954+ * @param string $environment_type
946955 * @return array<string,mixed>
947956 */
948- private function resolve_woo ( array $ config , InputInterface $ input ): array {
957+ private function resolve_woo ( array $ config , InputInterface $ input, string $ environment_type = ' e2e ' ): array {
949958 /** @var \QIT_CLI\QITInput $input */
950- if ( ! $ input ->hasOption ( 'woo ' ) ) {
959+ if ( ! $ input ->hasOption ( 'woo ' ) && $ environment_type !== ' performance ' ) {
951960 return $ config ;
952961 }
953962
954963 $ woo_version = $ input ->getOption ( 'woo ' );
955964
965+ // For performance environments, default to 'latest' if not explicitly set
966+ if ( empty ( $ woo_version ) && $ environment_type === 'performance ' ) {
967+ $ woo_version = 'latest ' ;
968+ }
969+
956970 if ( empty ( $ woo_version ) ) {
957971 return $ config ;
958972 }
@@ -1026,9 +1040,9 @@ private function resolve_wp( array $config, InputInterface $input ): array {
10261040 /**
10271041 * Save environment info to a JSON file for later use.
10281042 *
1029- * @param E2EEnvInfo $env_info The environment info to save.
1043+ * @param E2EEnvInfo|PerformanceEnvInfo $env_info The environment info to save.
10301044 */
1031- private function save_environment_info ( E2EEnvInfo $ env_info ): void {
1045+ private function save_environment_info ( $ env_info ): void {
10321046 $ env_dir = $ this ->environment_vars ->get_env_directory ();
10331047 $ info_file = $ env_dir . '/ ' . $ env_info ->env_id . '.json ' ;
10341048
@@ -1038,7 +1052,7 @@ private function save_environment_info( E2EEnvInfo $env_info ): void {
10381052 'site_url ' => $ env_info ->site_url ,
10391053 'php ' => $ env_info ->php ,
10401054 'wp ' => $ env_info ->wp ,
1041- 'woo ' => $ env_info ->woo ,
1055+ 'woo ' => $ env_info ->woo ?? '' ,
10421056 'db_port ' => $ env_info ->db_port ?? 0 ,
10431057 'php_container ' => $ env_info ->php_container ?: 'qit_env_php_ ' . $ env_info ->env_id ,
10441058 'db_container ' => $ env_info ->db_container ?: 'qit_env_db_ ' . $ env_info ->env_id ,
@@ -1049,7 +1063,13 @@ private function save_environment_info( E2EEnvInfo $env_info ): void {
10491063 file_put_contents ( $ info_file , json_encode ( $ data , JSON_PRETTY_PRINT ) );
10501064 }
10511065
1052- private function renderHumanSummary ( OutputInterface $ out , EnvInfo $ info ): void {
1066+ /**
1067+ * Render a human-readable summary of the environment.
1068+ *
1069+ * @param OutputInterface $out The output interface.
1070+ * @param QITEnvInfo $info The environment info.
1071+ */
1072+ private function renderHumanSummary ( OutputInterface $ out , QITEnvInfo $ info ): void {
10531073 $ out ->writeln ( '' );
10541074 $ out ->writeln ( sprintf ( '<info>✅ Environment ready: %s</info> ' , $ info ->env_id ) );
10551075 $ out ->writeln ( '' );
@@ -1059,64 +1079,53 @@ private function renderHumanSummary( OutputInterface $out, EnvInfo $info ): void
10591079 $ out ->writeln ( ' Credentials: admin/password ' );
10601080
10611081 // Stack information
1062- if ( $ info instanceof E2EEnvInfo ) {
1063- $ stack_parts = [];
1064- $ stack_parts [] = sprintf ( 'WordPress %s ' , $ info ->wp );
1065- $ stack_parts [] = sprintf ( 'PHP %s ' , $ info ->php );
1066- $ out ->writeln ( sprintf ( ' Stack: %s ' , implode ( ', ' , $ stack_parts ) ) );
1067-
1068- // Plugins line (only if plugins exist)
1069- $ plugin_names = [];
1070- foreach ( $ info ->plugins as $ plugin ) {
1071- if ( $ plugin ->slug === 'woocommerce ' && $ info ->woo ) {
1072- $ plugin_names [] = sprintf ( 'WooCommerce %s ' , $ info ->woo );
1073- } elseif ( $ plugin ->slug !== 'woocommerce ' ) {
1074- $ plugin_names [] = sprintf ( '%s %s ' , $ this ->format_plugin_name ( $ plugin ->slug ), $ plugin ->version );
1075- }
1076- }
1077- if ( ! empty ( $ plugin_names ) ) {
1078- $ out ->writeln ( sprintf ( ' Plugins: %s ' , implode ( ', ' , $ plugin_names ) ) );
1082+ $ stack_parts = [];
1083+ $ stack_parts [] = sprintf ( 'WordPress %s ' , $ info ->wp );
1084+ $ stack_parts [] = sprintf ( 'PHP %s ' , $ info ->php );
1085+ $ out ->writeln ( sprintf ( ' Stack: %s ' , implode ( ', ' , $ stack_parts ) ) );
1086+
1087+ // Plugins line (only if plugins exist)
1088+ $ plugin_names = [];
1089+ foreach ( $ info ->plugins as $ plugin ) {
1090+ if ( $ plugin ->slug === 'woocommerce ' && $ info ->woo ) {
1091+ $ plugin_names [] = sprintf ( 'WooCommerce %s ' , $ info ->woo );
1092+ } elseif ( $ plugin ->slug !== 'woocommerce ' ) {
1093+ $ plugin_names [] = sprintf ( '%s %s ' , $ this ->format_plugin_name ( $ plugin ->slug ), $ plugin ->version );
10791094 }
1095+ }
1096+ if ( ! empty ( $ plugin_names ) ) {
1097+ $ out ->writeln ( sprintf ( ' Plugins: %s ' , implode ( ', ' , $ plugin_names ) ) );
1098+ }
10801099
1081- // Theme line (only if non-default theme exists)
1082- $ theme_names = [];
1083- foreach ( $ info ->themes as $ theme ) {
1084- // Skip default themes
1085- if ( ! in_array ( $ theme ->slug , [ 'twentytwentyfour ' , 'twentytwentythree ' , 'twentytwentytwo ' ], true ) ) {
1086- $ theme_names [] = sprintf ( '%s %s ' , $ this ->format_plugin_name ( $ theme ->slug ), $ theme ->version );
1087- }
1088- }
1089- if ( ! empty ( $ theme_names ) ) {
1090- $ out ->writeln ( sprintf ( ' Theme: %s ' , implode ( ', ' , $ theme_names ) ) );
1100+ // Theme line (only if non-default theme exists)
1101+ $ theme_names = [];
1102+ foreach ( $ info ->themes as $ theme ) {
1103+ // Skip default themes
1104+ if ( ! in_array ( $ theme ->slug , [ 'twentytwentyfour ' , 'twentytwentythree ' , 'twentytwentytwo ' ], true ) ) {
1105+ $ theme_names [] = sprintf ( '%s %s ' , $ this ->format_plugin_name ( $ theme ->slug ), $ theme ->version );
10911106 }
1107+ }
1108+ if ( ! empty ( $ theme_names ) ) {
1109+ $ out ->writeln ( sprintf ( ' Theme: %s ' , implode ( ', ' , $ theme_names ) ) );
1110+ }
10921111
1093- // Test packages that were set up
1094- if ( ! empty ( $ info ->test_packages_for_setup ) ) {
1095- $ out ->writeln ( '' );
1096- $ out ->writeln ( ' Test packages prepared: ' );
1097- if ( $ info ->skip_test_phases ) {
1098- // When phases are skipped, just list the packages
1099- foreach ( $ info ->test_packages_for_setup as $ pkg_id => $ pkg_info ) {
1100- $ out ->writeln ( sprintf ( ' • %s (phases deferred) ' , $ pkg_id ) );
1101- }
1102- } else {
1103- // When phases ran, show which phases ran for each package
1104- $ is_first = true ;
1105- foreach ( $ info ->test_packages_for_setup as $ pkg_id => $ pkg_info ) {
1106- $ phases = $ is_first ? 'globalSetup + setup ' : 'globalSetup only ' ;
1107- $ out ->writeln ( sprintf ( ' • %s (%s) ' , $ pkg_id , $ phases ) );
1108- $ is_first = false ;
1109- }
1112+ // Test packages that were set up
1113+ if ( ! empty ( $ info ->test_packages_for_setup ) ) {
1114+ $ out ->writeln ( '' );
1115+ $ out ->writeln ( ' Test packages prepared: ' );
1116+ if ( $ info ->skip_test_phases ) {
1117+ // When phases are skipped, just list the packages
1118+ foreach ( $ info ->test_packages_for_setup as $ pkg_id => $ pkg_info ) {
1119+ $ out ->writeln ( sprintf ( ' • %s (phases deferred) ' , $ pkg_id ) );
1120+ }
1121+ } else {
1122+ // When phases ran, show which phases ran for each package
1123+ $ is_first = true ;
1124+ foreach ( $ info ->test_packages_for_setup as $ pkg_id => $ pkg_info ) {
1125+ $ phases = $ is_first ? 'globalSetup + setup ' : 'globalSetup only ' ;
1126+ $ out ->writeln ( sprintf ( ' • %s (%s) ' , $ pkg_id , $ phases ) );
1127+ $ is_first = false ;
11101128 }
1111- }
1112- } elseif ( $ info instanceof PerformanceEnvInfo ) {
1113- $ stack_parts = [];
1114- $ stack_parts [] = sprintf ( 'WordPress %s ' , $ info ->wp );
1115- $ stack_parts [] = sprintf ( 'PHP %s ' , $ info ->php_version );
1116- $ out ->writeln ( sprintf ( ' Stack: %s ' , implode ( ', ' , $ stack_parts ) ) );
1117-
1118- if ( property_exists ( $ info , 'woo ' ) && $ info ->woo ) {
1119- $ out ->writeln ( sprintf ( ' Plugins: WooCommerce %s ' , $ info ->woo ) );
11201129 }
11211130 }
11221131
@@ -1294,9 +1303,6 @@ private function determineMainPackage( array $packages, OutputInterface $output
12941303 return $ packages [0 ];
12951304 }
12961305
1297- /**
1298- * Run test setup phases from qit-test.json if present.
1299-
13001306 /**
13011307 * Process test packages to extract requirements.
13021308 *
@@ -1495,10 +1501,10 @@ private function convert_sut_to_extension( array $sut ): array {
14951501 * Create a database backup for env:reset functionality.
14961502 * This backup captures the state after all setup phases have completed.
14971503 *
1498- * @param E2EEnvInfo $env_info The environment info.
1499- * @param OutputInterface $output The output interface.
1504+ * @param E2EEnvInfo|PerformanceEnvInfo $env_info The environment info.
1505+ * @param OutputInterface $output The output interface.
15001506 */
1501- private function createDatabaseBackup ( E2EEnvInfo $ env_info , OutputInterface $ output ): void {
1507+ private function createDatabaseBackup ( $ env_info , OutputInterface $ output ): void {
15021508 $ output ->write ( 'Creating database backup for env:reset... ' );
15031509
15041510 // Create backup directory
@@ -1522,7 +1528,7 @@ private function createDatabaseBackup( E2EEnvInfo $env_info, OutputInterface $ou
15221528 'test_packages ' => array_keys ( $ env_info ->test_packages_for_setup ),
15231529 'php ' => $ env_info ->php ,
15241530 'wp ' => $ env_info ->wp ,
1525- 'woo ' => $ env_info ->woo ,
1531+ 'woo ' => $ env_info ->woo ?? '' ,
15261532 ];
15271533 file_put_contents ( $ backup_dir . '/metadata.json ' , json_encode ( $ metadata , JSON_PRETTY_PRINT ) );
15281534
@@ -1534,4 +1540,16 @@ private function createDatabaseBackup( E2EEnvInfo $env_info, OutputInterface $ou
15341540 $ output ->writeln ( '<comment>Note: env:reset will not be available for this environment.</comment> ' );
15351541 }
15361542 }
1543+
1544+ /**
1545+ * Get the appropriate EnvInfo class based on environment type.
1546+ *
1547+ * @param string $environment_type The environment type ('performance' or 'e2e').
1548+ * @return class-string<E2EEnvInfo|PerformanceEnvInfo> The EnvInfo class name.
1549+ */
1550+ private function get_env_info_class ( string $ environment_type ): string {
1551+ return $ environment_type === 'performance '
1552+ ? PerformanceEnvInfo::class
1553+ : E2EEnvInfo::class;
1554+ }
15371555}
0 commit comments