1222 lines
36 KiB
PHP
1222 lines
36 KiB
PHP
<?php
|
|
namespace WPO\IPS\Settings;
|
|
|
|
use WPO\IPS\Documents\SequentialNumberStore;
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit; // Exit if accessed directly
|
|
}
|
|
|
|
if ( ! class_exists( '\\WPO\\IPS\\Settings\\SettingsCallbacks' ) ) :
|
|
|
|
class SettingsCallbacks {
|
|
|
|
protected static ?self $_instance = null;
|
|
|
|
/**
|
|
* Instance of this class.
|
|
*/
|
|
public static function instance(): ?self {
|
|
if ( is_null( self::$_instance ) ) {
|
|
self::$_instance = new self();
|
|
}
|
|
return self::$_instance;
|
|
}
|
|
|
|
/**
|
|
* Section null callback.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function section(): void {}
|
|
|
|
/**
|
|
* Debug section callback.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function debug_section(): void {
|
|
echo wp_kses_post( '<strong>' . __( 'Warning!', 'woocommerce-pdf-invoices-packing-slips' ) . '</strong>' . ' ' .
|
|
__( 'The settings below are meant for debugging/development only. Do not use them on a live website!' , 'woocommerce-pdf-invoices-packing-slips' ) );
|
|
}
|
|
|
|
/**
|
|
* Custom fields section callback.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function custom_fields_section(): void {
|
|
echo wp_kses_post( sprintf(
|
|
/* translators: %s Modern (Premium) */
|
|
__( 'These are used for the (optional) footer columns in the %s template, but can also be used for other elements in your custom template.' , 'woocommerce-pdf-invoices-packing-slips' ),
|
|
'<em>Modern (Premium)</em>'
|
|
) );
|
|
}
|
|
|
|
/**
|
|
* HTML section callback.
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function html_section( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
// output HTML
|
|
echo wp_kses_post( $html );
|
|
}
|
|
|
|
/**
|
|
* Checkbox callback.
|
|
*
|
|
* args:
|
|
* option_name - name of the main option
|
|
* id - key of the setting
|
|
* value - value if not 1 (optional)
|
|
* default - default setting (optional)
|
|
* description - description (optional)
|
|
* custom_attributes - custom attributes (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function checkbox( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
// output checkbox
|
|
printf(
|
|
'<input type="checkbox" id="%1$s" name="%2$s" value="%3$s" %4$s %5$s %6$s/>',
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
esc_attr( $value ),
|
|
checked( $value, $current, false ),
|
|
! empty( $disabled ) ? 'disabled="disabled"' : '',
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
|
|
if ( ! empty( $title ) ) {
|
|
printf(
|
|
'<label for="%1$s">%2$s</label>',
|
|
esc_attr( $id ),
|
|
esc_html( $title )
|
|
);
|
|
}
|
|
|
|
// print store empty input if true
|
|
if ( $store_unchecked ) {
|
|
printf(
|
|
'<input type="hidden" name="%s[wpo_wcpdf_setting_store_empty][]" value="%s"/>',
|
|
esc_attr( $option_name ),
|
|
esc_attr( $id )
|
|
);
|
|
}
|
|
|
|
// output description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Text input callback.
|
|
*
|
|
* args:
|
|
* title - secondary title of the input (optional)
|
|
* option_name - name of the main option
|
|
* id - key of the setting
|
|
* size - size of the text input (em)
|
|
* default - default setting (optional)
|
|
* description - description (optional)
|
|
* type - type (optional)
|
|
* custom_attributes - custom attributes (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function text_input( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
if ( empty( $type ) ) {
|
|
$type = 'text';
|
|
}
|
|
|
|
if ( ! empty( $action_button ) ) {
|
|
echo '<div class="wpo-wcpdf-input-wrapper input ', esc_attr( $id ), '">';
|
|
}
|
|
|
|
if ( ! empty( $title ) ) {
|
|
printf(
|
|
'<label for="%1$s">%2$s</label>',
|
|
esc_attr( $id ),
|
|
esc_html( $title )
|
|
);
|
|
}
|
|
|
|
$size = ! empty( $size ) ? sprintf( 'size="%s"', esc_attr( $size ) ) : '';
|
|
printf(
|
|
'<input type="%1$s" id="%2$s" name="%3$s" value="%4$s" %5$s placeholder="%6$s" %7$s %8$s/>',
|
|
esc_attr( $type ),
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
esc_attr( $current ),
|
|
esc_attr( $size ),
|
|
esc_attr( $placeholder ),
|
|
! empty( $disabled ) ? 'disabled="disabled"' : '',
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
|
|
// Output action button.
|
|
if ( ! empty( $action_button ) ) {
|
|
$this->output_action_button( $action_button, $id );
|
|
echo '</div>';
|
|
}
|
|
|
|
// output description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* URL input callback.
|
|
*
|
|
* args:
|
|
* option_name - name of the main option
|
|
* id - key of the setting
|
|
* size - size of the text input (em)
|
|
* default - default setting (optional)
|
|
* description - description (optional)
|
|
* type - type (optional)
|
|
* custom_attributes - custom attributes (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function url_input( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
if ( empty( $type ) ) {
|
|
$type = 'url';
|
|
}
|
|
|
|
$size = ! empty( $size ) ? sprintf( 'size="%s"', esc_attr( $size ) ) : '';
|
|
|
|
printf(
|
|
'<input type="%1$s" id="%2$s" name="%3$s" value="%4$s" %5$s placeholder="%6$s" %7$s %8$s/>',
|
|
esc_attr( $type ),
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
esc_attr( $current ),
|
|
esc_attr( $size ),
|
|
esc_attr( $placeholder ),
|
|
! empty( $disabled ) ? 'disabled="disabled"' : '',
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
|
|
// output description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Email input callback.
|
|
*
|
|
* args:
|
|
* option_name - name of the main option
|
|
* id - key of the setting
|
|
* size - size of the text input (em)
|
|
* default - default setting (optional)
|
|
* description - description (optional)
|
|
* type - type (optional)
|
|
* custom_attributes - custom attributes (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function email_input( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
if ( empty( $type ) ) {
|
|
$type = 'email';
|
|
}
|
|
|
|
$size = ! empty( $size ) ? sprintf( 'size="%s"', esc_attr( $size ) ) : '';
|
|
|
|
printf(
|
|
'<input type="%1$s" id="%2$s" name="%3$s" value="%4$s" %5$s placeholder="%6$s" %7$s %8$s/>',
|
|
esc_attr( $type ),
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
esc_attr( sanitize_email( $current ) ),
|
|
esc_attr( $size ),
|
|
esc_attr( $placeholder ),
|
|
! empty( $disabled ) ? 'disabled="disabled"' : '',
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
|
|
// output description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Combined checkbox & text input callback.
|
|
*
|
|
* args:
|
|
* option_name - name of the main option
|
|
* id - key of the setting
|
|
* value - value if not 1 (optional)
|
|
* default - default setting (optional)
|
|
* description - description (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function checkbox_text_input( array $args ): void {
|
|
$args = $this->normalize_settings_args( $args );
|
|
extract( $args );
|
|
unset( $args['description'] ); // already extracted, should only be used here
|
|
|
|
// get checkbox
|
|
ob_start();
|
|
$this->checkbox( $args );
|
|
$checkbox = ob_get_clean();
|
|
|
|
// get text input for insertion in wrapper
|
|
$input_args = array(
|
|
'id' => $args['text_input_id'],
|
|
'default' => isset( $args['text_input_default'] ) ? (string) $args['text_input_default'] : null,
|
|
'size' => isset( $args['text_input_size'] ) ? $args['text_input_size'] : null,
|
|
) + $args;
|
|
unset( $input_args['current'] );
|
|
unset( $input_args['setting_name'] );
|
|
|
|
ob_start();
|
|
$this->text_input( $input_args );
|
|
$text_input = ob_get_clean();
|
|
|
|
$allowed_html = array(
|
|
'input' => array(
|
|
'type' => true,
|
|
'name' => true,
|
|
'id' => true,
|
|
'value' => true,
|
|
'class' => true,
|
|
'placeholder' => true,
|
|
'disabled' => true,
|
|
'checked' => true,
|
|
'size' => true,
|
|
),
|
|
);
|
|
|
|
if ( ! empty( $text_input_wrap ) ) {
|
|
$text_input = sprintf( $text_input_wrap, $text_input );
|
|
}
|
|
|
|
echo wp_kses( "{$checkbox} {$text_input}", $allowed_html );
|
|
|
|
// output description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Single text option (not part of any settings array)
|
|
*
|
|
* args:
|
|
* option_name - name of the main option
|
|
* id - key of the setting
|
|
* default - default setting (optional)
|
|
* description - description (optional)
|
|
* custom_attributes - custom attributes (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function singular_text_element( array $args ): void {
|
|
$args = $this->normalize_settings_args( $args );
|
|
extract( $args );
|
|
|
|
$size = $size ?? '25';
|
|
$class = isset( $translatable ) && true === $translatable ? 'translatable' : '';
|
|
$option = get_option( $option_name ?? '' );
|
|
|
|
if ( ! empty( $option ) ) {
|
|
$current = $option;
|
|
} else {
|
|
$current = $default ?? '';
|
|
}
|
|
|
|
printf(
|
|
'<input type="text" id="%1$s" name="%2$s" value="%3$s" size="%4$s" class="%5$s" %6$s/>',
|
|
esc_attr( $id ),
|
|
esc_attr( $option_name ),
|
|
esc_attr( $current ),
|
|
esc_attr( $size ),
|
|
esc_attr( $class ),
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
|
|
// output description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Textarea callback.
|
|
*
|
|
* args:
|
|
* title - secondary title of the input (optional)
|
|
* option_name - name of the main option
|
|
* id - key of the setting
|
|
* width - width of the text input (em)
|
|
* height - height of the text input (lines)
|
|
* default - default setting (optional)
|
|
* description - description (optional)
|
|
* custom_attributes - custom attributes (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function textarea( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
printf(
|
|
'<textarea id="%1$s" name="%2$s" cols="%4$s" rows="%5$s" placeholder="%6$s" %7$s/>%3$s</textarea>',
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
esc_textarea( $current ),
|
|
esc_attr( $width ),
|
|
esc_attr( $height ),
|
|
esc_attr( $placeholder ),
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
|
|
// output description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Select element callback.
|
|
*
|
|
* args:
|
|
* title - secondary title of the input (optional)
|
|
* setting_name - name of the main setting
|
|
* id - key of the setting
|
|
* multiple - whether the select is multiple (optional)
|
|
* options - array of options for the select
|
|
* current - current value(s) of the setting
|
|
* disabled - whether the select is disabled (optional)
|
|
* custom_attributes - custom attributes (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function select( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
if ( ! empty( $action_button ) ) {
|
|
echo '<div class="wpo-wcpdf-input-wrapper select ', esc_attr( $id ), '">';
|
|
}
|
|
|
|
if ( ! empty( $title ) ) {
|
|
printf(
|
|
'<label for="%1$s">%2$s</label>',
|
|
esc_attr( $id ),
|
|
esc_html( $title )
|
|
);
|
|
}
|
|
|
|
if ( ! empty( $enhanced_select ) ) {
|
|
if ( ! empty( $multiple ) ) {
|
|
$setting_name = "{$setting_name}[]";
|
|
$multiple = 'multiple=multiple';
|
|
} else {
|
|
$multiple = '';
|
|
}
|
|
|
|
$placeholder = ! empty( $placeholder ) ? esc_attr( $placeholder ) : '';
|
|
$title = ! empty( $title ) ? esc_attr( $title ) : '';
|
|
$class = 'wc-enhanced-select wpo-wcpdf-enhanced-select';
|
|
$css = 'width:400px';
|
|
|
|
printf(
|
|
'<select id="%1$s" name="%2$s" data-placeholder="%3$s" title="%4$s" class="%5$s" style="%6$s" %7$s %8$s %9$s>',
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
esc_attr( $placeholder ),
|
|
esc_attr( $title ),
|
|
esc_attr( $class ),
|
|
esc_attr( $css ),
|
|
esc_attr( $multiple ),
|
|
! empty( $disabled ) ? 'disabled="disabled"' : '',
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
} else {
|
|
printf(
|
|
'<select id="%1$s" name="%2$s" %3$s %4$s>',
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
! empty( $disabled ) ? 'disabled="disabled"' : '',
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
}
|
|
|
|
if ( ! empty( $options_callback ) ) {
|
|
$options = isset( $options_callback_args ) ? call_user_func_array( $options_callback, $options_callback_args ) : call_user_func( $options_callback );
|
|
}
|
|
|
|
foreach ( $options as $key => $label ) {
|
|
// Normalize both sides to string
|
|
$key_str = (string) $key;
|
|
|
|
// Determine if selected (works for both single and multiple)
|
|
if ( ! empty( $multiple ) && is_array( $current ) ) {
|
|
$is_selected = in_array( $key_str, array_map( 'strval', $current ), true );
|
|
$selected_attr = $is_selected ? ' selected="selected"' : '';
|
|
} else {
|
|
$selected_attr = selected( (string) $current, $key_str, false );
|
|
}
|
|
|
|
printf(
|
|
'<option value="%s"%s>%s</option>',
|
|
esc_attr( $key_str ),
|
|
esc_attr( $selected_attr ),
|
|
esc_html( $label )
|
|
);
|
|
}
|
|
|
|
echo '</select>';
|
|
|
|
// Output action button.
|
|
if ( ! empty( $action_button ) ) {
|
|
$this->output_action_button( $action_button, $id );
|
|
echo '</div>';
|
|
}
|
|
|
|
// output description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
|
|
if ( ! empty( $custom ) ) {
|
|
printf(
|
|
'<div class="%1$s_custom custom">',
|
|
esc_attr( $id )
|
|
);
|
|
|
|
if ( is_callable( array( $this, $custom['type'] ) ) ) {
|
|
$this->{$custom['type']}( $custom['args'] );
|
|
}
|
|
|
|
echo '</div>';
|
|
|
|
$custom_option = ! empty( $custom['custom_option'] ) ? $custom['custom_option'] : 'custom';
|
|
?>
|
|
<script>
|
|
jQuery( function( $ ) {
|
|
function check_<?php echo esc_attr( $id ); ?>_custom() {
|
|
var custom = $( '#<?php echo esc_attr( $id ); ?>' ).val();
|
|
|
|
if ( custom == '<?php echo esc_attr( $custom_option ); ?>' ) {
|
|
$( '.<?php echo esc_attr( $id ); ?>_custom' ).show();
|
|
} else {
|
|
$( '.<?php echo esc_attr( $id ); ?>_custom' ).hide();
|
|
}
|
|
}
|
|
|
|
check_<?php echo esc_attr( $id ); ?>_custom();
|
|
|
|
$( '#<?php echo esc_attr( $id ); ?>' ).on( 'change', function() {
|
|
check_<?php echo esc_attr( $id ); ?>_custom();
|
|
} );
|
|
} );
|
|
</script>
|
|
<?php
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Radio button callback.
|
|
*
|
|
* args:
|
|
* title - secondary title of the input (optional)
|
|
* setting_name - name of the main setting
|
|
* id - key of the setting
|
|
* options - array of options for the radio buttons
|
|
* current - current value of the setting
|
|
* disabled - whether the radio buttons are disabled (optional)
|
|
* custom_attributes - custom attributes (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function radio_button( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
if ( ! empty( $options_callback ) ) {
|
|
$options = isset( $options_callback_args ) ? call_user_func_array( $options_callback, $options_callback_args ) : call_user_func( $options_callback );
|
|
}
|
|
|
|
foreach ( $options as $key => $label ) {
|
|
printf(
|
|
'<input type="radio" class="radio" id="%1$s[%3$s]" name="%2$s" value="%3$s"%4$s %5$s />',
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
esc_attr( $key ),
|
|
checked( $current, $key, false ),
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
|
|
printf(
|
|
'<label for="%1$s[%2$s]"> %3$s</label><br>',
|
|
esc_attr( $id ),
|
|
esc_attr( $key ),
|
|
esc_html( $label )
|
|
);
|
|
}
|
|
|
|
|
|
// output description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Multiple text element callback.
|
|
*
|
|
* args:
|
|
* id - key of the setting
|
|
* setting_name - name of the main setting
|
|
* fields_callback - callback function to get the fields
|
|
* fields_callback_args - arguments for the fields callback (optional)
|
|
* current - current values of the setting
|
|
* header - header for the table (optional)
|
|
* description - description for the table (optional)
|
|
* custom_attributes - custom attributes for the input fields (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function multiple_text_input( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
if ( ! empty( $fields_callback ) ) {
|
|
$fields = isset( $fields_callback_args ) ? call_user_func_array( $fields_callback, $fields_callback_args ) : call_user_func( $fields_callback );
|
|
}
|
|
|
|
printf( '<table class="%s multiple-text-input">', esc_attr( $id ) );
|
|
|
|
if ( ! empty( $header ) ) {
|
|
echo wp_kses_post( "<tr><td><strong>{$header}</strong>:</td></tr>" );
|
|
}
|
|
|
|
foreach ( $fields as $name => $field ) {
|
|
echo '<tr>';
|
|
|
|
$size = $field['size'];
|
|
$placeholder = isset( $field['placeholder'] ) ? $field['placeholder'] : '';
|
|
$field_description = ! empty( $field['description'] ) ? $field['description']: '';
|
|
|
|
// output field label
|
|
if ( isset( $field['label'] ) ) {
|
|
printf(
|
|
'<td class="label"><label for="%1$s_%2$s">%3$s:</label></td>',
|
|
esc_attr( $id ),
|
|
esc_attr( $name ),
|
|
esc_html( $field['label'] )
|
|
);
|
|
} else {
|
|
echo '<td></td>';
|
|
}
|
|
|
|
$field_current = isset( $current[ $name ] ) ? $current[ $name ] : '';
|
|
$type = isset( $field['type'] ) ? $field['type'] : 'text';
|
|
|
|
// output field
|
|
printf(
|
|
'<td><input type="%1$s" id="%2$s_%4$s" name="%3$s[%4$s]" value="%5$s" size="%6$s" placeholder="%7$s" %8$s/></td>',
|
|
esc_attr( $type ),
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
esc_attr( $name ),
|
|
esc_attr( $field_current ),
|
|
esc_attr( $size ),
|
|
esc_attr( $placeholder ),
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
|
|
// field description.
|
|
if ( ! empty( $field_description ) ) {
|
|
echo '<td>' . wp_kses_post( wc_help_tip( $field_description, true ) ) . '</td>';
|
|
} else {
|
|
echo '<td></td>';
|
|
}
|
|
echo '</tr>';
|
|
}
|
|
echo "</table>";
|
|
|
|
// group description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Multiple text element callback.
|
|
*
|
|
* args:
|
|
* id - key of the setting
|
|
* setting_name - name of the main setting
|
|
* fields_callback - callback function to get the fields
|
|
* fields_callback_args - arguments for the fields callback (optional)
|
|
* current - current values of the setting
|
|
* header - header for the table (optional)
|
|
* description - description for the table (optional)
|
|
* custom_attributes - custom attributes for the input fields (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function multiple_checkboxes( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
if ( ! empty( $fields_callback ) ) {
|
|
$fields = isset( $fields_callback_args ) ? call_user_func_array( $fields_callback, $fields_callback_args ) : call_user_func( $fields_callback );
|
|
}
|
|
|
|
foreach ( $fields as $name => $label ) {
|
|
$field_current = isset( $current[ $name ] ) ? $current[ $name ] : '';
|
|
|
|
// output checkbox
|
|
printf(
|
|
'<input type="checkbox" id="%1$s_%3$s" name="%2$s[%3$s]" value="%4$s"%5$s %6$s/>',
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
esc_attr( $name ),
|
|
esc_attr( $value ),
|
|
checked( $value, $field_current, false ),
|
|
wp_kses_post( $custom_attributes )
|
|
);
|
|
|
|
// output field label
|
|
printf(
|
|
'<label for="%1$s_%2$s">%3$s</label><br>',
|
|
esc_attr( $id ),
|
|
esc_attr( $name ),
|
|
esc_html( $label )
|
|
);
|
|
|
|
}
|
|
|
|
// output description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Media upload callback.
|
|
*
|
|
* args:
|
|
* id - key of the setting
|
|
* setting_name - name of the main setting
|
|
* current - current value of the setting
|
|
* uploader_title - title of the media uploader
|
|
* uploader_button_text - text of the media uploader button
|
|
* remove_button_text - text of the remove button
|
|
* description - description for the media upload field
|
|
* custom_attributes - custom attributes for the input field
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function media_upload( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
$setting_name = $this->append_language( $setting_name, $args );
|
|
$attachment = ! empty( $current ) ? wp_get_attachment_image_src( $current, 'full', false ) : '';
|
|
|
|
if ( ! empty( $attachment ) ) {
|
|
$general_settings = get_option( 'wpo_wcpdf_settings_general', array() );
|
|
$attachment_src = $attachment[0];
|
|
$attachment_width = $attachment[1];
|
|
$attachment_height = $attachment[2];
|
|
|
|
// check if we have the height saved on settings
|
|
$header_logo_height = ! empty( $general_settings['header_logo_height'] ) ? $general_settings['header_logo_height'] : '3cm';
|
|
|
|
if ( false !== stripos( $header_logo_height, 'mm' ) ) {
|
|
$in_height = floatval( $header_logo_height ) / 25.4;
|
|
} elseif ( false !== stripos( $header_logo_height, 'cm' ) ) {
|
|
$in_height = floatval( $header_logo_height ) / 2.54;
|
|
} elseif ( false !== stripos( $header_logo_height, 'in' ) ) {
|
|
$in_height = floatval( $header_logo_height );
|
|
} else {
|
|
// don't display resolution
|
|
}
|
|
|
|
/**
|
|
* .webp support can be disabled but still showing the image in settings.
|
|
* We should add a notice because this will display an error when redering the PDF using DOMPDF.
|
|
*/
|
|
if ( 'webp' === wp_check_filetype( $attachment_src )['ext'] && ! function_exists( 'imagecreatefromwebp' ) ) {
|
|
printf(
|
|
'<div class="notice notice-warning inline" style="display:inline-block; width:auto;"><p>%s</p></div>',
|
|
wp_kses_post(
|
|
/* translators: %1$s: file type, %2$s: System Configurations, %3$s: Advanced */
|
|
__( 'File type %1$s is not supported by your server! Please check your %2$s under the %3$s tab.', 'woocommerce-pdf-invoices-packing-slips' ),
|
|
'<strong>webp</strong>',
|
|
'<strong>' . __( 'System Configurations', 'woocommerce-pdf-invoices-packing-slips' ) . '</strong>',
|
|
'<strong>' . __( 'Advanced', 'woocommerce-pdf-invoices-packing-slips' ) . '</strong>'
|
|
)
|
|
);
|
|
}
|
|
|
|
printf(
|
|
'<img src="%1$s" style="display:block" id="img-%2$s" class="media-upload-preview"/>',
|
|
esc_attr( $attachment_src ),
|
|
esc_attr( $id )
|
|
);
|
|
|
|
if ( ! empty( $attachment_height ) && ! empty( $in_height ) ) {
|
|
$attachment_resolution = round( absint( $attachment_height ) / $in_height );
|
|
|
|
printf(
|
|
'<div class="attachment-resolution"><p class="description">%s: %sdpi</p></div>',
|
|
esc_html__( 'Image resolution', 'woocommerce-pdf-invoices-packing-slips' ),
|
|
esc_html( $attachment_resolution )
|
|
);
|
|
|
|
// warn the user if the image is unnecessarily large
|
|
if ( $attachment_resolution > 600 ) {
|
|
printf(
|
|
'<div class="attachment-resolution-warning notice notice-warning inline"><p>%s</p></div>',
|
|
esc_html__( 'The image resolution exceeds the recommended maximum of 600dpi. This will unnecessarily increase the size of your PDF files and could negatively affect performance.', 'woocommerce-pdf-invoices-packing-slips' )
|
|
);
|
|
}
|
|
}
|
|
|
|
printf(
|
|
'<span class="button wpo_remove_image_button" data-input_id="%1$s">%2$s</span> ',
|
|
esc_attr( $id ),
|
|
esc_attr( $remove_button_text )
|
|
);
|
|
}
|
|
|
|
printf(
|
|
'<input id="%1$s" name="%2$s" type="hidden" value="%3$s" data-settings_callback_args="%4$s" data-ajax_nonce="%5$s" class="media-upload-id"/>',
|
|
esc_attr( $id ),
|
|
esc_attr( $setting_name ),
|
|
esc_attr( $current ),
|
|
esc_attr( wp_json_encode( $args ) ),
|
|
esc_attr( wp_create_nonce( 'wpo_wcpdf_get_media_upload_setting_html' ) )
|
|
);
|
|
|
|
printf(
|
|
'<span class="button wpo_upload_image_button %4$s" data-uploader_title="%1$s" data-uploader_button_text="%2$s" data-remove_button_text="%3$s" data-input_id="%4$s">%2$s</span>',
|
|
esc_attr( $uploader_title ),
|
|
esc_attr( $uploader_button_text ),
|
|
esc_attr( $remove_button_text ),
|
|
esc_attr( $id )
|
|
);
|
|
|
|
// Displays option description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Next document number edit callback.
|
|
*
|
|
* args:
|
|
* store - name of the store (e.g. 'invoice', 'packing_slip')
|
|
* size - size of the input field (optional)
|
|
* description - description of the field (optional)
|
|
* store_callback - callback function to get the store (optional)
|
|
* store_callback_args - arguments for the store callback (optional)
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return void
|
|
*/
|
|
public function next_number_edit( array $args ): void {
|
|
extract( $args ); // $store, $size, $description
|
|
|
|
if ( ! empty( $store_callback ) ) {
|
|
$store = isset( $store_callback_args ) ? call_user_func_array( $store_callback, $store_callback_args ) : call_user_func( $store_callback );
|
|
}
|
|
|
|
// SequentialNumberStore object
|
|
if ( is_object( $store ) ) {
|
|
$next_number = $store->get_next();
|
|
$store = $store->store_name;
|
|
// legacy
|
|
} else {
|
|
$number_store_method = WPO_WCPDF()->settings->get_sequential_number_store_method();
|
|
$number_store = new SequentialNumberStore( $store, $number_store_method );
|
|
$next_number = $number_store->get_next();
|
|
}
|
|
|
|
$nonce = wp_create_nonce( "wpo_wcpdf_next_{$store}" );
|
|
|
|
printf(
|
|
'<input id="next_%1$s" class="next-number-input" type="number" size="%2$s" value="%3$s" disabled="disabled" data-store="%1$s" data-nonce="%4$s"/> <span class="edit-next-number dashicons dashicons-edit"></span><span class="save-next-number button secondary" style="display:none;">%5$s</span>',
|
|
esc_attr( $store ),
|
|
esc_attr( $size ),
|
|
esc_attr( $next_number ),
|
|
esc_attr( $nonce ),
|
|
esc_html__( 'Save', 'woocommerce-pdf-invoices-packing-slips' )
|
|
);
|
|
|
|
// Displays option description.
|
|
if ( ! empty( $description ) ) {
|
|
printf(
|
|
'<p class="description">%s</p>',
|
|
wp_kses_post( $description )
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wrapper function to create tabs for settings in different languages
|
|
*
|
|
* args:
|
|
* option_name - name of the main option
|
|
* id - key of the setting
|
|
* callback - callback function to render the fields
|
|
* fields - array of fields to render (optional, used for multiple_text_input)
|
|
* i18n_description - description for the internationalized fields
|
|
*
|
|
* @param array $args
|
|
*
|
|
* @return void
|
|
*/
|
|
public function i18n_wrap( array $args ): void {
|
|
extract( $this->normalize_settings_args( $args ) );
|
|
|
|
$languages = wpo_wcpdf_get_multilingual_languages();
|
|
|
|
if ( ! empty( $languages ) ) {
|
|
printf(
|
|
'<div id="%s-%s-translations" class="translations">',
|
|
esc_attr( $option_name ),
|
|
esc_attr( $id )
|
|
);
|
|
?>
|
|
<ul>
|
|
<?php
|
|
foreach ( $languages as $lang_code => $language_name ) {
|
|
$translation_id = "{$option_name}_{$id}_{$lang_code}";
|
|
|
|
printf(
|
|
'<li><a href="#%s">%s</a></li>',
|
|
esc_attr( $translation_id ),
|
|
esc_html( $language_name )
|
|
);
|
|
}
|
|
?>
|
|
</ul>
|
|
<?php
|
|
foreach ( $languages as $lang_code => $language_name ) {
|
|
$translation_id = "{$option_name}_{$id}_{$lang_code}";
|
|
|
|
printf(
|
|
'<div id="%s">',
|
|
esc_attr( $translation_id )
|
|
);
|
|
|
|
$args['lang'] = $lang_code;
|
|
|
|
// don't use internationalized placeholders since they're not translated,
|
|
// to avoid confusion (user thinking they're all the same)
|
|
if ( 'multiple_text_input' === $callback ) {
|
|
foreach ( $fields as $key => $field_args ) {
|
|
if ( ! empty( $field_args['placeholder'] ) && isset( $field_args['i18n_placeholder'] ) ) {
|
|
$args['fields'][$key]['placeholder'] = '';
|
|
}
|
|
}
|
|
} else {
|
|
if ( ! empty( $args['placeholder'] ) && isset( $args['i18n_placeholder'] ) ) {
|
|
$args['placeholder'] = '';
|
|
}
|
|
}
|
|
|
|
// specific description for internationalized fields (to compensate for missing placeholder)
|
|
if ( ! empty( $args['i18n_description'] ) ) {
|
|
$args['description'] = $args['i18n_description'];
|
|
}
|
|
|
|
if ( is_array( $callback ) ) {
|
|
call_user_func( $callback, $args );
|
|
} else {
|
|
call_user_func( array( $this, $callback ), $args );
|
|
}
|
|
|
|
echo '</div>';
|
|
}
|
|
?>
|
|
</div>
|
|
<?php
|
|
} else {
|
|
$args['lang'] = 'default';
|
|
|
|
if ( is_array( $callback ) ) {
|
|
call_user_func( $callback, $args );
|
|
} else {
|
|
call_user_func( array( $this, $callback ), $args );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Normalize settings arguments.
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return array
|
|
*/
|
|
public function normalize_settings_args( array $args ): array {
|
|
$args['value'] = isset( $args['value'] ) ? $args['value'] : 1;
|
|
$args['placeholder'] = isset( $args['placeholder'] ) ? $args['placeholder'] : '';
|
|
$args['store_unchecked'] = isset( $args['store_unchecked'] ) && $args['store_unchecked'] ? true : false;
|
|
|
|
// Get main settings array
|
|
$option = get_option( $args['option_name'] );
|
|
|
|
if ( empty( $args['setting_name'] ) ) {
|
|
$args['setting_name'] = "{$args['option_name']}[{$args['id']}]";
|
|
}
|
|
|
|
if ( ! isset( $args['lang'] ) && ! empty( $args['translatable'] ) ) {
|
|
$args['lang'] = 'default';
|
|
}
|
|
|
|
if ( ! array_key_exists( 'current', $args ) ) {
|
|
if ( isset( $args['lang'] ) ) {
|
|
// i18n settings name
|
|
$args['setting_name'] = "{$args['setting_name']}[{$args['lang']}]";
|
|
// Copy current option value if set
|
|
|
|
if ( 'default' === $args['lang'] && ! empty( $option[ $args['id'] ] ) && ! isset( $option[ $args['id'] ]['default'] ) ) {
|
|
// We're switching back from WPML to normal
|
|
// Try English first
|
|
if ( isset( $option[ $args['id'] ]['en'] ) ) {
|
|
$args['current'] = $option[ $args['id'] ]['en'];
|
|
|
|
} elseif ( is_array( $option[ $args['id'] ] ) ) {
|
|
// Fallback to the first language if English not found
|
|
$first = array_shift( $option[ $args['id'] ] );
|
|
if ( ! empty( $first ) ) {
|
|
$args['current'] = $first;
|
|
}
|
|
|
|
} elseif ( is_string( $option[ $args['id'] ] ) ) {
|
|
$args['current'] = $option[ $args['id'] ];
|
|
|
|
} else {
|
|
// Nothing, really?
|
|
$args['current'] = '';
|
|
}
|
|
|
|
} else {
|
|
if ( isset( $option[ $args['id'] ][ $args['lang'] ] ) ) {
|
|
$args['current'] = $option[ $args['id'] ][ $args['lang'] ];
|
|
|
|
} elseif ( isset( $option[ $args['id'] ]['default'] ) ) {
|
|
$args['current'] = $option[ $args['id'] ]['default'];
|
|
|
|
} elseif ( isset( $option[ $args['id'] ] ) && ! is_array( $option[ $args['id'] ] ) ) {
|
|
$args['current'] = $option[ $args['id'] ];
|
|
}
|
|
|
|
}
|
|
} else {
|
|
// Copy current option value if set
|
|
if ( isset( $option[ $args['id'] ] ) ) {
|
|
$args['current'] = $option[ $args['id'] ];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback to default or empty if no value in option
|
|
if ( ! isset( $args['current'] ) ) {
|
|
$args['current'] = isset( $args['default'] ) ? $args['default'] : '';
|
|
|
|
} elseif ( empty( $args['current'] ) && isset( $args['default_if_empty'] ) && true === $args['default_if_empty'] ) {
|
|
// Force fallback if empty 'current' and 'default_if_empty' equals to true
|
|
$args['current'] = isset( $args['default'] ) ? $args['default'] : '';
|
|
}
|
|
|
|
// Normalize custom attributes
|
|
$args['custom_attributes'] = $this->normalize_custom_attributes( $args );
|
|
|
|
return $args;
|
|
}
|
|
|
|
/**
|
|
* Normalize custom attributes.
|
|
*
|
|
* @param array $args Field arguments.
|
|
* @return string
|
|
*/
|
|
public function normalize_custom_attributes( array $args ): string {
|
|
$custom_attributes = array();
|
|
|
|
if ( ! empty( $args['custom_attributes'] ) && is_array( $args['custom_attributes'] ) ) {
|
|
foreach ( $args['custom_attributes'] as $attribute => $attribute_value ) {
|
|
$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
|
|
}
|
|
}
|
|
|
|
return ! empty( $custom_attributes ) ? implode( ' ', $custom_attributes ) : '';
|
|
}
|
|
|
|
/**
|
|
* Validate options.
|
|
*
|
|
* @param array|false|null $input Options to validate.
|
|
* @return array Validated options.
|
|
*/
|
|
public function validate( $input ): array {
|
|
$output = array(); // Create our array for storing the validated options.
|
|
|
|
if ( ! empty( $input ) && is_array( $input ) ) {
|
|
if ( ! empty( $input['wpo_wcpdf_setting_store_empty'] ) && is_array( $input['wpo_wcpdf_setting_store_empty'] ) ) {
|
|
foreach ( $input['wpo_wcpdf_setting_store_empty'] as $key ) {
|
|
if ( empty( $input[ $key ] ) ) {
|
|
$output[ $key ] = 0;
|
|
}
|
|
}
|
|
unset( $input['wpo_wcpdf_setting_store_empty'] );
|
|
}
|
|
|
|
// Loop through each of the incoming options.
|
|
foreach ( $input as $key => $value ) {
|
|
if ( is_array( $value ) ) {
|
|
foreach ( $value as $sub_key => $sub_value ) {
|
|
$output[ $key ][ $sub_key ] = $sub_value;
|
|
}
|
|
} else {
|
|
// Normalize identifiers like VAT / CoC on save.
|
|
if ( in_array( $key, array( 'vat_number', 'coc_number' ), true ) ) {
|
|
$value = $this->normalize_identifier( (string) $value );
|
|
}
|
|
|
|
$output[ $key ] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return the array processing any additional functions filtered by this action.
|
|
return apply_filters( 'wpo_wcpdf_validate_input', $output, $input );
|
|
}
|
|
|
|
/**
|
|
* Appends language at the end of the setting provided, in case the setting is translatable
|
|
* and it does not have a language set.
|
|
*
|
|
* @param string $setting Settings field that needs a language.
|
|
* @param array $args Setting arguments.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function append_language( string $setting, array $args ): string {
|
|
if (
|
|
isset( $args['translatable'] ) &&
|
|
true === $args['translatable'] &&
|
|
isset( $args['lang'] ) &&
|
|
'default' !== $args['lang'] &&
|
|
! ( substr( $setting, -strlen( "[{$args['lang']}]" ) ) === "[{$args['lang']}]" )
|
|
) {
|
|
return $setting .= "[{$args['lang']}]";
|
|
} else {
|
|
return $setting;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Output the action button.
|
|
*
|
|
* @param array $action_button
|
|
* @param string $id
|
|
*
|
|
* @return void
|
|
*/
|
|
private function output_action_button( array $action_button, string $id ): void {
|
|
printf(
|
|
'<button type="button" %1$s %2$s %3$s>%4$s%5$s</button><span class="sync-tooltip"></span>',
|
|
! empty( $action_button['class'] ) ? sprintf( 'class="%s"', esc_attr( $action_button['class'] ) ) : '',
|
|
sprintf( 'id="%s"', esc_attr( $action_button['id'] ?? esc_attr( $id ) ) . '_action' ),
|
|
! empty( $action_button['title'] ) ? sprintf( 'title="%s"', esc_attr( $action_button['title'] ) ) : '',
|
|
esc_html( $action_button['text'] ),
|
|
! empty( $action_button['icon'] ) ? sprintf( '<span class="dashicons dashicons-%s"></span>', esc_attr( $action_button['icon'] ) ) : ''
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Normalize identifier-like values (VAT / CoC).
|
|
*
|
|
* @param string $value
|
|
* @return string
|
|
*/
|
|
protected function normalize_identifier( string $value ): string {
|
|
$value = wp_strip_all_tags( $value );
|
|
$value = trim( $value );
|
|
|
|
// Uppercase for consistency (VAT formats often expect it).
|
|
$value = strtoupper( $value );
|
|
|
|
// Keep only A-Z and 0-9, strip spaces, dots, dashes, etc.
|
|
$value = preg_replace( '/[^A-Z0-9]/', '', $value );
|
|
|
|
return $value;
|
|
}
|
|
|
|
}
|
|
|
|
endif; // class_exists
|