*/ public static function abilities(): array { $formId = ['minimum' => 1, 'type' => 'integer']; return [ new Ability( 'sarcio/forms-list', __('Look at the forms', 'sarcio'), Ability::READ, 'The site’s Gravity Forms: id, title, how many entries, the fields and where notifications go. Other form plugins show up as their own abilities, if they register any.', ['properties' => [], 'required' => [], 'type' => 'object'], static fn (array $args): bool => self::canEdit(), static fn (array $args): array => self::list(), ), new Ability( 'sarcio/form-entries', __('Look at form entries', 'sarcio'), Ability::READ, 'Recent entries of a Gravity Form: who wrote what and when. These are people’s details: use them for the question asked and nothing else; they are not kept in the conversation.', ['properties' => ['formId' => $formId, 'limit' => ['maximum' => 50, 'minimum' => 1, 'type' => 'integer']], 'required' => ['formId'], 'type' => 'object'], static fn (array $args): bool => self::canViewEntries(), static fn (array $args): array => self::entries($args), ), new Ability( 'sarcio/form-notification-update', __('Change where a form’s emails go', 'sarcio'), Ability::WRITE, 'Change a Gravity Forms notification by its id from forms-list: the addresses it goes to (comma-separated), its subject, or its message. Only the fields given change; undo puts the old ones back.', [ 'properties' => [ 'formId' => $formId, 'message' => ['maxLength' => 5000, 'type' => 'string'], 'notificationId' => ['maxLength' => 64, 'minLength' => 1, 'type' => 'string'], 'subject' => ['maxLength' => 300, 'type' => 'string'], 'to' => ['maxLength' => 500, 'type' => 'string'], ], 'required' => ['formId', 'notificationId'], 'type' => 'object', ], static fn (array $args): bool => self::canEdit(), static fn (array $args): array => self::updateNotification($args), null, static fn (array $before, array $after): array => self::restoreNotification($before), ), ]; } public static function available(): bool { return class_exists('\GFAPI'); } private static function missing(): array { return ['error' => __('This needs Gravity Forms. Other form plugins show up as their own abilities when they register any.', 'sarcio')]; } private static function canEdit(): bool { return current_user_can('gravityforms_edit_forms') || current_user_can('manage_options'); } private static function canViewEntries(): bool { return current_user_can('gravityforms_view_entries') || current_user_can('manage_options'); } private static function list(): array { if (!self::available()) { return self::missing(); } $out = []; foreach ((array) \GFAPI::get_forms() as $form) { $fields = []; foreach ((array) ($form['fields'] ?? []) as $field) { $fields[] = ['id' => (string) ($field->id ?? $field['id'] ?? ''), 'label' => (string) ($field->label ?? $field['label'] ?? ''), 'type' => (string) ($field->type ?? $field['type'] ?? '')]; } $notifications = []; foreach ((array) ($form['notifications'] ?? []) as $notification) { $notifications[] = ['id' => (string) ($notification['id'] ?? ''), 'name' => (string) ($notification['name'] ?? ''), 'subject' => (string) ($notification['subject'] ?? ''), 'to' => (string) ($notification['to'] ?? '')]; } $out[] = [ 'entries' => (int) \GFAPI::count_entries((int) $form['id']), 'fields' => $fields, 'id' => (int) $form['id'], 'notifications' => $notifications, 'title' => (string) $form['title'], ]; } return ['forms' => $out]; } /** @param array $args */ private static function entries(array $args): array { if (!self::available()) { return self::missing(); } $form = \GFAPI::get_form((int) $args['formId']); if (!is_array($form)) { return ['error' => __('There is no form with that id.', 'sarcio')]; } $labels = []; foreach ((array) ($form['fields'] ?? []) as $field) { $labels[(string) ($field->id ?? $field['id'] ?? '')] = (string) ($field->label ?? $field['label'] ?? ''); } $entries = \GFAPI::get_entries((int) $args['formId'], ['status' => 'active'], ['direction' => 'DESC', 'key' => 'date_created'], ['offset' => 0, 'page_size' => (int) ($args['limit'] ?? 10)]); $out = []; foreach (is_array($entries) ? $entries : [] as $entry) { $values = []; foreach ($labels as $fieldId => $label) { $value = $entry[$fieldId] ?? ''; if (!is_scalar($value) || (string) $value === '') { continue; } $values[$label !== '' ? $label : $fieldId] = mb_substr((string) $value, 0, 500); } $out[] = ['date' => (string) ($entry['date_created'] ?? ''), 'id' => (int) ($entry['id'] ?? 0), 'values' => $values]; } return ['entries' => $out, 'form' => (string) $form['title'], 'transient' => true]; } /** @param array $args */ private static function updateNotification(array $args): array { if (!self::available()) { return self::missing(); } $form = \GFAPI::get_form((int) $args['formId']); if (!is_array($form)) { return ['error' => __('There is no form with that id.', 'sarcio')]; } $id = (string) $args['notificationId']; if (!isset($form['notifications'][$id])) { return ['error' => __('That form has no notification with that id.', 'sarcio')]; } $before = array_intersect_key((array) $form['notifications'][$id], array_flip(['message', 'subject', 'to'])); $changes = []; foreach (['to', 'subject', 'message'] as $field) { if (array_key_exists($field, $args)) { $changes[$field] = $field === 'message' ? wp_kses_post((string) $args[$field]) : sanitize_text_field((string) $args[$field]); } } if ($changes === []) { return ['error' => __('Nothing would change.', 'sarcio')]; } if (isset($changes['to'])) { foreach (array_map('trim', explode(',', $changes['to'])) as $address) { if ($address !== '' && !is_email($address) && !str_starts_with($address, '{')) { return ['error' => sprintf( /* translators: %s: the address. */ __('%s is not an email address.', 'sarcio'), $address, )]; } } } $form['notifications'][$id] = array_merge($form['notifications'][$id], $changes); $result = \GFAPI::update_form($form); if (is_wp_error($result)) { return ['error' => sanitize_text_field($result->get_error_message())]; } return [ 'journal' => [ 'after' => ['formId' => (int) $args['formId'], 'notificationId' => $id, 'values' => $changes], 'before' => ['formId' => (int) $args['formId'], 'notificationId' => $id, 'values' => $before], 'summary' => sprintf( /* translators: 1: the notification name, 2: the form title. */ __('Changed the “%1$s” email of the form “%2$s”', 'sarcio'), (string) ($form['notifications'][$id]['name'] ?? $id), (string) $form['title'], ), 'target' => 'form:' . $args['formId'], ], 'notification' => $form['notifications'][$id], ]; } /** @param array $before */ private static function restoreNotification(array $before): array { if (!self::available()) { return self::missing(); } $form = \GFAPI::get_form((int) ($before['formId'] ?? 0)); $id = (string) ($before['notificationId'] ?? ''); if (!is_array($form) || !isset($form['notifications'][$id])) { return ['error' => __('That notification no longer exists.', 'sarcio')]; } $form['notifications'][$id] = array_merge($form['notifications'][$id], (array) ($before['values'] ?? [])); $result = \GFAPI::update_form($form); return is_wp_error($result) ? ['error' => sanitize_text_field($result->get_error_message())] : ['restored' => true]; } }