@@ -30,10 +30,13 @@ class NextcloudApiContext implements Context {
3030 protected RunServerListener $ server ;
3131 protected string $ currentUser = '' ;
3232 protected array $ fields = [];
33+ protected static array $ environments = [];
34+ protected static string $ commandOutput = '' ;
35+
3336 /**
3437 * @var string[]
3538 */
36- protected array $ createdUsers = [];
39+ protected static array $ createdUsers = [];
3740 protected ResponseInterface $ response ;
3841 /** @var CookieJar[] */
3942 protected $ cookieJars ;
@@ -66,8 +69,9 @@ public static function beforeSuite(BeforeSuiteScope $scope):void {
6669 }
6770
6871 #[BeforeScenario()]
69- public function setUp (): void {
70- $ this ->createdUsers = [];
72+ public function beforeScenario (): void {
73+ self ::$ createdUsers = [];
74+ self ::$ environments = [];
7175 }
7276
7377 #[Given('as user :user ' )]
@@ -110,7 +114,7 @@ protected function createUser(string $user): void {
110114 $ this ->sendOCSRequest ('GET ' , '/cloud/users ' . '/ ' . $ user );
111115 $ this ->assertStatusCode ($ this ->response , 200 , 'Failed to do first login ' );
112116
113- $ this -> createdUsers [] = $ user ;
117+ self :: $ createdUsers [] = $ user ;
114118
115119 $ this ->setCurrentUser ($ currentUser );
116120 }
@@ -448,9 +452,102 @@ protected function parseText(string $text): string {
448452 return $ text ;
449453 }
450454
455+ #[Given('/^run the command "(?P<command>(?:[^"]| \\")*)"$/ ' )]
456+ public static function runCommand (string $ command ): array {
457+ $ console = static ::findParentDirContainingFile ('console.php ' );
458+ $ console .= '/console.php ' ;
459+ $ fileOwnerUid = fileowner ($ console );
460+ if (!is_int ($ fileOwnerUid )) {
461+ throw new \Exception ('The console file owner of ' . $ console . ' is not an integer UID. ' );
462+ }
463+ $ owner = posix_getpwuid ($ fileOwnerUid );
464+ if ($ owner === false ) {
465+ throw new \Exception ('Could not retrieve owner information for UID ' . $ fileOwnerUid );
466+ }
467+ $ fullCommand = 'php ' . $ console . ' ' . $ command ;
468+ if (!empty (self ::$ environments )) {
469+ $ fullCommand = http_build_query (self ::$ environments , '' , ' ' ) . ' ' . $ fullCommand ;
470+ }
471+ if (posix_getuid () !== $ owner ['uid ' ]) {
472+ $ fullCommand = 'runuser -u ' . $ owner ['name ' ] . ' -- ' . $ fullCommand ;
473+ }
474+ $ fullCommand .= ' 2>&1 ' ;
475+ return self ::runBashCommand ($ fullCommand );
476+ }
477+
478+ public static function findParentDirContainingFile (string $ filename ): string {
479+ $ dir = getcwd ();
480+ if (is_bool ($ dir )) {
481+ throw new \Exception ('Could not get current working directory (getcwd() returned false) ' );
482+ }
483+
484+ while ($ dir !== dirname ($ dir )) {
485+ if (file_exists ($ dir . DIRECTORY_SEPARATOR . $ filename )) {
486+ return $ dir ;
487+ }
488+ $ dir = dirname ($ dir );
489+ }
490+
491+ throw new \Exception ('The file ' . $ filename . ' was not found in the parent directories of ' . $ dir );
492+ }
493+
494+ private static function runBashCommand (string $ command ): array {
495+ $ command = str_replace ('\" ' , '" ' , $ command );
496+ $ patterns = [];
497+ $ replacements = [];
498+ $ fields = [
499+ 'appRootDir ' => static ::findParentDirContainingFile ('appinfo ' ),
500+ 'nextcloudRootDir ' => static ::findParentDirContainingFile ('console.php ' ),
501+ ];
502+ foreach ($ fields as $ key => $ value ) {
503+ $ patterns [] = '/< ' . $ key . '>/ ' ;
504+ $ replacements [] = $ value ;
505+ }
506+ $ command = preg_replace ($ patterns , $ replacements , $ command );
507+ if (!is_string ($ command )) {
508+ throw new \Exception ('The command is not a string after preg_replace: ' . print_r ($ command , true ));
509+ }
510+
511+ exec ($ command , $ output , $ resultCode );
512+ self ::$ commandOutput = implode ("\n" , $ output );
513+ return [
514+ 'command ' => $ command ,
515+ 'output ' => $ output ,
516+ 'resultCode ' => $ resultCode ,
517+ ];
518+ }
519+
520+ #[Given('the output of the last command should contain the following text: ' )]
521+ public static function theOutputOfTheLastCommandContains (PyStringNode $ text ): void {
522+ Assert::assertStringContainsString ((string ) $ text , self ::$ commandOutput , 'The output of the last command does not contain: ' . $ text );
523+ }
524+
525+ #[Given('the output of the last command should be empty ' )]
526+ public static function theOutputOfTheLastCommandShouldBeEmpty (): void {
527+ Assert::assertEmpty (self ::$ commandOutput , 'The output of the last command should be empty, but got: ' . self ::$ commandOutput );
528+ }
529+
530+ #[Given('/^run the command "(?P<command>(?:[^"]| \\")*)" with result code (\d+)$/ ' )]
531+ public static function runCommandWithResultCode (string $ command , int $ resultCode = 0 ): void {
532+ $ return = self ::runCommand ($ command );
533+ Assert::assertEquals ($ resultCode , $ return ['resultCode ' ], print_r ($ return , true ));
534+ }
535+
536+ #[Given('/^run the bash command "(?P<command>(?:[^"]| \\")*)" with result code (\d+)$/ ' )]
537+ public static function runBashCommandWithResultCode (string $ command , int $ resultCode = 0 ): void {
538+ $ return = self ::runBashCommand ($ command );
539+ Assert::assertEquals ($ resultCode , $ return ['resultCode ' ], print_r ($ return , true ));
540+ }
541+
542+ #[Given('create an environment :name with value :value to be used by occ command ' )]
543+ public static function createAnEnvironmentWithValueToBeUsedByOccCommand (string $ name , string $ value ):void {
544+ self ::$ environments [$ name ] = $ value ;
545+ }
546+
451547 #[AfterScenario()]
452548 public function tearDown (): void {
453- foreach ($ this ->createdUsers as $ user ) {
549+ self ::$ environments = [];
550+ foreach (self ::$ createdUsers as $ user ) {
454551 $ this ->deleteUser ($ user );
455552 }
456553 }
@@ -461,7 +558,7 @@ protected function deleteUser(string $user): ResponseInterface {
461558 $ this ->sendOCSRequest ('DELETE ' , '/cloud/users/ ' . $ user );
462559 $ this ->setCurrentUser ($ currentUser );
463560
464- unset($ this -> createdUsers [array_search ($ user , $ this -> createdUsers , true )]);
561+ unset(self :: $ createdUsers [array_search ($ user , self :: $ createdUsers , true )]);
465562
466563 return $ this ->response ;
467564 }
0 commit comments