|
1 | 1 | #' Executes modifications to the result of a module |
2 | 2 | #' |
3 | | -#' Primarily used to modify the output object of module to change the containing |
4 | | -#' report. |
5 | | -#' @param x (`teal_module`). |
6 | | -#' @param ui (`function(id, elem, ...)`) function to receive output (`shiny.tag`) from `x$ui` |
7 | | -#' @param server (`function(input, output, session, data, ...)`) function to receive output data from `x$server` |
8 | | -#' @param ... additional argument passed to `ui` and `server` by matching their formals names. |
9 | | -#' @return A `teal_report` object with the result of the server function. |
| 3 | +#' @description |
| 4 | +#' `r lifecycle::badge("experimental")` |
| 5 | +#' |
| 6 | +#' Exported to be able to use methods not to be used directly by module-developers or app-users. |
| 7 | +#' Primarily used to modify the output object of module. |
| 8 | +#' @seealso [disable_src()], [disable_report()] |
| 9 | +#' @param x (`teal_module` or `teal_modules`). |
| 10 | +#' @param server (`function(input, output, session, data, ...)`) function to receive output data from `tm$server`. |
| 11 | +#' Must return data |
| 12 | +#' @param ... Additional arguments passed to the server wrapper function by matching their formal names. |
| 13 | +#' @return A `teal_module` or `teal_modules` object with a wrapped server. |
10 | 14 | #' @export |
| 15 | +#' @keywords internal |
| 16 | +#' @examples |
| 17 | +#' library("teal.reporter") |
| 18 | +#' hide_code <- function(input, output, session, data) { |
| 19 | +#' teal_card(data) <- Filter(function(x) !inherits(x, "code_chunk"), teal_card(data)) |
| 20 | +#' data |
| 21 | +#' } |
| 22 | +#' app <- init( |
| 23 | +#' data = teal_data(IRIS = iris, MTCARS = mtcars), |
| 24 | +#' modules = example_module() |> |
| 25 | +#' after(server = hide_code) |
| 26 | +#' ) |
| 27 | +#' |
| 28 | +#' if (interactive()) { |
| 29 | +#' runApp(app) |
| 30 | +#' } |
11 | 31 | after <- function(x, |
12 | | - ui = function(id, elem) elem, |
13 | 32 | server = function(input, output, session, data) data, |
14 | 33 | ...) { |
| 34 | + UseMethod("after") |
| 35 | +} |
| 36 | + |
| 37 | + |
| 38 | +#' @export |
| 39 | +after.default <- function(x, |
| 40 | + server = function(input, output, session, data) data, |
| 41 | + ...) { |
| 42 | + stop("`after` is only implemented for `teal_module` and `teal_modules` objects.") |
| 43 | +} |
| 44 | + |
| 45 | +#' @export |
| 46 | +after.teal_modules <- function(x, |
| 47 | + server = function(input, output, session, data) data, |
| 48 | + ...) { |
| 49 | + x$children <- lapply(x$children, after, |
| 50 | + server = server, ... |
| 51 | + ) |
| 52 | + x |
| 53 | +} |
| 54 | + |
| 55 | +#' @export |
| 56 | +after.teal_module <- function(x, |
| 57 | + server = function(input, output, session, data) data, |
| 58 | + ...) { |
15 | 59 | checkmate::assert_multi_class(x, "teal_module") |
16 | | - if (!is.function(ui) || !all(names(formals(ui)) %in% c("id", "elem"))) { |
17 | | - stop("ui should be a function of id and elem") |
18 | | - } |
19 | | - if (!is.function(server) || !all(names(formals(server)) %in% c("input", "output", "session", "data"))) { |
20 | | - stop("server should be a function of `input` and `output`, `session`, `data`") |
| 60 | + |
| 61 | + names_srv <- names(formals(server)) |
| 62 | + args_callModule <- c("input", "output", "session", "data") # nolint object_name_linter. |
| 63 | + if (!is.function(server) || !(!all(identical(names_srv, c("id", "data"))) || !all(names_srv %in% args_callModule))) { |
| 64 | + stop("`server` must be a function whose arguments are a subset of c('input', 'output', 'session', 'data'), or exactly 'id' AND 'data'.") # nolint line_length_lint |
21 | 65 | } |
22 | 66 |
|
23 | 67 | additional_args <- list(...) |
24 | | - new_x <- x # because overwriting x$ui/server will cause infinite recursion |
25 | | - new_x$ui <- .after_ui(x$ui, ui, additional_args) |
26 | | - new_x$server <- .after_server(x$server, server, additional_args) |
27 | | - new_x |
| 68 | + x$ui <- after_ui(x$ui, function(id, elem) { |
| 69 | + elem |
| 70 | + }, additional_args) |
| 71 | + x$server <- after_srv(x$server, server, additional_args) |
| 72 | + x |
28 | 73 | } |
29 | 74 |
|
30 | | -.after_ui <- function(x, y, additional_args) { |
31 | | - # add `_`-prefix to make sure objects are not masked in the wrapper functions |
32 | | - `_x` <- x # nolint: object_name. |
33 | | - `_y` <- y # nolint: object_name. |
34 | | - new_x <- function(id, ...) { |
| 75 | +after_ui <- function(old, new, additional_args) { |
| 76 | + new_ui <- function(id, ...) { |
35 | 77 | original_args <- as.list(environment()) |
36 | | - if ("..." %in% names(formals(`_x`))) { |
| 78 | + if ("..." %in% names(formals(old))) { |
37 | 79 | original_args <- c(original_args, list(...)) |
38 | 80 | } |
39 | 81 | ns <- NS(id) |
40 | 82 | original_args$id <- ns("wrapped") |
41 | | - original_out <- do.call(`_x`, original_args, quote = TRUE) |
| 83 | + original_out <- do.call(old, original_args, quote = TRUE) |
42 | 84 |
|
43 | 85 | wrapper_args <- c( |
44 | 86 | additional_args, |
45 | 87 | list(id = ns("wrapper"), elem = original_out) |
46 | 88 | ) |
47 | | - do.call(`_y`, args = wrapper_args[names(formals(`_y`))]) |
| 89 | + do.call(new, args = wrapper_args[names(formals(new))]) |
48 | 90 | } |
49 | | - formals(new_x) <- formals(x) |
50 | | - new_x |
| 91 | + formals(new_ui) <- formals(old) |
| 92 | + new_ui |
51 | 93 | } |
52 | 94 |
|
53 | | -.after_server <- function(x, y, additional_args) { |
54 | | - # add `_`-prefix to make sure objects are not masked in the wrapper functions |
55 | | - `_x` <- x # nolint: object_name. |
56 | | - `_y` <- y # nolint: object_name. |
57 | | - new_x <- function(id, ...) { |
| 95 | +after_srv <- function(old, new, additional_args) { |
| 96 | + new_srv <- function(id, ...) { |
58 | 97 | original_args <- as.list(environment()) |
59 | 98 | original_args$id <- "wrapped" |
60 | | - if ("..." %in% names(formals(`_x`))) { |
| 99 | + if ("..." %in% names(formals(old))) { |
61 | 100 | original_args <- c(original_args, list(...)) |
62 | 101 | } |
63 | 102 | moduleServer(id, function(input, output, session) { |
64 | | - original_out <- if (all(c("input", "output", "session") %in% names(formals(`_x`)))) { |
65 | | - original_args$module <- `_x` |
| 103 | + original_out <- if (all(c("input", "output", "session") %in% names(formals(old)))) { |
| 104 | + original_args$module <- old |
66 | 105 | do.call(shiny::callModule, args = original_args) |
67 | 106 | } else { |
68 | | - do.call(`_x`, original_args) |
| 107 | + do.call(old, original_args) |
69 | 108 | } |
70 | | - original_out_r <- reactive( |
71 | | - if (is.reactive(original_out)) { |
72 | | - original_out() |
73 | | - } else { |
74 | | - original_out |
75 | | - } |
76 | | - ) |
| 109 | + |
77 | 110 | wrapper_args <- utils::modifyList( |
78 | 111 | additional_args, |
79 | 112 | list(id = "wrapper", input = input, output = output, session = session) |
80 | 113 | ) |
81 | 114 | reactive({ |
82 | | - req(original_out_r()) |
| 115 | + req(original_out()) |
83 | 116 | wrapper_args$data <- original_out() |
84 | | - do.call(`_y`, wrapper_args[names(formals(`_y`))], quote = TRUE) |
| 117 | + do.call(new, wrapper_args[names(formals(new))], quote = TRUE) |
85 | 118 | }) |
86 | 119 | }) |
87 | 120 | } |
88 | | - formals(new_x) <- formals(x) |
89 | | - new_x |
| 121 | + formals(new_srv) <- formals(old) |
| 122 | + new_srv |
90 | 123 | } |
0 commit comments