#' Add a new column of Drive file information
#'
#' @description
#' `drive_reveal()` adds extra information about your Drive files that is not
#' readily available in the default [`dribble`] produced by googledrive. Why is
#' this info not always included in the default `dribble`?
#' * You don't always care about it. There is a lot of esoteric information in
#' the `drive_resource` that has little value for most users.
#' * It might be "expensive" to get this information and put it into a usable
#' form. For example, revealing a file's `"path"`, `"permissions"`, or
#' `"published"` status all require additional API calls.
#'
#' `drive_reveal()` can also **hoist** any property out of the `drive_resource`
#' list-column, when the property's name is passed as the `what` argument. The
#' resulting new column is simplified if it is easy to do so, e.g., if the
#' individual elements are all string or logical. If `what` extracts a
#' date-time, we return [`POSIXct`][DateTimeClasses]. Otherwise, you'll get a
#' list-column. If this makes you sad, consider using `tidyr::hoist()` instead.
#' It is more powerful due to a richer "plucking specification" and its `ptype`
#' and `transform` arguments. Another useful function is
#' `tidyr::unnest_wider()`.
#'
#'
#' @section File path:
#' When `what = "path"` the [`dribble`] gains a character column holding each
#' file's path. This can be *very slow*, so use with caution.
#'
#' The example path `~/a/b/` illustrates two conventions used in googledrive:
#' * The leading `~/` means that the folder `a` is located in the current
#' user's "My Drive" root folder.
#' * The trailing `/` means that `b`, located in `a`, is *a folder or a folder
#' shortcut*.
#' @section Permissions:
#' When `what = "permissions"` the [`dribble`] gains a logical column `shared`
#' that indicates whether a file is shared and a new list-column
#' `permissions_resource` containing lists of
#' [Permissions resources](https://developers.google.com/drive/api/v3/reference/permissions).
#'
#' @section Publishing:
#' When `what = "published"` the [`dribble`] gains a logical column
#' `published` that indicates whether a file is published and a new list-column
#' `revision_resource` containing lists of
#' [Revisions resources](https://developers.google.com/drive/api/v3/reference/revisions).
#'
#' @section Parent:
#' When `what = "parent"` the [`dribble`] gains a character column `id_parent`
#' that is the file id of this item's parent folder. This information is
#' available in the `drive_resource`, but can't just be hoisted out:
#' * Google Drive used to allow files to have multiple parents, but this is no
#' longer supported and googledrive now assumes this is impossible. However,
#' we have seen (very old) files that still have >1 parent folder. If we see
#' this we message about it and drop all but the first parent.
#' * The `parents` property in `drive_resource` has an "extra" layer of nesting
#' and needs to be flattened.
#'
#' If you really want the raw `parents` property, call `drive_reveal(what =
#' "parents")`.
#' @template file-plural
#' @param what Character, describing the type of info you want to add. These
#' values get special handling (more details below):
#' * `path`
#' * `permissions`
#' * `published`
#' * `parent`
#'
#' You can also request any property in the `drive_resource` column by name.
#' The request can be in `camelCase` or `snake_case`, but the new column name
#' will always be `snake_case`. Some examples of `what`:
#' * `mime_type` (or `mimeType`)
#' * `trashed`
#' * `starred`
#' * `description`
#' * `version`
#' * `web_view_link` (or `webViewLink`)
#' * `modified_time` (or `modifiedTime`)
#' * `created_time` (or `createdTime`)
#' * `owned_by_me` (or `ownedByMe`)
#' * `size`
#' * `quota_bytes_used` (or `quotaBytesUsed`)
#'
#' @eval return_dribble(extras = "The additional info requested via `what`
#' appears in one (or more) extra columns.")
#'
#' @seealso To learn more about the properties present in the metadata of a
#' Drive file (which is what's in the `drive_resource` list-column of a
#' [`dribble`]), see the API docs:
#' * <https://developers.google.com/drive/api/v3/reference/files#resource-representations>
#'
#' @export
#' @examplesIf drive_has_token()
#' # Get a few of your files
#' files <- drive_find(n_max = 10, trashed = NA)
#'
#' # the "special" cases that require additional API calls and can be slow
#' drive_reveal(files, "path")
#' drive_reveal(files, "permissions")
#' drive_reveal(files, "published")
#'
#' # a "special" case of digging info out of `drive_resource`, then processing
#' # a bit
#' drive_reveal(files, "parent")
#'
#' # the "simple" cases of digging info out of `drive_resource`
#' drive_reveal(files, "trashed")
#' drive_reveal(files, "mime_type")
#' drive_reveal(files, "starred")
#' drive_reveal(files, "description")
#' drive_reveal(files, "version")
#' drive_reveal(files, "web_view_link")
#' drive_reveal(files, "modified_time")
#' drive_reveal(files, "created_time")
#' drive_reveal(files, "owned_by_me")
#' drive_reveal(files, "size")
#' drive_reveal(files, "quota_bytes_used")
#'
#' # 'root' is a special file id that represents your My Drive root folder
#' drive_get(id = "root") %>%
#' drive_reveal("path")
drive_reveal <- function(file,
what = c("path", "permissions", "published", "parent")) {
stopifnot(is_string(what))
file <- as_dribble(file)
if (what %in% c("path", "permissions", "published", "parent")) {
reveal <- switch(
what,
"path" = drive_reveal_canonical_path,
"permissions" = drive_reveal_permissions,
"published" = drive_reveal_published,
"parent" = drive_reveal_parent
)
return(reveal(file))
}
drive_reveal_this(file, what)
}
drive_reveal_this <- function(file, this) {
elem_snake_case <- snake_case(this)
is_dttm <- grepl("_time$", elem_snake_case)
if (no_file(file)) {
return(
put_column(
file,
nm = elem_snake_case,
val = list(),
.after = "name"
)
)
}
out <- promote(file, elem_snake_case)
if (is_dttm && is.character(out[[elem_snake_case]])) {
out[[elem_snake_case]] <- as.POSIXct(
out[[elem_snake_case]],
format = "%Y-%m-%dT%H:%M:%OSZ",
tz = "UTC"
)
}
out
}
drive_reveal_parent <- function(file) {
confirm_dribble(file)
file <- drive_reveal(file, "parents")
# due to the historical use of multiple parents, there is a gratuitous level
# of nesting here
file$parents <- map(file$parents, 1)
n_parents <- lengths(file$parents)
has_multiple_parents <- n_parents > 1
if (any(has_multiple_parents)) {
drive_bullets(c(
"{sum(has_multiple_parents)} file{?s} {?has/have} >1 parent, which is a \\
remnant of legacy Drive behaviour:",
bulletize(gargle_map_cli(file[has_multiple_parents, ])),
"!" = "Only the first parent will be used"
))
}
file <- put_column(
file,
nm = "id_parent",
val = as_id(map_chr(file$parents, 1, .default = NA)),
.after = "name"
)
file$parents <- NULL
file
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.