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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ The format follows [Keep a Changelog] (https://keepachangelog.com/en/1.1.0/).
- **Form fields follow the form's font, and Public Design offers Arial** (#1727). Fields, selects and buttons inherit the font the labels use instead of the browser's; the font choice is the theme's (default), the plugin's system font or Arial, as in Email Signature Generator and Institutional Email.
- **Required certificate tags have their own Settings tab and protect their fields** (#1734). The list moved from Advanced to a new Certificates tab; the layout and template screens list the configured tags instead of a fixed three. A field a required tag calls for is amber, badged, always required, and cannot be renamed or removed; a form missing one is warned on save.
- **Required form fields are a list of their own** (#1741). Settings → Certificates keeps the layout tags and, apart, the fields every form needs with label and type (default `name`, `cpf_rf`, `email`; Email stays). New forms start with them, their type is locked, and the editor adds missing ones.
- **Ordered three-level settings use the steps control** (#1745). The four geofence display modes, the two private-calendar displays and the IP API fallback store the same values as before; an unknown stored value shows the old default.

### Fixed

Expand Down
63 changes: 39 additions & 24 deletions includes/admin/class-ffc-form-editor-geofence-metabox.php
Original file line number Diff line number Diff line change
Expand Up @@ -255,35 +255,23 @@ public function render_time( WP_Post $post ): void {
</td>
</tr>
<tr>
<th><label for="ffc_datetime_hide_mode_before"><?php esc_html_e( 'Display before opening', 'ffcertificate' ); ?></label></th>
<th><?php esc_html_e( 'Display before opening', 'ffcertificate' ); ?></th>
<td>
<select id="ffc_datetime_hide_mode_before" name="ffc_geofence[datetime_hide_mode_before]">
<option value="message" <?php selected( $datetime_hide_mode_before, 'message' ); ?>><?php esc_html_e( 'Show blocked message (Recommended)', 'ffcertificate' ); ?></option>
<option value="title_message" <?php selected( $datetime_hide_mode_before, 'title_message' ); ?>><?php esc_html_e( 'Show title + description + message', 'ffcertificate' ); ?></option>
<option value="hide" <?php selected( $datetime_hide_mode_before, 'hide' ); ?>><?php esc_html_e( 'Hide form completely', 'ffcertificate' ); ?></option>
</select>
<?php self::render_hide_mode( 'datetime_hide_mode_before', $datetime_hide_mode_before, __( 'Display before opening', 'ffcertificate' ) ); ?>
<p class="description"><?php esc_html_e( 'How to display the form before the start date / start time. "Hide form completely" makes the page render as if the form did not exist yet.', 'ffcertificate' ); ?></p>
</td>
</tr>
<tr id="ffc-datetime-hide-mode-during-row" class="ffc-datetime-hide-during<?php echo $show_during_row ? '' : ' ffc-hidden'; ?>">
<th><label for="ffc_datetime_hide_mode_during"><?php esc_html_e( 'Display during, outside daily slot', 'ffcertificate' ); ?></label></th>
<th><?php esc_html_e( 'Display during, outside daily slot', 'ffcertificate' ); ?></th>
<td>
<select id="ffc_datetime_hide_mode_during" name="ffc_geofence[datetime_hide_mode_during]">
<option value="message" <?php selected( $datetime_hide_mode_during, 'message' ); ?>><?php esc_html_e( 'Show blocked message (Recommended)', 'ffcertificate' ); ?></option>
<option value="title_message" <?php selected( $datetime_hide_mode_during, 'title_message' ); ?>><?php esc_html_e( 'Show title + description + message', 'ffcertificate' ); ?></option>
<option value="hide" <?php selected( $datetime_hide_mode_during, 'hide' ); ?>><?php esc_html_e( 'Hide form completely', 'ffcertificate' ); ?></option>
</select>
<?php self::render_hide_mode( 'datetime_hide_mode_during', $datetime_hide_mode_during, __( 'Display during, outside daily slot', 'ffcertificate' ) ); ?>
<p class="description"><?php esc_html_e( 'How to display the form when the campaign is in its date range but the current time is outside today\'s daily slot (only used in Time Behavior = "applies to each day individually").', 'ffcertificate' ); ?></p>
</td>
</tr>
<tr>
<th><label for="ffc_datetime_hide_mode_after"><?php esc_html_e( 'Display after closing', 'ffcertificate' ); ?></label></th>
<th><?php esc_html_e( 'Display after closing', 'ffcertificate' ); ?></th>
<td>
<select id="ffc_datetime_hide_mode_after" name="ffc_geofence[datetime_hide_mode_after]">
<option value="message" <?php selected( $datetime_hide_mode_after, 'message' ); ?>><?php esc_html_e( 'Show blocked message (Recommended)', 'ffcertificate' ); ?></option>
<option value="title_message" <?php selected( $datetime_hide_mode_after, 'title_message' ); ?>><?php esc_html_e( 'Show title + description + message', 'ffcertificate' ); ?></option>
<option value="hide" <?php selected( $datetime_hide_mode_after, 'hide' ); ?>><?php esc_html_e( 'Hide form completely', 'ffcertificate' ); ?></option>
</select>
<?php self::render_hide_mode( 'datetime_hide_mode_after', $datetime_hide_mode_after, __( 'Display after closing', 'ffcertificate' ) ); ?>
<p class="description"><?php esc_html_e( 'How to display the form after the end date / end time.', 'ffcertificate' ); ?></p>
</td>
</tr>
Expand Down Expand Up @@ -588,13 +576,9 @@ public function render_geolocation( WP_Post $post ): void {
?>
<table class="form-table">
<tr>
<th><label><?php esc_html_e( 'Display Mode', 'ffcertificate' ); ?></label></th>
<th><?php esc_html_e( 'Display Mode', 'ffcertificate' ); ?></th>
<td>
<select name="ffc_geofence[geo_hide_mode]">
<option value="message" <?php selected( $geo_hide_mode, 'message' ); ?>><?php esc_html_e( 'Show blocked message (Recommended)', 'ffcertificate' ); ?></option>
<option value="title_message" <?php selected( $geo_hide_mode, 'title_message' ); ?>><?php esc_html_e( 'Show title + description + message', 'ffcertificate' ); ?></option>
<option value="hide" <?php selected( $geo_hide_mode, 'hide' ); ?>><?php esc_html_e( 'Hide form completely', 'ffcertificate' ); ?></option>
</select>
<?php self::render_hide_mode( 'geo_hide_mode', (string) $geo_hide_mode, __( 'Display Mode', 'ffcertificate' ) ); ?>
<p class="description"><?php esc_html_e( 'How to display the form when user is outside allowed areas.', 'ffcertificate' ); ?></p>
</td>
</tr>
Expand All @@ -620,6 +604,37 @@ public function render_geolocation( WP_Post $post ): void {
$this->enqueue_metabox_script();
}

/**
* A "what does a blocked visitor see" setting, as a steps control
* ordered from the most shown to nothing (#1745). The stored values are
* the ones the select used to post.
*
* @param string $key Key under `ffc_geofence`.
* @param string $value Stored value.
* @param string $legend Group name read by screen readers.
*/
private static function render_hide_mode( string $key, string $value, string $legend ): void {
AdminUI::render_steps(
array(
'name' => 'ffc_geofence[' . $key . ']',
'id' => 'ffc_' . $key,
'value' => $value,
'default' => 'message',
'legend' => $legend,
'options' => array(
'title_message' => __( 'Title and message', 'ffcertificate' ),
'message' => __( 'Message only', 'ffcertificate' ),
'hide' => __( 'Hidden', 'ffcertificate' ),
),
'descriptions' => array(
'title_message' => __( 'Show title + description + message', 'ffcertificate' ),
'message' => __( 'Show blocked message (Recommended)', 'ffcertificate' ),
'hide' => __( 'Hide form completely', 'ffcertificate' ),
),
)
);
}

/**
* Registered-locations picker: one checkbox per location (#1614).
*
Expand Down
35 changes: 23 additions & 12 deletions includes/settings/views/ffc-tab-geolocation.php
Original file line number Diff line number Diff line change
Expand Up @@ -449,20 +449,31 @@ class="regular-text"
<!-- API Failure Fallback (IP-dependent — collapsed when IP API off). -->
<tr data-ffc-section="ip_api_full">
<th scope="row">
<label for="ffc_api_fallback"><?php esc_html_e( 'When IP API Fails', 'ffcertificate' ); ?></label>
<?php esc_html_e( 'When IP API Fails', 'ffcertificate' ); ?>
</th>
<td>
<select name="api_fallback" id="ffc_api_fallback">
<option value="allow" <?php selected( $settings['api_fallback'], 'allow' ); ?>>
<?php esc_html_e( 'Allow access (assume valid)', 'ffcertificate' ); ?>
</option>
<option value="block" <?php selected( $settings['api_fallback'], 'block' ); ?>>
<?php esc_html_e( 'Block access (assume invalid)', 'ffcertificate' ); ?>
</option>
<option value="gps_only" <?php selected( $settings['api_fallback'], 'gps_only' ); ?>>
<?php esc_html_e( 'Use GPS only (ignore IP validation)', 'ffcertificate' ); ?>
</option>
</select>
<?php
\FreeFormCertificate\Admin\AdminUI::render_steps(
array(
'name' => 'api_fallback',
'id' => 'ffc_api_fallback',
'value' => (string) $settings['api_fallback'],
'default' => 'gps_only',
'palette' => 'severity',
'legend' => __( 'When IP API Fails', 'ffcertificate' ),
'options' => array(
'allow' => __( 'Allow', 'ffcertificate' ),
'gps_only' => __( 'GPS only', 'ffcertificate' ),
'block' => __( 'Block', 'ffcertificate' ),
),
'descriptions' => array(
'allow' => __( 'Allow access (assume valid)', 'ffcertificate' ),
'gps_only' => __( 'Use GPS only (ignore IP validation)', 'ffcertificate' ),
'block' => __( 'Block access (assume invalid)', 'ffcertificate' ),
),
)
);
?>
<p class="description">
<?php esc_html_e( 'What to do when IP geolocation API is unavailable or returns error.', 'ffcertificate' ); ?>
</p>
Expand Down
2 changes: 1 addition & 1 deletion languages/ffcertificate-pt_BR.l10n.php

Large diffs are not rendered by default.

Binary file modified languages/ffcertificate-pt_BR.mo
Binary file not shown.
12 changes: 12 additions & 0 deletions languages/ffcertificate-pt_BR.po
Original file line number Diff line number Diff line change
Expand Up @@ -25914,3 +25914,15 @@ msgstr "Você saiu desta página enquanto respondia o quiz, então as respostas
#: includes/settings/views/documentation/feature-quiz.php:32
msgid "a three-step scale: Off (the default), Moderate or Strict. Moderate clears the scored answers when the participant switches to another tab or minimises the browser; Strict also clears them when another window takes the focus, such as two windows side by side, unless the focus comes back within the grace set on Settings → Certificates (1000 ms by default; a click inside an embedded video does not count). The form warns the participant before they start; once they have started, leaving clears the scored answers (name, CPF/RF and the other fields stay) and a dialog explains why on return. Its Start again button reloads the page, so options marked to shuffle are shuffled again, and personal fields the browser does not restore must be typed again. Leaving does not count as an attempt; the number of times it happened is stored with the submission and shown on its edit screen as \"Times the quiz window was left\". It is a deterrent, not a lock: another device, or a browser without JavaScript, is not stopped, and the count is reported by the browser."
msgstr "uma escala de três passos: Desligado (padrão), Moderado ou Restritivo. Moderado apaga as respostas pontuadas quando o participante troca de aba ou minimiza o navegador; Restritivo também as apaga quando outra janela recebe o foco, como duas janelas lado a lado, a menos que o foco volte dentro da tolerância definida em Configurações → Certificados (1000 ms por padrão; um clique dentro de um vídeo incorporado não conta). O formulário avisa o participante antes de começar; depois que ele começa, sair apaga as respostas pontuadas (nome, CPF/RF e os outros campos ficam) e um diálogo explica o motivo na volta. O botão Recomeçar recarrega a página, para que as opções marcadas para embaralhar sejam embaralhadas de novo, e os campos pessoais que o navegador não restaurar precisam ser digitados de novo. Sair não conta como tentativa; o número de vezes que isso aconteceu é guardado com o envio e mostrado na tela de edição como \"Saídas da janela do quiz\". É uma dissuasão, não uma trava: outro dispositivo ou um navegador sem JavaScript não são impedidos, e a contagem é informada pelo navegador."

#: includes/admin/class-ffc-form-editor-geofence-metabox.php:624
msgid "Title and message"
msgstr "Título e mensagem"

#: includes/admin/class-ffc-form-editor-geofence-metabox.php:625
msgid "Message only"
msgstr "Somente a mensagem"

#: includes/settings/views/ffc-tab-geolocation.php:465
msgid "GPS only"
msgstr "Somente GPS"
12 changes: 12 additions & 0 deletions languages/ffcertificate.pot
Original file line number Diff line number Diff line change
Expand Up @@ -25830,3 +25830,15 @@ msgstr ""
#: includes/settings/views/documentation/feature-quiz.php:32
msgid "a three-step scale: Off (the default), Moderate or Strict. Moderate clears the scored answers when the participant switches to another tab or minimises the browser; Strict also clears them when another window takes the focus, such as two windows side by side, unless the focus comes back within the grace set on Settings → Certificates (1000 ms by default; a click inside an embedded video does not count). The form warns the participant before they start; once they have started, leaving clears the scored answers (name, CPF/RF and the other fields stay) and a dialog explains why on return. Its Start again button reloads the page, so options marked to shuffle are shuffled again, and personal fields the browser does not restore must be typed again. Leaving does not count as an attempt; the number of times it happened is stored with the submission and shown on its edit screen as \"Times the quiz window was left\". It is a deterrent, not a lock: another device, or a browser without JavaScript, is not stopped, and the count is reported by the browser."
msgstr ""

#: includes/admin/class-ffc-form-editor-geofence-metabox.php:624
msgid "Title and message"
msgstr ""

#: includes/admin/class-ffc-form-editor-geofence-metabox.php:625
msgid "Message only"
msgstr ""

#: includes/settings/views/ffc-tab-geolocation.php:465
msgid "GPS only"
msgstr ""
34 changes: 22 additions & 12 deletions templates/admin/audience/audience-tab.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,30 @@
<tbody>
<tr>
<th scope="row">
<label for="ffc_aud_private_display_mode"><?php esc_html_e( 'Private Calendar Display', 'ffcertificate' ); ?></label>
<?php esc_html_e( 'Private Calendar Display', 'ffcertificate' ); ?>
</th>
<td>
<select name="ffc_aud_private_display_mode" id="ffc_aud_private_display_mode">
<option value="show_message" <?php selected( $display_mode, 'show_message' ); ?>>
<?php esc_html_e( 'Show message', 'ffcertificate' ); ?>
</option>
<option value="show_title_message" <?php selected( $display_mode, 'show_title_message' ); ?>>
<?php esc_html_e( 'Show calendar title + message', 'ffcertificate' ); ?>
</option>
<option value="hide" <?php selected( $display_mode, 'hide' ); ?>>
<?php esc_html_e( 'Hide completely', 'ffcertificate' ); ?>
</option>
</select>
<?php
\FreeFormCertificate\Admin\AdminUI::render_steps(
array(
'name' => 'ffc_aud_private_display_mode',
'id' => 'ffc_aud_private_display_mode',
'value' => (string) $display_mode,
'default' => 'show_message',
'legend' => __( 'Private Calendar Display', 'ffcertificate' ),
'options' => array(
'show_title_message' => __( 'Title and message', 'ffcertificate' ),
'show_message' => __( 'Message only', 'ffcertificate' ),
'hide' => __( 'Hidden', 'ffcertificate' ),
),
'descriptions' => array(
'show_title_message' => __( 'Show calendar title + message', 'ffcertificate' ),
'show_message' => __( 'Show message', 'ffcertificate' ),
'hide' => __( 'Hide completely', 'ffcertificate' ),
),
)
);
?>
<p class="description"><?php esc_html_e( 'What to show when a private calendar is accessed by a non-logged-in user.', 'ffcertificate' ); ?></p>
</td>
</tr>
Expand Down
34 changes: 22 additions & 12 deletions templates/admin/audience/self-scheduling-tab.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,30 @@
<tbody>
<tr>
<th scope="row">
<label for="ffc_ss_private_display_mode"><?php esc_html_e( 'Private Calendar Display', 'ffcertificate' ); ?></label>
<?php esc_html_e( 'Private Calendar Display', 'ffcertificate' ); ?>
</th>
<td>
<select name="ffc_ss_private_display_mode" id="ffc_ss_private_display_mode">
<option value="show_message" <?php selected( $display_mode, 'show_message' ); ?>>
<?php esc_html_e( 'Show message', 'ffcertificate' ); ?>
</option>
<option value="show_title_message" <?php selected( $display_mode, 'show_title_message' ); ?>>
<?php esc_html_e( 'Show calendar title + message', 'ffcertificate' ); ?>
</option>
<option value="hide" <?php selected( $display_mode, 'hide' ); ?>>
<?php esc_html_e( 'Hide completely', 'ffcertificate' ); ?>
</option>
</select>
<?php
\FreeFormCertificate\Admin\AdminUI::render_steps(
array(
'name' => 'ffc_ss_private_display_mode',
'id' => 'ffc_ss_private_display_mode',
'value' => (string) $display_mode,
'default' => 'show_message',
'legend' => __( 'Private Calendar Display', 'ffcertificate' ),
'options' => array(
'show_title_message' => __( 'Title and message', 'ffcertificate' ),
'show_message' => __( 'Message only', 'ffcertificate' ),
'hide' => __( 'Hidden', 'ffcertificate' ),
),
'descriptions' => array(
'show_title_message' => __( 'Show calendar title + message', 'ffcertificate' ),
'show_message' => __( 'Show message', 'ffcertificate' ),
'hide' => __( 'Hide completely', 'ffcertificate' ),
),
)
);
?>
<p class="description"><?php esc_html_e( 'What to show when a private calendar is accessed by a non-logged-in user.', 'ffcertificate' ); ?></p>
</td>
</tr>
Expand Down
8 changes: 8 additions & 0 deletions tests/Unit/AudienceAdminSettingsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,18 @@ private function render( AudienceAdminSettings $page ): string {
public function test_render_page_self_scheduling_tab_shows_the_stored_messages(): void {
$_GET['tab'] = 'self-scheduling';
Functions\when( 'get_option' )->alias( function ( $key, $default = false ) {
if ( 'ffc_ss_private_display_mode' === $key ) {
return 'hide';
}
return 'ffc_ss_business_hours_booking_message' === $key ? 'Stored booking text' : $default;
} );

$html = $this->render( $this->page() );

// #1745: the display mode is a steps control, most shown first.
$this->assertStringContainsString( 'id="ffc_ss_private_display_mode-3" name="ffc_ss_private_display_mode" value="hide" checked', $html );
$this->assertStringNotContainsString( '<select name="ffc_ss_private_display_mode"', $html );

$this->assertStringContainsString( 'id="ffc-scheduling-tabpanel-self-scheduling"', $html );
$this->assertStringContainsString( 'Stored booking text', $html );
$this->assertStringContainsString( 'save_ss_visibility_settings', $html );
Expand All @@ -285,6 +292,7 @@ public function test_render_page_audience_tab_shows_its_form(): void {
$this->assertStringContainsString( 'id="ffc-scheduling-tabpanel-audience"', $html );
$this->assertStringContainsString( 'save_aud_visibility_settings', $html );
$this->assertStringContainsString( 'aria-selected="true"', $html );
$this->assertStringContainsString( 'id="ffc_aud_private_display_mode-2" name="ffc_aud_private_display_mode" value="show_message" checked', $html, 'The default is the middle position.' );
}

public function test_render_page_import_tab_delegates_to_the_import_page(): void {
Expand Down
Loading
Loading