2017-07-26 13:33:32 +03:00
< ? php
/**
2019-12-03 21:57:53 +03:00
*
*
* @ author Georg Ehrke < oc . list @ georgehrke . com >
* @ author Roeland Jago Douma < roeland @ famdouma . nl >
2020-03-31 11:49:10 +03:00
* @ author Thomas Citharel < nextcloud @ tcit . fr >
2017-07-26 13:33:32 +03:00
*
2019-12-03 21:57:53 +03:00
* @ license GNU AGPL version 3 or any later version
2017-07-26 13:33:32 +03:00
*
2019-12-03 21:57:53 +03:00
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
2017-07-26 13:33:32 +03:00
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
2019-12-03 21:57:53 +03:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
2017-07-26 13:33:32 +03:00
* GNU Affero General Public License for more details .
*
2019-12-03 21:57:53 +03:00
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < http :// www . gnu . org / licenses />.
2017-07-26 13:33:32 +03:00
*
*/
2019-11-22 22:52:10 +03:00
2017-07-26 13:33:32 +03:00
namespace OCA\DAV\Command ;
use OCA\DAV\CalDAV\CalDavBackend ;
use OCA\DAV\CalDAV\Calendar ;
2018-03-08 16:44:02 +03:00
use OCP\IConfig ;
2017-07-26 13:33:32 +03:00
use OCP\IGroupManager ;
use OCP\IL10N ;
use OCP\IUserManager ;
2019-01-03 20:31:10 +03:00
use OCP\Share\IManager as IShareManager ;
2017-07-26 13:33:32 +03:00
use Symfony\Component\Console\Command\Command ;
use Symfony\Component\Console\Input\InputArgument ;
use Symfony\Component\Console\Input\InputInterface ;
use Symfony\Component\Console\Input\InputOption ;
use Symfony\Component\Console\Output\OutputInterface ;
use Symfony\Component\Console\Style\SymfonyStyle ;
class MoveCalendar extends Command {
/** @var IUserManager */
2018-03-08 16:44:02 +03:00
private $userManager ;
2017-07-26 13:33:32 +03:00
2019-01-03 20:31:10 +03:00
/** @var IGroupManager */
2017-07-26 13:33:32 +03:00
private $groupManager ;
2019-01-03 20:31:10 +03:00
/** @var IShareManager */
private $shareManager ;
2018-03-08 16:44:02 +03:00
/** @var IConfig $config */
private $config ;
2017-07-26 13:33:32 +03:00
/** @var IL10N */
2018-03-08 16:44:02 +03:00
private $l10n ;
2017-07-26 13:33:32 +03:00
/** @var SymfonyStyle */
private $io ;
/** @var CalDavBackend */
2018-03-08 16:44:02 +03:00
private $calDav ;
2017-07-26 13:33:32 +03:00
const URI_USERS = 'principals/users/' ;
/**
* @ param IUserManager $userManager
* @ param IGroupManager $groupManager
2019-01-03 20:31:10 +03:00
* @ param IShareManager $shareManager
2018-03-08 16:44:02 +03:00
* @ param IConfig $config
2017-07-26 13:33:32 +03:00
* @ param IL10N $l10n
2018-03-08 16:44:02 +03:00
* @ param CalDavBackend $calDav
2017-07-26 13:33:32 +03:00
*/
2018-03-08 16:44:02 +03:00
function __construct (
IUserManager $userManager ,
IGroupManager $groupManager ,
2019-01-03 20:31:10 +03:00
IShareManager $shareManager ,
2018-03-08 16:44:02 +03:00
IConfig $config ,
IL10N $l10n ,
CalDavBackend $calDav
) {
2017-07-26 13:33:32 +03:00
parent :: __construct ();
$this -> userManager = $userManager ;
$this -> groupManager = $groupManager ;
2019-01-03 20:31:10 +03:00
$this -> shareManager = $shareManager ;
2018-03-08 16:44:02 +03:00
$this -> config = $config ;
2017-07-26 13:33:32 +03:00
$this -> l10n = $l10n ;
2018-03-08 16:44:02 +03:00
$this -> calDav = $calDav ;
2017-07-26 13:33:32 +03:00
}
protected function configure () {
$this
-> setName ( 'dav:move-calendar' )
-> setDescription ( 'Move a calendar from an user to another' )
-> addArgument ( 'name' ,
InputArgument :: REQUIRED ,
'Name of the calendar to move' )
2019-01-15 15:59:54 +03:00
-> addArgument ( 'sourceuid' ,
2017-07-26 13:33:32 +03:00
InputArgument :: REQUIRED ,
'User who currently owns the calendar' )
2019-01-15 15:59:54 +03:00
-> addArgument ( 'destinationuid' ,
2017-07-26 13:33:32 +03:00
InputArgument :: REQUIRED ,
'User who will receive the calendar' )
2019-01-15 15:59:54 +03:00
-> addOption ( 'force' , 'f' , InputOption :: VALUE_NONE , " Force the migration by removing existing shares " );
2017-07-26 13:33:32 +03:00
}
protected function execute ( InputInterface $input , OutputInterface $output ) {
2019-01-15 15:59:54 +03:00
$userOrigin = $input -> getArgument ( 'sourceuid' );
$userDestination = $input -> getArgument ( 'destinationuid' );
2017-07-26 13:33:32 +03:00
$this -> io = new SymfonyStyle ( $input , $output );
if ( ! $this -> userManager -> userExists ( $userOrigin )) {
throw new \InvalidArgumentException ( " User < $userOrigin > is unknown. " );
}
if ( ! $this -> userManager -> userExists ( $userDestination )) {
throw new \InvalidArgumentException ( " User < $userDestination > is unknown. " );
}
$name = $input -> getArgument ( 'name' );
2018-03-08 16:44:02 +03:00
$calendar = $this -> calDav -> getCalendarByUri ( self :: URI_USERS . $userOrigin , $name );
2017-07-26 13:33:32 +03:00
if ( null === $calendar ) {
2018-03-08 16:44:02 +03:00
throw new \InvalidArgumentException ( " User < $userOrigin > has no calendar named < $name >. You can run occ dav:list-calendars to list calendars URIs for this user. " );
2017-07-26 13:33:32 +03:00
}
2018-03-08 16:44:02 +03:00
if ( null !== $this -> calDav -> getCalendarByUri ( self :: URI_USERS . $userDestination , $name )) {
2017-07-26 13:33:32 +03:00
throw new \InvalidArgumentException ( " User < $userDestination > already has a calendar named < $name >. " );
}
2019-01-15 15:59:54 +03:00
$this -> checkShares ( $calendar , $userOrigin , $userDestination , $input -> getOption ( 'force' ));
2017-07-26 13:33:32 +03:00
2018-03-08 16:44:02 +03:00
$this -> calDav -> moveCalendar ( $name , self :: URI_USERS . $userOrigin , self :: URI_USERS . $userDestination );
2017-07-26 13:33:32 +03:00
$this -> io -> success ( " Calendar < $name > was moved from user < $userOrigin > to < $userDestination > " );
}
/**
2019-01-15 15:59:54 +03:00
* Check that moving the calendar won ' t break shares
2017-07-26 13:33:32 +03:00
*
2019-01-15 15:59:54 +03:00
* @ param array $calendar
* @ param string $userOrigin
* @ param string $userDestination
2017-07-26 13:33:32 +03:00
* @ param bool $force
*/
2019-01-15 15:59:54 +03:00
private function checkShares ( array $calendar , string $userOrigin , string $userDestination , bool $force = false )
2017-07-26 13:33:32 +03:00
{
2018-03-08 16:44:02 +03:00
$shares = $this -> calDav -> getShares ( $calendar [ 'id' ]);
2017-07-26 13:33:32 +03:00
foreach ( $shares as $share ) {
2019-01-15 15:59:54 +03:00
list (, $prefix , $userOrGroup ) = explode ( '/' , $share [ 'href' ], 3 );
/**
* Check that user destination is member of the groups which whom the calendar was shared
* If we ask to force the migration , the share with the group is dropped
*/
if ( $this -> shareManager -> shareWithGroupMembersOnly () === true && 'groups' === $prefix && ! $this -> groupManager -> isInGroup ( $userDestination , $userOrGroup )) {
if ( $force ) {
$this -> calDav -> updateShares ( new Calendar ( $this -> calDav , $calendar , $this -> l10n , $this -> config ), [], [ 'href' => 'principal:principals/groups/' . $userOrGroup ]);
} else {
throw new \InvalidArgumentException ( " User < $userDestination > is not part of the group < $userOrGroup > with whom the calendar < " . $calendar [ 'uri' ] . " > was shared. You may use -f to move the calendar while deleting this share. " );
}
}
/**
* Check that calendar isn ' t already shared with user destination
*/
if ( $userOrGroup === $userDestination ) {
2017-07-26 13:33:32 +03:00
if ( $force ) {
2019-01-15 15:59:54 +03:00
$this -> calDav -> updateShares ( new Calendar ( $this -> calDav , $calendar , $this -> l10n , $this -> config ), [], [ 'href' => 'principal:principals/users/' . $userOrGroup ]);
2017-07-26 13:33:32 +03:00
} else {
2019-01-15 15:59:54 +03:00
throw new \InvalidArgumentException ( " The calendar < " . $calendar [ 'uri' ] . " > is already shared to user < $userDestination >.You may use -f to move the calendar while deleting this share. " );
2017-07-26 13:33:32 +03:00
}
}
}
2019-01-15 15:59:54 +03:00
/**
* Warn that share links have changed if there are shares
*/
if ( count ( $shares ) > 0 ) {
$this -> io -> note ([
" Please note that moving calendar " . $calendar [ 'uri' ] . " from user < $userOrigin > to < $userDestination > has caused share links to change. " ,
" Sharees will need to change \" example.com/remote.php/dav/calendars/uid/ " . $calendar [ 'uri' ] . " _shared_by_ $userOrigin\ " to \ " example.com/remote.php/dav/calendars/uid/ " . $calendar [ 'uri' ] . " _shared_by_ $userDestination\ " "
]);
}
2017-07-26 13:33:32 +03:00
}
}