@@ -448,6 +448,79 @@ protected function parseText(string $text): string {
448448 return $ text ;
449449 }
450450
451+ #[Given('/^run the command "(?P<command>(?:[^"]| \\")*)"$/ ' )]
452+ public static function runCommand (string $ command ): array {
453+ $ console = self ::findParentDirContainingFile ('console.php ' );
454+ $ console .= '/console.php ' ;
455+ $ fileOwnerUid = fileowner ($ console );
456+ if (!is_int ($ fileOwnerUid )) {
457+ throw new \Exception ('The console file owner of ' . $ console . ' is not an integer UID. ' );
458+ }
459+ $ owner = posix_getpwuid ($ fileOwnerUid );
460+ if ($ owner === false ) {
461+ throw new \Exception ('Could not retrieve owner information for UID ' . $ fileOwnerUid );
462+ }
463+ $ fullCommand = 'php ' . $ console . ' ' . $ command ;
464+ if (posix_getuid () !== $ owner ['uid ' ]) {
465+ $ fullCommand = 'runuser -u ' . $ owner ['name ' ] . ' -- ' . $ fullCommand ;
466+ }
467+ $ fullCommand .= ' 2>&1 ' ;
468+ return self ::runBashCommand ($ fullCommand );
469+ }
470+
471+ public static function findParentDirContainingFile (string $ filename ): string {
472+ $ dir = getcwd ();
473+ if (is_bool ($ dir )) {
474+ throw new \Exception ('Could not get current working directory (getcwd() returned false) ' );
475+ }
476+
477+ while ($ dir !== dirname ($ dir )) {
478+ if (file_exists ($ dir . DIRECTORY_SEPARATOR . $ filename )) {
479+ return $ dir ;
480+ }
481+ $ dir = dirname ($ dir );
482+ }
483+
484+ throw new \Exception ('The file ' . $ filename . ' was not found in the parent directories of ' . $ dir );
485+ }
486+
487+ private static function runBashCommand (string $ command ): array {
488+ $ command = str_replace ('\" ' , '" ' , $ command );
489+ $ patterns = [];
490+ $ replacements = [];
491+ $ fields = [
492+ 'appRootDir ' => self ::findParentDirContainingFile ('appinfo ' ),
493+ 'nextcloudRootDir ' => self ::findParentDirContainingFile ('console.php ' ),
494+ ];
495+ foreach ($ fields as $ key => $ value ) {
496+ $ patterns [] = '/< ' . $ key . '>/ ' ;
497+ $ replacements [] = $ value ;
498+ }
499+ $ command = preg_replace ($ patterns , $ replacements , $ command );
500+ if (!is_string ($ command )) {
501+ throw new \Exception ('The command is not a string after preg_replace: ' . print_r ($ command , true ));
502+ }
503+
504+ exec ($ command , $ output , $ resultCode );
505+ return [
506+ 'command ' => $ command ,
507+ 'output ' => $ output ,
508+ 'resultCode ' => $ resultCode ,
509+ ];
510+ }
511+
512+ #[Given('/^run the command "(?P<command>(?:[^"]| \\")*)" with result code (\d+)$/ ' )]
513+ public static function runCommandWithResultCode (string $ command , int $ resultCode = 0 ): void {
514+ $ return = self ::runCommand ($ command );
515+ Assert::assertEquals ($ resultCode , $ return ['resultCode ' ], print_r ($ return , true ));
516+ }
517+
518+ #[Given('/^run the bash command "(?P<command>(?:[^"]| \\")*)" with result code (\d+)$/ ' )]
519+ public static function runBashCommandWithResultCode (string $ command , int $ resultCode = 0 ): void {
520+ $ return = self ::runBashCommand ($ command );
521+ Assert::assertEquals ($ resultCode , $ return ['resultCode ' ], print_r ($ return , true ));
522+ }
523+
451524 #[AfterScenario()]
452525 public function tearDown (): void {
453526 foreach ($ this ->createdUsers as $ user ) {
0 commit comments