Skip to content

Commit

Permalink
Merge pull request #11 from OxfordIHTM/dev
Browse files Browse the repository at this point in the history
add all search query parameters to search function
  • Loading branch information
ernestguevarra authored Feb 11, 2024
2 parents d70c0d1 + b020da6 commit 1542472
Show file tree
Hide file tree
Showing 33 changed files with 107,935 additions and 240 deletions.
6 changes: 4 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ License: GPL (>= 3)
Depends:
R (>= 2.10)
Imports:
httr
httr,
httr2
Suggests:
covr,
httpuv,
spelling
spelling,
tibble
Encoding: UTF-8
LazyData: true
Language: en-GB
Expand Down
11 changes: 8 additions & 3 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Generated by roxygen2: do not edit by hand

export(icd_endpoint)
export(icd_oauth_app)
export(icd_token)
export(icd_oauth_client)
export(icd_search_foundation)
importFrom(httr,oauth2.0_token)
importFrom(httr,oauth_app)
importFrom(httr,oauth_endpoint)
importFrom(httr2,oauth_client)
importFrom(httr2,req_headers)
importFrom(httr2,req_oauth_client_credentials)
importFrom(httr2,req_perform)
importFrom(httr2,req_url_query)
importFrom(httr2,request)
2 changes: 2 additions & 0 deletions R/icd.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@
#' @keywords internal
#' @name icd
#' @importFrom httr oauth2.0_token oauth_app oauth_endpoint
#' @importFrom httr2 oauth_client request req_url_query req_headers
#' req_oauth_client_credentials req_perform
#'
"_PACKAGE"
76 changes: 18 additions & 58 deletions R/icd_authenticate.R
Original file line number Diff line number Diff line change
@@ -1,77 +1,37 @@
#'
#' OAuth2 authentication to ICD API
#'
#' @param authorize url to send client to for authorisation. Set to NULL if not
#' needed.
#' @param access url used to exchange unauthenticated for authenticated token.
#' @param endpoint OAuth endpoint for the ICD API, created by `icd_endpoint()`
#' @param app An OAuth consumer application, created by `icd_oauth_app()` by
#' default.
#' @param scope ICD API scope to request. Default is "icdapi_access".
#' @param as_header If TRUE, the default, configures the token to add itself to
#' the bearer header of subsequent requests. If FALSE, configures the token to
#' add itself as a url parameter of subsequent requests.
#' @param client_credentials Default to FALSE. Set to TRUE to use Client
#' Credentials Grant instead of Authorization Code Grant. See
#' https://www.rfc-editor.org/rfc/rfc6749#section-4.4.
#' @param ... Other parameters/arguments to be passed onto `httr::oauth2.0_token()`
#' @param appname Name of the application. This is not used for OAuth, but is
#' used to make it easier to identify different applications.
#' @param key Consumer key, also sometimes called the client ID.
#' @param id Consumer key, also sometimes called the client ID.
#' @param token_url url used to exchange unauthenticated for authenticated token.
#' @param secret Consumer secret, also sometimes called the client secret.
#' Despite its name, this does not necessarily need to be protected like a
#' password, i.e. the user still has to authenticate themselves and grant the
#' app permission to access resources on their behalf.
#' @param name Name of the application. This is not used for OAuth, but is
#' used to make it easier to identify different applications.
#' @param ... Other parameters/arguments to be passed onto `httr2::oauth_client()`
#'
#' @return For `icd_token()`, a Token2.0 reference class (RC) object.
#' @return An `httr2_oauth_client` class (RC) object.
#'
#' @examples
#' icd_endpoint()
#' icd_token()
#' icd_oauth_app()
#'
#' @rdname icd_authenticate
#'
#' @export
#'
icd_endpoint <- function(authorize = NULL,
access = "https://icdaccessmanagement.who.int/connect/token") {
httr::oauth_endpoint(authorize = authorize, access = access)
}

#' icd_oauth_client()
#'
#' @rdname icd_authenticate
#' @export
#'
icd_oauth_app <- function(appname = "icd_app",
key = "6fc8a1e4-4da9-43a8-bd0c-c164c0cb0ebd_3c7e272e-2f4b-46de-b127-df7454e36be8",
secret = "OGIly8mTatQ2ILuhBTbviIp2FofWiQR3fj4HaPiGseE=") {
httr::oauth_app(
appname = appname,
key = key,
secret = secret
)
}

#'
#' @rdname icd_authenticate
#' @export
#'
icd_token <- function(endpoint = icd_endpoint(),
app = icd_oauth_app(),
scope = "icdapi_access",
as_header = TRUE,
client_credentials = TRUE, ...) {
httr::oauth2.0_token(
endpoint = endpoint,
app = app,
scope = scope,
#use_oob = use_oob,
as_header = as_header,
client_credentials = client_credentials,
...
icd_oauth_client <- function(id = "6fc8a1e4-4da9-43a8-bd0c-c164c0cb0ebd_3c7e272e-2f4b-46de-b127-df7454e36be8",
token_url = "https://icdaccessmanagement.who.int/connect/token",
secret = "OGIly8mTatQ2ILuhBTbviIp2FofWiQR3fj4HaPiGseE=",
name = "icd_client",
...) {
httr2::oauth_client(
id = id,
token_url = token_url,
secret = secret,
auth = "header",
name = name
)
}



133 changes: 133 additions & 0 deletions R/icd_search.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#'
#' Search the foundation component of the ICD-11
#'
#' @param base_url The base URL of the API. Default uses the WHO API server at
#' https://id.who.int. If you are using a locally deployed server or hosting
#' your own ICD API server, you should specify the URL of your instance here.
#' @param client The OAuth2 client produced through a call to `icd_oauth_client()`.
#' @param q String. Text to be searched. Having the character `%` at the end will
#' be regarded as a wild card for that word.
#' @param subtree A string or vector of strings of URIs. If provided, the
#' search will be performed on the entities provided and their descendants.
#' @param chapter A string or vector of strings of chapter codes
#' eg: c("01", "02") When provided, the search will be performed only on
#' these chapters.
#' @param flexisearch Logical. Default is FALSE. Changes the search mode to
#' flexible search. In the regular search mode, the Coding Tool will only give
#' you results that contain all of the words that you've used in your search.
#' It accepts different variants or synonyms of the words but essentially it
#' searches for a result that contains all components of your search. Whereas
#' in flexible search mode, the results do not have to contain all of the words
#' that are typed. It would still try to find the best matching phrase but
#' there may be words in your search that are not matched at all. It is
#' recommended to use flexible search only when regular search does not
#' provide a result.
#' @param flat Logical. Default is FALSE. If set to true the search result
#' entities are provided in a nested data structure representing the
#' ICD-11 hierarchy. Otherwise they are listed as flat list of matches.
#' @param properties A string or a vector of strings for the properties to be
#' searched. By default the system searches, *"Title"*, *"Synonyms"*, and
#' *"FullySpecifiedName"*. The valid values that could be used are: *Title"*,
#' *"Synonym"*, *"NarrowerTerm"*, *"FullySpecifiedName"*, *"Definition"*, and
#' *"Exclusion"*.
#' @param release A string specifying the release version of the Foundation to
#' search from. If not specified, defaults to the latest release version. See
#' the available versions with `icd_versions`.
#' @param highlight Logical. Default is FALSE. If set to FALSE the search result
#' highlighting is turned off and the results don't contain special tags for
#' highlighting where the results are found within the text.
#' @param api_version Version of the API. Possible values are `v1` or `v2`.
#' For example, if you provide value v2, the API will respond in the format of
#' the version 2 of the API. Default is `v2`.
#' @param language ICD-API is multi-lingual. By changing this header, you may
#' make the API respond in different languages. Languages will be available as
#' the translations of ICD-11 completes. The values are language codes such as
#' en, es, zh, etc. Depending on the `release_id` specified, the available
#' languages will vary. Default is English ("en").
#'
#' @return An `httr2_response` object
#'
#' @examples
#' icd_search_foundation(q = "cholera")
#'
#' @rdname icd_search
#' @export
#'

icd_search_foundation <- function(base_url = "https://id.who.int",
client = icd_oauth_client(),
q,
subtree = NULL,
chapter = NULL,
flexisearch = FALSE,
flat = TRUE,
properties = NULL,
release = NULL,
highlight = FALSE,
api_version = c("v2", "v1"),
language = "en") {
## Get API version to use ----
api_version <- match.arg(api_version)

## Make base request ----
req <- httr2::request(file.path(base_url, "icd/entity/search")) |>
httr2::req_url_query(q = q)

## Add query components ----

### Subtrees filter ----
if (!is.null(subtree)) {
req <- req |>
httr2::req_url_query(subtreesFilter = paste(subtree, collapse = ","))
}

### Chapters filter ----
if (!is.null(chapter)) {
req <- req |>
httr2::req_url_query(chapterFilter = paste(chapter, collapse = ","))
}

### Flexi search and flatResults component ----
req <- req |>
httr2::req_url_query(
useFlexisearch = ifelse(flexisearch, "true", "false"),
flatResults = ifelse(flat, "true", "false")
)

### Properties ----
if (!is.null(properties)) {
req <- req |>
httr2::req_url_query(
propertiesToBeSearched = paste(properties, collapse = ",")
)
}

### Release ID ----
if (!is.null(release)) {
req <- req |>
httr2::req_url_query(releaseId = release)
}

### Highlighting ----
req <- req |>
httr2::req_url_query(
highlightingEnabled = ifelse(highlight, "true", "false")
)

## Add headers ----
req <- req |>
httr2::req_headers(
Accept = "application/json",
"API-Version" = api_version,
"Accept-Language" = language
) |>
## Authenticate ----
httr2::req_oauth_client_credentials(
client = client,
scope = "icdapi_access"
) |>
## Perform request ----
httr2::req_perform()
}


6 changes: 6 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#'
#'
#'
#'
#'
#'
27 changes: 13 additions & 14 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The [International Classification of Diseases (ICD)](https://www.who.int/standar

## What does `icd` do?

Please note that `icd` is still highly experimental and is undergoing a lot of development. Hence, any functionalities described below have a high likelihood of changing interface or approach as we approach a stable working version.
Please note that `icd` is still highly experimental and is undergoing a lot of development. Hence, any functionalities described below have a high likelihood of changing interface or approach as we aim for a stable working version.

Currently, the package provides functions for authenticating with the ICD API. From here, the plan is to develop functions that wrap the various available [API endpoints](https://id.who.int/swagger/index.html).

Expand All @@ -54,33 +54,32 @@ library(icd)

### Authenticating with the ICD API

The ICD API uses OAuth2 for authentication. The package has a set of utility functions that support the ICD API authentication specifications leading to the generation of an OAuth2 token. The `icd_token()` function is the downstream and user-facing function that creates an ICD OAuth2 token that can be used by future functions that wrap ICD API for entity and linearization information retrieval.
The ICD API uses OAuth2 for authentication. The package has a set of utility functions that support the ICD API authentication specifications leading to the generation of an OAuth2 token. The `icd_oauth_client()` function is the downstream and user-facing function that creates an ICD OAuth2 client that can be used for token retrieval by future functions that wrap ICD API for entity and linearization information retrieval.

An ICD OAuth2 token can be generated as follows:
An ICD OAuth2 client can be generated as follows:

```R
icd_token()
icd_oauth_client()
```

This function uses a built in OAuth2 application created for light use and for purposes of package development and testing.
This function uses a built in OAuth2 client created for light use and for purposes of package development and testing.

It is recommended that those intending to use this package for programmatically performing high volume of calls to the ICD API to create their own **access keys** (`client id` and `client secret`) using [these instructions](https://icd.who.int/docs/icd-api/API-Authentication/).

Then, with your access keys, perform the following commands:


```R
## Create your own OAuth application ----
my_app <- icd_oauth_app(
appname = "NAME_OF_YOUR_APP",
key = "YOUR_CLIEND_ID",
secret = "YOUR_CLIENT_SECRET"
## Create your own OAuth client ----
my_oauth_client <- icd_oauth_client(
id = "YOUR_CLIENT_ID",
token_url = "https://icdaccessmanagement.who.int/connect/token",
secret = "YOUR_CLIENT_SECRET",
name = "NAME_OF_YOUR_APP
)

## Create authentication token ----
my_token <- icd_token(app = my_app)
```
This OAuth2 client can now be used to the various functions in the package that require an OAuth2 client for authentication for making requests to the ICD API.
## Citation
If you find the `icd` package useful please cite using the suggested citation provided by a call to the `citation()` function as follows:
Expand Down
38 changes: 20 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ interface with the ICD API.

Please note that `icd` is still highly experimental and is undergoing a
lot of development. Hence, any functionalities described below have a
high likelihood of changing interface or approach as we approach a
stable working version.
high likelihood of changing interface or approach as we aim for a stable
working version.

Currently, the package provides functions for authenticating with the
ICD API. From here, the plan is to develop functions that wrap the
Expand Down Expand Up @@ -63,19 +63,19 @@ library(icd)

The ICD API uses OAuth2 for authentication. The package has a set of
utility functions that support the ICD API authentication specifications
leading to the generation of an OAuth2 token. The `icd_token()` function
is the downstream and user-facing function that creates an ICD OAuth2
token that can be used by future functions that wrap ICD API for entity
and linearization information retrieval.
leading to the generation of an OAuth2 token. The `icd_oauth_client()`
function is the downstream and user-facing function that creates an ICD
OAuth2 client that can be used for token retrieval by future functions
that wrap ICD API for entity and linearization information retrieval.

An ICD OAuth2 token can be generated as follows:
An ICD OAuth2 client can be generated as follows:

``` r
icd_token()
icd_oauth_client()
```

This function uses a built in OAuth2 application created for light use
and for purposes of package development and testing.
This function uses a built in OAuth2 client created for light use and
for purposes of package development and testing.

It is recommended that those intending to use this package for
programmatically performing high volume of calls to the ICD API to
Expand All @@ -86,17 +86,19 @@ instructions](https://icd.who.int/docs/icd-api/API-Authentication/).
Then, with your access keys, perform the following commands:

``` r
## Create your own OAuth application ----
my_app <- icd_oauth_app(
appname = "NAME_OF_YOUR_APP",
key = "YOUR_CLIEND_ID",
secret = "YOUR_CLIENT_SECRET"
## Create your own OAuth client ----
my_oauth_client <- icd_oauth_client(
id = "YOUR_CLIENT_ID",
token_url = "https://icdaccessmanagement.who.int/connect/token",
secret = "YOUR_CLIENT_SECRET",
name = "NAME_OF_YOUR_APP
)

## Create authentication token ----
my_token <- icd_token(app = my_app)
```
This OAuth2 client can now be used to the various functions in the
package that require an OAuth2 client for authentication for making
requests to the ICD API.
## Citation
If you find the `icd` package useful please cite using the suggested
Expand Down
Binary file added data-raw/icd-mapping.zip
Binary file not shown.
Loading

0 comments on commit 1542472

Please sign in to comment.