Skip to content

Commit a0fdd02

Browse files
committed
Sync admin files from FreemKit with RTL support and public properties
- Update class-admin-banner.php with RTL stylesheet support and public properties/methods - Update class-settings-form.php with color-field class and repeater markup - Update class-settings-wizard-api.php with admin_enqueue_scripts hook and wp_add_inline_style - Copy settings-admin-scripts.js and .min.js files - Adjust namespaces to WebberZone\Knowledge_Base
1 parent 8eba84c commit a0fdd02

5 files changed

Lines changed: 124 additions & 135 deletions

File tree

includes/admin/class-admin-banner.php

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,42 +29,42 @@ class Admin_Banner {
2929
*
3030
* @var array<string, mixed>
3131
*/
32-
private array $config = array();
32+
public array $config = array();
3333

3434
/**
3535
* Derived class names keyed by component.
3636
*
3737
* @var array<string, array<int, string>>
3838
*/
39-
private array $class_names = array();
39+
public array $class_names = array();
4040

4141
/**
4242
* Localized strings.
4343
*
4444
* @var array<string, string>
4545
*/
46-
private array $strings = array();
46+
public array $strings = array();
4747

4848
/**
4949
* Style configuration.
5050
*
5151
* @var array<string, mixed>
5252
*/
53-
private array $style = array();
53+
public array $style = array();
5454

5555
/**
5656
* Base class prefix shared by all banners.
5757
*
5858
* @var string
5959
*/
60-
private string $base_prefix = 'wz-admin-banner';
60+
public string $base_prefix = 'wz-admin-banner';
6161

6262
/**
6363
* Unique class prefix derived from the provided prefix.
6464
*
6565
* @var string
6666
*/
67-
private string $unique_prefix = 'admin-banner';
67+
public string $unique_prefix = 'admin-banner';
6868

6969
/**
7070
* Constructor.
@@ -108,7 +108,7 @@ public function __construct( array $config ) {
108108
/**
109109
* Register hooks.
110110
*/
111-
private function hooks(): void {
111+
public function hooks(): void {
112112
Hook_Registry::add_action( 'admin_enqueue_scripts', array( $this, 'maybe_enqueue_styles' ) );
113113
Hook_Registry::add_action( 'in_admin_header', array( $this, 'render' ) );
114114
}
@@ -197,7 +197,7 @@ public function render(): void {
197197
/**
198198
* Enqueue the banner stylesheet.
199199
*/
200-
private function enqueue_style(): void {
200+
public function enqueue_style(): void {
201201
wp_register_style(
202202
$this->style['handle'],
203203
$this->style['url'],
@@ -213,7 +213,7 @@ private function enqueue_style(): void {
213213
* @param \WP_Screen $screen Current admin screen.
214214
* @param string $page_slug Current request page slug.
215215
*/
216-
private function should_render_on_screen( \WP_Screen $screen, string $page_slug ): bool {
216+
public function should_render_on_screen( \WP_Screen $screen, string $page_slug ): bool {
217217
$screen_base = (string) $screen->base;
218218
if ( '' !== $screen_base && in_array( $screen_base, (array) $this->config['exclude_screen_bases'], true ) ) {
219219
return false;
@@ -237,7 +237,7 @@ private function should_render_on_screen( \WP_Screen $screen, string $page_slug
237237
* @param \WP_Screen $screen Current admin screen.
238238
* @param string $page_slug Current request page slug.
239239
*/
240-
private function resolve_current_section( \WP_Screen $screen, string $page_slug ): string {
240+
public function resolve_current_section( \WP_Screen $screen, string $page_slug ): string {
241241
$screen_id = (string) $screen->id;
242242

243243
foreach ( $this->config['sections'] as $section_key => $section ) {
@@ -260,7 +260,7 @@ private function resolve_current_section( \WP_Screen $screen, string $page_slug
260260
*
261261
* @param array $strings Raw strings array.
262262
*/
263-
private function prepare_strings( array $strings ): array {
263+
public function prepare_strings( array $strings ): array {
264264
$defaults = array(
265265
'region_label' => '',
266266
'nav_label' => '',
@@ -277,7 +277,7 @@ private function prepare_strings( array $strings ): array {
277277
*
278278
* @param string $prefix Base prefix.
279279
*/
280-
private function resolve_wrapper_prefix( string $prefix ): string {
280+
public function resolve_wrapper_prefix( string $prefix ): string {
281281
$prefix = sanitize_key( $prefix );
282282

283283
if ( '' === $prefix ) {
@@ -292,7 +292,7 @@ private function resolve_wrapper_prefix( string $prefix ): string {
292292
*
293293
* @param array $style Style configuration.
294294
*/
295-
private function prepare_style_config( array $style ): array {
295+
public function prepare_style_config( array $style ): array {
296296
$defaults = array(
297297
'handle' => $this->sanitize_handle( "{$this->unique_prefix}-styles" ),
298298
'deps' => array(),
@@ -306,7 +306,8 @@ private function prepare_style_config( array $style ): array {
306306
if ( empty( $style_config['url'] ) ) {
307307
$assets_base = trailingslashit( plugin_dir_url( __FILE__ ) ) . 'css/';
308308
$min_suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
309-
$style_config['url'] = $assets_base . $style_config['filename'] . $min_suffix . '.css';
309+
$rtl_suffix = is_rtl() ? '-rtl' : '';
310+
$style_config['url'] = $assets_base . $style_config['filename'] . $rtl_suffix . $min_suffix . '.css';
310311
}
311312

312313
return $style_config;
@@ -319,7 +320,7 @@ private function prepare_style_config( array $style ): array {
319320
*
320321
* @return array
321322
*/
322-
private function sanitize_sections( array $sections ): array {
323+
public function sanitize_sections( array $sections ): array {
323324
$sanitized = array();
324325

325326
foreach ( $sections as $key => $section ) {
@@ -348,7 +349,7 @@ private function sanitize_sections( array $sections ): array {
348349
*
349350
* @return array<string, array<int, string>>
350351
*/
351-
private function derive_class_names(): array {
352+
public function derive_class_names(): array {
352353
$build = function ( string $suffix = '' ): array {
353354
$classes = array( $this->base_prefix . $suffix );
354355

@@ -381,7 +382,7 @@ private function derive_class_names(): array {
381382
*
382383
* @return array
383384
*/
384-
private function collect_targets_from_sections( string $target_key ): array {
385+
public function collect_targets_from_sections( string $target_key ): array {
385386
$values = array();
386387

387388
foreach ( $this->config['sections'] as $section ) {
@@ -401,7 +402,7 @@ private function collect_targets_from_sections( string $target_key ): array {
401402
*
402403
* @param array $section Section configuration.
403404
*/
404-
private function get_section_link_classes( array $section ): array {
405+
public function get_section_link_classes( array $section ): array {
405406
$classes = $this->class_names['link'] ?? array();
406407
$type = isset( $section['type'] ) ? sanitize_key( $section['type'] ) : 'secondary';
407408
$type = '' !== $type ? $type : 'secondary';
@@ -422,7 +423,7 @@ private function get_section_link_classes( array $section ): array {
422423
* @param array $classes Class list.
423424
* @return string Class attribute string.
424425
*/
425-
private function implode_classes( array $classes ): string {
426+
public function implode_classes( array $classes ): string {
426427
return implode( ' ', array_unique( array_filter( $classes ) ) );
427428
}
428429

@@ -432,7 +433,7 @@ private function implode_classes( array $classes ): string {
432433
* @param string $key Classes array key.
433434
* @return string Class attribute string.
434435
*/
435-
private function class_attr( string $key ): string {
436+
public function class_attr( string $key ): string {
436437
return $this->implode_classes( $this->class_names[ $key ] ?? array() );
437438
}
438439

@@ -441,19 +442,15 @@ private function class_attr( string $key ): string {
441442
*
442443
* @param string $handle Raw handle.
443444
*/
444-
private function sanitize_handle( string $handle ): string {
445+
public function sanitize_handle( string $handle ): string {
445446
return sanitize_title_with_dashes( $handle );
446447
}
447448

448449
/**
449450
* Get the current page slug from the request.
450451
*/
451-
private function get_request_page_slug(): string {
452-
$page_param_raw = filter_input( INPUT_GET, 'page', FILTER_UNSAFE_RAW );
453-
454-
if ( is_string( $page_param_raw ) && '' !== $page_param_raw ) {
455-
$page_raw = sanitize_text_field( $page_param_raw );
456-
} elseif ( isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
452+
public function get_request_page_slug(): string {
453+
if ( isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
457454
$page_raw = sanitize_text_field( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
458455
} else {
459456
return '';

includes/admin/settings/class-settings-form.php

Lines changed: 5 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* @link https://webberzone.com
66
*
7-
* @package WebberZone\Better_External_Links
7+
* @package WebberZone\Knowledge_Base
88
*/
99

1010
namespace WebberZone\Knowledge_Base\Admin\Settings;
@@ -238,6 +238,8 @@ public function callback_csv( $args ) {
238238
* @param array $args Array of arguments.
239239
*/
240240
public function callback_color( $args ) {
241+
// Add color-field class for wpColorPicker initialization.
242+
$args['field_class'] = isset( $args['field_class'] ) ? $args['field_class'] . ' color-field' : 'color-field';
241243
$this->callback_text( $args );
242244
}
243245

@@ -842,8 +844,8 @@ public function callback_repeater( $args ) {
842844

843845
ob_start();
844846
?>
845-
<div class="<?php echo esc_attr( $class ); ?> wz-repeater-wrapper" id="<?php echo esc_attr( $args['id'] ); ?>-wrapper" <?php echo $attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
846-
<div class="<?php echo esc_attr( $args['id'] ); ?>-items">
847+
<div class="<?php echo esc_attr( $class ); ?> wz-repeater-wrapper" id="<?php echo esc_attr( $args['id'] ); ?>-wrapper" data-index="<?php echo esc_attr( (string) count( $value ) ); ?>" data-live-update-field="<?php echo esc_attr( ! empty( $args['live_update_field'] ) ? $args['live_update_field'] : 'name' ); ?>" data-fallback-title="<?php echo esc_attr( ! empty( $args['new_item_text'] ) ? $args['new_item_text'] : $this->translation_strings['repeater_new_item'] ); ?>" <?php echo $attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
848+
<div class="<?php echo esc_attr( $args['id'] ); ?>-items wz-repeater-items">
847849
<?php
848850
if ( ! empty( $value ) ) {
849851
foreach ( array_values( $value ) as $index => $item ) {
@@ -860,101 +862,6 @@ public function callback_repeater( $args ) {
860862
<?php $this->render_repeater_item( $args, '{{INDEX}}' ); ?>
861863
</script>
862864
</div>
863-
864-
<script>
865-
jQuery(document).ready(function($) {
866-
var wrapper = $('#<?php echo esc_js( $args['id'] ); ?>-wrapper');
867-
var itemsContainer = wrapper.find('.<?php echo esc_js( $args['id'] ); ?>-items');
868-
var index = <?php echo esc_js( (string) count( $value ) ); ?>;
869-
var liveUpdateField = '<?php echo esc_js( ! empty( $args['live_update_field'] ) ? $args['live_update_field'] : 'name' ); ?>';
870-
var fallbackTitle = '<?php echo esc_js( ! empty( $args['new_item_text'] ) ? $args['new_item_text'] : $this->translation_strings['repeater_new_item'] ); ?>';
871-
872-
// Add Item
873-
wrapper.on('click', '.add-item', function() {
874-
var template = wrapper.find('.repeater-template').html();
875-
var uniqueId = 'row_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
876-
template = template.replace(/{{INDEX}}/g, index);
877-
template = template.replace(/{{ROW_ID}}/g, uniqueId);
878-
itemsContainer.append(template);
879-
index++;
880-
var newItem = itemsContainer.find('.wz-repeater-item:last');
881-
882-
// Ensure the toggle icon for the new item is set to the collapsed state (▲)
883-
itemsContainer.find('.repeater-item-header:last .toggle-icon').text('▲');
884-
885-
// Ensure that .repeater-item-content is set to display:block
886-
itemsContainer.find('.repeater-item-content:last').css('display', 'block');
887-
888-
if (window.WZInitTomSelect) {
889-
window.WZInitTomSelect(newItem.get(0));
890-
}
891-
document.dispatchEvent(new CustomEvent('wz:repeater-item-added', { detail: { container: newItem.get(0) } }));
892-
});
893-
894-
// Remove Item
895-
wrapper.on('click', '.remove-item', function() {
896-
$(this).closest('.wz-repeater-item').remove();
897-
reindexItems();
898-
});
899-
900-
// Move Up
901-
wrapper.on('click', '.move-up', function() {
902-
var item = $(this).closest('.wz-repeater-item');
903-
var prev = item.prev();
904-
if (prev.length) {
905-
item.insertBefore(prev);
906-
reindexItems();
907-
}
908-
});
909-
910-
// Move Down
911-
wrapper.on('click', '.move-down', function() {
912-
var item = $(this).closest('.wz-repeater-item');
913-
var next = item.next();
914-
if (next.length) {
915-
item.insertAfter(next);
916-
reindexItems();
917-
}
918-
});
919-
920-
// Toggle Accordion
921-
wrapper.on('click', '.repeater-item-header', function() {
922-
var $this = $(this);
923-
var $toggleIcon = $this.find('.toggle-icon');
924-
var $content = $this.next('.repeater-item-content');
925-
926-
// Check if content is currently visible or hidden, and toggle accordingly
927-
if ($content.is(':visible')) {
928-
$content.slideUp();
929-
$toggleIcon.text('▼'); // Expanded state
930-
} else {
931-
$content.slideDown();
932-
$toggleIcon.text('▲'); // Collapsed state
933-
}
934-
});
935-
936-
// Reindex Items After Adding, Removing, or Moving
937-
function reindexItems() {
938-
itemsContainer.find('.wz-repeater-item').each(function(idx) {
939-
$(this).find(':input').each(function() {
940-
var name = $(this).attr('name');
941-
if (name) {
942-
name = name.replace(/\[\d+\](?=\[(?:fields|row_id)\])/, '[' + idx + ']');
943-
$(this).attr('name', name);
944-
}
945-
});
946-
});
947-
}
948-
949-
// Live update repeater title when the specified field changes.
950-
wrapper.on('input', '.wz-repeater-item :input[name$="[fields][' + liveUpdateField + ']"]', function() {
951-
var $this = $(this);
952-
var newName = $this.val();
953-
var $repeaterTitle = $this.closest('.wz-repeater-item').find('.repeater-title');
954-
$repeaterTitle.text(newName || fallbackTitle);
955-
});
956-
});
957-
</script>
958865
<?php
959866
$html = ob_get_clean();
960867
$html .= $this->get_field_description( $args );

includes/admin/settings/class-settings-wizard-api.php

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* A reusable API class for creating multi-step settings wizards.
66
* This class provides the framework for creating guided setup experiences.
77
*
8-
* @package WebberZone\Better_External_Links
8+
* @package WebberZone\Knowledge_Base
99
*/
1010

1111
namespace WebberZone\Knowledge_Base\Admin\Settings;
@@ -239,7 +239,7 @@ public function admin_menu() {
239239
( ( $this->args['hide_when_completed'] ?? true ) && $this->is_wizard_completed() );
240240

241241
if ( $hide_submenu ) {
242-
add_action( 'admin_head', array( $this, 'hide_completed_wizard_submenu' ) );
242+
add_action( 'admin_enqueue_scripts', array( $this, 'hide_completed_wizard_submenu' ) );
243243
}
244244
}
245245

@@ -250,14 +250,11 @@ public function admin_menu() {
250250
*/
251251
public function hide_completed_wizard_submenu() {
252252
$slug = sanitize_key( $this->page_slug );
253-
?>
254-
<style>
255-
#adminmenu a[href$="page=<?php echo esc_attr( $slug ); ?>"],
256-
#adminmenu a[href*="page=<?php echo esc_attr( $slug ); ?>&"] {
253+
$css = '#adminmenu a[href$="page=' . $slug . '"],
254+
#adminmenu a[href*="page=' . $slug . '&"] {
257255
display: none;
258-
}
259-
</style>
260-
<?php
256+
}';
257+
wp_add_inline_style( 'wp-admin', $css );
261258
}
262259

263260
/**

0 commit comments

Comments
 (0)