From 0e85ba0cff7fc199acf9f90a9e025de05805bb01 Mon Sep 17 00:00:00 2001 From: Hong Ooi Date: Sat, 27 May 2023 22:46:24 +1000 Subject: [PATCH] copy and move --- R/ms_drive.R | 16 ++++++++++ R/ms_drive_item.R | 74 ++++++++++++++++++++++++++++++++++++++++++++ man/ms_drive.Rd | 7 +++++ man/ms_drive_item.Rd | 17 ++++++++++ 4 files changed, 114 insertions(+) diff --git a/R/ms_drive.R b/R/ms_drive.R index be02f2b..68c9f3b 100644 --- a/R/ms_drive.R +++ b/R/ms_drive.R @@ -26,6 +26,8 @@ #' - `get_item(path, itemid)`: Get an item representing a file or folder. #' - `get_item_properties(path, itemid)`: Get the properties (metadata) for a file or folder. #' - `set_item_properties(path, itemid, ...)`: Set the properties for a file or folder. +#' - `copy_item(path, itemid, dest, dest_item_id)`: Copy a file or folder. +#' - `move_item(path, itemid, dest, dest_item_id)`: Move a file or folder. #' - `list_shared_items(...), list_shared_files(...)`: List the drive items shared with you. See 'Shared items' below. #' - `load_dataframe(path, itemid, ...)`: Download a delimited file and return its contents as a data frame. See 'Saving and loading data' below. #' - `load_rds(path, itemid)`: Download a .rds file and return the saved object. @@ -52,6 +54,10 @@ #' #' `set_item_properties` sets the properties of a file or folder. The new properties should be specified as individual named arguments to the method. Any existing properties that aren't listed as arguments will retain their previous values or be recalculated based on changes to other properties, as appropriate. You can also call the `update` method on the corresponding `ms_drive_item` object. #' +#' - `copy_item` and `move_item` can take the destination location as either a full pathname (in the `dest` argument), or a name plus a drive item object (in the `dest_folder_item` argument). If the latter is supplied, any path in `dest` is ignored with a warning. Note that copying is an _asynchronous_ operation, meaning the method returns before the copy is complete. +#' +#' For copying and moving, the destination folder must exist beforehand. When copying/moving a large number of files, it's much more efficient to supply the destination folder in the `dest_folder_item` argument rather than as a path. +#' #' `list_items(path, info, full_names, pagesize)` lists the items under the specified path. #' #' `list_files` is a synonym for `list_items`. @@ -236,6 +242,16 @@ public=list( self$get_item(path, itemid)$update(...) }, + copy_item=function(path=NULL, itemid=NULL, dest, dest_folder_item=NULL) + { + self$get_item(path, itemid)$copy(dest, dest_folder_item) + }, + + move_item=function(path=NULL, itemid=NULL, dest, dest_folder_item=NULL) + { + self$get_item(path, itemid)$move(dest, dest_folder_item) + }, + list_shared_items=function(allow_external=TRUE, filter=NULL, n=Inf, pagesize=1000, info=NULL) { if(!is.null(info) && info != "items") diff --git a/R/ms_drive_item.R b/R/ms_drive_item.R index bfaee75..7176266 100644 --- a/R/ms_drive_item.R +++ b/R/ms_drive_item.R @@ -15,6 +15,8 @@ #' - `do_operation(...)`: Carry out an arbitrary operation on the item. #' - `sync_fields()`: Synchronise the R object with the item metadata in Microsoft Graph. #' - `open()`: Open the item in your browser. +#' - `copy(dest, dest_folder_item=NULL)`: Copy the item to the given location. +#' - `move(dest, dest_folder_item=NULL)`: Move the item to the given location. #' - `list_items(...), list_files(...)`: List the files and folders under the specified path. #' - `download(dest, overwrite, recursive, parallel)`: Download the file or folder. See below. #' - `create_share_link(type, expiry, password, scope)`: Create a shareable link to the file or folder. @@ -62,6 +64,10 @@ #' #' `get_item` retrieves the file or folder with the given path, as another object of class `ms_drive_item`. #' +#' - `copy` and `move` can take the destination location as either a full pathname (in the `dest` argument), or a name plus a drive item object (in the `dest_folder_item` argument). If the latter is supplied, any path in `dest` is ignored with a warning. Note that copying is an _asynchronous_ operation, meaning the method returns before the copy is complete. +#' +#' For copying and moving, the destination folder must exist beforehand. When copying/moving a large number of files, it's much more efficient to supply the destination folder in the `dest_folder_item` argument rather than as a path. +#' #' `create_folder` creates a folder with the specified path. Trying to create an already existing folder is an error. This returns an `ms_drive_item` object, invisibly. #' #' `create_share_link(path, type, expiry, password, scope)` returns a shareable link to the item. Its arguments are @@ -109,6 +115,16 @@ #' # rename a file #' myfile$update(name="newname.docx") #' +#' # copy a file (destination folder must exist) +#' myfile$copy("/Documents/folder2/myfile_copied.docx") +#' +#' # alternate way of copying: supply the destination folder +#' destfolder <- docs$get_item("folder2") +#' myfile$copy("myfile_copied.docx", dest_folder_item=destfolder) +#' +#' # move a file (destination folder must exist) +#' myfile$move("Documents/folder2/myfile_moved.docx") +#' #' # open the file in the browser #' myfile$open() #' @@ -466,6 +482,58 @@ public=list( self$upload(tmpsave, file) }, + copy=function(dest, dest_folder_item=NULL) + { + path <- dirname(dest) + body <- list(name=basename(dest)) + + if(!is.null(dest_folder_item)) + { + if(path != ".") + warning("Destination folder object supplied; path will be ignored") + body$parentReference <- list( + driveId=dest_folder_item$properties$parentReference$driveId, + id=dest_folder_item$properties$id + ) + } + else if(path != ".") + { + dest_folder_item <- private$get_drive()$get_item(path) + body$parentReference <- list( + driveId=dest_folder_item$properties$parentReference$driveId, + id=dest_folder_item$properties$id + ) + } + + self$do_operation("copy", body=body, http_verb="POST") + invisible(NULL) + }, + + move=function(dest, dest_folder_item=NULL) + { + path <- dirname(dest) + body <- list(name=basename(dest)) + + if(!is.null(dest_folder_item)) + { + if(path != ".") + warning("Destination folder object supplied; path will be ignored") + body$parentReference <- list( + id=dest_folder_item$properties$id + ) + } + else if(path != ".") + { + dest_folder_item <- private$get_drive()$get_item(path) + body$parentReference <- list( + id=dest_folder_item$properties$id + ) + } + + self$properties <- self$do_operation(body=body, encode="json", http_verb="PATCH") + invisible(self) + }, + get_path=function() { private$assert_is_not_remote() @@ -618,6 +686,12 @@ private=list( utils::URLencode(enc2utf8(op)) }, + get_drive=function() + { + dummy_props <- list(id=self$properties$parentReference$driveId) + ms_drive$new(self$token, self$tenant, dummy_props) + }, + assert_is_folder=function() { if(!self$is_folder()) diff --git a/man/ms_drive.Rd b/man/ms_drive.Rd index eba1211..fdcac0f 100644 --- a/man/ms_drive.Rd +++ b/man/ms_drive.Rd @@ -40,6 +40,8 @@ Class representing a personal OneDrive or SharePoint document library. \item \code{get_item(path, itemid)}: Get an item representing a file or folder. \item \code{get_item_properties(path, itemid)}: Get the properties (metadata) for a file or folder. \item \code{set_item_properties(path, itemid, ...)}: Set the properties for a file or folder. +\item \code{copy_item(path, itemid, dest, dest_item_id)}: Copy a file or folder. +\item \code{move_item(path, itemid, dest, dest_item_id)}: Move a file or folder. \item \verb{list_shared_items(...), list_shared_files(...)}: List the drive items shared with you. See 'Shared items' below. \item \code{load_dataframe(path, itemid, ...)}: Download a delimited file and return its contents as a data frame. See 'Saving and loading data' below. \item \code{load_rds(path, itemid)}: Download a .rds file and return the saved object. @@ -70,6 +72,11 @@ This class exposes methods for carrying out common operations on files and folde \code{get_item_properties} is a convenience function that returns the properties of a file or folder as a list. \code{set_item_properties} sets the properties of a file or folder. The new properties should be specified as individual named arguments to the method. Any existing properties that aren't listed as arguments will retain their previous values or be recalculated based on changes to other properties, as appropriate. You can also call the \code{update} method on the corresponding \code{ms_drive_item} object. +\itemize{ +\item \code{copy_item} and \code{move_item} can take the destination location as either a full pathname (in the \code{dest} argument), or a name plus a drive item object (in the \code{dest_folder_item} argument). If the latter is supplied, any path in \code{dest} is ignored with a warning. Note that copying is an \emph{asynchronous} operation, meaning the method returns before the copy is complete. +} + +For copying and moving, the destination folder must exist beforehand. When copying/moving a large number of files, it's much more efficient to supply the destination folder in the \code{dest_folder_item} argument rather than as a path. \code{list_items(path, info, full_names, pagesize)} lists the items under the specified path. diff --git a/man/ms_drive_item.Rd b/man/ms_drive_item.Rd index fa706e7..294fdb2 100644 --- a/man/ms_drive_item.Rd +++ b/man/ms_drive_item.Rd @@ -29,6 +29,8 @@ Class representing an item (file or folder) in a OneDrive or SharePoint document \item \code{do_operation(...)}: Carry out an arbitrary operation on the item. \item \code{sync_fields()}: Synchronise the R object with the item metadata in Microsoft Graph. \item \code{open()}: Open the item in your browser. +\item \code{copy(dest, dest_folder_item=NULL)}: Copy the item to the given location. +\item \code{move(dest, dest_folder_item=NULL)}: Move the item to the given location. \item \verb{list_items(...), list_files(...)}: List the files and folders under the specified path. \item \code{download(dest, overwrite, recursive, parallel)}: Download the file or folder. See below. \item \code{create_share_link(type, expiry, password, scope)}: Create a shareable link to the file or folder. @@ -84,6 +86,11 @@ Uploading and downloading folders can be done in parallel, which can result in s } \code{get_item} retrieves the file or folder with the given path, as another object of class \code{ms_drive_item}. +\itemize{ +\item \code{copy} and \code{move} can take the destination location as either a full pathname (in the \code{dest} argument), or a name plus a drive item object (in the \code{dest_folder_item} argument). If the latter is supplied, any path in \code{dest} is ignored with a warning. Note that copying is an \emph{asynchronous} operation, meaning the method returns before the copy is complete. +} + +For copying and moving, the destination folder must exist beforehand. When copying/moving a large number of files, it's much more efficient to supply the destination folder in the \code{dest_folder_item} argument rather than as a path. \code{create_folder} creates a folder with the specified path. Trying to create an already existing folder is an error. This returns an \code{ms_drive_item} object, invisibly. @@ -136,6 +143,16 @@ myfile$properties # rename a file myfile$update(name="newname.docx") +# copy a file (destination folder must exist) +myfile$copy("/Documents/folder2/myfile_copied.docx") + +# alternate way of copying: supply the destination folder +destfolder <- docs$get_item("folder2") +myfile$copy("myfile_copied.docx", dest_folder_item=destfolder) + +# move a file (destination folder must exist) +myfile$move("Documents/folder2/myfile_moved.docx") + # open the file in the browser myfile$open()