Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export(fp_extract_doi)
export(fp_get_article_fairness)
export(fp_get_journal_fairness)
export(fp_list_dafnee_journals)
export(fp_retrieve_article_doi)
45 changes: 45 additions & 0 deletions R/checks.R
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,48 @@ check_arg_string <- function(x) {

invisible(NULL)
}


#' @noRd
check_arg_n <- function(n) {
if (is.null(n)) {
stop("Argument 'n' is required", call. = FALSE)
}

if (!is.numeric(n)) {
stop(
"Argument 'n' must be an integer",
call. = FALSE
)
}

if (length(n) != 1) {
stop(
"Argument 'n' must be of length 1",
call. = FALSE
)
}

if (!is.finite(n)) {
stop(
"Argument 'n' must be finite",
call. = FALSE
)
}

if (n %% 1 != 0) {
stop(
"Argument 'n' must be an integer",
call. = FALSE
)
}

if (n < 1 || n > 200) {
stop(
"Argument 'n' must be a positive integer between 1 and 200",
call. = FALSE
)
}

invisible(NULL)
}
102 changes: 102 additions & 0 deletions R/fp_retrieve_article_doi.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#' Retrieve the DOI of an article from OpenAlex
#'
#' @description
#' This function queries the OpenAlex bibliographic database
#' (<https://openalex.org>) to retrieve the DOI of an article based on its
#' title.
#'
#' @param title a `character` of length 1. The title of the article.
#'
#' @param n an `integer` of length 1. The number of results to return (between
#' 1 and 200). Default is `5`.
#'
#' @return A `data.frame` with the following columns:
#' - `display_name`, the publication titles matching the query
#' - `publication_year`, the year of publication
#' - `source_display_name`, the name of the journal
#' - `doi`, the DOI of the publications
#'
#' @export
#'
#' @examples
#' \dontrun{
#' # Be polite and send your email to OpenAlex API ----
#' options(openalexR.mailto = 'anonymous@mail.com')
#'
#' # Search for an full title ----
#' fp_retrieve_article_doi(
#' "Citation self-awareness for a fairer academic publishing landscape"
#' )
#' #> display_name publication_year
#' #> 1 Citation self-awareness for a fairer academic... 2026
#' #> source_display_name doi
#' #> 1 BioScience 10.1093/biosci/biag028
#'
#' # Search for a partial title ----
#' fp_retrieve_article_doi(
#' "Citation fairer academic landscape"
#' )
#' #> display_name publication_year
#' #> 1 Strategic citations for a fairer academic... 2025
#' #> 2 Citation self-awareness for a fairer academic... 2026
#' #> source_display_name doi
#' #> 1 bioRxiv (Cold Spring Harbor Laboratory) 10.1101/2025.08.06.668908
#' #> 2 BioScience 10.1093/biosci/biag028
#' }

fp_retrieve_article_doi <- function(title, n = 5) {
fp_check_mailto()

check_arg_string(title)
check_arg_n(n)

meta <- tryCatch(
suppressMessages(
openalexR::oa_fetch(
entity = "works",
title.search = title,
per_page = n,
paging = "page",
pages = 1,
options = list(
sort = "relevance_score:desc",
select = c(
"doi",
"display_name",
"publication_year",
"primary_location"
)
)
)
),
error = function(e) {
stop(
"Failed to retrieve data from OpenAlex",
call. = FALSE
)
}
)

meta <- as.data.frame(meta)

if (nrow(meta) > 0) {
meta <- meta[, c(
"display_name",
"publication_year",
"source_display_name",
"doi"
)]

meta$doi <- fp_clean_doi(meta$doi)
meta$display_name <- fp_shorten_string(meta$display_name)
} else {
meta <- data.frame(
display_name = character(),
publication_year = integer(),
source_display_name = character(),
doi = character()
)
}

meta
}
12 changes: 12 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,15 @@ fp_extract_doi_from_string <- function(x) {

unlist(matches, use.names = FALSE)
}


#' @noRd
fp_shorten_string <- function(x, width = 50) {
is_short <- nchar(x) <= width

shortened <- substr(x, 1, width - 3)
shortened <- sub("\\s+\\S*$", "", shortened)
shortened <- paste0(shortened, "...")

ifelse(is_short, x, shortened)
}
1 change: 1 addition & 0 deletions _pkgdown.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ reference:
desc: |
Functions to retrieve, extract and clean DOI.
contents:
- fp_retrieve_article_doi
- fp_extract_doi
- fp_clean_doi

Expand Down
54 changes: 54 additions & 0 deletions man/fp_retrieve_article_doi.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 18 additions & 18 deletions tests/testthat/_vcr/fp_compute_citation_ratio_not_in_dafnee.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions tests/testthat/_vcr/fp_compute_citation_ratio_not_in_oa.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading