add occ command to trashbin to remove deleted files
This commit is contained in:
parent
7a3cfbc3c8
commit
407db913de
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Björn Schießle <schiessle@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* 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/>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
use OCA\Files_Trashbin\Command\CleanUp;
|
||||
|
||||
$userManager = OC::$server->getUserManager();
|
||||
$rootFolder = \OC::$server->getRootFolder();
|
||||
$dbConnection = \OC::$server->getDatabaseConnection();
|
||||
/** @var Symfony\Component\Console\Application $application */
|
||||
$application->add(new CleanUp($rootFolder, $userManager, $dbConnection));
|
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Björn Schießle <schiessle@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* 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_Trashbin\Command;
|
||||
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUserBackend;
|
||||
use OCP\IUserManager;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class CleanUp extends Command {
|
||||
|
||||
/** @var IUserManager */
|
||||
protected $userManager;
|
||||
|
||||
/** @var IRootFolder */
|
||||
protected $rootFolder;
|
||||
|
||||
/** @var \OC\DB\Connection */
|
||||
protected $dbConnection;
|
||||
|
||||
/**
|
||||
* @param IRootFolder $rootFolder
|
||||
* @param IUserManager $userManager
|
||||
* @param IDBConnection $dbConnection
|
||||
*/
|
||||
function __construct(IRootFolder $rootFolder, IUserManager $userManager, IDBConnection $dbConnection) {
|
||||
parent::__construct();
|
||||
$this->userManager = $userManager;
|
||||
$this->rootFolder = $rootFolder;
|
||||
$this->dbConnection = $dbConnection;
|
||||
}
|
||||
|
||||
protected function configure() {
|
||||
$this
|
||||
->setName('trashbin:cleanup')
|
||||
->setDescription('Remove deleted files')
|
||||
->addArgument(
|
||||
'user_id',
|
||||
InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
|
||||
'remove deleted files of the given user(s), if no user is given all deleted files will be removed'
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$users = $input->getArgument('user_id');
|
||||
if (!empty($users)) {
|
||||
foreach ($users as $user) {
|
||||
if ($this->userManager->userExists($user)) {
|
||||
$output->writeln("Remove deleted files of <info>$user</info>");
|
||||
$this->removeDeletedFiles($user);
|
||||
} else {
|
||||
$output->writeln("<error>Unknown user $user</error>");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$output->writeln('Remove all deleted files');
|
||||
foreach ($this->userManager->getBackends() as $backend) {
|
||||
$name = get_class($backend);
|
||||
if ($backend instanceof IUserBackend) {
|
||||
$name = $backend->getBackendName();
|
||||
}
|
||||
$output->writeln("Remove deleted files for users on backend <info>$name</info>");
|
||||
$limit = 500;
|
||||
$offset = 0;
|
||||
do {
|
||||
$users = $backend->getUsers('', $limit, $offset);
|
||||
foreach ($users as $user) {
|
||||
$output->writeln(" <info>$user</info>");
|
||||
$this->removeDeletedFiles($user);
|
||||
}
|
||||
$offset += $limit;
|
||||
} while (count($users) >= $limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove deleted files for the given user
|
||||
*
|
||||
* @param string $uid
|
||||
*/
|
||||
protected function removeDeletedFiles($uid) {
|
||||
\OC_Util::tearDownFS();
|
||||
\OC_Util::setupFS($uid);
|
||||
if ($this->rootFolder->nodeExists('/' . $uid . '/files_trashbin')) {
|
||||
$this->rootFolder->get('/' . $uid . '/files_trashbin')->delete();
|
||||
$query = $this->dbConnection->createQueryBuilder();
|
||||
$query->delete('`*PREFIX*files_trash`')
|
||||
->where($query->expr()->eq('`user`', ':uid'))
|
||||
->setParameter('uid', $uid);
|
||||
$query->execute();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Björn Schießle <schiessle@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* 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_Trashbin\Tests\Command;
|
||||
|
||||
|
||||
use OCA\Files_Trashbin\Command\CleanUp;
|
||||
use Test\TestCase;
|
||||
use OC\User\Manager;
|
||||
use OCP\Files\IRootFolder;
|
||||
|
||||
class CleanUpTest extends TestCase {
|
||||
|
||||
/** @var CleanUp */
|
||||
protected $cleanup;
|
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject | Manager */
|
||||
protected $userManager;
|
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject | IRootFolder */
|
||||
protected $rootFolder;
|
||||
|
||||
/** @var \OC\DB\Connection */
|
||||
protected $dbConnection;
|
||||
|
||||
/** @var string */
|
||||
protected $trashTable = '`*PREFIX*files_trash`';
|
||||
|
||||
/** @var string */
|
||||
protected $user0 = 'user0';
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->rootFolder = $this->getMockBuilder('OCP\Files\IRootFolder')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->userManager = $this->getMockBuilder('OC\User\Manager')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
|
||||
$this->dbConnection = \OC::$server->getDatabaseConnection();
|
||||
|
||||
$this->cleanup = new CleanUp($this->rootFolder, $this->userManager, $this->dbConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
* populate files_trash table with 10 dummy values
|
||||
*/
|
||||
public function initTable() {
|
||||
$query = $this->dbConnection->createQueryBuilder();
|
||||
$query->delete($this->trashTable)->execute();
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$query->insert($this->trashTable)
|
||||
->values(array(
|
||||
'`id`' => $query->expr()->literal('file'.$i),
|
||||
'`timestamp`' => $query->expr()->literal($i),
|
||||
'`location`' => $query->expr()->literal('.'),
|
||||
'`user`' => $query->expr()->literal('user'.$i%2)
|
||||
))->execute();
|
||||
}
|
||||
$getAllQuery = $this->dbConnection->createQueryBuilder();
|
||||
$result = $getAllQuery->select('`id`')->from($this->trashTable)->execute()->fetchAll();
|
||||
$this->assertSame(10, count($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTestRemoveDeletedFiles
|
||||
* @param boolean $nodeExists
|
||||
*/
|
||||
public function testRemoveDeletedFiles($nodeExists) {
|
||||
$this->initTable();
|
||||
$this->rootFolder->expects($this->once())
|
||||
->method('nodeExists')
|
||||
->with('/' . $this->user0 . '/files_trashbin')
|
||||
->willReturn($nodeExists);
|
||||
if($nodeExists) {
|
||||
$this->rootFolder->expects($this->once())
|
||||
->method('get')
|
||||
->with('/' . $this->user0 . '/files_trashbin')
|
||||
->willReturn($this->rootFolder);
|
||||
$this->rootFolder->expects($this->once())
|
||||
->method('delete');
|
||||
} else {
|
||||
$this->rootFolder->expects($this->never())->method('get');
|
||||
$this->rootFolder->expects($this->never())->method('delete');
|
||||
}
|
||||
$this->invokePrivate($this->cleanup, 'removeDeletedFiles', [$this->user0]);
|
||||
|
||||
if ($nodeExists) {
|
||||
// if the delete operation was execute only files from user1
|
||||
// should be left.
|
||||
$query = $this->dbConnection->createQueryBuilder();
|
||||
$result = $query->select('`user`')
|
||||
->from($this->trashTable)
|
||||
->execute()->fetchAll();
|
||||
$this->assertSame(5, count($result));
|
||||
foreach ($result as $r) {
|
||||
$this->assertSame('user1', $r['user']);
|
||||
}
|
||||
} else {
|
||||
// if no delete operation was execute we should still have all 10
|
||||
// database entries
|
||||
$getAllQuery = $this->dbConnection->createQueryBuilder();
|
||||
$result = $getAllQuery->select('`id`')->from($this->trashTable)->execute()->fetchAll();
|
||||
$this->assertSame(10, count($result));
|
||||
}
|
||||
|
||||
}
|
||||
public function dataTestRemoveDeletedFiles() {
|
||||
return array(
|
||||
array(true),
|
||||
array(false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* test remove deleted files from users given as parameter
|
||||
*/
|
||||
public function testExecuteDeleteListOfUsers() {
|
||||
$userIds = ['user1', 'user2', 'user3'];
|
||||
$instance = $this->getMockBuilder('OCA\Files_Trashbin\Command\CleanUp')
|
||||
->setMethods(['removeDeletedFiles'])
|
||||
->setConstructorArgs([$this->rootFolder, $this->userManager, $this->dbConnection])
|
||||
->getMock();
|
||||
$instance->expects($this->exactly(count($userIds)))
|
||||
->method('removeDeletedFiles')
|
||||
->willReturnCallback(function ($user) use ($userIds) {
|
||||
$this->assertTrue(in_array($user, $userIds));
|
||||
});
|
||||
$this->userManager->expects($this->exactly(count($userIds)))
|
||||
->method('userExists')->willReturn(true);
|
||||
$inputInterface = $this->getMockBuilder('\Symfony\Component\Console\Input\InputInterface')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$inputInterface->expects($this->once())->method('getArgument')
|
||||
->with('user_id')
|
||||
->willReturn($userIds);
|
||||
$outputInterface = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
/**
|
||||
* test remove deleted files of all users
|
||||
*/
|
||||
public function testExecuteAllUsers() {
|
||||
$userIds = [];
|
||||
$backendUsers = ['user1', 'user2'];
|
||||
$instance = $this->getMockBuilder('OCA\Files_Trashbin\Command\CleanUp')
|
||||
->setMethods(['removeDeletedFiles'])
|
||||
->setConstructorArgs([$this->rootFolder, $this->userManager, $this->dbConnection])
|
||||
->getMock();
|
||||
$backend = $this->getMockBuilder('OC_User_Interface')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$backend->expects($this->once())->method('getUsers')
|
||||
->with('', 500, 0)
|
||||
->willReturn($backendUsers);
|
||||
$instance->expects($this->exactly(count($backendUsers)))
|
||||
->method('removeDeletedFiles')
|
||||
->willReturnCallback(function ($user) use ($backendUsers) {
|
||||
$this->assertTrue(in_array($user, $backendUsers));
|
||||
});
|
||||
$inputInterface = $this->getMockBuilder('\Symfony\Component\Console\Input\InputInterface')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$inputInterface->expects($this->once())->method('getArgument')
|
||||
->with('user_id')
|
||||
->willReturn($userIds);
|
||||
$outputInterface = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->userManager->expects($this->once())
|
||||
->method('getBackends')
|
||||
->willReturn([$backend]);
|
||||
$this->invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue