|
9 | 9 | #' `r lifecycle::badge("experimental")`
|
10 | 10 | #'
|
11 | 11 | #' @param url The url of the remote resource. Must be of length one.
|
12 |
| -#' @param token your authorization token. |
| 12 | +#' @inheritParams arcgisutils::arc_item |
13 | 13 | #'
|
14 | 14 | #' @seealso arc_select arc_raster
|
15 | 15 | #' @export
|
16 | 16 | #' @returns
|
17 |
| -#' Depending on the provided URL returns a `FeatureLayer`, `Table`, `FeatureServer`, `ImageServer`, or `MapServer`. Each of these objects is a named list containing the properties of the service. |
| 17 | +#' Depending on item ID or URL returns a `PortalItem`, `FeatureLayer`, `Table`, `FeatureServer`, `ImageServer`, or `MapServer`, `GeocodeServer`, among other. Each of these objects is a named list containing the properties of the service. |
18 | 18 | #' @examples
|
19 | 19 | #' \dontrun{
|
| 20 | +#' |
| 21 | +#' # FeatureServer ID |
| 22 | +#' arc_open("3b7221d4e47740cab9235b839fa55cd7") |
| 23 | +#' |
20 | 24 | #' # FeatureLayer
|
21 | 25 | #' furl <- paste0(
|
22 | 26 | #' "https://services3.arcgis.com/ZvidGQkLaDJxRSJ2/arcgis/rest/services/",
|
|
54 | 58 | #'
|
55 | 59 | #' arc_open(map_url)
|
56 | 60 | #' }
|
57 |
| -arc_open <- function(url, token = arc_token()) { |
58 |
| - check_url(url) |
| 61 | +arc_open <- function(url, host = arc_host(), token = arc_token()) { |
| 62 | + check_string(url, allow_empty = FALSE) |
59 | 63 |
|
60 |
| - # parse url query and strip from url if query matches default |
61 |
| - query <- parse_url_query(url) %||% list() |
62 |
| - url <- clear_url_query(url) |
63 |
| - |
64 |
| - # extract layer metadata |
65 |
| - meta <- fetch_layer_metadata(url, token) |
| 64 | + if (!is_url(url)) { |
| 65 | + e_msg <- "Expected an item ID or url to a portal item." |
66 | 66 |
|
67 |
| - # set url for later use |
68 |
| - meta[["url"]] <- url |
| 67 | + item <- rlang::try_fetch( |
| 68 | + arc_item(url, host, token), |
| 69 | + error = function(cnd) cli::cli_abort(e_msg, call = rlang::caller_call(2)) |
| 70 | + ) |
69 | 71 |
|
70 |
| - # layer class |
71 |
| - layer_class <- gsub("\\s", "", meta[["type"]]) |
| 72 | + if (is.null(item$url)) { |
| 73 | + # return a portal item if the url is null |
| 74 | + return(item) |
| 75 | + } |
72 | 76 |
|
73 |
| - # if it's missing it means it's a server type. Need to deduce. |
74 |
| - if (length(layer_class) == 0) { |
75 |
| - if (any(grepl("pixel|band|raster", names(meta)))) { |
76 |
| - layer_class <- "ImageServer" |
77 |
| - } else if (grepl("MapServer", meta[["url"]])) { |
78 |
| - layer_class <- "MapServer" |
79 |
| - } else if ( |
80 |
| - "layers" %in% names(meta) || grepl("FeatureServer", meta[["url"]]) |
81 |
| - ) { |
82 |
| - layer_class <- "FeatureServer" |
83 |
| - } else { |
84 |
| - return(meta) |
| 77 | + # return the portal item if the url type is null |
| 78 | + if (is.null(arc_url_type(item$url))) { |
| 79 | + return(item) |
85 | 80 | }
|
| 81 | + |
| 82 | + # otherwise we fetch the url from the new item |
| 83 | + url <- item$url |
86 | 84 | }
|
87 | 85 |
|
88 |
| - # construct the appropriate class based on the resultant `layer_class` |
89 |
| - res <- switch( |
90 |
| - layer_class, |
91 |
| - "FeatureLayer" = structure( |
92 |
| - meta, |
93 |
| - class = layer_class, |
94 |
| - query = query |
95 |
| - ), |
96 |
| - "Table" = structure( |
97 |
| - meta, |
98 |
| - class = layer_class, |
99 |
| - query = query |
| 86 | + # parse the provided url |
| 87 | + info <- arc_url_parse(url) |
| 88 | + |
| 89 | + if (is.null(info$type)) { |
| 90 | + cli::cli_abort( |
| 91 | + c( |
| 92 | + "!" = "Unable to open the provided url or item ID.", |
| 93 | + "i" = "If you think this an error, please create an issue:", |
| 94 | + "{.url https://github.com/r-arcgis/arcgislayers/issues/new}" |
| 95 | + ) |
| 96 | + ) |
| 97 | + } |
| 98 | + |
| 99 | + switch( |
| 100 | + info$type, |
| 101 | + "FeatureServer" = { |
| 102 | + as_layer_class(clear_url_query(url), token, info$type) |
| 103 | + }, |
| 104 | + "MapServer" = as_layer_class( |
| 105 | + clear_url_query(url), |
| 106 | + token, |
| 107 | + info$type |
100 | 108 | ),
|
101 |
| - "FeatureServer" = structure( |
102 |
| - meta, |
103 |
| - class = layer_class |
| 109 | + "ImageServer" = as_layer_class( |
| 110 | + clear_url_query(url), |
| 111 | + token, |
| 112 | + info$type |
104 | 113 | ),
|
105 |
| - "ImageServer" = structure(meta, class = layer_class), |
106 |
| - "MapServer" = structure(meta, class = layer_class), |
107 |
| - "GroupLayer" = structure(meta, class = layer_class), |
| 114 | + "SceneServer" = as_layer_class(url, token, info$type), |
| 115 | + "GeocodeServer" = as_layer_class(url, token, info$type), |
| 116 | + # FIXME, unclear how to use this... |
| 117 | + "GeometryServer" = as_layer_class(url, token, info$type), |
| 118 | + # FIXME, unclear how to use this... |
| 119 | + "GPServer" = as_layer_class(url, token, info$type), |
| 120 | + "item" = { |
| 121 | + # if we have an item url, we fetch the item |
| 122 | + item <- arc_item(info$query$id, host = host, token = token) |
| 123 | + |
| 124 | + # if there is no associated url we return the item |
| 125 | + if (is.null(item[["url"]])) { |
| 126 | + return(item) |
| 127 | + } |
| 128 | + |
| 129 | + url_type <- arc_url_type(item[["url"]]) |
| 130 | + |
| 131 | + if (is.null(url_type)) { |
| 132 | + return(item) |
| 133 | + } |
| 134 | + |
| 135 | + # if there is a URL we're going to recurse |
| 136 | + arc_open(item[["url"]], host = host, token = token) |
| 137 | + }, |
| 138 | + "user" = arc_user(info$query$user, host = host, token = token), |
| 139 | + "group" = arc_group(info$query$id, host = host, token = token), |
| 140 | + "webscene" = arc_item(info$query$webscene, host = host, token = token), |
| 141 | + "app" = arc_item(info$query$appid, host = host, token = token), |
| 142 | + "notebook" = arc_item(info$query$id, host = host, token = token), |
| 143 | + "experience" = { |
| 144 | + path_components <- strsplit(info$path, "/")[[1]] |
| 145 | + exp_id <- path_components[which(path_components == "experience") + 1] |
| 146 | + arc_item(exp_id, host = host, token = token) |
| 147 | + }, |
| 148 | + "storymap" = { |
| 149 | + path_components <- strsplit(info$path, "/")[[1]] |
| 150 | + sm_id <- path_components[which(path_components == "stories") + 1] |
| 151 | + arc_item(sm_id, host = host, token = token) |
| 152 | + }, |
| 153 | + "dashboard" = { |
| 154 | + path_components <- strsplit(info$path, "/")[[1]] |
| 155 | + db_id <- path_components[which(path_components == "dashboards") + 1] |
| 156 | + arc_item(db_id, host = host, token = token) |
| 157 | + }, |
| 158 | + "datapipeline" = arc_item(info$query$item, host = host, token = token), |
| 159 | + "webapp" = arc_item(info$query$id, host = host, token = token), |
108 | 160 | cli::cli_abort(
|
109 | 161 | c(
|
110 |
| - "Service type {.val {layer_class}} is not supported.", |
| 162 | + "Service type {.val {info$type}} is not supported at this time.", |
111 | 163 | "i" = "Please report this at {.url https://github.com/R-ArcGIS/arcgislayers/issues}"
|
112 | 164 | )
|
113 | 165 | )
|
114 | 166 | )
|
| 167 | +} |
| 168 | + |
| 169 | +#' Fetch metadata and an appropriate class |
| 170 | +#' @noRd |
| 171 | +as_layer_class <- function(url, token, class = NULL) { |
| 172 | + meta <- fetch_layer_metadata(url, token) |
| 173 | + meta[["url"]] <- url |
| 174 | + cls <- if (is.null(meta[["type"]])) { |
| 175 | + NULL |
| 176 | + } else { |
| 177 | + gsub("\\s+", "", meta[["type"]]) |
| 178 | + } |
115 | 179 |
|
116 |
| - res |
| 180 | + structure(meta, class = c(cls %||% class, "list")) |
117 | 181 | }
|
0 commit comments