diff --git a/includes/Hooks/CreateWikiHookRunner.php b/includes/Hooks/CreateWikiHookRunner.php index 0a64804ebb..dcfc2670a0 100644 --- a/includes/Hooks/CreateWikiHookRunner.php +++ b/includes/Hooks/CreateWikiHookRunner.php @@ -16,6 +16,7 @@ class CreateWikiHookRunner implements CreateWikiReadPersistentModelHook, CreateWikiRemoteWikiCommitHook, CreateWikiRenameHook, + CreateWikiSetContainersAccessFailedHook, CreateWikiStateClosedHook, CreateWikiStateOpenHook, CreateWikiStatePrivateHook, @@ -110,6 +111,14 @@ public function onCreateWikiRename( ); } + /** @inheritDoc */ + public function onCreateWikiSetContainersAccessFailed( string $dir, string $zone ): bool { + return $this->hookContainer->run( + 'CreateWikiSetContainersAccessFailed', + [ $dir, $zone ] + ); + } + /** @inheritDoc */ public function onCreateWikiStateClosed( string $dbname ): void { $this->hookContainer->run( diff --git a/includes/Hooks/CreateWikiSetContainersAccessFailedHook.php b/includes/Hooks/CreateWikiSetContainersAccessFailedHook.php new file mode 100644 index 0000000000..9a5edd5586 --- /dev/null +++ b/includes/Hooks/CreateWikiSetContainersAccessFailedHook.php @@ -0,0 +1,14 @@ +getServiceContainer(); + $this->hookRunner = $services->get( 'CreateWikiHookRunner' ); $this->remoteWikiFactory = $services->get( 'RemoteWikiFactory' ); } public function execute(): void { $this->initServices(); + $this->processContainers(); + + if ( $this->needsRetry && !$this->isRetrying ) { + $this->isRetrying = true; + $this->needsRetry = false; + + $this->processContainers(); + } + } + private function processContainers(): void { $repo = $this->getServiceContainer()->getRepoGroup()->getLocalRepo(); $backend = $repo->getBackend(); @@ -38,22 +54,24 @@ public function execute(): void { ); $isPrivate = $remoteWiki->isPrivate(); - - foreach ( $this->getConfig()->get( ConfigNames::Containers ) as $zone => $status ) { + foreach ( $this->getConfig()->get( ConfigNames::Containers ) as $zone => $state ) { $dir = $backend->getContainerStoragePath( $zone ); - $private = $status === 'private'; - $publicPrivate = $status === 'public-private'; + + $private = $state === 'private'; + $publicPrivate = $state === 'public-private'; + $secure = ( $private || ( $publicPrivate && $isPrivate ) ) ? [ 'noAccess' => true, 'noListing' => true ] : []; - $this->prepareDirectory( $backend, $dir, $secure ); + $this->prepareDirectory( $backend, $secure, $dir, $zone ); } } - protected function prepareDirectory( + private function prepareDirectory( FileBackend $backend, + array $secure, string $dir, - array $secure + string $zone ): void { // Create zone if it doesn't exist... $this->output( "Making sure '$dir' exists..." ); @@ -61,7 +79,8 @@ protected function prepareDirectory( $status = $backend->prepare( [ 'dir' => $dir ] + $secure ); if ( !$status->isOK() ) { - $this->output( 'failed...' ); + $this->handleFailure( $status, $dir, $zone ); + return; } // Make sure zone has the right ACLs... @@ -75,11 +94,32 @@ protected function prepareDirectory( $status->merge( $backend->publish( [ 'dir' => $dir, 'access' => true ] ) ); } - if ( $status->isOK() ) { - $this->output( "done.\n" ); - } else { - $this->output( "failed.\n" ); - print_r( $status->getMessages( 'error' ) ); + if ( !$status->isOK() ) { + $this->handleFailure( $status, $dir, $zone ); + return; + } + + $this->output( "done.\n" ); + } + + private function handleFailure( + StatusValue $status, + string $dir, + string $zone + ): void { + if ( $this->isRetrying ) { + $this->output( "retry failed.\n" ); + $this->error( $status ); + return; + } + + $this->output( "failed.\n" ); + $this->error( $status ); + + if ( $this->hookRunner->onCreateWikiSetContainersAccessFailed( $dir, $zone ) ) { + // If the hook returned true, we can try this script one time. + $this->output( "retrying.\n" ); + $this->needsRetry = true; } } }