Skip to content

Commit e2b8bcc

Browse files
authored
Merge pull request #26 from nationalparkservice/dev
Dev
2 parents 94b25e1 + 67ec4e4 commit e2b8bcc

74 files changed

Lines changed: 3663 additions & 2201 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
.quarto
77
inst/doc
88
scratchpad
9+
docs

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Description: Interact with the National Park Service (NPS) DataStore in R. NPS D
77
License: MIT + file LICENSE
88
Encoding: UTF-8
99
Roxygen: list(markdown = TRUE)
10-
RoxygenNote: 7.3.2
10+
RoxygenNote: 7.3.3
1111
Suggests:
1212
httptest2,
1313
knitr,

NAMESPACE

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
export("%>%")
44
export(active_directory_lookup)
5-
export(add_bibliography)
65
export(add_external_link)
76
export(add_keywords)
87
export(add_reference_owners)
@@ -12,15 +11,20 @@ export(delete_all_keywords)
1211
export(delete_reference_owner)
1312
export(example_ref_ids)
1413
export(get_bibliography)
14+
export(get_by_for_nps)
1515
export(get_date_precision)
1616
export(get_external_links)
1717
export(get_file_info)
1818
export(get_keywords)
19+
export(get_lifecycle_info)
1920
export(get_reference_owners)
2021
export(get_reference_types)
2122
export(search_references_by_id)
2223
export(search_references_by_id_basic)
24+
export(set_bibliography)
25+
export(set_by_for_nps)
2326
export(set_file_info)
2427
export(set_license)
28+
export(set_lifecycle_active)
2529
export(upload_file_to_reference)
2630
importFrom(magrittr,"%>%")

NEWS.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# NPSdatastore (development version 2026-01-28)
2+
3+
## New features
4+
* added `set_by_for_nps()` which designates a reference as created by or for the NPS (or not)
5+
* added `get_lifecycle_info()` which retrieves a reference's current lifecycle and indicates whether it can be altered
6+
* added `set_lifecycle_active()` and `set_lifecycle_draft()`, allowing reference lifecycle to be changed
7+
8+
## Enhancements
9+
* updated pkgdown site with better organized function reference

R/get.R

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,53 @@ get_bibliography <- function(reference_id, nps_internal = FALSE, dev = FALSE) {
355355

356356
return(bib)
357357
}
358+
359+
#' Determine if a reference was created by/for the NPS
360+
#'
361+
#' @inheritParams get_bibliography
362+
#'
363+
#' @returns TRUE if the reference was created by or for the NPS, FALSE if not.
364+
#' @export
365+
#'
366+
#' @examples
367+
#' \dontrun{
368+
#' by_for_nps <- get_by_for_nps(reference_id = 652358)
369+
#' }
370+
#'
371+
get_by_for_nps <- function(reference_id, nps_internal = FALSE, dev = FALSE) {
372+
bib <- get_bibliography(reference_id, nps_internal, dev)
373+
by_for_nps <- bib$isAgencyOriginated
374+
375+
return(by_for_nps)
376+
}
377+
378+
#' Retrieve the current lifecycle status of a reference.
379+
#' Only works for internal NPS users.
380+
#'
381+
#' @inheritParams get_bibliography
382+
#'
383+
#' @returns A list of lifecycle information for the reference
384+
#' @export
385+
#'
386+
#' @examples
387+
#' \dontrun{
388+
#' lifecycle_info <- get_lifecycle_info(reference_id = 652358)
389+
#' lifecycle = lifecycle_info$lifecycle
390+
#' }
391+
#'
392+
get_lifecycle_info <- function(reference_id, dev = FALSE) {
393+
.validate_ref_id(reference_id)
394+
395+
nps_internal <- TRUE
396+
397+
lifecycle_info <- .datastore_request(is_secure = nps_internal, is_dev = dev) |>
398+
httr2::req_url_path_append("Reference", reference_id, "LifecycleConstraints") |>
399+
httr2::req_method("GET") |>
400+
httr2::req_perform()
401+
402+
.validate_resp(lifecycle_info)
403+
404+
lifecycle_info <- httr2::resp_body_json(lifecycle_info)
405+
406+
return(lifecycle_info)
407+
}

R/helpers.R

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,25 @@
55

66
# datastore API base URL:
77
assign("ds_public_api",
8-
"https://irmaservices.nps.gov/datastore/v7/rest",
8+
"https://irmaservices.nps.gov/datastore/v8/rest",
99
envir = .pkgglobalenv
1010
)
1111

1212
# datastore secure API base URL:
1313
assign("ds_secure_api",
14-
"https://irmaservices.nps.gov/datastore-secure/v7/rest",
14+
"https://irmaservices.nps.gov/datastore-secure/v8/rest",
1515
envir = .pkgglobalenv
1616
)
1717

1818
# datastore secure dev api
1919
assign("ds_dev_secure_api",
20-
"https://irmadevservices.nps.gov/datastore-secure/v7/rest",
20+
"https://irmadevservices.nps.gov/datastore-secure/v8/rest",
2121
envir = .pkgglobalenv
2222
)
2323

2424
# datastore dev API
2525
assign("ds_dev_public_api",
26-
"https://irmadevservices.nps.gov/datastore/v7/rest",
26+
"https://irmadevservices.nps.gov/datastore/v8/rest",
2727
envir = .pkgglobalenv
2828
)
2929

@@ -62,7 +62,9 @@ globalVariables(c("public_refs",
6262
"mimeType",
6363
"downloadLink",
6464
"is508Compliant",
65-
"fileSize_kb"))
65+
"fileSize_kb",
66+
"extensionAttribute2",
67+
"orcid"))
6668

6769

6870
#' Get the right base URL for the DataStore API
@@ -71,6 +73,7 @@ globalVariables(c("public_refs",
7173
#' @param is_dev Retrieve the dev version of the API base URL?
7274
#'
7375
#' @returns One of four base URLs for the DataStore API (public, secure, public+dev, secure+dev)
76+
#' @keywords internal
7477
#'
7578
.get_base_url <- function(is_secure, is_dev) {
7679
datastore_url <- dplyr::case_when(
@@ -89,6 +92,7 @@ globalVariables(c("public_refs",
8992
#' @inheritParams .get_base_url
9093
#'
9194
#' @returns The url to the reference profile page
95+
#' @keywords internal
9296
#'
9397
.get_ref_profile_url <- function(ref_id, is_dev) {
9498
ref_profile_url <- dplyr::case_when(
@@ -106,6 +110,7 @@ globalVariables(c("public_refs",
106110
#' @param suppress_errors Suppress HTTP errors? Set to TRUE if using `.validate_resp()`
107111
#'
108112
#' @returns A httr2 request object with curl options set to allow authentication for NPS users (if using secure API)
113+
#' @keywords internal
109114
#'
110115
.datastore_request <- function(is_secure, is_dev, suppress_errors = TRUE) {
111116
base_url <- .get_base_url(is_secure = is_secure, is_dev = is_dev)
@@ -132,6 +137,7 @@ globalVariables(c("public_refs",
132137
#' @inheritParams .get_base_url
133138
#'
134139
#' @returns List of reference profiles
140+
#' @keywords internal
135141
#'
136142
.get_reference_profiles <- function(reference_ids, is_secure, is_dev) {
137143
request <- .datastore_request(is_secure = is_secure, is_dev = is_dev) |>
@@ -169,6 +175,7 @@ globalVariables(c("public_refs",
169175
#' @param child_list_names The elements of the reference profile that should be converted to vectors
170176
#'
171177
#' @returns The tidied reference profile
178+
#' @keywords internal
172179
#'
173180
.lists2vectors <- function(parent_list, child_list_names) {
174181
for (child_list in child_list_names) {
@@ -188,6 +195,7 @@ globalVariables(c("public_refs",
188195
#' @param child_list_names The elements of the reference profile that should be converted to tibbles
189196
#'
190197
#' @returns The tidied reference profile
198+
#' @keywords internal
191199
#'
192200
.lists2tibbles <- function(parent_list, child_list_names) {
193201
for (child_list in child_list_names) {
@@ -245,6 +253,7 @@ example_ref_ids <- function(visibility = c("public", "internal", "both"), n, see
245253
#' @param multiple_ok Can ref_id be a vector of multiple IDs?
246254
#' @param arg Used to get the actual name of the argument in the calling function. See `?rlang::`topic-error-call``
247255
#' @param call The caller environment, for more helpful error messages. See `?rlang::`topic-error-call``
256+
#' @keywords internal
248257
#'
249258
.validate_ref_id <- function(ref_id, multiple_ok = FALSE,
250259
arg = rlang::caller_arg(ref_id),
@@ -271,6 +280,22 @@ example_ref_ids <- function(visibility = c("public", "internal", "both"), n, see
271280

272281
}
273282

283+
.validate_lifecycle <- function(ref_id, expected_lifecycle = c("Draft", "Active"), is_dev,
284+
call = rlang::caller_env()) {
285+
286+
expected_lifecycle <- match.arg(expected_lifecycle, several.ok = FALSE)
287+
288+
# Get actual lifecycle
289+
actual_lifecycle <- get_lifecycle_info(reference_id = ref_id, dev = is_dev)
290+
actual_lifecycle <- actual_lifecycle$lifecycle
291+
292+
# Enforce is file, not folder
293+
if (actual_lifecycle != expected_lifecycle) {
294+
cli::cli_abort("Lifecycle for reference {ref_id} must be set to {expected_lifecycle}. It is currently set to {actual_lifecycle}.",
295+
call = call)
296+
}
297+
}
298+
274299
.validate_file_path <- function(file_path,
275300
arg = rlang::caller_arg(file_path),
276301
call = rlang::caller_env()) {
@@ -286,6 +311,25 @@ example_ref_ids <- function(visibility = c("public", "internal", "both"), n, see
286311
}
287312
}
288313

314+
#' Validate TRUE/FALSE arguments
315+
#'
316+
#' @param bool Value to check
317+
#' @param arg Used to get the actual name of the argument in the calling function. See `?rlang::`topic-error-call``
318+
#' @param call The caller environment, for more helpful error messages. See `?rlang::`topic-error-call``
319+
#' @keywords internal
320+
#'
321+
.validate_truefalse <- function(bool,
322+
arg = rlang::caller_arg(bool),
323+
call = rlang::caller_env()) {
324+
325+
# Enforce a TRUE/FALSE value
326+
if (!is.logical(bool) || is.na(bool)) {
327+
cli::cli_abort("{.arg {arg}} is invalid. Must be logical (`TRUE` or `FALSE`).",
328+
call = call)
329+
}
330+
331+
}
332+
289333
.validate_retry <- function(retry,
290334
arg = rlang::caller_arg(retry),
291335
call = rlang::caller_env()) {

R/set.R

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,8 @@ add_external_link <- function(reference_id, url, description, last_verified = fo
471471

472472
#' Replace the bibliography in a DataStore reference
473473
#'
474+
#' To update specific elements of the bibliography, use the "set_" functions for those elements instead.
475+
#'
474476
#' @param bibliography A list representing a DataStore bibliography. It is recommended that you retrieve the current bibliography using `get_bibliography()` and then modify it as needed.
475477
#' @inheritParams upload_file_to_reference
476478
#'
@@ -482,10 +484,10 @@ add_external_link <- function(reference_id, url, description, last_verified = fo
482484
#' bib <- get_bibliography(reference_id = 00000)
483485
#' bib$description <- "This is a new description for this reference"
484486
#' bib$notes <- "This reference is for testing purposes only"
485-
#' new_bib <- add_bibliography(reference_id = 00000, bibliography = bib, dev = TRUE)
487+
#' new_bib <- set_bibliography(reference_id = 00000, bibliography = bib, dev = TRUE)
486488
#' }
487489
#'
488-
add_bibliography <- function(reference_id, bibliography, dev = TRUE, interactive = TRUE) {
490+
set_bibliography <- function(reference_id, bibliography, dev = TRUE, interactive = TRUE) {
489491

490492
.validate_ref_id(reference_id)
491493

@@ -512,6 +514,56 @@ add_bibliography <- function(reference_id, bibliography, dev = TRUE, interactive
512514
return(bib)
513515
}
514516

517+
#' Set the flag that indicates whether a reference was created by or for NPS
518+
#'
519+
#' @param by_for_nps TRUE or FALSE: was this reference created by or for NPS?
520+
#' @inheritParams upload_file_to_reference
521+
#'
522+
#' @returns A list representing the full updated bibliography.
523+
#' @export
524+
#'
525+
#' @examples
526+
#' \dontrun{
527+
#' new_bib <- set_by_for_nps(reference_id = 000000, by_for_nps = TRUE)
528+
#' new_bib <- set_by_for_nps(reference_id = 000000, by_for_nps = TRUE, dev = FALSE)
529+
#' }
530+
set_by_for_nps <- function(reference_id, by_for_nps, dev = TRUE, interactive = TRUE) {
531+
532+
# Validate arguments
533+
.validate_truefalse(by_for_nps)
534+
.validate_ref_id(reference_id)
535+
536+
# Validate that reference is in draft mode, otherwise can't alter bibliography
537+
.validate_lifecycle(ref_id = reference_id, expected_lifecycle = "Draft", is_dev = dev)
538+
539+
# Set values
540+
nps_internal <- TRUE
541+
by_for_nps <- dplyr::case_when(by_for_nps ~ 'true',
542+
!by_for_nps ~ 'false',
543+
.default = NA_character_) # convert by_for_nps to a string for the API
544+
545+
# Verify that we're modifying the right reference
546+
if (interactive) {
547+
.user_validate_ref_title(ref_id = reference_id,
548+
is_secure = TRUE,
549+
is_dev = dev)
550+
}
551+
552+
body <- list(isAgencyOriginated = by_for_nps)
553+
554+
bib <- .datastore_request(is_secure = TRUE, is_dev = dev) |>
555+
httr2::req_url_path_append("Reference", reference_id, "Bibliography") |>
556+
httr2::req_body_json(body) |>
557+
httr2::req_method("PATCH") |> # PATCH ensures that only the specified field (isAgencyOriginated) gets modified, not the whole bibliography
558+
httr2::req_perform()
559+
560+
.validate_resp(bib)
561+
562+
bib <- httr2::resp_body_json(bib)
563+
564+
invisible(bib)
565+
}
566+
515567
#' Add DataStore reference(s) to a Project reference
516568
#'
517569
#' @param project_id The reference ID of the Project
@@ -594,3 +646,64 @@ set_license <- function(reference_id, license_type_id, dev = TRUE, interactive =
594646

595647
return(license_info)
596648
}
649+
650+
651+
#' Activate a reference
652+
#'
653+
#' Use with caution! It's usually a better idea to review the reference on the DataStore website and manually activate it.
654+
#'
655+
#' @inheritParams upload_file_to_reference
656+
#'
657+
#' @returns Invisibly returns the current lifecycle information for the reference
658+
#'
659+
#' @export
660+
#'
661+
#' @examples
662+
#' \dontrun{
663+
#' lifecycle_info <- set_lifecycle_active(reference_id = 652358)
664+
#' }
665+
#'
666+
set_lifecycle_active <- function(reference_id, dev = TRUE, interactive = TRUE) {
667+
.validate_ref_id(reference_id)
668+
669+
lifecycle_info <- .datastore_request(is_secure = TRUE, is_dev = dev) |>
670+
httr2::req_url_path_append("Reference", reference_id, "Lifecycle", "Active") |>
671+
httr2::req_body_json(list()) |>
672+
httr2::req_method("PUT") |>
673+
httr2::req_perform()
674+
675+
.validate_resp(lifecycle_info)
676+
677+
lifecycle_info <- get_lifecycle_info(reference_id = reference_id, dev = dev)
678+
679+
invisible(lifecycle_info)
680+
}
681+
682+
#' Set a reference to draft mode
683+
#'
684+
#' Use with extreme caution! You may not be able to reactivate via the API if you are working with an older reference that is missing multiple required fields.
685+
#'
686+
#' @inheritParams upload_file_to_reference
687+
#'
688+
#' @returns Invisibly returns the current lifecycle information for the reference
689+
#'
690+
#' @examples
691+
#' \dontrun{
692+
#' lifecycle_info <- set_lifecycle_draft(reference_id = 652358)
693+
#' }
694+
#'
695+
set_lifecycle_draft <- function(reference_id, dev = TRUE, interactive = TRUE) {
696+
.validate_ref_id(reference_id)
697+
698+
lifecycle_info <- .datastore_request(is_secure = TRUE, is_dev = dev) |>
699+
httr2::req_url_path_append("Reference", reference_id, "Lifecycle", "Draft") |>
700+
httr2::req_body_json(list()) |>
701+
httr2::req_method("PUT") |>
702+
httr2::req_perform()
703+
704+
.validate_resp(lifecycle_info)
705+
706+
lifecycle_info <- get_lifecycle_info(reference_id = reference_id, dev = dev)
707+
708+
invisible(lifecycle_info)
709+
}

0 commit comments

Comments
 (0)