---
title: "Go further: understand and build your own functions"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Go further: understand and build your own functions}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = FALSE
)
```

```{r setup}
library(gitlabr)
```

There are more locations and actions that can be accessed through the GitLab API.
See the [documentation of the GitLab API](https://docs.gitlab.com/ce/api/) for this.

# API calls

This section describes how R function calls are translated into HTTP requests to the GitLab API ('gitlabr' "low level interface"). For a documentation using 'gitlabr' without knowledge of the GitLab API ('gitlabr' "high level interface"), see the ["Quick Start Example"](#quick-start-example) above or refer to the individual function documentation in the Reference section of 'gitlabr' pkgdown [site](https://thinkr-open.github.io/gitlabr/reference/index.html).

Currently ('gitlabr' >= 1.1.6) GitLab API v4 is supported. Support for GitLab API v3 (for GitLab version < 9.0) is still included via flag parameters, but is no longer maintained. For details see the section "API version" of the documentation of `gl_connection()`.

The core function of the low level interface is `gitlab()`, with the help of which arbitrary calls to the GitLab API can be formulated. It takes as required arguments the request location as a character vector, API endpoint URL and HTTP verb and passes additional arguments as query parameters (keeping their names) on to the API request.

```{r eval = FALSE}
gitlab(c("projects", 12, "issues"),
  api_root = "https://gitlab.com/api/v4",
  private_token = "XXX", # authentication for API
  verb = httr::GET, # defaults to GET, but POST, PUT, DELETE can be used likewise
  state = "active"
) # additional parameters (...) for the query
```

translates to

```
GET https://gitlab.com/api/v4/projects/12/issues?state=active&private_token=XXX
```

This way, any request documented in the [GitLab API documentation](https://docs.gitlab.com/ce/api) can be issued from 'gitlabr'.

The high level interface consists of a number of functions that each have additional arguments from which the request location is constructed, while all other arguments are simply passed on to `gitlab()`. For example:

```{r eval = FALSE}
gl_edit_issue(
  project = "test-project", 12, description = "Really cool new feature",
  api_root = "...", private_token = "XXX"
)
```

does nothing but

```{r eval = FALSE}
gitlab(
  c(
    "projects",
    4, # numeric id of test-project is found by search
    "issues",
    12
  ),
  description = "Really cool new feature",
  api_root = "...",
  private_token = "XXX",
  verb = httr::PUT
)
```

and hence translates to

```
PUT .../projects/4/issues/12?private_token=XXX?description=Really%20cool%20new%20feature
```

To spare you the repetitive task of specifying the API root and key in every call, you can use `set_gitlab_connection()` as described in the "quick start guide" vignette.

# Writing custom gitlab request functions

It is very easy to write your own convenience wrappers for accessing API endpoints you wish and make sure they fully integrate into 'gitlabr' and work conveniently with all connection and call idioms described in this vignette.
The only requirement to your function is that it executes an R function call to `gitlab()` (or another convenience function) to which the `...` argument is passed on.

That is, a simple function to block users directly from R is as simple as:
```{r}
gl_block_user <- function(uid, ...) {
  gitlab(c("users", uid, "block"), ## for API side documentation see:
    verb = httr::PUT, ## https://docs.gitlab.com/ce/api/users.html#block-user
    ...
  ) ## don't forget the dots to make 'gitlabr' features fully available
}
```

More hints for more convenience:

- To be consistent with another important 'gitlabr' principle, make sure your function returns a `tibble` (which it does if you simply pass up the return value of `gitlab()` or one of the package's own convenience functions). 
`gitlab()` has some heuristics to format the API response to a `tibble`, if these fail for your specific request, you can pass `auto_format = FALSE` and format the response manually.
- To translate project names to numeric ids automatically, you can use 'gitlabr's internal functions `proj_req()` translating the request location.
- To translate user-visible project-wide issue ids to global ids used by the GitLab API, you can use 'gitlabr' internal function `to_issue_id()` when constructing the request.

And last but not least, if you've written a convenience wrapper for yourself, keep in mind that it might be of help to many others and you can contribute it to 'gitlabr' on [https://github.com/ThinkR-open/gitlabr](https://github.com/ThinkR-open/gitlabr).
