Multiple fix for files externaltags/v26.0.0beta1
@@ -36,20 +36,9 @@ use Symfony\Component\Console\Input\InputOption; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class Applicable extends Base { | |||
/** | |||
* @var GlobalStoragesService | |||
*/ | |||
protected $globalService; | |||
/** | |||
* @var IUserManager | |||
*/ | |||
private $userManager; | |||
/** | |||
* @var IGroupManager | |||
*/ | |||
private $groupManager; | |||
protected GlobalStoragesService $globalService; | |||
private IUserManager $userManager; | |||
private IGroupManager $groupManager; | |||
public function __construct( | |||
GlobalStoragesService $globalService, | |||
@@ -62,7 +51,7 @@ class Applicable extends Base { | |||
$this->groupManager = $groupManager; | |||
} | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:applicable') | |||
->setDescription('Manage applicable users and groups for a mount') |
@@ -33,8 +33,7 @@ use Symfony\Component\Console\Input\InputInterface; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class Backends extends Base { | |||
/** @var BackendService */ | |||
private $backendService; | |||
private BackendService $backendService; | |||
public function __construct(BackendService $backendService | |||
) { | |||
@@ -43,7 +42,7 @@ class Backends extends Base { | |||
$this->backendService = $backendService; | |||
} | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:backends') | |||
->setDescription('Show available authentication and storage backends') |
@@ -33,17 +33,14 @@ use Symfony\Component\Console\Input\InputInterface; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class Config extends Base { | |||
/** | |||
* @var GlobalStoragesService | |||
*/ | |||
protected $globalService; | |||
protected GlobalStoragesService $globalService; | |||
public function __construct(GlobalStoragesService $globalService) { | |||
parent::__construct(); | |||
$this->globalService = $globalService; | |||
} | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:config') | |||
->setDescription('Manage backend configuration for a mount') |
@@ -34,6 +34,7 @@ use OCA\Files_External\Lib\StorageConfig; | |||
use OCA\Files_External\Service\BackendService; | |||
use OCA\Files_External\Service\GlobalStoragesService; | |||
use OCA\Files_External\Service\UserStoragesService; | |||
use OCA\Files_External\Service\StoragesService; | |||
use OCP\IUserManager; | |||
use OCP\IUserSession; | |||
use Symfony\Component\Console\Input\ArrayInput; | |||
@@ -43,26 +44,11 @@ use Symfony\Component\Console\Input\InputOption; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class Create extends Base { | |||
/** | |||
* @var GlobalStoragesService | |||
*/ | |||
private $globalService; | |||
/** | |||
* @var UserStoragesService | |||
*/ | |||
private $userService; | |||
/** | |||
* @var IUserManager | |||
*/ | |||
private $userManager; | |||
/** @var BackendService */ | |||
private $backendService; | |||
/** @var IUserSession */ | |||
private $userSession; | |||
private GlobalStoragesService $globalService; | |||
private UserStoragesService $userService; | |||
private IUserManager $userManager; | |||
private BackendService $backendService; | |||
private IUserSession $userSession; | |||
public function __construct(GlobalStoragesService $globalService, | |||
UserStoragesService $userService, | |||
@@ -78,7 +64,7 @@ class Create extends Base { | |||
$this->backendService = $backendService; | |||
} | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:create') | |||
->setDescription('Create a new mount configuration') | |||
@@ -119,7 +105,7 @@ class Create extends Base { | |||
} | |||
protected function execute(InputInterface $input, OutputInterface $output): int { | |||
$user = (string) $input->getOption('user'); | |||
$user = (string)$input->getOption('user'); | |||
$mountPoint = $input->getArgument('mount_point'); | |||
$storageIdentifier = $input->getArgument('storage_backend'); | |||
$authIdentifier = $input->getArgument('authentication_backend'); | |||
@@ -187,7 +173,7 @@ class Create extends Base { | |||
return 0; | |||
} | |||
private function validateParam($key, &$value, Backend $storageBackend, AuthMechanism $authBackend) { | |||
private function validateParam(string $key, &$value, Backend $storageBackend, AuthMechanism $authBackend): bool { | |||
$params = array_merge($storageBackend->getParameters(), $authBackend->getParameters()); | |||
foreach ($params as $param) { | |||
/** @var DefinitionParameter $param */ | |||
@@ -201,7 +187,7 @@ class Create extends Base { | |||
return false; | |||
} | |||
private function showMount($user, StorageConfig $mount, InputInterface $input, OutputInterface $output) { | |||
private function showMount(string $user, StorageConfig $mount, InputInterface $input, OutputInterface $output): void { | |||
$listCommand = new ListCommand($this->globalService, $this->userService, $this->userSession, $this->userManager); | |||
$listInput = new ArrayInput([], $listCommand->getDefinition()); | |||
$listInput->setOption('output', $input->getOption('output')); | |||
@@ -209,7 +195,7 @@ class Create extends Base { | |||
$listCommand->listMounts($user, [$mount], $listInput, $output); | |||
} | |||
protected function getStorageService($userId) { | |||
protected function getStorageService(string $userId): StoragesService { | |||
if (!empty($userId)) { | |||
$user = $this->userManager->get($userId); | |||
if (is_null($user)) { |
@@ -37,25 +37,10 @@ use Symfony\Component\Console\Output\OutputInterface; | |||
use Symfony\Component\Console\Question\ConfirmationQuestion; | |||
class Delete extends Base { | |||
/** | |||
* @var GlobalStoragesService | |||
*/ | |||
protected $globalService; | |||
/** | |||
* @var UserStoragesService | |||
*/ | |||
protected $userService; | |||
/** | |||
* @var IUserSession | |||
*/ | |||
protected $userSession; | |||
/** | |||
* @var IUserManager | |||
*/ | |||
protected $userManager; | |||
protected GlobalStoragesService $globalService; | |||
protected UserStoragesService $userService; | |||
protected IUserSession $userSession; | |||
protected IUserManager $userManager; | |||
public function __construct(GlobalStoragesService $globalService, UserStoragesService $userService, IUserSession $userSession, IUserManager $userManager) { | |||
parent::__construct(); | |||
@@ -65,7 +50,7 @@ class Delete extends Base { | |||
$this->userManager = $userManager; | |||
} | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:delete') | |||
->setDescription('Delete an external mount') |
@@ -29,7 +29,7 @@ use Symfony\Component\Console\Input\InputOption; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class Export extends ListCommand { | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:export') | |||
->setDescription('Export mount configurations') |
@@ -40,31 +40,12 @@ use Symfony\Component\Console\Input\InputOption; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class Import extends Base { | |||
/** | |||
* @var GlobalStoragesService | |||
*/ | |||
private $globalService; | |||
/** | |||
* @var UserStoragesService | |||
*/ | |||
private $userService; | |||
/** | |||
* @var IUserSession | |||
*/ | |||
private $userSession; | |||
/** | |||
* @var IUserManager | |||
*/ | |||
private $userManager; | |||
/** @var ImportLegacyStoragesService */ | |||
private $importLegacyStorageService; | |||
/** @var BackendService */ | |||
private $backendService; | |||
private GlobalStoragesService $globalService; | |||
private UserStoragesService $userService; | |||
private IUserSession $userSession; | |||
private IUserManager $userManager; | |||
private ImportLegacyStoragesService $importLegacyStorageService; | |||
private BackendService $backendService; | |||
public function __construct(GlobalStoragesService $globalService, | |||
UserStoragesService $userService, | |||
@@ -82,7 +63,7 @@ class Import extends Base { | |||
$this->backendService = $backendService; | |||
} | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:import') | |||
->setDescription('Import mount configurations') | |||
@@ -189,7 +170,7 @@ class Import extends Base { | |||
return 0; | |||
} | |||
private function parseData(array $data) { | |||
private function parseData(array $data): StorageConfig { | |||
$mount = new StorageConfig($data['mount_id']); | |||
$mount->setMountPoint($data['mount_point']); | |||
$mount->setBackend($this->getBackendByClass($data['storage'])); | |||
@@ -202,7 +183,7 @@ class Import extends Base { | |||
return $mount; | |||
} | |||
private function getBackendByClass($className) { | |||
private function getBackendByClass(string $className) { | |||
$backends = $this->backendService->getBackends(); | |||
foreach ($backends as $backend) { | |||
if ($backend->getStorageClass() === $className) { |
@@ -39,25 +39,10 @@ use Symfony\Component\Console\Input\InputOption; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class ListCommand extends Base { | |||
/** | |||
* @var GlobalStoragesService | |||
*/ | |||
protected $globalService; | |||
/** | |||
* @var UserStoragesService | |||
*/ | |||
protected $userService; | |||
/** | |||
* @var IUserSession | |||
*/ | |||
protected $userSession; | |||
/** | |||
* @var IUserManager | |||
*/ | |||
protected $userManager; | |||
protected GlobalStoragesService $globalService; | |||
protected UserStoragesService $userService; | |||
protected IUserSession $userSession; | |||
protected IUserManager $userManager; | |||
public const ALL = -1; | |||
@@ -69,7 +54,7 @@ class ListCommand extends Base { | |||
$this->userManager = $userManager; | |||
} | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:list') | |||
->setDescription('List configured admin or personal mounts') | |||
@@ -102,7 +87,7 @@ class ListCommand extends Base { | |||
$mounts = $this->globalService->getStorageForAllUsers(); | |||
$userId = self::ALL; | |||
} else { | |||
$userId = $input->getArgument('user_id'); | |||
$userId = (string)$input->getArgument('user_id'); | |||
$storageService = $this->getStorageService($userId); | |||
$mounts = $storageService->getAllStorages(); | |||
} | |||
@@ -112,12 +97,10 @@ class ListCommand extends Base { | |||
} | |||
/** | |||
* @param string $userId | |||
* @param ?string|ListCommand::ALL $userId | |||
* @param StorageConfig[] $mounts | |||
* @param InputInterface $input | |||
* @param OutputInterface $output | |||
*/ | |||
public function listMounts($userId, array $mounts, InputInterface $input, OutputInterface $output) { | |||
public function listMounts($userId, array $mounts, InputInterface $input, OutputInterface $output): void { | |||
$outputType = $input->getOption('output'); | |||
if (count($mounts) === 0) { | |||
if ($outputType === self::OUTPUT_FORMAT_JSON || $outputType === self::OUTPUT_FORMAT_JSON_PRETTY) { |
@@ -39,27 +39,24 @@ use OCP\Files\Storage\INotifyStorage; | |||
use OCP\Files\Storage\IStorage; | |||
use OCP\Files\StorageNotAvailableException; | |||
use OCP\IDBConnection; | |||
use OCP\ILogger; | |||
use OCP\IUserManager; | |||
use Psr\Log\LoggerInterface; | |||
use Symfony\Component\Console\Input\InputArgument; | |||
use Symfony\Component\Console\Input\InputInterface; | |||
use Symfony\Component\Console\Input\InputOption; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class Notify extends Base { | |||
/** @var GlobalStoragesService */ | |||
private $globalService; | |||
/** @var IDBConnection */ | |||
private $connection; | |||
/** @var ILogger */ | |||
private $logger; | |||
private GlobalStoragesService $globalService; | |||
private IDBConnection $connection; | |||
private LoggerInterface $logger; | |||
/** @var IUserManager */ | |||
private $userManager; | |||
public function __construct( | |||
GlobalStoragesService $globalService, | |||
IDBConnection $connection, | |||
ILogger $logger, | |||
LoggerInterface $logger, | |||
IUserManager $userManager | |||
) { | |||
parent::__construct(); | |||
@@ -69,7 +66,7 @@ class Notify extends Base { | |||
$this->userManager = $userManager; | |||
} | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:notify') | |||
->setDescription('Listen for active update notifications for a configured external mount') | |||
@@ -207,7 +204,7 @@ class Notify extends Base { | |||
return 0; | |||
} | |||
private function createStorage(StorageConfig $mount) { | |||
private function createStorage(StorageConfig $mount): IStorage { | |||
$class = $mount->getBackend()->getStorageClass(); | |||
return new $class($mount->getBackendOptions()); | |||
} | |||
@@ -221,7 +218,7 @@ class Notify extends Base { | |||
try { | |||
$storages = $this->getStorageIds($mountId, $parent); | |||
} catch (DriverException $ex) { | |||
$this->logger->logException($ex, ['message' => 'Error while trying to find correct storage ids.', 'level' => ILogger::WARN]); | |||
$this->logger->warning('Error while trying to find correct storage ids.', ['exception' => $ex]); | |||
$this->connection = $this->reconnectToDatabase($this->connection, $output); | |||
$output->writeln('<info>Needed to reconnect to the database</info>'); | |||
$storages = $this->getStorageIds($mountId, $path); | |||
@@ -292,37 +289,30 @@ class Notify extends Base { | |||
->fetchAll(); | |||
} | |||
/** | |||
* @param array $storageIds | |||
* @param string $parent | |||
* @return int | |||
*/ | |||
private function updateParent($storageIds, $parent) { | |||
$pathHash = md5(trim(\OC_Util::normalizeUnicode($parent), '/')); | |||
private function updateParent(array $storageIds, string $parent): int { | |||
$pathHash = md5(trim((string)\OC_Util::normalizeUnicode($parent), '/')); | |||
$qb = $this->connection->getQueryBuilder(); | |||
return $qb | |||
->update('filecache') | |||
->set('size', $qb->createNamedParameter(-1, IQueryBuilder::PARAM_INT)) | |||
->where($qb->expr()->in('storage', $qb->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY, ':storage_ids'))) | |||
->andWhere($qb->expr()->eq('path_hash', $qb->createNamedParameter($pathHash, IQueryBuilder::PARAM_STR))) | |||
->execute(); | |||
->executeStatement(); | |||
} | |||
/** | |||
* @return \OCP\IDBConnection | |||
*/ | |||
private function reconnectToDatabase(IDBConnection $connection, OutputInterface $output) { | |||
private function reconnectToDatabase(IDBConnection $connection, OutputInterface $output): IDBConnection { | |||
try { | |||
$connection->close(); | |||
} catch (\Exception $ex) { | |||
$this->logger->logException($ex, ['app' => 'files_external', 'message' => 'Error while disconnecting from DB', 'level' => ILogger::WARN]); | |||
$this->logger->warning('Error while disconnecting from DB', ['exception' => $ex]); | |||
$output->writeln("<info>Error while disconnecting from database: {$ex->getMessage()}</info>"); | |||
} | |||
while (!$connection->isConnected()) { | |||
$connected = false; | |||
while (!$connected) { | |||
try { | |||
$connection->connect(); | |||
$connected = $connection->connect(); | |||
} catch (\Exception $ex) { | |||
$this->logger->logException($ex, ['app' => 'files_external', 'message' => 'Error while re-connecting to database', 'level' => ILogger::WARN]); | |||
$this->logger->warning('Error while re-connecting to database', ['exception' => $ex]); | |||
$output->writeln("<info>Error while re-connecting to database: {$ex->getMessage()}</info>"); | |||
sleep(60); | |||
} |
@@ -27,7 +27,7 @@ use Symfony\Component\Console\Input\InputArgument; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class Option extends Config { | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:option') | |||
->setDescription('Manage mount options for a mount') |
@@ -38,17 +38,14 @@ use Symfony\Component\Console\Input\InputOption; | |||
use Symfony\Component\Console\Output\OutputInterface; | |||
class Verify extends Base { | |||
/** | |||
* @var GlobalStoragesService | |||
*/ | |||
protected $globalService; | |||
protected GlobalStoragesService $globalService; | |||
public function __construct(GlobalStoragesService $globalService) { | |||
parent::__construct(); | |||
$this->globalService = $globalService; | |||
} | |||
protected function configure() { | |||
protected function configure(): void { | |||
$this | |||
->setName('files_external:verify') | |||
->setDescription('Verify mount configuration') |
@@ -294,12 +294,12 @@ abstract class StoragesController extends Controller { | |||
} catch (InsufficientDataForMeaningfulAnswerException $e) { | |||
$status = $e->getCode() ? $e->getCode() : StorageNotAvailableException::STATUS_INDETERMINATE; | |||
$storage->setStatus( | |||
$status, | |||
(int)$status, | |||
$this->l10n->t('Insufficient data: %s', [$e->getMessage()]) | |||
); | |||
} catch (StorageNotAvailableException $e) { | |||
$storage->setStatus( | |||
$e->getCode(), | |||
(int)$e->getCode(), | |||
$this->l10n->t('%s', [$e->getMessage()]) | |||
); | |||
} catch (\Exception $e) { |
@@ -29,6 +29,8 @@ use OCA\Files_External\Lib\IdentifierTrait; | |||
use OCA\Files_External\Lib\StorageConfig; | |||
use OCA\Files_External\Lib\StorageModifierTrait; | |||
use OCA\Files_External\Lib\VisibilityTrait; | |||
use OCA\Files_External\Lib\IIdentifier; | |||
use OCA\Files_External\Lib\IFrontendDefinition; | |||
/** | |||
* Authentication mechanism | |||
@@ -50,7 +52,7 @@ use OCA\Files_External\Lib\VisibilityTrait; | |||
* - StorageModifierTrait | |||
* Object can affect storage mounting | |||
*/ | |||
class AuthMechanism implements \JsonSerializable { | |||
class AuthMechanism implements \JsonSerializable, IIdentifier, IFrontendDefinition { | |||
/** Standard authentication schemes */ | |||
public const SCHEME_NULL = 'null'; | |||
public const SCHEME_BUILTIN = 'builtin'; |
@@ -30,6 +30,9 @@ use OCA\Files_External\Lib\PriorityTrait; | |||
use OCA\Files_External\Lib\StorageConfig; | |||
use OCA\Files_External\Lib\StorageModifierTrait; | |||
use OCA\Files_External\Lib\VisibilityTrait; | |||
use OCA\Files_External\Lib\IIdentifier; | |||
use OCA\Files_External\Lib\IFrontendDefinition; | |||
use OCP\Files\Storage\IStorage; | |||
/** | |||
* Storage backend | |||
@@ -55,7 +58,7 @@ use OCA\Files_External\Lib\VisibilityTrait; | |||
* - StorageModifierTrait | |||
* Object can affect storage mounting | |||
*/ | |||
class Backend implements \JsonSerializable { | |||
class Backend implements \JsonSerializable, IIdentifier, IFrontendDefinition { | |||
use VisibilityTrait; | |||
use FrontendDefinitionTrait; | |||
use PriorityTrait; | |||
@@ -73,7 +76,7 @@ class Backend implements \JsonSerializable { | |||
private $legacyAuthMechanism; | |||
/** | |||
* @return string | |||
* @return class-string<IStorage> | |||
*/ | |||
public function getStorageClass() { | |||
return $this->storageClass; | |||
@@ -118,21 +121,17 @@ class Backend implements \JsonSerializable { | |||
return $this->legacyAuthMechanism; | |||
} | |||
/** | |||
* @param AuthMechanism $authMechanism | |||
* @return self | |||
*/ | |||
public function setLegacyAuthMechanism(AuthMechanism $authMechanism) { | |||
public function setLegacyAuthMechanism(AuthMechanism $authMechanism): self { | |||
$this->legacyAuthMechanism = $authMechanism; | |||
return $this; | |||
} | |||
/** | |||
* @param callable $callback dynamic auth mechanism selection | |||
* @return self | |||
*/ | |||
public function setLegacyAuthMechanismCallback(callable $callback) { | |||
public function setLegacyAuthMechanismCallback(callable $callback): self { | |||
$this->legacyAuthMechanism = $callback; | |||
return $this; | |||
} | |||
/** |
@@ -29,62 +29,45 @@ namespace OCA\Files_External\Lib; | |||
trait FrontendDefinitionTrait { | |||
/** @var string human-readable mechanism name */ | |||
private $text; | |||
private string $text = ""; | |||
/** @var DefinitionParameter[] parameters for mechanism */ | |||
private $parameters = []; | |||
/** @var array<string, DefinitionParameter> parameters for mechanism */ | |||
private array $parameters = []; | |||
/** @var string[] custom JS */ | |||
private $customJs = []; | |||
private array $customJs = []; | |||
/** | |||
* @return string | |||
*/ | |||
public function getText() { | |||
public function getText(): string { | |||
return $this->text; | |||
} | |||
/** | |||
* @param string $text | |||
* @return $this | |||
*/ | |||
public function setText($text) { | |||
public function setText(string $text): self { | |||
$this->text = $text; | |||
return $this; | |||
} | |||
/** | |||
* @param FrontendDefinitionTrait $a | |||
* @param FrontendDefinitionTrait $b | |||
* @return int | |||
*/ | |||
public static function lexicalCompare(FrontendDefinitionTrait $a, FrontendDefinitionTrait $b) { | |||
public static function lexicalCompare(IFrontendDefinition $a, IFrontendDefinition $b): int { | |||
return strcmp($a->getText(), $b->getText()); | |||
} | |||
/** | |||
* @return DefinitionParameter[] | |||
* @return array<string, DefinitionParameter> | |||
*/ | |||
public function getParameters() { | |||
public function getParameters(): array { | |||
return $this->parameters; | |||
} | |||
/** | |||
* @param DefinitionParameter[] $parameters | |||
* @return self | |||
* @param list<DefinitionParameter> $parameters | |||
*/ | |||
public function addParameters(array $parameters) { | |||
public function addParameters(array $parameters): self { | |||
foreach ($parameters as $parameter) { | |||
$this->addParameter($parameter); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* @param DefinitionParameter $parameter | |||
* @return self | |||
*/ | |||
public function addParameter(DefinitionParameter $parameter) { | |||
public function addParameter(DefinitionParameter $parameter): self { | |||
$this->parameters[$parameter->getName()] = $parameter; | |||
return $this; | |||
} | |||
@@ -92,7 +75,7 @@ trait FrontendDefinitionTrait { | |||
/** | |||
* @return string[] | |||
*/ | |||
public function getCustomJs() { | |||
public function getCustomJs(): array { | |||
return $this->customJs; | |||
} | |||
@@ -100,17 +83,15 @@ trait FrontendDefinitionTrait { | |||
* @param string $custom | |||
* @return self | |||
*/ | |||
public function addCustomJs($custom) { | |||
public function addCustomJs(string $custom): self { | |||
$this->customJs[] = $custom; | |||
return $this; | |||
} | |||
/** | |||
* Serialize into JSON for client-side JS | |||
* | |||
* @return array | |||
*/ | |||
public function jsonSerializeDefinition() { | |||
public function jsonSerializeDefinition(): array { | |||
$configuration = []; | |||
foreach ($this->getParameters() as $parameter) { | |||
$configuration[$parameter->getName()] = $parameter; | |||
@@ -126,11 +107,8 @@ trait FrontendDefinitionTrait { | |||
/** | |||
* Check if parameters are satisfied in a StorageConfig | |||
* | |||
* @param StorageConfig $storage | |||
* @return bool | |||
*/ | |||
public function validateStorageDefinition(StorageConfig $storage) { | |||
public function validateStorageDefinition(StorageConfig $storage): bool { | |||
foreach ($this->getParameters() as $name => $parameter) { | |||
$value = $storage->getBackendOption($name); | |||
if (!is_null($value) || !$parameter->isOptional()) { |
@@ -0,0 +1,56 @@ | |||
<?php | |||
/** | |||
* @copyright 2022 Carl Schwan <carl@carlschwan.eu> | |||
* | |||
* @license AGPL-3.0-or-later | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\Files_External\Lib; | |||
interface IFrontendDefinition { | |||
public function getText(): string; | |||
public function setText(string $text): self; | |||
/** | |||
* @return array<string, DefinitionParameter> | |||
*/ | |||
public function getParameters(): array; | |||
/** | |||
* @param list<DefinitionParameter> $parameters | |||
*/ | |||
public function addParameters(array $parameters): self; | |||
public function addParameter(DefinitionParameter $parameter): self; | |||
/** | |||
* @return string[] | |||
*/ | |||
public function getCustomJs(): array; | |||
public function addCustomJs(string $custom): self; | |||
/** | |||
* Serialize into JSON for client-side JS | |||
*/ | |||
public function jsonSerializeDefinition(): array; | |||
/** | |||
* Check if parameters are satisfied in a StorageConfig | |||
*/ | |||
public function validateStorageDefinition(StorageConfig $storage): bool; | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
/** | |||
* @copyright 2022 Carl Schwan <carl@carlschwan.eu> | |||
* | |||
* @license AGPL-3.0-or-later | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\Files_External\Lib; | |||
interface IIdentifier { | |||
public function getIdentifier(): string; | |||
public function setIdentifier(string $identifier): self; | |||
} |
@@ -28,27 +28,17 @@ namespace OCA\Files_External\Lib; | |||
*/ | |||
trait IdentifierTrait { | |||
/** @var string */ | |||
protected $identifier; | |||
protected string $identifier = ''; | |||
/** @var string[] */ | |||
protected $identifierAliases = []; | |||
protected array $identifierAliases = []; | |||
protected ?IIdentifier $deprecateTo = null; | |||
/** @var IdentifierTrait */ | |||
protected $deprecateTo = null; | |||
/** | |||
* @return string | |||
*/ | |||
public function getIdentifier() { | |||
public function getIdentifier(): string { | |||
return $this->identifier; | |||
} | |||
/** | |||
* @param string $identifier | |||
* @return $this | |||
*/ | |||
public function setIdentifier($identifier) { | |||
public function setIdentifier(string $identifier): self { | |||
$this->identifier = $identifier; | |||
$this->identifierAliases[] = $identifier; | |||
return $this; | |||
@@ -57,39 +47,25 @@ trait IdentifierTrait { | |||
/** | |||
* @return string[] | |||
*/ | |||
public function getIdentifierAliases() { | |||
public function getIdentifierAliases(): array { | |||
return $this->identifierAliases; | |||
} | |||
/** | |||
* @param string $alias | |||
* @return $this | |||
*/ | |||
public function addIdentifierAlias($alias) { | |||
public function addIdentifierAlias(string $alias): self { | |||
$this->identifierAliases[] = $alias; | |||
return $this; | |||
} | |||
/** | |||
* @return object|null | |||
*/ | |||
public function getDeprecateTo() { | |||
public function getDeprecateTo(): ?IIdentifier { | |||
return $this->deprecateTo; | |||
} | |||
/** | |||
* @param object $destinationObject | |||
* @return self | |||
*/ | |||
public function deprecateTo($destinationObject) { | |||
public function deprecateTo(IIdentifier $destinationObject): self { | |||
$this->deprecateTo = $destinationObject; | |||
return $this; | |||
} | |||
/** | |||
* @return array | |||
*/ | |||
public function jsonSerializeIdentifier() { | |||
public function jsonSerializeIdentifier(): array { | |||
$data = [ | |||
'identifier' => $this->identifier, | |||
'identifierAliases' => $this->identifierAliases, |
@@ -21,13 +21,15 @@ | |||
*/ | |||
namespace OCA\Files_External\Lib; | |||
use OCP\Files\Storage\IStorage; | |||
/** | |||
* Polyfill for checking dependencies using legacy Storage::checkDependencies() | |||
*/ | |||
trait LegacyDependencyCheckPolyfill { | |||
/** | |||
* @return string | |||
* @return class-string<IStorage> | |||
*/ | |||
abstract public function getStorageClass(); | |||
@@ -54,7 +56,7 @@ trait LegacyDependencyCheckPolyfill { | |||
$module = $key; | |||
$message = $value; | |||
} | |||
$value = new MissingDependency($module, $this); | |||
$value = new MissingDependency($module); | |||
$value->setMessage($message); | |||
} | |||
$ret[] = $value; |
@@ -39,17 +39,11 @@ class MissingDependency { | |||
$this->dependency = $dependency; | |||
} | |||
/** | |||
* @return string | |||
*/ | |||
public function getDependency() { | |||
public function getDependency(): string { | |||
return $this->dependency; | |||
} | |||
/** | |||
* @return string|null | |||
*/ | |||
public function getMessage() { | |||
public function getMessage(): ?string { | |||
return $this->message; | |||
} | |||
@@ -47,13 +47,4 @@ trait PriorityTrait { | |||
$this->priority = $priority; | |||
return $this; | |||
} | |||
/** | |||
* @param PriorityTrait $a | |||
* @param PriorityTrait $b | |||
* @return int | |||
*/ | |||
public static function priorityCompare(PriorityTrait $a, PriorityTrait $b) { | |||
return ($a->getPriority() - $b->getPriority()); | |||
} | |||
} |
@@ -55,11 +55,14 @@ use OCP\ICacheFactory; | |||
use OCP\IMemcache; | |||
use OCP\Server; | |||
use OCP\ICache; | |||
use Psr\Log\LoggerInterface; | |||
class AmazonS3 extends \OC\Files\Storage\Common { | |||
use S3ConnectionTrait; | |||
use S3ObjectTrait; | |||
private LoggerInterface $logger; | |||
public function needsPartFile() { | |||
return false; | |||
} | |||
@@ -88,6 +91,7 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
/** @var ICacheFactory $cacheFactory */ | |||
$cacheFactory = Server::get(ICacheFactory::class); | |||
$this->memCache = $cacheFactory->createLocal('s3-external'); | |||
$this->logger = Server::get(LoggerInterface::class); | |||
} | |||
/** | |||
@@ -255,7 +259,10 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
]); | |||
$this->testTimeout(); | |||
} catch (S3Exception $e) { | |||
\OC::$server->getLogger()->logException($e, ['app' => 'files_external']); | |||
$this->logger->error($e->getMessage(), [ | |||
'app' => 'files_external', | |||
'exception' => $e, | |||
]); | |||
return false; | |||
} | |||
@@ -286,18 +293,11 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
protected function clearBucket() { | |||
$this->clearCache(); | |||
try { | |||
$this->getConnection()->clearBucket([ | |||
"Bucket" => $this->bucket | |||
]); | |||
return true; | |||
// clearBucket() is not working with Ceph, so if it fails we try the slower approach | |||
} catch (\Exception $e) { | |||
return $this->batchDelete(); | |||
} | |||
return $this->batchDelete(); | |||
} | |||
private function batchDelete($path = null) { | |||
// TODO explore using https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.S3.BatchDelete.html | |||
$params = [ | |||
'Bucket' => $this->bucket | |||
]; | |||
@@ -327,7 +327,10 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
$this->deleteObject($path); | |||
} | |||
} catch (S3Exception $e) { | |||
\OC::$server->getLogger()->logException($e, ['app' => 'files_external']); | |||
$this->logger->error($e->getMessage(), [ | |||
'app' => 'files_external', | |||
'exception' => $e, | |||
]); | |||
return false; | |||
} | |||
return true; | |||
@@ -415,7 +418,10 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
try { | |||
return $this->doesDirectoryExist($path); | |||
} catch (S3Exception $e) { | |||
\OC::$server->getLogger()->logException($e, ['app' => 'files_external']); | |||
$this->logger->error($e->getMessage(), [ | |||
'app' => 'files_external', | |||
'exception' => $e, | |||
]); | |||
return false; | |||
} | |||
} | |||
@@ -438,7 +444,10 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
return 'dir'; | |||
} | |||
} catch (S3Exception $e) { | |||
\OC::$server->getLogger()->logException($e, ['app' => 'files_external']); | |||
$this->logger->error($e->getMessage(), [ | |||
'app' => 'files_external', | |||
'exception' => $e, | |||
]); | |||
return false; | |||
} | |||
@@ -464,7 +473,10 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
$this->deleteObject($path); | |||
$this->invalidateCache($path); | |||
} catch (S3Exception $e) { | |||
\OC::$server->getLogger()->logException($e, ['app' => 'files_external']); | |||
$this->logger->error($e->getMessage(), [ | |||
'app' => 'files_external', | |||
'exception' => $e, | |||
]); | |||
return false; | |||
} | |||
@@ -486,7 +498,10 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
try { | |||
return $this->readObject($path); | |||
} catch (S3Exception $e) { | |||
\OC::$server->getLogger()->logException($e, ['app' => 'files_external']); | |||
$this->logger->error($e->getMessage(), [ | |||
'app' => 'files_external', | |||
'exception' => $e, | |||
]); | |||
return false; | |||
} | |||
case 'w': | |||
@@ -548,7 +563,10 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
$this->testTimeout(); | |||
} | |||
} catch (S3Exception $e) { | |||
\OC::$server->getLogger()->logException($e, ['app' => 'files_external']); | |||
$this->logger->error($e->getMessage(), [ | |||
'app' => 'files_external', | |||
'exception' => $e, | |||
]); | |||
return false; | |||
} | |||
@@ -556,65 +574,71 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
return true; | |||
} | |||
public function copy($path1, $path2, $isFile = null) { | |||
$path1 = $this->normalizePath($path1); | |||
$path2 = $this->normalizePath($path2); | |||
public function copy($source, $target, $isFile = null) { | |||
$source = $this->normalizePath($source); | |||
$target = $this->normalizePath($target); | |||
if ($isFile === true || $this->is_file($path1)) { | |||
if ($isFile === true || $this->is_file($source)) { | |||
try { | |||
$this->getConnection()->copyObject([ | |||
'Bucket' => $this->bucket, | |||
'Key' => $this->cleanKey($path2), | |||
'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1) | |||
'Key' => $this->cleanKey($target), | |||
'CopySource' => S3Client::encodeKey($this->bucket . '/' . $source) | |||
]); | |||
$this->testTimeout(); | |||
} catch (S3Exception $e) { | |||
\OC::$server->getLogger()->logException($e, ['app' => 'files_external']); | |||
$this->logger->error($e->getMessage(), [ | |||
'app' => 'files_external', | |||
'exception' => $e, | |||
]); | |||
return false; | |||
} | |||
} else { | |||
$this->remove($path2); | |||
$this->remove($target); | |||
try { | |||
$this->mkdir($path2); | |||
$this->mkdir($target); | |||
$this->testTimeout(); | |||
} catch (S3Exception $e) { | |||
\OC::$server->getLogger()->logException($e, ['app' => 'files_external']); | |||
$this->logger->error($e->getMessage(), [ | |||
'app' => 'files_external', | |||
'exception' => $e, | |||
]); | |||
return false; | |||
} | |||
foreach ($this->getDirectoryContent($path1) as $item) { | |||
$source = $path1 . '/' . $item['name']; | |||
$target = $path2 . '/' . $item['name']; | |||
foreach ($this->getDirectoryContent($source) as $item) { | |||
$source = $source . '/' . $item['name']; | |||
$target = $target . '/' . $item['name']; | |||
$this->copy($source, $target, $item['mimetype'] !== FileInfo::MIMETYPE_FOLDER); | |||
} | |||
} | |||
$this->invalidateCache($path2); | |||
$this->invalidateCache($target); | |||
return true; | |||
} | |||
public function rename($path1, $path2) { | |||
$path1 = $this->normalizePath($path1); | |||
$path2 = $this->normalizePath($path2); | |||
public function rename($source, $target) { | |||
$source = $this->normalizePath($source); | |||
$target = $this->normalizePath($target); | |||
if ($this->is_file($path1)) { | |||
if ($this->copy($path1, $path2) === false) { | |||
if ($this->is_file($source)) { | |||
if ($this->copy($source, $target) === false) { | |||
return false; | |||
} | |||
if ($this->unlink($path1) === false) { | |||
$this->unlink($path2); | |||
if ($this->unlink($source) === false) { | |||
$this->unlink($target); | |||
return false; | |||
} | |||
} else { | |||
if ($this->copy($path1, $path2) === false) { | |||
if ($this->copy($source, $target) === false) { | |||
return false; | |||
} | |||
if ($this->rmdir($path1) === false) { | |||
$this->rmdir($path2); | |||
if ($this->rmdir($source) === false) { | |||
$this->rmdir($target); | |||
return false; | |||
} | |||
} | |||
@@ -642,7 +666,10 @@ class AmazonS3 extends \OC\Files\Storage\Common { | |||
unlink($tmpFile); | |||
return true; | |||
} catch (S3Exception $e) { | |||
\OC::$server->getLogger()->logException($e, ['app' => 'files_external']); | |||
$this->logger->error($e->getMessage(), [ | |||
'app' => 'files_external', | |||
'exception' => $e, | |||
]); | |||
return false; | |||
} | |||
} |
@@ -333,9 +333,9 @@ class FTP extends Common { | |||
} | |||
} | |||
public function rename($path1, $path2) { | |||
$this->unlink($path2); | |||
return $this->getConnection()->rename($this->buildPath($path1), $this->buildPath($path2)); | |||
public function rename($source, $target) { | |||
$this->unlink($target); | |||
return $this->getConnection()->rename($this->buildPath($source), $this->buildPath($target)); | |||
} | |||
public function getDirectoryContent($directory): \Traversable { |
@@ -85,8 +85,8 @@ class FtpConnection { | |||
return @ftp_rmdir($this->connection, $path); | |||
} | |||
public function rename(string $path1, string $path2) { | |||
return @ftp_rename($this->connection, $path1, $path2); | |||
public function rename(string $source, string $target) { | |||
return @ftp_rename($this->connection, $source, $target); | |||
} | |||
public function mdtm(string $path) { |
@@ -36,7 +36,7 @@ class SFTPReadStream implements File { | |||
/** @var \phpseclib\Net\SFTP */ | |||
private $sftp; | |||
/** @var resource */ | |||
/** @var string */ | |||
private $handle; | |||
/** @var int */ | |||
@@ -61,7 +61,6 @@ class SFTPReadStream implements File { | |||
* Load the source from the stream context and return the context options | |||
* | |||
* @param string $name | |||
* @return array | |||
* @throws \BadMethodCallException | |||
*/ | |||
protected function loadContext($name) { | |||
@@ -202,5 +201,6 @@ class SFTPReadStream implements File { | |||
if (!$this->sftp->_close_handle($this->handle)) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@@ -36,7 +36,7 @@ class SFTPWriteStream implements File { | |||
/** @var \phpseclib\Net\SFTP */ | |||
private $sftp; | |||
/** @var resource */ | |||
/** @var string */ | |||
private $handle; | |||
/** @var int */ | |||
@@ -61,7 +61,6 @@ class SFTPWriteStream implements File { | |||
* Load the source from the stream context and return the context options | |||
* | |||
* @param string $name | |||
* @return array | |||
* @throws \BadMethodCallException | |||
*/ | |||
protected function loadContext($name) { | |||
@@ -180,5 +179,6 @@ class SFTPWriteStream implements File { | |||
if (!$this->sftp->_close_handle($this->handle)) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@@ -282,7 +282,7 @@ class SMB extends Common implements INotifyStorage { | |||
} | |||
} catch (ConnectException $e) { | |||
$this->logger->logException($e, ['message' => 'Error while getting folder content']); | |||
throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e); | |||
throw new StorageNotAvailableException($e->getMessage(), (int)$e->getCode(), $e); | |||
} | |||
} | |||
@@ -310,7 +310,7 @@ class SMB extends Common implements INotifyStorage { | |||
* @param string $target the new name of the path | |||
* @return bool true if the rename is successful, false otherwise | |||
*/ | |||
public function rename($source, $target, $retry = true) { | |||
public function rename($source, $target, $retry = true): bool { | |||
if ($this->isRootDir($source) || $this->isRootDir($target)) { | |||
return false; | |||
} | |||
@@ -322,7 +322,7 @@ class SMB extends Common implements INotifyStorage { | |||
} catch (AlreadyExistsException $e) { | |||
if ($retry) { | |||
$this->remove($target); | |||
$result = $this->share->rename($absoluteSource, $absoluteTarget, false); | |||
$result = $this->share->rename($absoluteSource, $absoluteTarget); | |||
} else { | |||
$this->logger->logException($e, ['level' => ILogger::WARN]); | |||
return false; | |||
@@ -330,7 +330,7 @@ class SMB extends Common implements INotifyStorage { | |||
} catch (InvalidArgumentException $e) { | |||
if ($retry) { | |||
$this->remove($target); | |||
$result = $this->share->rename($absoluteSource, $absoluteTarget, false); | |||
$result = $this->share->rename($absoluteSource, $absoluteTarget); | |||
} else { | |||
$this->logger->logException($e, ['level' => ILogger::WARN]); | |||
return false; | |||
@@ -428,7 +428,7 @@ class SMB extends Common implements INotifyStorage { | |||
return false; | |||
} catch (ConnectException $e) { | |||
$this->logger->logException($e, ['message' => 'Error while deleting file']); | |||
throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e); | |||
throw new StorageNotAvailableException($e->getMessage(), (int)$e->getCode(), $e); | |||
} | |||
} | |||
@@ -515,7 +515,7 @@ class SMB extends Common implements INotifyStorage { | |||
throw new EntityTooLargeException("not enough available space to create file", 0, $e); | |||
} catch (ConnectException $e) { | |||
$this->logger->logException($e, ['message' => 'Error while opening file']); | |||
throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e); | |||
throw new StorageNotAvailableException($e->getMessage(), (int)$e->getCode(), $e); | |||
} | |||
} | |||
@@ -542,7 +542,7 @@ class SMB extends Common implements INotifyStorage { | |||
return false; | |||
} catch (ConnectException $e) { | |||
$this->logger->logException($e, ['message' => 'Error while removing folder']); | |||
throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e); | |||
throw new StorageNotAvailableException($e->getMessage(), (int)$e->getCode(), $e); | |||
} | |||
} | |||
@@ -558,7 +558,7 @@ class SMB extends Common implements INotifyStorage { | |||
throw new EntityTooLargeException("not enough available space to create file", 0, $e); | |||
} catch (ConnectException $e) { | |||
$this->logger->logException($e, ['message' => 'Error while creating file']); | |||
throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e); | |||
throw new StorageNotAvailableException($e->getMessage(), (int)$e->getCode(), $e); | |||
} | |||
} | |||
@@ -655,7 +655,7 @@ class SMB extends Common implements INotifyStorage { | |||
return true; | |||
} catch (ConnectException $e) { | |||
$this->logger->logException($e, ['message' => 'Error while creating folder']); | |||
throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e); | |||
throw new StorageNotAvailableException($e->getMessage(), (int)$e->getCode(), $e); | |||
} catch (Exception $e) { | |||
return false; | |||
} | |||
@@ -670,7 +670,7 @@ class SMB extends Common implements INotifyStorage { | |||
} catch (ForbiddenException $e) { | |||
return false; | |||
} catch (ConnectException $e) { | |||
throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e); | |||
throw new StorageNotAvailableException($e->getMessage(), (int)$e->getCode(), $e); | |||
} | |||
} | |||
@@ -117,8 +117,8 @@ abstract class StreamWrapper extends \OC\Files\Storage\Common { | |||
return copy($path, $this->constructUrl($target)); | |||
} | |||
public function rename($path1, $path2) { | |||
return rename($this->constructUrl($path1), $this->constructUrl($path2)); | |||
public function rename($source, $target) { | |||
return rename($this->constructUrl($source), $this->constructUrl($target)); | |||
} | |||
public function stat($path) { |
@@ -482,25 +482,25 @@ class Swift extends \OC\Files\Storage\Common { | |||
} | |||
} | |||
public function copy($path1, $path2) { | |||
$path1 = $this->normalizePath($path1); | |||
$path2 = $this->normalizePath($path2); | |||
public function copy($source, $target) { | |||
$source = $this->normalizePath($source); | |||
$target = $this->normalizePath($target); | |||
$fileType = $this->filetype($path1); | |||
$fileType = $this->filetype($source); | |||
if ($fileType) { | |||
// make way | |||
$this->unlink($path2); | |||
$this->unlink($target); | |||
} | |||
if ($fileType === 'file') { | |||
try { | |||
$source = $this->fetchObject($path1); | |||
$source->copy([ | |||
'destination' => $this->bucket . '/' . $path2 | |||
$sourceObject = $this->fetchObject($source); | |||
$sourceObject->copy([ | |||
'destination' => $this->bucket . '/' . $target | |||
]); | |||
// invalidate target object to force repopulation on fetch | |||
$this->objectCache->remove($path2); | |||
$this->objectCache->remove($path2 . '/'); | |||
$this->objectCache->remove($target); | |||
$this->objectCache->remove($target . '/'); | |||
} catch (BadResponseError $e) { | |||
\OC::$server->get(LoggerInterface::class)->error($e->getMessage(), [ | |||
'exception' => $e, | |||
@@ -510,13 +510,13 @@ class Swift extends \OC\Files\Storage\Common { | |||
} | |||
} elseif ($fileType === 'dir') { | |||
try { | |||
$source = $this->fetchObject($path1 . '/'); | |||
$source->copy([ | |||
'destination' => $this->bucket . '/' . $path2 . '/' | |||
$sourceObject = $this->fetchObject($source . '/'); | |||
$sourceObject->copy([ | |||
'destination' => $this->bucket . '/' . $target . '/' | |||
]); | |||
// invalidate target object to force repopulation on fetch | |||
$this->objectCache->remove($path2); | |||
$this->objectCache->remove($path2 . '/'); | |||
$this->objectCache->remove($target); | |||
$this->objectCache->remove($target . '/'); | |||
} catch (BadResponseError $e) { | |||
\OC::$server->get(LoggerInterface::class)->error($e->getMessage(), [ | |||
'exception' => $e, | |||
@@ -525,14 +525,14 @@ class Swift extends \OC\Files\Storage\Common { | |||
return false; | |||
} | |||
$dh = $this->opendir($path1); | |||
$dh = $this->opendir($source); | |||
while ($file = readdir($dh)) { | |||
if (\OC\Files\Filesystem::isIgnoredDir($file)) { | |||
continue; | |||
} | |||
$source = $path1 . '/' . $file; | |||
$target = $path2 . '/' . $file; | |||
$source = $source . '/' . $file; | |||
$target = $target . '/' . $file; | |||
$this->copy($source, $target); | |||
} | |||
} else { | |||
@@ -543,22 +543,22 @@ class Swift extends \OC\Files\Storage\Common { | |||
return true; | |||
} | |||
public function rename($path1, $path2) { | |||
$path1 = $this->normalizePath($path1); | |||
$path2 = $this->normalizePath($path2); | |||
public function rename($source, $target) { | |||
$source = $this->normalizePath($source); | |||
$target = $this->normalizePath($target); | |||
$fileType = $this->filetype($path1); | |||
$fileType = $this->filetype($source); | |||
if ($fileType === 'dir' || $fileType === 'file') { | |||
// copy | |||
if ($this->copy($path1, $path2) === false) { | |||
if ($this->copy($source, $target) === false) { | |||
return false; | |||
} | |||
// cleanup | |||
if ($this->unlink($path1) === false) { | |||
if ($this->unlink($source) === false) { | |||
throw new \Exception('failed to remove original'); | |||
$this->unlink($path2); | |||
$this->unlink($target); | |||
return false; | |||
} | |||
@@ -126,17 +126,17 @@ class StorageConfig implements \JsonSerializable { | |||
/** | |||
* Creates a storage config | |||
* | |||
* @param int|null $id config id or null for a new config | |||
* @param int|string $id config id or null for a new config | |||
*/ | |||
public function __construct($id = null) { | |||
$this->id = $id; | |||
$this->id = $id ?? -1; | |||
$this->mountOptions['enable_sharing'] = false; | |||
} | |||
/** | |||
* Returns the configuration id | |||
* | |||
* @return int | |||
* @retun int | |||
*/ | |||
public function getId() { | |||
return $this->id; | |||
@@ -147,7 +147,7 @@ class StorageConfig implements \JsonSerializable { | |||
* | |||
* @param int $id configuration id | |||
*/ | |||
public function setId($id) { | |||
public function setId(int $id): void { | |||
$this->id = $id; | |||
} | |||
@@ -150,17 +150,17 @@ class MountConfig { | |||
* TODO: move into AppFramework along with templates | |||
* | |||
* @param Backend[] $backends | |||
* @return string | |||
*/ | |||
public static function dependencyMessage($backends) { | |||
public static function dependencyMessage(array $backends): string { | |||
$l = \OC::$server->getL10N('files_external'); | |||
$message = ''; | |||
$dependencyGroups = []; | |||
foreach ($backends as $backend) { | |||
foreach ($backend->checkDependencies() as $dependency) { | |||
if ($message = $dependency->getMessage()) { | |||
$message .= '<p>' . $message . '</p>'; | |||
$dependencyMessage = $dependency->getMessage(); | |||
if ($dependencyMessage !== null) { | |||
$message .= '<p>' . $dependencyMessage . '</p>'; | |||
} else { | |||
$dependencyGroups[$dependency->getDependency()][] = $backend; | |||
} | |||
@@ -168,7 +168,7 @@ class MountConfig { | |||
} | |||
foreach ($dependencyGroups as $module => $dependants) { | |||
$backends = implode(', ', array_map(function ($backend) { | |||
$backends = implode(', ', array_map(function (Backend $backend): string { | |||
return '"' . $backend->getText() . '"'; | |||
}, $dependants)); | |||
$message .= '<p>' . MountConfig::getSingleDependencyMessage($l, $module, $backends) . '</p>'; | |||
@@ -179,13 +179,8 @@ class MountConfig { | |||
/** | |||
* Returns a dependency missing message | |||
* | |||
* @param \OCP\IL10N $l | |||
* @param string $module | |||
* @param string $backend | |||
* @return string | |||
*/ | |||
private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) { | |||
private static function getSingleDependencyMessage(\OCP\IL10N $l, string $module, string $backend): string { | |||
switch (strtolower($module)) { | |||
case 'curl': | |||
return $l->t('The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]); |
@@ -64,11 +64,7 @@ class DBConfigService { | |||
$this->crypto = $crypto; | |||
} | |||
/** | |||
* @param int $mountId | |||
* @return array | |||
*/ | |||
public function getMountById($mountId) { | |||
public function getMountById(int $mountId): ?array { | |||
$builder = $this->connection->getQueryBuilder(); | |||
$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type']) | |||
->from('external_mounts', 'm') |
@@ -155,7 +155,7 @@ class GlobalStoragesService extends StoragesService { | |||
/** | |||
* Get the visibility type for this controller, used in validation | |||
* | |||
* @return string BackendService::VISIBILITY_* constants | |||
* @return int BackendService::VISIBILITY_* constants | |||
*/ | |||
public function getVisibilityType() { | |||
return BackendService::VISIBILITY_ADMIN; |
@@ -231,7 +231,7 @@ abstract class StoragesService { | |||
/** | |||
* Get the visibility type for this controller, used in validation | |||
* | |||
* @return string BackendService::VISIBILITY_* constants | |||
* @return int BackendService::VISIBILITY_* constants | |||
*/ | |||
abstract public function getVisibilityType(); | |||
@@ -510,6 +510,7 @@ abstract class StoragesService { | |||
$storage = $storageConfig->getBackend()->wrapStorage($storage); | |||
$storage = $storageConfig->getAuthMechanism()->wrapStorage($storage); | |||
/** @var \OC\Files\Storage\Storage $storage */ | |||
return $storage->getStorageCache()->getNumericId(); | |||
} catch (\Exception $e) { | |||
return -1; |
@@ -134,7 +134,7 @@ class UserStoragesService extends StoragesService { | |||
/** | |||
* Get the visibility type for this controller, used in validation | |||
* | |||
* @return string BackendService::VISIBILITY_* constants | |||
* @return int BackendService::VISIBILITY_* constants | |||
*/ | |||
public function getVisibilityType() { | |||
return BackendService::VISIBILITY_PERSONAL; |
@@ -1,9 +1,11 @@ | |||
<?php | |||
use \OCA\Files_External\Lib\Backend\Backend; | |||
use \OCA\Files_External\Lib\Backend\Backend; | |||
use \OCA\Files_External\Lib\Auth\AuthMechanism; | |||
use \OCA\Files_External\Lib\DefinitionParameter; | |||
use \OCA\Files_External\Service\BackendService; | |||
/** @var array $_ */ | |||
$canCreateMounts = $_['visibilityType'] === BackendService::VISIBILITY_ADMIN || $_['allowUserMounting']; | |||
$l->t("Enable encryption"); |
@@ -334,15 +334,15 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto | |||
/** | |||
* see https://www.php.net/manual/en/function.rename.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
*/ | |||
public function rename($path1, $path2): bool { | |||
public function rename($source, $target): bool { | |||
$this->init(); | |||
$isPartFile = pathinfo($path1, PATHINFO_EXTENSION) === 'part'; | |||
$targetExists = $this->file_exists($path2); | |||
$sameFolder = dirname($path1) === dirname($path2); | |||
$isPartFile = pathinfo($source, PATHINFO_EXTENSION) === 'part'; | |||
$targetExists = $this->file_exists($target); | |||
$sameFolder = dirname($source) === dirname($target); | |||
if ($targetExists || ($sameFolder && !$isPartFile)) { | |||
if (!$this->isUpdatable('')) { | |||
@@ -354,7 +354,7 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto | |||
} | |||
} | |||
return $this->nonMaskedStorage->rename($this->getUnjailedPath($path1), $this->getUnjailedPath($path2)); | |||
return $this->nonMaskedStorage->rename($this->getUnjailedPath($source), $this->getUnjailedPath($target)); | |||
} | |||
/** |
@@ -1044,31 +1044,6 @@ | |||
<code>$this</code> | |||
</InvalidScope> | |||
</file> | |||
<file src="apps/files_external/lib/Command/Delete.php"> | |||
<NullArgument occurrences="1"> | |||
<code>null</code> | |||
</NullArgument> | |||
</file> | |||
<file src="apps/files_external/lib/Command/ListCommand.php"> | |||
<InvalidScalarArgument occurrences="1"> | |||
<code>$userId</code> | |||
</InvalidScalarArgument> | |||
</file> | |||
<file src="apps/files_external/lib/Command/Notify.php"> | |||
<InvalidArgument occurrences="1"> | |||
<code>$storage</code> | |||
</InvalidArgument> | |||
<InvalidReturnStatement occurrences="1"/> | |||
<InvalidReturnType occurrences="1"> | |||
<code>int</code> | |||
</InvalidReturnType> | |||
<InvalidScalarArgument occurrences="1"> | |||
<code>\OC_Util::normalizeUnicode($parent)</code> | |||
</InvalidScalarArgument> | |||
<UndefinedInterfaceMethod occurrences="1"> | |||
<code>isConnected</code> | |||
</UndefinedInterfaceMethod> | |||
</file> | |||
<file src="apps/files_external/lib/Command/Verify.php"> | |||
<InvalidScalarArgument occurrences="2"> | |||
<code>$e->getCode()</code> | |||
@@ -1080,14 +1055,6 @@ | |||
<code>new $objectClass($objectStore)</code> | |||
</UndefinedClass> | |||
</file> | |||
<file src="apps/files_external/lib/Controller/StoragesController.php"> | |||
<InvalidScalarArgument occurrences="4"> | |||
<code>$e->getCode()</code> | |||
<code>$status</code> | |||
<code>$this->service->getVisibilityType()</code> | |||
<code>$this->service->getVisibilityType()</code> | |||
</InvalidScalarArgument> | |||
</file> | |||
<file src="apps/files_external/lib/Controller/UserGlobalStoragesController.php"> | |||
<UndefinedMethod occurrences="1"> | |||
<code>getUniqueStorages</code> | |||
@@ -1099,102 +1066,10 @@ | |||
<code>addServiceListener</code> | |||
</InvalidArgument> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/Backend/Backend.php"> | |||
<InvalidReturnType occurrences="1"> | |||
<code>self</code> | |||
</InvalidReturnType> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/FrontendDefinitionTrait.php"> | |||
<UndefinedClass occurrences="2"> | |||
<code>FrontendDefinitionTrait</code> | |||
<code>FrontendDefinitionTrait</code> | |||
</UndefinedClass> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/IdentifierTrait.php"> | |||
<UndefinedDocblockClass occurrences="2"> | |||
<code>$this->deprecateTo</code> | |||
<code>IdentifierTrait</code> | |||
</UndefinedDocblockClass> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/LegacyDependencyCheckPolyfill.php"> | |||
<TooManyArguments occurrences="1"> | |||
<code>new MissingDependency($module, $this)</code> | |||
</TooManyArguments> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/PriorityTrait.php"> | |||
<UndefinedClass occurrences="2"> | |||
<code>PriorityTrait</code> | |||
<code>PriorityTrait</code> | |||
</UndefinedClass> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/Storage/AmazonS3.php"> | |||
<UndefinedMagicMethod occurrences="1"> | |||
<code>clearBucket</code> | |||
</UndefinedMagicMethod> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/Storage/SFTP.php"> | |||
<InternalMethod occurrences="1"> | |||
<code>put</code> | |||
</InternalMethod> | |||
<ParamNameMismatch occurrences="2"> | |||
<code>$source</code> | |||
<code>$target</code> | |||
</ParamNameMismatch> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/Storage/SFTPReadStream.php"> | |||
<InvalidArgument occurrences="2"> | |||
<code>$this->handle</code> | |||
<code>$this->handle</code> | |||
</InvalidArgument> | |||
<InvalidNullableReturnType occurrences="1"> | |||
<code>stream_close</code> | |||
</InvalidNullableReturnType> | |||
<InvalidPropertyAssignmentValue occurrences="1"> | |||
<code>substr($response, 4)</code> | |||
</InvalidPropertyAssignmentValue> | |||
<InvalidReturnStatement occurrences="1"> | |||
<code>$context</code> | |||
</InvalidReturnStatement> | |||
<InvalidReturnType occurrences="1"> | |||
<code>array</code> | |||
</InvalidReturnType> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/Storage/SFTPWriteStream.php"> | |||
<InvalidArgument occurrences="2"> | |||
<code>$this->handle</code> | |||
<code>$this->handle</code> | |||
</InvalidArgument> | |||
<InvalidNullableReturnType occurrences="1"> | |||
<code>stream_close</code> | |||
</InvalidNullableReturnType> | |||
<InvalidPropertyAssignmentValue occurrences="1"> | |||
<code>substr($response, 4)</code> | |||
</InvalidPropertyAssignmentValue> | |||
<InvalidReturnStatement occurrences="1"> | |||
<code>$context</code> | |||
</InvalidReturnStatement> | |||
<InvalidReturnType occurrences="1"> | |||
<code>array</code> | |||
</InvalidReturnType> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/Storage/SMB.php"> | |||
<InvalidScalarArgument occurrences="7"> | |||
<code>$e->getCode()</code> | |||
<code>$e->getCode()</code> | |||
<code>$e->getCode()</code> | |||
<code>$e->getCode()</code> | |||
<code>$e->getCode()</code> | |||
<code>$e->getCode()</code> | |||
<code>$e->getCode()</code> | |||
</InvalidScalarArgument> | |||
<ParamNameMismatch occurrences="2"> | |||
<code>$source</code> | |||
<code>$target</code> | |||
</ParamNameMismatch> | |||
<TooManyArguments occurrences="2"> | |||
<code>rename</code> | |||
<code>rename</code> | |||
</TooManyArguments> | |||
</file> | |||
<file src="apps/files_external/lib/Lib/Storage/Swift.php"> | |||
<InvalidArgument occurrences="1"> | |||
@@ -1217,63 +1092,15 @@ | |||
<code>setIV</code> | |||
<code>setIV</code> | |||
</InternalMethod> | |||
<InvalidNullableReturnType occurrences="1"> | |||
<code>string</code> | |||
</InvalidNullableReturnType> | |||
<NullableReturnStatement occurrences="1"> | |||
<code>$message</code> | |||
</NullableReturnStatement> | |||
<TooManyArguments occurrences="1"> | |||
<code>test</code> | |||
</TooManyArguments> | |||
</file> | |||
<file src="apps/files_external/lib/Service/BackendService.php"> | |||
<InvalidArgument occurrences="1"> | |||
<code>'OCA\\Files_External::loadAdditionalBackends'</code> | |||
</InvalidArgument> | |||
<TooManyArguments occurrences="1"> | |||
<code>dispatch</code> | |||
</TooManyArguments> | |||
</file> | |||
<file src="apps/files_external/lib/Service/DBConfigService.php"> | |||
<NullableReturnStatement occurrences="1"> | |||
<code>null</code> | |||
</NullableReturnStatement> | |||
</file> | |||
<file src="apps/files_external/lib/Service/GlobalStoragesService.php"> | |||
<InvalidReturnStatement occurrences="1"> | |||
<code>BackendService::VISIBILITY_ADMIN</code> | |||
</InvalidReturnStatement> | |||
<InvalidReturnType occurrences="1"> | |||
<code>string</code> | |||
</InvalidReturnType> | |||
</file> | |||
<file src="apps/files_external/lib/Service/LegacyStoragesService.php"> | |||
<InvalidScalarArgument occurrences="1"> | |||
<code>$configId</code> | |||
</InvalidScalarArgument> | |||
</file> | |||
<file src="apps/files_external/lib/Service/StoragesService.php"> | |||
<InvalidScalarArgument occurrences="2"> | |||
<code>$this->getVisibilityType()</code> | |||
<code>$this->getVisibilityType()</code> | |||
</InvalidScalarArgument> | |||
<UndefinedInterfaceMethod occurrences="1"> | |||
<code>getStorageCache</code> | |||
</UndefinedInterfaceMethod> | |||
</file> | |||
<file src="apps/files_external/lib/Service/UserStoragesService.php"> | |||
<InvalidReturnStatement occurrences="1"> | |||
<code>BackendService::VISIBILITY_PERSONAL</code> | |||
</InvalidReturnStatement> | |||
<InvalidReturnType occurrences="1"> | |||
<code>string</code> | |||
</InvalidReturnType> | |||
</file> | |||
<file src="apps/files_external/templates/settings.php"> | |||
<UndefinedVariable occurrences="1"> | |||
<code>$_</code> | |||
</UndefinedVariable> | |||
<InvalidArgument occurrences="1"/> | |||
</file> | |||
<file src="apps/files_sharing/lib/AppInfo/Application.php"> | |||
<InvalidArgument occurrences="6"> | |||
@@ -2824,10 +2651,6 @@ | |||
<InvalidScalarArgument occurrences="1"> | |||
<code>$source</code> | |||
</InvalidScalarArgument> | |||
<ParamNameMismatch occurrences="2"> | |||
<code>$source</code> | |||
<code>$target</code> | |||
</ParamNameMismatch> | |||
</file> | |||
<file src="lib/private/Files/ObjectStore/S3ConnectionTrait.php"> | |||
<InternalClass occurrences="1"> | |||
@@ -3089,10 +2912,6 @@ | |||
<code>$free</code> | |||
<code>'ext'</code> | |||
</InvalidScalarArgument> | |||
<ParamNameMismatch occurrences="2"> | |||
<code>$source</code> | |||
<code>$target</code> | |||
</ParamNameMismatch> | |||
</file> | |||
<file src="lib/private/Files/Storage/Wrapper/Wrapper.php"> | |||
<InvalidReturnStatement occurrences="1"> |
@@ -599,12 +599,12 @@ class Filesystem { | |||
return self::$defaultInstance->unlink($path); | |||
} | |||
public static function rename($path1, $path2) { | |||
return self::$defaultInstance->rename($path1, $path2); | |||
public static function rename($source, $target) { | |||
return self::$defaultInstance->rename($source, $target); | |||
} | |||
public static function copy($path1, $path2) { | |||
return self::$defaultInstance->copy($path1, $path2); | |||
public static function copy($source, $target) { | |||
return self::$defaultInstance->copy($source, $target); | |||
} | |||
public static function fopen($path, $mode) { |
@@ -558,17 +558,17 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common { | |||
return parent::copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); | |||
} | |||
public function copy($path1, $path2) { | |||
$path1 = $this->normalizePath($path1); | |||
$path2 = $this->normalizePath($path2); | |||
public function copy($source, $target) { | |||
$source = $this->normalizePath($source); | |||
$target = $this->normalizePath($target); | |||
$cache = $this->getCache(); | |||
$sourceEntry = $cache->get($path1); | |||
$sourceEntry = $cache->get($source); | |||
if (!$sourceEntry) { | |||
throw new NotFoundException('Source object not found'); | |||
} | |||
$this->copyInner($sourceEntry, $path2); | |||
$this->copyInner($sourceEntry, $target); | |||
return true; | |||
} |
@@ -213,21 +213,21 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { | |||
return $count; | |||
} | |||
public function rename($path1, $path2) { | |||
$this->remove($path2); | |||
public function rename($source, $target) { | |||
$this->remove($target); | |||
$this->removeCachedFile($path1); | |||
return $this->copy($path1, $path2) and $this->remove($path1); | |||
$this->removeCachedFile($source); | |||
return $this->copy($source, $target) and $this->remove($source); | |||
} | |||
public function copy($path1, $path2) { | |||
if ($this->is_dir($path1)) { | |||
$this->remove($path2); | |||
$dir = $this->opendir($path1); | |||
$this->mkdir($path2); | |||
public function copy($source, $target) { | |||
if ($this->is_dir($source)) { | |||
$this->remove($target); | |||
$dir = $this->opendir($source); | |||
$this->mkdir($target); | |||
while ($file = readdir($dir)) { | |||
if (!Filesystem::isIgnoredDir($file)) { | |||
if (!$this->copy($path1 . '/' . $file, $path2 . '/' . $file)) { | |||
if (!$this->copy($source . '/' . $file, $target . '/' . $file)) { | |||
closedir($dir); | |||
return false; | |||
} | |||
@@ -236,13 +236,13 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { | |||
closedir($dir); | |||
return true; | |||
} else { | |||
$source = $this->fopen($path1, 'r'); | |||
$target = $this->fopen($path2, 'w'); | |||
[, $result] = \OC_Helper::streamCopy($source, $target); | |||
$sourceStream = $this->fopen($source, 'r'); | |||
$targetStream = $this->fopen($target, 'w'); | |||
[, $result] = \OC_Helper::streamCopy($sourceStream, $targetStream); | |||
if (!$result) { | |||
\OC::$server->get(LoggerInterface::class)->warning("Failed to write data while copying $path1 to $path2"); | |||
\OCP\Server::get(LoggerInterface::class)->warning("Failed to write data while copying $source to $target"); | |||
} | |||
$this->removeCachedFile($path2); | |||
$this->removeCachedFile($target); | |||
return $result; | |||
} | |||
} |
@@ -518,30 +518,30 @@ class DAV extends Common { | |||
} | |||
/** {@inheritdoc} */ | |||
public function rename($path1, $path2) { | |||
public function rename($source, $target) { | |||
$this->init(); | |||
$path1 = $this->cleanPath($path1); | |||
$path2 = $this->cleanPath($path2); | |||
$source = $this->cleanPath($source); | |||
$target = $this->cleanPath($target); | |||
try { | |||
// overwrite directory ? | |||
if ($this->is_dir($path2)) { | |||
if ($this->is_dir($target)) { | |||
// needs trailing slash in destination | |||
$path2 = rtrim($path2, '/') . '/'; | |||
$target = rtrim($target, '/') . '/'; | |||
} | |||
$this->client->request( | |||
'MOVE', | |||
$this->encodePath($path1), | |||
$this->encodePath($source), | |||
null, | |||
[ | |||
'Destination' => $this->createBaseUri() . $this->encodePath($path2), | |||
'Destination' => $this->createBaseUri() . $this->encodePath($target), | |||
] | |||
); | |||
$this->statCache->clear($path1 . '/'); | |||
$this->statCache->clear($path2 . '/'); | |||
$this->statCache->set($path1, false); | |||
$this->statCache->set($path2, true); | |||
$this->removeCachedFile($path1); | |||
$this->removeCachedFile($path2); | |||
$this->statCache->clear($source . '/'); | |||
$this->statCache->clear($target . '/'); | |||
$this->statCache->set($source, false); | |||
$this->statCache->set($target, true); | |||
$this->removeCachedFile($source); | |||
$this->removeCachedFile($target); | |||
return true; | |||
} catch (\Exception $e) { | |||
$this->convertException($e); | |||
@@ -550,27 +550,27 @@ class DAV extends Common { | |||
} | |||
/** {@inheritdoc} */ | |||
public function copy($path1, $path2) { | |||
public function copy($source, $target) { | |||
$this->init(); | |||
$path1 = $this->cleanPath($path1); | |||
$path2 = $this->cleanPath($path2); | |||
$source = $this->cleanPath($source); | |||
$target = $this->cleanPath($target); | |||
try { | |||
// overwrite directory ? | |||
if ($this->is_dir($path2)) { | |||
if ($this->is_dir($target)) { | |||
// needs trailing slash in destination | |||
$path2 = rtrim($path2, '/') . '/'; | |||
$target = rtrim($target, '/') . '/'; | |||
} | |||
$this->client->request( | |||
'COPY', | |||
$this->encodePath($path1), | |||
$this->encodePath($source), | |||
null, | |||
[ | |||
'Destination' => $this->createBaseUri() . $this->encodePath($path2), | |||
'Destination' => $this->createBaseUri() . $this->encodePath($target), | |||
] | |||
); | |||
$this->statCache->clear($path2 . '/'); | |||
$this->statCache->set($path2, true); | |||
$this->removeCachedFile($path2); | |||
$this->statCache->clear($target . '/'); | |||
$this->statCache->set($target, true); | |||
$this->removeCachedFile($target); | |||
return true; | |||
} catch (\Exception $e) { | |||
$this->convertException($e); |
@@ -129,11 +129,11 @@ class FailedStorage extends Common { | |||
throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); | |||
} | |||
public function rename($path1, $path2) { | |||
public function rename($source, $target) { | |||
throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); | |||
} | |||
public function copy($path1, $path2) { | |||
public function copy($source, $target) { | |||
throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); | |||
} | |||
@@ -333,9 +333,9 @@ class Local extends \OC\Files\Storage\Common { | |||
} | |||
} | |||
public function rename($path1, $path2) { | |||
$srcParent = dirname($path1); | |||
$dstParent = dirname($path2); | |||
public function rename($source, $target) { | |||
$srcParent = dirname($source); | |||
$dstParent = dirname($target); | |||
if (!$this->isUpdatable($srcParent)) { | |||
\OC::$server->get(LoggerInterface::class)->error('unable to rename, source directory is not writable : ' . $srcParent, ['app' => 'core']); | |||
@@ -347,44 +347,44 @@ class Local extends \OC\Files\Storage\Common { | |||
return false; | |||
} | |||
if (!$this->file_exists($path1)) { | |||
\OC::$server->get(LoggerInterface::class)->error('unable to rename, file does not exists : ' . $path1, ['app' => 'core']); | |||
if (!$this->file_exists($source)) { | |||
\OC::$server->get(LoggerInterface::class)->error('unable to rename, file does not exists : ' . $source, ['app' => 'core']); | |||
return false; | |||
} | |||
if ($this->is_dir($path2)) { | |||
$this->rmdir($path2); | |||
} elseif ($this->is_file($path2)) { | |||
$this->unlink($path2); | |||
if ($this->is_dir($target)) { | |||
$this->rmdir($target); | |||
} elseif ($this->is_file($target)) { | |||
$this->unlink($target); | |||
} | |||
if ($this->is_dir($path1)) { | |||
if ($this->is_dir($source)) { | |||
// we can't move folders across devices, use copy instead | |||
$stat1 = stat(dirname($this->getSourcePath($path1))); | |||
$stat2 = stat(dirname($this->getSourcePath($path2))); | |||
$stat1 = stat(dirname($this->getSourcePath($source))); | |||
$stat2 = stat(dirname($this->getSourcePath($target))); | |||
if ($stat1['dev'] !== $stat2['dev']) { | |||
$result = $this->copy($path1, $path2); | |||
$result = $this->copy($source, $target); | |||
if ($result) { | |||
$result &= $this->rmdir($path1); | |||
$result &= $this->rmdir($source); | |||
} | |||
return $result; | |||
} | |||
$this->checkTreeForForbiddenItems($this->getSourcePath($path1)); | |||
$this->checkTreeForForbiddenItems($this->getSourcePath($source)); | |||
} | |||
return rename($this->getSourcePath($path1), $this->getSourcePath($path2)); | |||
return rename($this->getSourcePath($source), $this->getSourcePath($target)); | |||
} | |||
public function copy($path1, $path2) { | |||
if ($this->is_dir($path1)) { | |||
return parent::copy($path1, $path2); | |||
public function copy($source, $target) { | |||
if ($this->is_dir($source)) { | |||
return parent::copy($source, $target); | |||
} else { | |||
$oldMask = umask($this->defUMask); | |||
if ($this->unlinkOnTruncate) { | |||
$this->unlink($path2); | |||
$this->unlink($target); | |||
} | |||
$result = copy($this->getSourcePath($path1), $this->getSourcePath($path2)); | |||
$result = copy($this->getSourcePath($source), $this->getSourcePath($target)); | |||
umask($oldMask); | |||
return $result; | |||
} |
@@ -64,15 +64,15 @@ trait CopyDirectory { | |||
*/ | |||
abstract public function mkdir($path); | |||
public function copy($path1, $path2) { | |||
if ($this->is_dir($path1)) { | |||
if ($this->file_exists($path2)) { | |||
$this->unlink($path2); | |||
public function copy($source, $target) { | |||
if ($this->is_dir($source)) { | |||
if ($this->file_exists($target)) { | |||
$this->unlink($target); | |||
} | |||
$this->mkdir($path2); | |||
return $this->copyRecursive($path1, $path2); | |||
$this->mkdir($target); | |||
return $this->copyRecursive($source, $target); | |||
} else { | |||
return parent::copy($path1, $path2); | |||
return parent::copy($source, $target); | |||
} | |||
} | |||
@@ -288,20 +288,20 @@ class Availability extends Wrapper { | |||
} | |||
/** {@inheritdoc} */ | |||
public function rename($path1, $path2) { | |||
public function rename($source, $target) { | |||
$this->checkAvailability(); | |||
try { | |||
return parent::rename($path1, $path2); | |||
return parent::rename($source, $target); | |||
} catch (StorageNotAvailableException $e) { | |||
$this->setUnavailable($e); | |||
} | |||
} | |||
/** {@inheritdoc} */ | |||
public function copy($path1, $path2) { | |||
public function copy($source, $target) { | |||
$this->checkAvailability(); | |||
try { | |||
return parent::copy($path1, $path2); | |||
return parent::copy($source, $target); | |||
} catch (StorageNotAvailableException $e) { | |||
$this->setUnavailable($e); | |||
} |
@@ -338,24 +338,24 @@ class Encoding extends Wrapper { | |||
/** | |||
* see https://www.php.net/manual/en/function.rename.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
*/ | |||
public function rename($path1, $path2) { | |||
public function rename($source, $target) { | |||
// second name always NFC | |||
return $this->storage->rename($this->findPathToUse($path1), $this->findPathToUse($path2)); | |||
return $this->storage->rename($this->findPathToUse($source), $this->findPathToUse($target)); | |||
} | |||
/** | |||
* see https://www.php.net/manual/en/function.copy.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
*/ | |||
public function copy($path1, $path2) { | |||
return $this->storage->copy($this->findPathToUse($path1), $this->findPathToUse($path2)); | |||
public function copy($source, $target) { | |||
return $this->storage->copy($this->findPathToUse($source), $this->findPathToUse($target)); | |||
} | |||
/** |
@@ -270,28 +270,28 @@ class Encryption extends Wrapper { | |||
/** | |||
* see https://www.php.net/manual/en/function.rename.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
*/ | |||
public function rename($path1, $path2) { | |||
$result = $this->storage->rename($path1, $path2); | |||
public function rename($source, $target) { | |||
$result = $this->storage->rename($source, $target); | |||
if ($result && | |||
// versions always use the keys from the original file, so we can skip | |||
// this step for versions | |||
$this->isVersion($path2) === false && | |||
$this->isVersion($target) === false && | |||
$this->encryptionManager->isEnabled()) { | |||
$source = $this->getFullPath($path1); | |||
if (!$this->util->isExcluded($source)) { | |||
$target = $this->getFullPath($path2); | |||
if (isset($this->unencryptedSize[$source])) { | |||
$this->unencryptedSize[$target] = $this->unencryptedSize[$source]; | |||
$sourcePath = $this->getFullPath($source); | |||
if (!$this->util->isExcluded($sourcePath)) { | |||
$targetPath = $this->getFullPath($target); | |||
if (isset($this->unencryptedSize[$sourcePath])) { | |||
$this->unencryptedSize[$targetPath] = $this->unencryptedSize[$sourcePath]; | |||
} | |||
$this->keyStorage->renameKeys($source, $target); | |||
$module = $this->getEncryptionModule($path2); | |||
$this->keyStorage->renameKeys($sourcePath, $targetPath); | |||
$module = $this->getEncryptionModule($target); | |||
if ($module) { | |||
$module->update($target, $this->uid, []); | |||
$module->update($targetPath, $this->uid, []); | |||
} | |||
} | |||
} | |||
@@ -344,21 +344,20 @@ class Encryption extends Wrapper { | |||
/** | |||
* see https://www.php.net/manual/en/function.copy.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @return bool | |||
* @param string $source | |||
* @param string $target | |||
*/ | |||
public function copy($path1, $path2) { | |||
$source = $this->getFullPath($path1); | |||
public function copy($source, $target): bool { | |||
$sourcePath = $this->getFullPath($source); | |||
if ($this->util->isExcluded($source)) { | |||
return $this->storage->copy($path1, $path2); | |||
if ($this->util->isExcluded($sourcePath)) { | |||
return $this->storage->copy($source, $target); | |||
} | |||
// need to stream copy file by file in case we copy between a encrypted | |||
// and a unencrypted storage | |||
$this->unlink($path2); | |||
return $this->copyFromStorage($this, $path1, $path2); | |||
$this->unlink($target); | |||
return $this->copyFromStorage($this, $source, $target); | |||
} | |||
/** |
@@ -281,23 +281,23 @@ class Jail extends Wrapper { | |||
/** | |||
* see https://www.php.net/manual/en/function.rename.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
*/ | |||
public function rename($path1, $path2) { | |||
return $this->getWrapperStorage()->rename($this->getUnjailedPath($path1), $this->getUnjailedPath($path2)); | |||
public function rename($source, $target) { | |||
return $this->getWrapperStorage()->rename($this->getUnjailedPath($source), $this->getUnjailedPath($target)); | |||
} | |||
/** | |||
* see https://www.php.net/manual/en/function.copy.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
*/ | |||
public function copy($path1, $path2) { | |||
return $this->getWrapperStorage()->copy($this->getUnjailedPath($path1), $this->getUnjailedPath($path2)); | |||
public function copy($source, $target) { | |||
return $this->getWrapperStorage()->copy($this->getUnjailedPath($source), $this->getUnjailedPath($target)); | |||
} | |||
/** |
@@ -78,16 +78,16 @@ class PermissionsMask extends Wrapper { | |||
return $this->storage->getPermissions($path) & $this->mask; | |||
} | |||
public function rename($path1, $path2) { | |||
public function rename($source, $target) { | |||
//This is a rename of the transfer file to the original file | |||
if (dirname($path1) === dirname($path2) && strpos($path1, '.ocTransferId') > 0) { | |||
return $this->checkMask(Constants::PERMISSION_CREATE) and parent::rename($path1, $path2); | |||
if (dirname($source) === dirname($target) && strpos($source, '.ocTransferId') > 0) { | |||
return $this->checkMask(Constants::PERMISSION_CREATE) and parent::rename($source, $target); | |||
} | |||
return $this->checkMask(Constants::PERMISSION_UPDATE) and parent::rename($path1, $path2); | |||
return $this->checkMask(Constants::PERMISSION_UPDATE) and parent::rename($source, $target); | |||
} | |||
public function copy($path1, $path2) { | |||
return $this->checkMask(Constants::PERMISSION_CREATE) and parent::copy($path1, $path2); | |||
public function copy($source, $target) { | |||
return $this->checkMask(Constants::PERMISSION_CREATE) and parent::copy($source, $target); | |||
} | |||
public function touch($path, $mtime = null) { |
@@ -271,23 +271,23 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStrea | |||
/** | |||
* see https://www.php.net/manual/en/function.rename.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
*/ | |||
public function rename($path1, $path2) { | |||
return $this->getWrapperStorage()->rename($path1, $path2); | |||
public function rename($source, $target) { | |||
return $this->getWrapperStorage()->rename($source, $target); | |||
} | |||
/** | |||
* see https://www.php.net/manual/en/function.copy.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
*/ | |||
public function copy($path1, $path2) { | |||
return $this->getWrapperStorage()->copy($path1, $path2); | |||
public function copy($source, $target) { | |||
return $this->getWrapperStorage()->copy($source, $target); | |||
} | |||
/** |
@@ -749,65 +749,65 @@ class View { | |||
/** | |||
* Rename/move a file or folder from the source path to target path. | |||
* | |||
* @param string $path1 source path | |||
* @param string $path2 target path | |||
* @param string $source source path | |||
* @param string $target target path | |||
* | |||
* @return bool|mixed | |||
* @throws LockedException | |||
*/ | |||
public function rename($path1, $path2) { | |||
$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); | |||
$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2)); | |||
public function rename($source, $target) { | |||
$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($source)); | |||
$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($target)); | |||
$result = false; | |||
if ( | |||
Filesystem::isValidPath($path2) | |||
and Filesystem::isValidPath($path1) | |||
and !Filesystem::isFileBlacklisted($path2) | |||
Filesystem::isValidPath($target) | |||
and Filesystem::isValidPath($source) | |||
and !Filesystem::isFileBlacklisted($target) | |||
) { | |||
$path1 = $this->getRelativePath($absolutePath1); | |||
$path2 = $this->getRelativePath($absolutePath2); | |||
$exists = $this->file_exists($path2); | |||
$source = $this->getRelativePath($absolutePath1); | |||
$target = $this->getRelativePath($absolutePath2); | |||
$exists = $this->file_exists($target); | |||
if ($path1 == null or $path2 == null) { | |||
if ($source == null or $target == null) { | |||
return false; | |||
} | |||
$this->lockFile($path1, ILockingProvider::LOCK_SHARED, true); | |||
$this->lockFile($source, ILockingProvider::LOCK_SHARED, true); | |||
try { | |||
$this->lockFile($path2, ILockingProvider::LOCK_SHARED, true); | |||
$this->lockFile($target, ILockingProvider::LOCK_SHARED, true); | |||
$run = true; | |||
if ($this->shouldEmitHooks($path1) && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2))) { | |||
if ($this->shouldEmitHooks($source) && (Cache\Scanner::isPartialFile($source) && !Cache\Scanner::isPartialFile($target))) { | |||
// if it was a rename from a part file to a regular file it was a write and not a rename operation | |||
$this->emit_file_hooks_pre($exists, $path2, $run); | |||
} elseif ($this->shouldEmitHooks($path1)) { | |||
$this->emit_file_hooks_pre($exists, $target, $run); | |||
} elseif ($this->shouldEmitHooks($source)) { | |||
\OC_Hook::emit( | |||
Filesystem::CLASSNAME, Filesystem::signal_rename, | |||
[ | |||
Filesystem::signal_param_oldpath => $this->getHookPath($path1), | |||
Filesystem::signal_param_newpath => $this->getHookPath($path2), | |||
Filesystem::signal_param_oldpath => $this->getHookPath($source), | |||
Filesystem::signal_param_newpath => $this->getHookPath($target), | |||
Filesystem::signal_param_run => &$run | |||
] | |||
); | |||
} | |||
if ($run) { | |||
$this->verifyPath(dirname($path2), basename($path2)); | |||
$this->verifyPath(dirname($target), basename($target)); | |||
$manager = Filesystem::getMountManager(); | |||
$mount1 = $this->getMount($path1); | |||
$mount2 = $this->getMount($path2); | |||
$mount1 = $this->getMount($source); | |||
$mount2 = $this->getMount($target); | |||
$storage1 = $mount1->getStorage(); | |||
$storage2 = $mount2->getStorage(); | |||
$internalPath1 = $mount1->getInternalPath($absolutePath1); | |||
$internalPath2 = $mount2->getInternalPath($absolutePath2); | |||
$this->changeLock($path1, ILockingProvider::LOCK_EXCLUSIVE, true); | |||
$this->changeLock($source, ILockingProvider::LOCK_EXCLUSIVE, true); | |||
try { | |||
$this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE, true); | |||
$this->changeLock($target, ILockingProvider::LOCK_EXCLUSIVE, true); | |||
if ($internalPath1 === '') { | |||
if ($mount1 instanceof MoveableMount) { | |||
$sourceParentMount = $this->getMount(dirname($path1)); | |||
$sourceParentMount = $this->getMount(dirname($source)); | |||
if ($sourceParentMount === $mount2 && $this->targetIsNotShared($storage2, $internalPath2)) { | |||
/** | |||
* @var \OC\Files\Mount\MountPoint | \OC\Files\Mount\MoveableMount $mount1 | |||
@@ -833,7 +833,7 @@ class View { | |||
$result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2); | |||
} | |||
if ((Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) { | |||
if ((Cache\Scanner::isPartialFile($source) && !Cache\Scanner::isPartialFile($target)) && $result !== false) { | |||
// if it was a rename from a part file to a regular file it was a write and not a rename operation | |||
$this->writeUpdate($storage2, $internalPath2); | |||
} elseif ($result) { | |||
@@ -844,22 +844,22 @@ class View { | |||
} catch (\Exception $e) { | |||
throw $e; | |||
} finally { | |||
$this->changeLock($path1, ILockingProvider::LOCK_SHARED, true); | |||
$this->changeLock($path2, ILockingProvider::LOCK_SHARED, true); | |||
$this->changeLock($source, ILockingProvider::LOCK_SHARED, true); | |||
$this->changeLock($target, ILockingProvider::LOCK_SHARED, true); | |||
} | |||
if ((Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) { | |||
if ((Cache\Scanner::isPartialFile($source) && !Cache\Scanner::isPartialFile($target)) && $result !== false) { | |||
if ($this->shouldEmitHooks()) { | |||
$this->emit_file_hooks_post($exists, $path2); | |||
$this->emit_file_hooks_post($exists, $target); | |||
} | |||
} elseif ($result) { | |||
if ($this->shouldEmitHooks($path1) and $this->shouldEmitHooks($path2)) { | |||
if ($this->shouldEmitHooks($source) and $this->shouldEmitHooks($target)) { | |||
\OC_Hook::emit( | |||
Filesystem::CLASSNAME, | |||
Filesystem::signal_post_rename, | |||
[ | |||
Filesystem::signal_param_oldpath => $this->getHookPath($path1), | |||
Filesystem::signal_param_newpath => $this->getHookPath($path2) | |||
Filesystem::signal_param_oldpath => $this->getHookPath($source), | |||
Filesystem::signal_param_newpath => $this->getHookPath($target) | |||
] | |||
); | |||
} | |||
@@ -868,8 +868,8 @@ class View { | |||
} catch (\Exception $e) { | |||
throw $e; | |||
} finally { | |||
$this->unlockFile($path1, ILockingProvider::LOCK_SHARED, true); | |||
$this->unlockFile($path2, ILockingProvider::LOCK_SHARED, true); | |||
$this->unlockFile($source, ILockingProvider::LOCK_SHARED, true); | |||
$this->unlockFile($target, ILockingProvider::LOCK_SHARED, true); | |||
} | |||
} | |||
return $result; | |||
@@ -878,57 +878,57 @@ class View { | |||
/** | |||
* Copy a file/folder from the source path to target path | |||
* | |||
* @param string $path1 source path | |||
* @param string $path2 target path | |||
* @param string $source source path | |||
* @param string $target target path | |||
* @param bool $preserveMtime whether to preserve mtime on the copy | |||
* | |||
* @return bool|mixed | |||
*/ | |||
public function copy($path1, $path2, $preserveMtime = false) { | |||
$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); | |||
$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2)); | |||
public function copy($source, $target, $preserveMtime = false) { | |||
$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($source)); | |||
$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($target)); | |||
$result = false; | |||
if ( | |||
Filesystem::isValidPath($path2) | |||
and Filesystem::isValidPath($path1) | |||
and !Filesystem::isFileBlacklisted($path2) | |||
Filesystem::isValidPath($target) | |||
and Filesystem::isValidPath($source) | |||
and !Filesystem::isFileBlacklisted($target) | |||
) { | |||
$path1 = $this->getRelativePath($absolutePath1); | |||
$path2 = $this->getRelativePath($absolutePath2); | |||
$source = $this->getRelativePath($absolutePath1); | |||
$target = $this->getRelativePath($absolutePath2); | |||
if ($path1 == null or $path2 == null) { | |||
if ($source == null or $target == null) { | |||
return false; | |||
} | |||
$run = true; | |||
$this->lockFile($path2, ILockingProvider::LOCK_SHARED); | |||
$this->lockFile($path1, ILockingProvider::LOCK_SHARED); | |||
$this->lockFile($target, ILockingProvider::LOCK_SHARED); | |||
$this->lockFile($source, ILockingProvider::LOCK_SHARED); | |||
$lockTypePath1 = ILockingProvider::LOCK_SHARED; | |||
$lockTypePath2 = ILockingProvider::LOCK_SHARED; | |||
try { | |||
$exists = $this->file_exists($path2); | |||
$exists = $this->file_exists($target); | |||
if ($this->shouldEmitHooks()) { | |||
\OC_Hook::emit( | |||
Filesystem::CLASSNAME, | |||
Filesystem::signal_copy, | |||
[ | |||
Filesystem::signal_param_oldpath => $this->getHookPath($path1), | |||
Filesystem::signal_param_newpath => $this->getHookPath($path2), | |||
Filesystem::signal_param_oldpath => $this->getHookPath($source), | |||
Filesystem::signal_param_newpath => $this->getHookPath($target), | |||
Filesystem::signal_param_run => &$run | |||
] | |||
); | |||
$this->emit_file_hooks_pre($exists, $path2, $run); | |||
$this->emit_file_hooks_pre($exists, $target, $run); | |||
} | |||
if ($run) { | |||
$mount1 = $this->getMount($path1); | |||
$mount2 = $this->getMount($path2); | |||
$mount1 = $this->getMount($source); | |||
$mount2 = $this->getMount($target); | |||
$storage1 = $mount1->getStorage(); | |||
$internalPath1 = $mount1->getInternalPath($absolutePath1); | |||
$storage2 = $mount2->getStorage(); | |||
$internalPath2 = $mount2->getInternalPath($absolutePath2); | |||
$this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE); | |||
$this->changeLock($target, ILockingProvider::LOCK_EXCLUSIVE); | |||
$lockTypePath2 = ILockingProvider::LOCK_EXCLUSIVE; | |||
if ($mount1->getMountPoint() == $mount2->getMountPoint()) { | |||
@@ -943,7 +943,7 @@ class View { | |||
$this->writeUpdate($storage2, $internalPath2); | |||
$this->changeLock($path2, ILockingProvider::LOCK_SHARED); | |||
$this->changeLock($target, ILockingProvider::LOCK_SHARED); | |||
$lockTypePath2 = ILockingProvider::LOCK_SHARED; | |||
if ($this->shouldEmitHooks() && $result !== false) { | |||
@@ -951,21 +951,21 @@ class View { | |||
Filesystem::CLASSNAME, | |||
Filesystem::signal_post_copy, | |||
[ | |||
Filesystem::signal_param_oldpath => $this->getHookPath($path1), | |||
Filesystem::signal_param_newpath => $this->getHookPath($path2) | |||
Filesystem::signal_param_oldpath => $this->getHookPath($source), | |||
Filesystem::signal_param_newpath => $this->getHookPath($target) | |||
] | |||
); | |||
$this->emit_file_hooks_post($exists, $path2); | |||
$this->emit_file_hooks_post($exists, $target); | |||
} | |||
} | |||
} catch (\Exception $e) { | |||
$this->unlockFile($path2, $lockTypePath2); | |||
$this->unlockFile($path1, $lockTypePath1); | |||
$this->unlockFile($target, $lockTypePath2); | |||
$this->unlockFile($source, $lockTypePath1); | |||
throw $e; | |||
} | |||
$this->unlockFile($path2, $lockTypePath2); | |||
$this->unlockFile($path1, $lockTypePath1); | |||
$this->unlockFile($target, $lockTypePath2); | |||
$this->unlockFile($source, $lockTypePath1); | |||
} | |||
return $result; | |||
} |
@@ -113,11 +113,11 @@ class NullStorage extends Common { | |||
throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); | |||
} | |||
public function rename($path1, $path2) { | |||
public function rename($source, $target) { | |||
throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); | |||
} | |||
public function copy($path1, $path2) { | |||
public function copy($source, $target) { | |||
throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); | |||
} | |||
@@ -244,22 +244,22 @@ interface Storage extends IStorage { | |||
/** | |||
* see https://www.php.net/manual/en/function.rename.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
* @since 6.0.0 | |||
*/ | |||
public function rename($path1, $path2); | |||
public function rename($source, $target); | |||
/** | |||
* see https://www.php.net/manual/en/function.copy.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $soruce | |||
* @param string $target | |||
* @return bool | |||
* @since 6.0.0 | |||
*/ | |||
public function copy($path1, $path2); | |||
public function copy($source, $target); | |||
/** | |||
* see https://www.php.net/manual/en/function.fopen.php |
@@ -241,22 +241,22 @@ interface IStorage { | |||
/** | |||
* see https://www.php.net/manual/en/function.rename.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
* @since 9.0.0 | |||
*/ | |||
public function rename($path1, $path2); | |||
public function rename($source, $target); | |||
/** | |||
* see https://www.php.net/manual/en/function.copy.php | |||
* | |||
* @param string $path1 | |||
* @param string $path2 | |||
* @param string $source | |||
* @param string $target | |||
* @return bool | |||
* @since 9.0.0 | |||
*/ | |||
public function copy($path1, $path2); | |||
public function copy($source, $target); | |||
/** | |||
* see https://www.php.net/manual/en/function.fopen.php |