first commit

This commit is contained in:
2026-03-05 13:07:40 +01:00
commit 64ba0721ee
25709 changed files with 4691006 additions and 0 deletions

View File

@@ -0,0 +1,721 @@
<?php
namespace WPO\WC\PDF_Invoices\Settings;
use WPO\WC\PDF_Invoices\Documents\Sequential_Number_Store;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Settings\\Settings_Callbacks' ) ) :
class Settings_Callbacks {
protected static $_instance = null;
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Section null callback.
*
* @return void.
*/
public function section() {
}
/**
* Debug section callback.
*
* @return void.
*/
public function debug_section() {
echo wp_kses_post( __( '<b>Warning!</b> 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() {
echo wp_kses_post( __( 'These are used for the (optional) footer columns in the <em>Modern (Premium)</em> template, but can also be used for other elements in your custom template' , 'woocommerce-pdf-invoices-packing-slips' ) );
}
/**
* HTML section callback.
*
* @return void.
*/
public function html_section( $args ) {
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)
*
* @return void.
*/
public function checkbox( $args ) {
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/>', esc_attr( $id ), esc_attr( $setting_name ), esc_attr( $value ), checked( $value, $current, false ), ! empty( $disabled ) ? 'disabled="disabled"' : '' );
// print store empty input if true
if( $store_unchecked ) {
printf( '<input type="hidden" name="%s[wpo_wcpdf_setting_store_empty][]" value="%s"/>', $option_name, esc_attr( $id ) );
}
// output description.
if ( ! empty( $description ) ) {
printf( '<p class="description">%s</p>', wp_kses_post( $description ) );
}
}
/**
* Text 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)
*
* @return void.
*/
public function text_input( $args ) {
extract( $this->normalize_settings_args( $args ) );
if ( empty( $type ) ) {
$type = 'text';
}
$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/>', esc_attr( $type ), esc_attr( $id ), esc_attr( $setting_name ), esc_attr( $current ), $size, esc_attr( $placeholder ), ! empty( $disabled ) ? 'disabled="disabled"' : '' );
// 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)
*
* @return void.
*/
public function url_input( $args ) {
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/>', esc_attr( $type ), esc_attr( $id ), esc_attr( $setting_name ), sanitize_url( $current ), $size, esc_attr( $placeholder ), ! empty( $disabled ) ? 'disabled="disabled"' : '' );
// 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)
*
* @return void.
*/
public function checkbox_text_input( $args ) {
$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();
if (! empty( $text_input_wrap ) ) {
printf( "{$checkbox} {$text_input_wrap}", $text_input);
} else {
echo "{$checkbox} {$text_input}";
}
// output description.
if ( ! empty( $description ) ) {
printf( '<p class="description">%s</p>', wp_kses_post( $description ) );
}
}
// Single text option (not part of any settings array)
public function singular_text_element( $args ) {
$option_name = $args['option_name'];
$id = $args['id'];
$size = isset( $args['size'] ) ? $args['size'] : '25';
$class = isset( $args['translatable'] ) && $args['translatable'] === true ? 'translatable' : '';
$option = get_option( $option_name );
if ( isset( $option ) ) {
$current = $option;
} else {
$current = isset( $args['default'] ) ? $args['default'] : '';
}
printf( '<input type="text" id="%1$s" name="%2$s" value="%3$s" size="%4$s" class="%5$s"/>', esc_attr( $id ), esc_attr( $option_name ), esc_attr( $current ), esc_attr( $size ), esc_attr( $class ) );
// output description.
if ( isset( $args['description'] ) ) {
printf( '<p class="description">%s</p>', wp_kses_post( $args['description'] ) );
}
}
/**
* Textarea callback.
*
* args:
* 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)
*
* @return void.
*/
public function textarea( $args ) {
extract( $this->normalize_settings_args( $args ) );
printf( '<textarea id="%1$s" name="%2$s" cols="%4$s" rows="%5$s" placeholder="%6$s"/>%3$s</textarea>', esc_attr( $id ), esc_attr( $setting_name ), esc_textarea( $current ), esc_attr( $width ), esc_attr( $height ), esc_attr( $placeholder ) );
// output description.
if ( ! empty( $description ) ) {
printf( '<p class="description">%s</p>', wp_kses_post( $description ) );
}
}
/**
* Select element callback.
*
* @param array $args Field arguments.
*
* @return void
*/
public function select( $args ) {
extract( $this->normalize_settings_args( $args ) );
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>', esc_attr( $id ), esc_attr( $setting_name ), esc_attr( $placeholder ), esc_attr( $title ), esc_attr( $class ), esc_attr( $css ), esc_attr( $multiple ) );
} else {
printf( '<select id="%1$s" name="%2$s">', esc_attr( $id ), esc_attr( $setting_name ) );
}
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 ) {
if ( ! empty( $multiple ) && is_array( $current ) ) {
$selected = in_array( $key, $current ) ? ' selected="selected"' : '';
printf( '<option value="%s"%s>%s</option>', esc_attr( $key ), esc_attr( $selected ), esc_html( $label ) );
} else {
printf( '<option value="%s"%s>%s</option>', esc_attr( $key ), esc_attr( selected( $current, $key, false ) ), esc_html( $label ) );
}
}
echo '</select>';
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 type="text/javascript">
jQuery(document).ready(function($) {
function check_<?php echo esc_attr( $id ); ?>_custom() {
var custom = $('#<?php echo esc_attr( $id ); ?>').val();
if (custom == '<?php echo $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
}
// output description.
if ( ! empty( $description ) ) {
printf( '<p class="description">%s</p>', wp_kses_post( $description ) );
}
}
public function radio_button( $args ) {
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 />', esc_attr( $id ), esc_attr( $setting_name ), esc_attr( $key ), checked( $current, $key, false ) );
printf( '<label for="%1$s[%3$s]"> %4$s</label><br>', esc_attr( $id ), esc_attr( $setting_name ), 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.
* @param array $args Field arguments.
* @return void
*/
public function multiple_text_input( $args ) {
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>';
}
// output field
$field_current = isset( $current[$name] ) ? $current[$name] : '';
$type = isset( $field['type'] ) ? $field['type'] : 'text';
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"/></td>', esc_attr( $type ), esc_attr( $id ), esc_attr( $setting_name ), esc_attr( $name ), esc_attr( $field_current ), esc_attr( $size ), esc_attr( $placeholder ) );
// field description.
if ( ! empty( $field_description ) ) {
echo '<td>' . 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.
* @param array $args Field arguments.
* @return void
*/
public function multiple_checkboxes( $args ) {
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 ) {
// output checkbox
$field_current = isset( $current[$name] ) ? $current[$name] : '';
printf( '<input type="checkbox" id="%1$s_%3$s" name="%2$s[%3$s]" value="%4$s"%5$s />', esc_attr( $id ), esc_attr( $setting_name ), esc_attr( $name ), esc_attr( $value ), checked( $value, $field_current, false ) );
// 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.
*
* @param array $args Field arguments.
* @return void
*/
public function media_upload( $args ) {
extract( $this->normalize_settings_args( $args ) );
if( ! empty( $current ) && $attachment = wp_get_attachment_image_src( $current, 'full', false ) ) {
$general_settings = get_option('wpo_wcpdf_settings_general');
$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 ( stripos( $header_logo_height, 'mm' ) != false ) {
$in_height = floatval( $header_logo_height )/25.4;
} elseif ( stripos( $header_logo_height, 'cm' ) != false ) {
$in_height = floatval( $header_logo_height )/2.54;
} elseif ( stripos( $header_logo_height, 'in' ) != false ) {
$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( 'File type <strong>webp</strong> is not supported by your server! Please check your <strong>System Configurations</strong> under the <strong>Advanced</strong> tab.', 'woocommerce-pdf-invoices-packing-slips' )
);
}
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' ),
$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( json_encode( $args ) ), 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.
*
* @param array $args Field arguments.
*/
public function next_number_edit( $args ) {
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 );
}
// Sequential_Number_Store 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 Sequential_Number_Store( $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
* @param array $args
* @return void
*/
public function i18n_wrap ( $args ) {
extract( $this->normalize_settings_args( $args ) );
if ( $languages = $this->get_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 ( $callback == 'multiple_text_input' ) {
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 );
}
}
}
public function get_languages () {
$multilingual = function_exists( 'icl_get_languages' );
// $multilingual = true; // for development
if ( $multilingual ) {
// use this instead of function call for development outside of WPML
// $icl_get_languages = 'a:3:{s:2:"en";a:8:{s:2:"id";s:1:"1";s:6:"active";s:1:"1";s:11:"native_name";s:7:"English";s:7:"missing";s:1:"0";s:15:"translated_name";s:7:"English";s:13:"language_code";s:2:"en";s:16:"country_flag_url";s:43:"http://yourdomain/wpmlpath/res/flags/en.png";s:3:"url";s:23:"http://yourdomain/about";}s:2:"fr";a:8:{s:2:"id";s:1:"4";s:6:"active";s:1:"0";s:11:"native_name";s:9:"Français";s:7:"missing";s:1:"0";s:15:"translated_name";s:6:"French";s:13:"language_code";s:2:"fr";s:16:"country_flag_url";s:43:"http://yourdomain/wpmlpath/res/flags/fr.png";s:3:"url";s:29:"http://yourdomain/fr/a-propos";}s:2:"it";a:8:{s:2:"id";s:2:"27";s:6:"active";s:1:"0";s:11:"native_name";s:8:"Italiano";s:7:"missing";s:1:"0";s:15:"translated_name";s:7:"Italian";s:13:"language_code";s:2:"it";s:16:"country_flag_url";s:43:"http://yourdomain/wpmlpath/res/flags/it.png";s:3:"url";s:26:"http://yourdomain/it/circa";}}';
// $icl_get_languages = unserialize($icl_get_languages);
$icl_get_languages = icl_get_languages( 'skip_missing=0' );
$languages = array();
foreach ($icl_get_languages as $lang => $data) {
$languages[$data['language_code']] = $data['native_name'];
}
} else {
return false;
}
return $languages;
}
public function normalize_settings_args ( $args ) {
$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 ( $args['lang'] == 'default' && !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'];
}
}
} else {
// copy current option value if set
if ( isset( $option[$args['id']] ) ) {
$args['current'] = $option[$args['id']];
}
}
}
// falback 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']) && $args['default_if_empty'] == true ) { // force fallback if empty 'current' and 'default_if_empty' equals to true
$args['current'] = isset( $args['default'] ) ? $args['default'] : '';
}
return $args;
}
/**
* Validate options.
*
* @param array $input options to valid.
*
* @return array validated options.
*/
public function validate( $input ) {
// Create our array for storing the validated options.
$output = array();
if ( empty( $input ) || ! is_array( $input ) ) {
return $input;
}
if ( ! empty( $input['wpo_wcpdf_setting_store_empty'] ) ) { //perhaps we should use a more unique/specific name for this
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 ) {
// Check to see if the current option has a value. If so, process it.
if ( isset( $input[$key] ) ) {
if ( is_array( $input[$key] ) ) {
foreach ( $input[$key] as $sub_key => $sub_value ) {
$output[$key][$sub_key] = $input[$key][$sub_key];
}
} else {
$output[$key] = $input[$key];
}
}
}
// Return the array processing any additional functions filtered by this action.
return apply_filters( 'wpo_wcpdf_validate_input', $output, $input );
}
}
endif; // class_exists

View File

@@ -0,0 +1,810 @@
<?php
namespace WPO\WC\PDF_Invoices\Settings;
use WPO\WC\PDF_Invoices\Tables\Number_Store_List_Table;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Settings\\Settings_Debug' ) ) :
class Settings_Debug {
protected static $_instance = null;
public $sections;
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
public function __construct() {
$this->sections = array(
'settings' => __( 'Settings', 'woocommerce-pdf-invoices-packing-slips' ),
'status' => __( 'Status', 'woocommerce-pdf-invoices-packing-slips' ),
'tools' => __( 'Tools', 'woocommerce-pdf-invoices-packing-slips' ),
'numbers' => __( 'Numbers', 'woocommerce-pdf-invoices-packing-slips' ),
);
add_action( 'admin_init', array( $this, 'init_settings' ) );
add_action( 'wpo_wcpdf_settings_output_debug', array( $this, 'output' ), 10, 1 );
add_action( 'wp_ajax_wpo_wcpdf_debug_tools', array( $this, 'ajax_process_settings_debug_tools' ) );
add_action( 'wp_ajax_wpo_wcpdf_danger_zone_tools', array( $this, 'ajax_process_danger_zone_tools' ) );
}
public function output( $active_section ) {
$active_section = ! empty( $active_section ) ? $active_section : 'settings';
?>
<div class="wcpdf_debug_settings_sections">
<h2 class="nav-tab-wrapper">
<?php
foreach ( $this->sections as $section => $title ) {
$active = ( $section === $active_section ) ? 'nav-tab-active' : '';
printf( '<a href="%1$s" class="nav-tab nav-tab-%2$s %3$s">%4$s</a>', esc_url( add_query_arg( 'section', $section ) ), esc_attr( $section ), $active, esc_html( $title ) );
}
?>
</h2>
</div>
<?php
switch ( $active_section ) {
case 'settings':
$this->display_settings();
break;
case 'status':
$this->display_status();
break;
case 'tools':
$this->process_debug_tools();
$this->display_tools();
break;
case 'numbers':
$this->display_numbers();
break;
}
}
public function display_settings() {
settings_fields( 'wpo_wcpdf_settings_debug' );
do_settings_sections( 'wpo_wcpdf_settings_debug' );
submit_button();
}
public function display_status() {
include( WPO_WCPDF()->plugin_path() . '/includes/views/advanced-status.php' );
}
public function display_tools() {
include( WPO_WCPDF()->plugin_path() . '/includes/views/advanced-tools.php' );
}
public function display_numbers() {
global $wpdb;
$number_store_tables = $this->get_number_store_tables();
$invoice_number_store_doc_types = WPO_WCPDF()->settings->debug->get_additional_invoice_number_store_document_types();
$store_name = 'invoice_number';
if ( isset( $_GET['table_name'] ) ) {
$selected_table_name = esc_attr( $_GET['table_name'] );
} else {
$_GET['table_name'] = $selected_table_name = apply_filters( 'wpo_wcpdf_number_store_table_name', "{$wpdb->prefix}wcpdf_{$store_name}", $store_name, null ); // i.e. wp_wcpdf_invoice_number or wp_wcpdf_invoice_number_2021
}
if ( ! isset( $number_store_tables[ $_GET['table_name'] ] ) ) {
$_GET['table_name'] = $selected_table_name = null;
}
$document_type = WPO_WCPDF()->settings->debug->get_document_type_from_store_table_name( esc_attr( $_GET['table_name'] ) );
$list_table = new Number_Store_List_Table();
$list_table->prepare_items();
include( WPO_WCPDF()->plugin_path() . '/includes/views/advanced-numbers.php' );
}
private function get_number_store_tables() {
global $wpdb;
$tables = $wpdb->get_results( "SHOW TABLES LIKE '{$wpdb->prefix}wcpdf_%'" );
$document_titles = WPO_WCPDF()->documents->get_document_titles();
$table_names = array();
foreach ( $tables as $table ) {
foreach ( $table as $table_name ) {
if ( ! empty ( $table_name ) ) {
// strip the default prefix
$store_name = $full_store_name = substr( $table_name, strpos( $table_name, 'wcpdf_' ) + strlen( 'wcpdf_' ) );
// strip year suffix, if present
if ( is_numeric( substr( $full_store_name, -4 ) ) ) {
$store_name = trim( substr( $full_store_name, 0, -4 ), '_' );
}
if ( empty( $store_name ) || empty( $full_store_name ) ) {
continue;
}
// strip '_number' and other remaining suffixes
$suffix = substr( $full_store_name, strpos( $full_store_name, '_number' ) + strlen( '_number' ) );
$clean_suffix = ! empty( $suffix ) ? trim( str_replace( '_number', '', $suffix ), '_' ) : $suffix;
$name = substr( $store_name, 0, strpos( $store_name, '_number' ) );
$title = '';
if ( ! empty( $name ) ) {
$title = ! empty( $document_titles[ $name ] ) ? $document_titles[ $name ] : ucwords( str_replace( array( "__", "_", "-" ), ' ', $name ) );
}
if ( ! empty ( $suffix ) ) {
$title = "{$title} ({$clean_suffix})";
}
$table_names[ $table_name ] = $title;
}
}
}
ksort( $table_names );
return $table_names;
}
public function get_document_type_from_store_table_name( $table_name ) {
$document_type = '';
if ( empty( $table_name ) ) {
return $document_type;
}
// strip the default prefix
$store_name = $full_store_name = substr( $table_name, strpos( $table_name, 'wcpdf_' ) + strlen( 'wcpdf_' ) );
// strip year suffix, if present
if ( is_numeric( substr( $full_store_name, -4 ) ) ) {
$store_name = trim( substr( $full_store_name, 0, -4 ), '_' );
}
if ( ! empty( $store_name ) && ! empty( $full_store_name ) ) {
$name = substr( $store_name, 0, strpos( $store_name, '_number' ) );
$document_type = ! empty( $name ) ? str_replace( '_', '-', $name ) : '';
}
return $document_type;
}
public function get_additional_invoice_number_store_document_types() {
$additional_doc_types = array();
$documents = WPO_WCPDF()->documents->get_documents();
foreach ( $documents as $document ) {
if ( in_array( $document->get_type(), array( 'proforma', 'credit-note' ) ) && $document->is_enabled() && is_callable( array( $document, 'get_number_sequence' ) ) ) {
$number_sequence = $document->get_number_sequence( '', $document );
if ( 'invoice_number' === $number_sequence ) {
$additional_doc_types[] = $document->get_type();
}
}
}
return $additional_doc_types;
}
public function process_debug_tools() {
if ( isset( $_REQUEST['wpo_wcpdf_debug_tools_action'] ) && is_callable( array( $this, $_REQUEST['wpo_wcpdf_debug_tools_action'] ) ) ) {
if ( check_admin_referer( 'wpo_wcpdf_debug_tools_action', 'security' ) ) {
// generate_random_string, install_fonts, reschedule_yearly_reset, clear_tmp
call_user_func( array( $this, $_REQUEST['wpo_wcpdf_debug_tools_action'] ) );
}
}
}
private function generate_random_string() {
if ( ! empty( WPO_WCPDF()->main->get_random_string() ) ) {
$old_path = WPO_WCPDF()->main->get_tmp_base();
} else {
$old_path = WPO_WCPDF()->main->get_tmp_base( false );
}
WPO_WCPDF()->main->generate_random_string();
$new_path = WPO_WCPDF()->main->get_tmp_base();
WPO_WCPDF()->main->copy_directory( $old_path, $new_path );
WPO_WCPDF()->main->maybe_reinstall_fonts( true );
/* translators: directory path */
printf( '<div class="notice notice-success"><p>%s</p></div>', sprintf( esc_html__( 'Temporary folder moved to %s', 'woocommerce-pdf-invoices-packing-slips' ), '<code>'.$new_path.'</code>' ) );
}
private function install_fonts() {
WPO_WCPDF()->main->maybe_reinstall_fonts( true );
printf( '<div class="notice notice-success"><p>%s</p></div>', esc_html__( 'Fonts reinstalled!', 'woocommerce-pdf-invoices-packing-slips' ) );
}
private function reschedule_yearly_reset() {
WPO_WCPDF()->settings->schedule_yearly_reset_numbers();
printf( '<div class="notice notice-success"><p>%s</p></div>', esc_html__( 'Yearly reset numbering system rescheduled!', 'woocommerce-pdf-invoices-packing-slips' ) );
}
private function clear_tmp() {
$output = WPO_WCPDF()->main->temporary_files_cleanup( time() );
printf( '<div class="notice notice-%1$s"><p>%2$s</p></div>', key( $output ), reset( $output ) );
}
public function ajax_process_settings_debug_tools() {
check_ajax_referer( 'wpo_wcpdf_debug_nonce', 'nonce' );
$data = stripslashes_deep( $_REQUEST );
if ( empty( $data['action'] ) || 'wpo_wcpdf_debug_tools' !== $data['action'] || empty( $data['debug_tool'] ) ) {
return;
}
$debug_tool = str_replace( '-', '_', esc_attr( $data['debug_tool'] ) );
if ( is_callable( array( $this, $debug_tool ) ) ) {
// export_settings, import_settings, reset_settings
call_user_func_array( array( $this, $debug_tool ), array( $data ) );
}
wp_die();
}
private function export_settings( $data ) {
extract( $data );
if ( empty( $type ) ) {
$message = __( 'Export settings type is empty!', 'woocommerce-pdf-invoices-packing-slips' );
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
}
$settings = [];
switch ( $type ) {
case 'general':
$settings = WPO_WCPDF()->settings->general_settings;
break;
case 'debug':
$settings = WPO_WCPDF()->settings->debug_settings;
break;
case 'ubl_taxes':
$settings = WPO_WCPDF()->settings->ubl_tax_settings;
break;
default:
$settings = apply_filters( 'wpo_wcpdf_export_settings', $settings, $type );
break;
}
// maybe it's a document type settings request
if ( empty( $settings ) ) {
$documents = WPO_WCPDF()->documents->get_documents( 'all' );
foreach ( $documents as $document ) {
$document_type = $document->get_type();
if (
$document_type === substr( $type, 0, strlen( $document_type ) ) ||
false !== strpos( $type, '_ubl' )
) {
$settings = get_option( "wpo_wcpdf_documents_settings_{$type}", [] );
break;
}
}
if ( empty( $settings ) ) {
$message = __( 'Exported settings data is empty!', 'woocommerce-pdf-invoices-packing-slips' );
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
}
}
$filename = apply_filters( 'wpo_wcpdf_export_settings_filename', sprintf( "{$type}-settings-export_%s.json", date( 'Y-m-d_H-i-s' ) ), $type );
wp_send_json_success( compact( 'filename', 'settings' ) );
}
private function import_settings( $data ) {
extract( $data );
$file_data = [];
if ( ! empty( $_FILES['file']['tmp_name'] ) && ! empty( $_FILES['file']['name'] ) ) {
$json_data = file_get_contents( $_FILES['file']['tmp_name'], $_FILES['file']['name'] );
if ( false === $json_data ) {
$message = __( 'Failed to get contents from JSON file!', 'woocommerce-pdf-invoices-packing-slips' );
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
} else {
$file_data = json_decode( $json_data, true );
}
} else {
$message = __( 'JSON file not found!', 'woocommerce-pdf-invoices-packing-slips' );
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
}
if ( empty( $file_data ) || empty( $file_data['type'] ) || empty( $file_data['settings'] ) || ! is_array( $file_data['settings'] ) ) {
$message = __( 'The JSON file data is corrupted!', 'woocommerce-pdf-invoices-packing-slips' );
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
}
$setting_types = $this->get_setting_types();
$type = esc_attr( $file_data['type'] );
$new_settings = stripslashes_deep( $file_data['settings'] );
$settings_option = '';
if ( ! in_array( $type, array_keys( $setting_types ) ) ) {
$message = __( 'The JSON file settings type is not supported on this store!', 'woocommerce-pdf-invoices-packing-slips' );
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
}
if ( in_array( $type, array( 'general', 'debug', 'ubl_taxes' ) ) ) {
$settings_option = "wpo_wcpdf_settings_{$type}";
} else {
$documents = WPO_WCPDF()->documents->get_documents( 'all' );
foreach ( $documents as $document ) {
$document_type = $document->get_type();
if (
$document_type === substr( $type, 0, strlen( $document_type ) ) ||
false !== strpos( $type, '_ubl' )
) {
$settings_option = "wpo_wcpdf_documents_settings_{$type}";
break;
}
}
}
// used for extension settings
$settings_option = apply_filters( 'wpo_wcpdf_import_settings_option', $settings_option, $type, $new_settings );
if ( empty( $settings_option ) ) {
$message = __( "Couldn't determine the settings option for the import!", 'woocommerce-pdf-invoices-packing-slips' );
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
}
$updated = update_option( $settings_option, $new_settings );
if ( $updated ) {
$message = sprintf(
/* translators: settings type */
__( '%s settings imported successfully!', 'woocommerce-pdf-invoices-packing-slips' ),
$setting_types[$type]
);
wcpdf_log_error( $message, 'info' );
wp_send_json_success( compact( 'type', 'message' ) );
} else {
$message = sprintf(
/* translators: settings type */
__( 'The %s settings file you are trying to import is identical to your current settings, therefore, the settings were not imported.', 'woocommerce-pdf-invoices-packing-slips' ),
$setting_types[$type]
);
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
}
}
private function reset_settings( $data ) {
extract( $data );
if ( empty( $type ) ) {
$message = __( 'Reset settings type is empty!', 'woocommerce-pdf-invoices-packing-slips' );
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
}
$settings_option = '';
switch ( $type ) {
case 'general':
$settings_option = 'wpo_wcpdf_settings_general';
break;
case 'debug':
$settings_option = 'wpo_wcpdf_settings_debug';
break;
case 'ubl_taxes':
$settings_option = 'wpo_wcpdf_settings_ubl_taxes';
break;
default:
$settings_option = apply_filters( 'wpo_wcpdf_reset_settings_option', $settings_option, $type );
break;
}
// maybe it's a document type settings request
if ( empty( $settings_option ) ) {
$documents = WPO_WCPDF()->documents->get_documents( 'all' );
foreach ( $documents as $document ) {
$document_type = $document->get_type();
if (
$document_type === substr( $type, 0, strlen( $document_type ) ) ||
false !== strpos( $type, '_ubl' )
) {
$settings_option = "wpo_wcpdf_documents_settings_{$type}";
break;
}
}
if ( empty( $settings_option ) ) {
$message = sprintf(
/* translators: settings type */
__( '%s settings reset not supported!', 'woocommerce-pdf-invoices-packing-slips' ),
$type
);
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
}
}
// settings already reset
$current_settings = get_option( $settings_option, [] );
if ( empty( $current_settings ) ) {
$message = sprintf(
/* translators: settings type */
__( '%s settings are already reset!', 'woocommerce-pdf-invoices-packing-slips' ),
$type
);
wcpdf_log_error( $message, 'info' );
wp_send_json_success( compact( 'type', 'message' ) );
}
// reset settings
$updated = update_option( $settings_option, [] );
if ( $updated ) {
$message = sprintf(
/* translators: settings type */
__( '%s settings reset successfully!', 'woocommerce-pdf-invoices-packing-slips' ),
$type
);
wcpdf_log_error( $message, 'info' );
wp_send_json_success( compact( 'type', 'message' ) );
} else {
$message = sprintf(
/* translators: settings type */
__( 'An error occurred when trying to reset the %s settings.', 'woocommerce-pdf-invoices-packing-slips' ),
$type
);
wcpdf_log_error( $message );
wp_send_json_error( compact( 'message' ) );
}
}
public function ajax_process_danger_zone_tools() {
check_ajax_referer( 'wpo_wcpdf_debug_nonce', 'nonce' );
$request = stripslashes_deep( $_REQUEST );
if ( ! isset( $request['document_type'] ) || ! isset( $request['date_from'] ) || ! isset( $request['date_to'] ) ) {
$message = __( 'One or more request parameters missing.', 'woocommerce-pdf-invoices-packing-slips' );
wp_send_json_error( compact( $message ) );
}
$from_date = date_i18n( 'Y-m-d', strtotime( $request['date_from'] ) );
$to_date = date_i18n( 'Y-m-d', strtotime( $request['date_to'] ) );
$document_type = esc_attr( $request['document_type'] );
$document_types = ! empty( $document_type ) && ( 'all' !== $document_type ) ? array( $document_type ) : array();
$document_title = ! empty( $document_type ) && ( 'all' !== $document_type ) ? ' ' . ucwords( str_replace( '-', ' ', $document_type ) ) . ' ' : ' ';
$page_count = absint( $request['page_count'] );
$document_count = absint( $request['document_count'] );
$delete_or_renumber = esc_attr( $request['delete_or_renumber'] );
$message = ( 'delete' === $delete_or_renumber ) ? $document_title . __( 'documents deleted.', 'woocommerce-pdf-invoices-packing-slips' ) : $document_title . __( 'documents renumbered.', 'woocommerce-pdf-invoices-packing-slips' );
$finished = false;
$args = array(
'return' => 'ids',
'type' => 'shop_order',
'limit' => -1,
'order' => 'ASC',
'paginate' => true,
'posts_per_page' => 50,
'page' => $page_count,
'date_created' => $from_date . '...' . $to_date,
);
$results = wc_get_orders( $args );
$order_ids = $results->orders;
if ( ! empty( $order_ids ) && ! empty( $document_type ) ) {
foreach ( $order_ids as $order_id ) {
$order = wc_get_order( $order_id );
if ( empty( $order ) ) {
continue;
}
if ( 'all' === $document_type ) {
$documents = WPO_WCPDF()->documents->get_documents( 'all' );
foreach ( $documents as $document ) {
$document_types[] = $document->get_type();
}
}
foreach ( $document_types as $type ) {
$document = wcpdf_get_document( $type, $order );
$return = $this->renumber_or_delete_document( $document, $delete_or_renumber );
if ( $return ) {
$document_count++;
}
}
}
$page_count++;
// no more order IDs
} else {
$finished = true;
}
$response = array(
'finished' => $finished,
'pageCount' => $page_count,
'documentCount' => $document_count,
'message' => $message,
);
wp_send_json_success( $response );
}
private function renumber_or_delete_document( $document, $delete_or_renumber ) {
$return = false;
if ( $document && $document->exists() ) {
switch ( $delete_or_renumber ) {
case 'renumber':
if ( is_callable( array( $document, 'init_number' ) ) ) {
$document->init_number();
$return = true;
} elseif ( 'packing-slip' === $document->get_type() && is_callable( array( WPO_WCPDF_Pro()->functions, 'init_packing_slip_number' ) ) ) {
WPO_WCPDF_Pro()->functions->init_packing_slip_number( $document );
$return = true;
}
if ( $return ) {
$document->save();
}
break;
case 'delete':
if ( is_callable( array( $document, 'delete' ) ) ) {
$document->delete();
$return = true;
}
break;
default:
break;
}
}
return $return;
}
public function get_setting_types() {
$setting_types = [
'general' => __( 'General', 'woocommerce-pdf-invoices-packing-slips' ),
'debug' => __( 'Debug', 'woocommerce-pdf-invoices-packing-slips' ),
'ubl_taxes' => __( 'UBL Taxes', 'woocommerce-pdf-invoices-packing-slips' ),
];
$documents = WPO_WCPDF()->documents->get_documents( 'all' );
foreach ( $documents as $document ) {
if ( $document->title != $document->get_title() ) {
$title = $document->title.' ('.$document->get_title().')';
} else {
$title = $document->get_title();
}
foreach ( $document->output_formats as $output_format ) {
$slug = $document->get_type();
if ( 'pdf' !== $output_format ) {
$slug .= "_{$output_format}";
}
$setting_types[$slug] = strtoupper( $output_format ) . ' ' . $title;
}
}
return apply_filters( 'wpo_wcpdf_setting_types', $setting_types );
}
public function init_settings() {
// Register settings.
$page = $option_group = $option_name = 'wpo_wcpdf_settings_debug';
$settings_fields = array(
array(
'type' => 'section',
'id' => 'debug_settings',
'title' => '',
'callback' => 'section',
),
array(
'type' => 'setting',
'id' => 'document_link_access_type',
'title' => __( 'Document link access type', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'select',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'document_link_access_type',
'default' => 'logged_in',
'options' => array(
'logged_in' => __( 'Logged in (recommended)', 'woocommerce-pdf-invoices-packing-slips' ),
'guest' => __( 'Guest', 'woocommerce-pdf-invoices-packing-slips' ),
'full' => __( 'Full', 'woocommerce-pdf-invoices-packing-slips' ),
),
)
),
array(
'type' => 'setting',
'id' => 'document_link_access_type_table',
'title' => '',
'callback' => array( $this, 'document_link_access_type_table' ),
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
),
),
array(
'type' => 'setting',
'id' => 'document_access_denied_redirect_page',
'title' => __( 'Document access denied redirect page', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'select',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'document_access_denied_redirect_page',
'default' => 'blank',
'options' => array(
'blank_page' => __( 'Blank page with message (default)', 'woocommerce-pdf-invoices-packing-slips' ),
'login_page' => __( 'Login page', 'woocommerce-pdf-invoices-packing-slips' ),
'myaccount_page' => __( 'My Account page', 'woocommerce-pdf-invoices-packing-slips' ),
'custom_page' => __( 'Custom page (enter below)', 'woocommerce-pdf-invoices-packing-slips' ),
),
'description' => __( 'Select a frontend page to be used to redirect users when the document access is denied.', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'document_custom_redirect_page',
'title' => '',
'callback' => 'url_input',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'document_custom_redirect_page',
'placeholder' => esc_url_raw( wc_get_page_permalink( 'shop' ) ),
'description' => __( 'Custom external URLs not allowed.', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'pretty_document_links',
'title' => __( 'Pretty document links', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'pretty_document_links',
'description' => __( 'Changes the document links to a prettier URL scheme.', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'calculate_document_numbers',
'title' => __( 'Calculate document numbers (slow)', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'calculate_document_numbers',
'description' => __( "Document numbers (such as invoice numbers) are generated using AUTO_INCREMENT by default. Use this setting if your database auto increments with more than 1.", 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'enable_debug',
'title' => __( 'Enable debug output', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'enable_debug',
'description' => __( "Enable this option to output plugin errors if you're getting a blank page or other PDF generation issues", 'woocommerce-pdf-invoices-packing-slips' ) . '<br>' .
__( '<b>Caution!</b> This setting may reveal errors (from other plugins) in other places on your site too, therefor this is not recommended to leave it enabled on live sites.', 'woocommerce-pdf-invoices-packing-slips' ) . ' ' .
__( 'You can also add <code>&debug=true</code> to the URL to apply this on a per-order basis.', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'enable_cleanup',
'title' => __( 'Enable automatic cleanup', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox_text_input',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'enable_cleanup',
/* translators: number of days */
'text_input_wrap' => __( "every %s days", 'woocommerce-pdf-invoices-packing-slips' ),
'text_input_size' => 4,
'text_input_id' => 'cleanup_days',
'text_input_default' => 7,
'description' => __( "Automatically clean up PDF files stored in the temporary folder (used for email attachments)", 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'html_output',
'title' => __( 'Output to HTML', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'html_output',
'description' => __( 'Send the template output as HTML to the browser instead of creating a PDF.', 'woocommerce-pdf-invoices-packing-slips' ) . ' ' .
__( 'You can also add <code>&output=html</code> to the URL to apply this on a per-order basis.', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'log_to_order_notes',
'title' => __( 'Log to order notes', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'log_to_order_notes',
'description' => __( 'Log PDF document creation and mark/unmark as printed to order notes.', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'disable_preview',
'title' => __( 'Disable document preview', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'disable_preview',
'description' => __( 'Disables the document preview on the plugin settings pages.', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'enable_danger_zone_tools',
'title' => __( 'Enable danger zone tools', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox',
'section' => 'debug_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'enable_danger_zone_tools',
'description' => __( 'Enables the danger zone tools. The actions performed by these tools are irreversible!', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
);
// allow plugins to alter settings fields
$settings_fields = apply_filters( 'wpo_wcpdf_settings_fields_debug', $settings_fields, $page, $option_group, $option_name );
WPO_WCPDF()->settings->add_settings_fields( $settings_fields, $page, $option_group, $option_name );
return;
}
public function document_link_access_type_table() {
?>
<table id="document-link-access-type">
<tr>
<td class="option"><strong><?php _e( 'Logged in', 'woocommerce-pdf-invoices-packing-slips' ); ?></strong></td>
<td><?php _e( "Document can be accessed by logged in users only.", 'woocommerce-pdf-invoices-packing-slips' ); ?></td>
</tr>
<tr>
<td class="option"><strong><?php _e( 'Guest', 'woocommerce-pdf-invoices-packing-slips' ); ?></strong></td>
<td><?php _e( 'Document can be accessed by logged in and guest users.', 'woocommerce-pdf-invoices-packing-slips' ); ?></td>
</tr>
<tr>
<td class="option"><strong><?php _e( 'Full', 'woocommerce-pdf-invoices-packing-slips' ); ?></strong></td>
<td><?php _e( 'Document can be accessed by everyone with the link.', 'woocommerce-pdf-invoices-packing-slips' ); ?></td>
</tr>
</table>
<?php
}
}
endif; // class_exists

View File

@@ -0,0 +1,107 @@
<?php
namespace WPO\WC\PDF_Invoices\Settings;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Settings\\Settings_Documents' ) ) :
class Settings_Documents {
protected static $_instance = null;
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
public function __construct() {
add_action( 'admin_init', array( $this, 'init_settings' ) );
add_action( 'wpo_wcpdf_settings_output_documents', array( $this, 'output' ), 10, 1 );
}
public function init_settings() {
$documents = WPO_WCPDF()->documents->get_documents( 'all' );
foreach ( $documents as $document ) {
if ( is_callable( array( $document, 'init_settings' ) ) ) {
$document->init_settings();
}
}
}
public function output( $section ) {
$section = ! empty( $section ) ? $section : 'invoice';
$documents = WPO_WCPDF()->documents->get_documents( 'all' );
$output_format = 'pdf';
$section_document = null;
if ( isset( $_REQUEST['output_format'] ) && 'ubl' === $_REQUEST['output_format'] ) {
$output_format = 'ubl';
}
foreach ( $documents as $document ) {
if ( $document->get_type() == $section ) {
$section_document = $document;
break;
}
}
if ( empty( $section_document ) ) {
return;
}
?>
<div class="wcpdf_document_settings_sections">
<?php echo '<h2>'.esc_html( $section_document->get_title() ).'<span class="arrow-down">&#9660;</span></h2>'; ?>
<ul>
<?php
foreach ( $documents as $document ) {
if( $document->get_type() != $section ) {
$title = strip_tags( $document->get_title() );
if ( empty( trim( $title ) ) ) {
$title = '['.__( 'untitled', 'woocommerce-pdf-invoices-packing-slips' ).']';
}
$active = $document->get_type() == $section ? 'active' : '';
printf( '<li class="%2$s"><a href="%1$s" class="%2$s">%3$s</a></li>', esc_url( add_query_arg( 'section', $document->get_type() ) ), esc_attr( $active ), esc_html( $title ) );
}
}
?>
</ul>
</div>
<div class="wcpdf_document_settings_document_output_formats">
<?php
if ( ! empty( $section_document->output_formats ) ) {
?>
<h2 class="nav-tab-wrapper">
<?php
foreach ( $section_document->output_formats as $document_output_format ) {
$active = ( $output_format == $document_output_format ) || ( 'pdf' !== $output_format && ! in_array( $output_format, $section_document->output_formats ) ) ? 'nav-tab-active' : '';
$tab_title = strtoupper( esc_html( $document_output_format ) );
if ( 'ubl' === $document_output_format ) {
$tab_title .= ' <sup class="wcpdf_beta">beta</sup>';
}
printf( '<a href="%1$s" class="nav-tab nav-tab-%2$s %3$s">%4$s</a>', esc_url( add_query_arg( 'output_format', $document_output_format ) ), esc_attr( $document_output_format ), $active, $tab_title );
}
?>
</h2>
<?php
}
?>
</div>
<?php
$output_format_compatible = false;
if ( 'pdf' !== $output_format && in_array( $output_format, $section_document->output_formats ) ) {
$output_format_compatible = true;
}
$option_name = ( 'pdf' === $output_format || ! $output_format_compatible ) ? "wpo_wcpdf_documents_settings_{$section}" : "wpo_wcpdf_documents_settings_{$section}_{$output_format}";
settings_fields( $option_name );
do_settings_sections( $option_name );
submit_button();
}
}
endif; // class_exists

View File

@@ -0,0 +1,387 @@
<?php
namespace WPO\WC\PDF_Invoices\Settings;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Settings\\Settings_General' ) ) :
class Settings_General {
protected $option_name = 'wpo_wcpdf_settings_general';
protected static $_instance = null;
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
public function __construct() {
add_action( 'admin_init', array( $this, 'init_settings' ) );
add_action( 'wpo_wcpdf_settings_output_general', array( $this, 'output' ), 10, 1 );
add_action( 'wpo_wcpdf_before_settings', array( $this, 'attachment_settings_hint' ), 10, 2 );
}
public function output( $section ) {
settings_fields( $this->option_name );
do_settings_sections( $this->option_name );
submit_button();
}
public function init_settings() {
$page = $option_group = $option_name = $this->option_name;
$template_base_path = ( defined( 'WC_TEMPLATE_PATH' ) ? WC_TEMPLATE_PATH : $GLOBALS['woocommerce']->template_url );
$theme_template_path = get_stylesheet_directory() . '/' . $template_base_path;
$wp_content_dir = defined( 'WP_CONTENT_DIR' ) && ! empty( WP_CONTENT_DIR ) ? str_replace( ABSPATH, '', WP_CONTENT_DIR ) : '';
$theme_template_path = substr( $theme_template_path, strpos( $theme_template_path, $wp_content_dir ) ) . 'pdf/yourtemplate';
$plugin_template_path = "{$wp_content_dir}/plugins/woocommerce-pdf-invoices-packing-slips/templates/Simple";
$settings_fields = array(
array(
'type' => 'section',
'id' => 'general_settings',
'title' => __( 'General settings', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'section',
),
array(
'type' => 'setting',
'id' => 'download_display',
'title' => __( 'How do you want to view the PDF?', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'select',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'download_display',
'options' => array(
'download' => __( 'Download the PDF' , 'woocommerce-pdf-invoices-packing-slips' ),
'display' => __( 'Open the PDF in a new browser tab/window' , 'woocommerce-pdf-invoices-packing-slips' ),
),
)
),
array(
'type' => 'setting',
'id' => 'template_path',
'title' => __( 'Choose a template', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'select',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'template_path',
'options_callback' => array( $this, 'get_installed_templates_list' ),
/* translators: 1,2. template paths */
'description' => sprintf( __( 'Want to use your own template? Copy all the files from %1$s to your (child) theme in %2$s to customize them' , 'woocommerce-pdf-invoices-packing-slips' ), '<code>'.$plugin_template_path.'</code>', '<code>'.$theme_template_path.'</code>' ),
)
),
array(
'type' => 'setting',
'id' => 'paper_size',
'title' => __( 'Paper size', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'select',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'paper_size',
'options' => apply_filters( 'wpo_wcpdf_template_settings_paper_size', array(
'a4' => __( 'A4' , 'woocommerce-pdf-invoices-packing-slips' ),
'letter' => __( 'Letter' , 'woocommerce-pdf-invoices-packing-slips' ),
) ),
)
),
array(
'type' => 'setting',
'id' => 'test_mode',
'title' => __( 'Test mode', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'test_mode',
'description' => __( 'With test mode enabled, any document generated will always use the latest settings, rather than using the settings as configured at the time the document was first created.' , 'woocommerce-pdf-invoices-packing-slips' ) . '<br>'. __( '<strong>Note:</strong> invoice numbers and dates are not affected by this setting and will still be generated.' , 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'currency_font',
'title' => __( 'Extended currency symbol support', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'currency_font',
'description' => __( 'Enable this if your currency symbol is not displaying properly' , 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'font_subsetting',
'title' => __( 'Enable font subsetting', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'checkbox',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'font_subsetting',
'description' => __( "Font subsetting can reduce file size by only including the characters that are used in the PDF, but limits the ability to edit PDF files later. Recommended if you're using an Asian font." , 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'header_logo',
'title' => __( 'Shop header/logo', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'media_upload',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'header_logo',
'uploader_title' => __( 'Select or upload your invoice header/logo', 'woocommerce-pdf-invoices-packing-slips' ),
'uploader_button_text' => __( 'Set image', 'woocommerce-pdf-invoices-packing-slips' ),
'remove_button_text' => __( 'Remove image', 'woocommerce-pdf-invoices-packing-slips' ),
//'description' => __( '...', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'header_logo_height',
'title' => __( 'Logo height', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'text_input',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'header_logo_height',
'size' => '5',
'placeholder' => '3cm',
'description' => __( 'Enter the total height of the logo in mm, cm or in and use a dot for decimals.<br/>For example: 1.15in or 40mm', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'shop_name',
'title' => __( 'Shop Name', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'text_input',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'shop_name',
'translatable' => true,
)
),
array(
'type' => 'setting',
'id' => 'vat_number',
'title' => __( 'Shop VAT Number', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'text_input',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'vat_number',
'translatable' => true,
)
),
array(
'type' => 'setting',
'id' => 'coc_number',
'title' => __( 'Shop Chamber of Commerce Number', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'text_input',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'coc_number',
'translatable' => true,
)
),
array(
'type' => 'setting',
'id' => 'shop_address',
'title' => __( 'Shop Address', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'textarea',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'shop_address',
'width' => '72',
'height' => '8',
'translatable' => true,
//'description' => __( '...', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'setting',
'id' => 'footer',
'title' => __( 'Footer: terms & conditions, policies, etc.', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'textarea',
'section' => 'general_settings',
'args' => array(
'option_name' => $option_name,
'id' => 'footer',
'width' => '72',
'height' => '4',
'translatable' => true,
//'description' => __( '...', 'woocommerce-pdf-invoices-packing-slips' ),
)
),
array(
'type' => 'section',
'id' => 'extra_template_fields',
'title' => __( 'Extra template fields', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'custom_fields_section',
),
array(
'type' => 'setting',
'id' => 'extra_1',
'title' => __( 'Extra field 1', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'textarea',
'section' => 'extra_template_fields',
'args' => array(
'option_name' => $option_name,
'id' => 'extra_1',
'width' => '72',
'height' => '8',
'description' => __( 'This is footer column 1 in the <i>Modern (Premium)</i> template', 'woocommerce-pdf-invoices-packing-slips' ),
'translatable' => true,
)
),
array(
'type' => 'setting',
'id' => 'extra_2',
'title' => __( 'Extra field 2', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'textarea',
'section' => 'extra_template_fields',
'args' => array(
'option_name' => $option_name,
'id' => 'extra_2',
'width' => '72',
'height' => '8',
'description' => __( 'This is footer column 2 in the <i>Modern (Premium)</i> template', 'woocommerce-pdf-invoices-packing-slips' ),
'translatable' => true,
)
),
array(
'type' => 'setting',
'id' => 'extra_3',
'title' => __( 'Extra field 3', 'woocommerce-pdf-invoices-packing-slips' ),
'callback' => 'textarea',
'section' => 'extra_template_fields',
'args' => array(
'option_name' => $option_name,
'id' => 'extra_3',
'width' => '72',
'height' => '8',
'description' => __( 'This is footer column 3 in the <i>Modern (Premium)</i> template', 'woocommerce-pdf-invoices-packing-slips' ),
'translatable' => true,
)
),
);
// allow plugins to alter settings fields
$settings_fields = apply_filters( 'wpo_wcpdf_settings_fields_general', $settings_fields, $page, $option_group, $option_name );
WPO_WCPDF()->settings->add_settings_fields( $settings_fields, $page, $option_group, $option_name );
return;
}
public function attachment_settings_hint( $active_tab, $active_section ) {
// save or check option to hide attachments settings hint
if ( isset( $_REQUEST['wpo_wcpdf_hide_attachments_hint'] ) && isset( $_REQUEST['_wpnonce'] ) ) {
// validate nonce
if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'hide_attachments_hint_nonce' ) ) {
wcpdf_log_error( 'You do not have sufficient permissions to perform this action: wpo_wcpdf_hide_attachments_hint' );
$hide_hint = false;
} else {
update_option( 'wpo_wcpdf_hide_attachments_hint', true );
$hide_hint = true;
}
} else {
$hide_hint = get_option( 'wpo_wcpdf_hide_attachments_hint' );
}
if ( $active_tab == 'general' && ! $hide_hint ) {
$documents = WPO_WCPDF()->documents->get_documents();
foreach ( $documents as $document ) {
if ( $document->get_type() == 'invoice' ) {
$invoice_email_ids = $document->get_attach_to_email_ids();
if ( empty( $invoice_email_ids ) ) {
include_once( WPO_WCPDF()->plugin_path() . '/includes/views/attachment-settings-hint.php' );
}
}
}
}
}
public function get_installed_templates_list() {
$installed_templates = WPO_WCPDF()->settings->get_installed_templates();
$template_list = array();
foreach ( $installed_templates as $path => $template_id ) {
$template_name = basename( $template_id );
$group = dirname( $template_id );
switch ( $group ) {
case 'default':
case 'premium_plugin':
// no suffix
break;
case 'theme':
default:
$template_name = sprintf( '%s (%s)', $template_name, __( 'Custom', 'woocommerce-pdf-invoices-packing-slips' ) );
break;
}
$template_list[$template_id] = $template_name;
}
return $template_list;
}
/**
* List templates in plugin folder, theme folder & child theme folder
* @return array template path => template name
*/
public function find_templates() {
$installed_templates = array();
// get base paths
$template_base_path = ( function_exists( 'WC' ) && is_callable( array( WC(), 'template_path' ) ) ) ? WC()->template_path() : apply_filters( 'woocommerce_template_path', 'woocommerce/' );
$template_base_path = untrailingslashit( $template_base_path );
$template_paths = array (
// note the order: child-theme before theme, so that array_unique filters out parent doubles
'default' => WPO_WCPDF()->plugin_path() . '/templates/',
'child-theme' => get_stylesheet_directory() . "/{$template_base_path}/pdf/",
'theme' => get_template_directory() . "/{$template_base_path}/pdf/",
);
$template_paths = apply_filters( 'wpo_wcpdf_template_paths', $template_paths );
if ( defined( 'WP_CONTENT_DIR' ) && ! empty( WP_CONTENT_DIR ) && false !== strpos( WP_CONTENT_DIR, ABSPATH ) ) {
$forwardslash_basepath = str_replace( '\\', '/', ABSPATH );
} else {
$forwardslash_basepath = str_replace( '\\', '/', WP_CONTENT_DIR );
}
foreach ( $template_paths as $template_source => $template_path ) {
$dirs = (array) glob( $template_path . '*' , GLOB_ONLYDIR );
foreach ( $dirs as $dir ) {
if ( empty( $dir ) ) {
continue;
}
// we're stripping abspath to make the plugin settings more portable
$forwardslash_dir = str_replace( '\\', '/', $dir );
$installed_templates[ str_replace( $forwardslash_basepath, '', $forwardslash_dir ) ] = basename( $dir );
}
}
// remove parent doubles
$installed_templates = array_unique( $installed_templates );
if ( empty( $installed_templates ) ) {
// fallback to Simple template for servers with glob() disabled
$simple_template_path = str_replace( ABSPATH, '', $template_paths['default'] . 'Simple' );
$installed_templates[$simple_template_path] = 'Simple';
}
return apply_filters( 'wpo_wcpdf_templates', $installed_templates );
}
}
endif; // class_exists

View File

@@ -0,0 +1,163 @@
<?php
namespace WPO\WC\PDF_Invoices\Settings;
use WPO\WC\UBL\Settings\TaxesSettings as UBL_Tax_Settings;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Settings\\Settings_UBL' ) ) :
class Settings_UBL {
public $sections;
protected static $_instance = null;
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
function __construct() {
$this->sections = [
'taxes' => __( 'Taxes classification', 'woocommerce-pdf-invoices-packing-slips' ),
];
add_action( 'admin_init', array( $this, 'init_tax_settings' ) );
add_action( 'wpo_wcpdf_settings_output_ubl', array( $this, 'output' ), 10, 1 );
add_action( 'woocommerce_order_after_calculate_totals', array( $this, 'save_taxes_on_order_totals' ), 10, 2 );
add_action( 'woocommerce_checkout_order_processed', array( $this, 'save_taxes_on_checkout' ), 10, 3 );
// VAT number or COC number is empty
add_action( 'admin_notices', array( $this, 'vat_coc_required_for_ubl_invoice') );
}
public function output( $active_section ) {
$active_section = ! empty( $active_section ) ? $active_section : 'taxes';
?>
<div class="wcpdf_ubl_settings_sections">
<?php if ( count( $this->sections ) > 1 ) : ?>
<h2 class="nav-tab-wrapper">
<?php
foreach ( $this->sections as $section => $title ) {
$active = ( $section == $active_section ) ? 'nav-tab-active' : '';
printf( '<a href="%1$s" class="nav-tab nav-tab-%2$s %3$s">%4$s</a>', esc_url( add_query_arg( 'section', $section ) ), esc_attr( $section ), $active, esc_html( $title ) );
}
?>
</h2>
<?php else : ?>
<h3><?php echo $this->sections[ $active_section ]; ?></h3>
<?php endif; ?>
</div>
<?php
switch ( $active_section ) {
default:
case 'taxes':
$setting = new UBL_Tax_Settings();
$setting->output();
break;
}
}
public function init_tax_settings() {
$page = $option_group = $option_name = 'wpo_wcpdf_settings_ubl_taxes';
$settings_fields = array(
array(
'type' => 'section',
'id' => 'taxes',
'title' => '',
'callback' => 'section',
),
);
$settings_fields = apply_filters( 'wpo_wcpdf_settings_fields_ubl_taxes', $settings_fields, $page, $option_group, $option_name );
WPO_WCPDF()->settings->add_settings_fields( $settings_fields, $page, $option_group, $option_name );
}
public function save_taxes_on_order_totals( $and_taxes, $order ) {
// it seems $and taxes is mostly false, meaning taxes are calculated separately,
// but we still update just in case anything changed
if ( ! empty( $order ) ) {
$this->save_order_taxes( $order );
}
}
public function save_taxes_on_checkout( $order_id, $posted_data, $order ) {
if ( empty( $order ) && ! empty( $order_id ) ) {
$order = wc_get_order( $order_id );
}
if ( $order ) {
$this->save_order_taxes( $order );
}
}
public function save_order_taxes( $order ) {
foreach ( $order->get_taxes() as $item_id => $tax_item ) {
if ( is_a( $tax_item, '\WC_Order_Item_Tax' ) && is_callable( array( $tax_item, 'get_rate_id' ) ) ) {
// get tax rate id from item
$tax_rate_id = $tax_item->get_rate_id();
// read tax rate data from db
if ( class_exists( '\WC_TAX' ) && is_callable( array( '\WC_TAX', '_get_tax_rate' ) ) ) {
$tax_rate = \WC_Tax::_get_tax_rate( $tax_rate_id, OBJECT );
if ( ! empty( $tax_rate ) && is_numeric( $tax_rate->tax_rate ) ) {
// store percentage in tax item meta
wc_update_order_item_meta( $item_id, '_wcpdf_rate_percentage', $tax_rate->tax_rate );
$ubl_tax_settings = get_option( 'wpo_wcpdf_settings_ubl_taxes' );
$category = isset( $ubl_tax_settings['rate'][$tax_rate->tax_rate_id]['category'] ) ? $ubl_tax_settings['rate'][$tax_rate->tax_rate_id]['category'] : '';
$scheme = isset( $ubl_tax_settings['rate'][$tax_rate->tax_rate_id]['scheme'] ) ? $ubl_tax_settings['rate'][$tax_rate->tax_rate_id]['scheme'] : '';
$tax_rate_class = $tax_rate->tax_rate_class;
if ( empty( $tax_rate_class ) ) {
$tax_rate_class = 'standard';
}
if ( empty( $category ) ) {
$category = isset( $ubl_tax_settings['class'][$tax_rate_class]['category'] ) ? $ubl_tax_settings['class'][$tax_rate_class]['category'] : '';
}
if ( empty( $scheme ) ) {
$scheme = isset( $ubl_tax_settings['class'][$tax_rate_class]['scheme'] ) ? $ubl_tax_settings['class'][$tax_rate_class]['scheme'] : '';
}
if ( ! empty( $category ) ) {
wc_update_order_item_meta( $item_id, '_wcpdf_ubl_tax_category', $category );
}
if ( ! empty( $scheme ) ) {
wc_update_order_item_meta( $item_id, '_wcpdf_ubl_tax_scheme', $scheme );
}
}
}
}
}
}
public function vat_coc_required_for_ubl_invoice() {
$invoice_ubl_settings = WPO_WCPDF()->settings->get_document_settings( 'invoice', 'ubl' );
if ( isset( $invoice_ubl_settings['enabled'] ) && ( ! isset( WPO_WCPDF()->settings->general_settings['vat_number'] ) || ! isset( WPO_WCPDF()->settings->general_settings['coc_number'] ) ) ) {
$message = sprintf(
/* translators: 1. General Settings, 2. UBL Settings */
__( 'You\'ve enabled UBL output for a document, but some essential details are missing. Please ensure you\'ve added your VAT and CoC numbers in the %1$s. Also, specify your tax rates in the %2$s.', 'woocommerce-pdf-invoices-packing-slips' ),
'<a href="' . esc_url( admin_url( 'admin.php?page=wpo_wcpdf_options_page' ) ) . '">' . __( 'General settings', 'woocommerce-pdf-invoices-packing-slips' ) . '</a>',
'<a href="' . esc_url( admin_url( 'admin.php?page=wpo_wcpdf_options_page&tab=ubl' ) ) . '">' . __( 'UBL settings', 'woocommerce-pdf-invoices-packing-slips' ) . '</a>'
);
echo '<div class="notice notice-warning"><p>' . $message . '</p></div>';
}
}
}
endif; // class_exists

View File

@@ -0,0 +1,245 @@
<?php
namespace WPO\WC\PDF_Invoices\Settings;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Settings\\Settings_Upgrade' ) ) :
class Settings_Upgrade {
protected static $_instance = null;
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
public function __construct() {
add_action( 'wpo_wcpdf_after_settings_page', array( $this, 'extension_overview' ), 10, 2 );
}
public function extension_overview( $tab, $section ) {
if ( 'upgrade' === $tab ) {
$features = array(
array(
'label' => __( 'Proforma Invoice, Credit Note & Receipt', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => __( 'Update your workflow and handle refunds. Both Proforma & Credit Note documents can either follow the main invoice numbering or have their own separate number sequence.', 'woocommerce-pdf-invoices-packing-slips' ),
'extensions' => array( 'pro', 'bundle' ),
),
array(
'label' => __( 'Attach to email', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => __( 'Also attach the Packing Slip, Proforma Invoice and Credit Note to any of the outgoing emails.', 'woocommerce-pdf-invoices-packing-slips' ),
'extensions' => array( 'pro', 'bundle' ),
),
array(
'label' => __( 'Cloud storage upload', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => __( 'Automatically upload your documents via FTP/SFTP or to Dropbox.', 'woocommerce-pdf-invoices-packing-slips' ),
'extensions' => array( 'pro', 'bundle' ),
),
array(
'label' => __( 'Bulk export', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => __( 'Easily export documents for a specific date range.', 'woocommerce-pdf-invoices-packing-slips' ),
'extensions' => array( 'pro', 'bundle' ),
),
array(
'label' => __( 'Multilingual support', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => __( 'Handle document translations with WPML, Polylang, Weglot, TranslatePress or GTranslate.', 'woocommerce-pdf-invoices-packing-slips' ),
'extensions' => array( 'pro', 'bundle' ),
),
array(
'label' => __( 'Attach static files', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => __( 'Add up to three static files to your emails.', 'woocommerce-pdf-invoices-packing-slips' ),
'extensions' => array( 'pro', 'bundle' ),
),
array(
'label' => __( 'Custom document titles and filenames', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => __( 'Customize document titles and filenames right in the plugin settings.', 'woocommerce-pdf-invoices-packing-slips' ),
'extensions' => array( 'pro', 'bundle' ),
),
array(
'label' => __( 'Custom address format', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => __( 'Customize the address format of the billing and shipping addresses.', 'woocommerce-pdf-invoices-packing-slips' ),
'extensions' => array( 'pro', 'bundle' ),
),
array(
'label' => __( 'Order notification email', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => sprintf(
'%s <a href="%s" target="_blank">%s</a>',
__( 'Send a notification email to user specified addresses.', 'woocommerce-pdf-invoices-packing-slips' ),
'https://docs.wpovernight.com/woocommerce-pdf-invoices-packing-slips/configuring-the-order-notification-email/',
__( 'Learn more', 'woocommerce-pdf-invoices-packing-slips' )
),
'extensions' => array( 'pro', 'bundle' ),
),
array(
'label' => __( 'PDF Customizer', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => sprintf(
'%s <a href="%s" target="_blank">%s</a>',
__( 'Fully customize the product table and totals table on your documents.', 'woocommerce-pdf-invoices-packing-slips' ),
'https://docs.wpovernight.com/woocommerce-pdf-invoices-packing-slips/using-the-customizer/',
__( 'Learn more', 'woocommerce-pdf-invoices-packing-slips' )
),
'extensions' => array( 'templates', 'bundle' ),
),
array(
'label' => __( 'Add custom data to your documents', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => sprintf(
'%s <a href="%s" target="_blank">%s</a>',
__( 'Display all sorts of data and apply conditional logic using Custom Blocks.', 'woocommerce-pdf-invoices-packing-slips' ),
'https://docs.wpovernight.com/woocommerce-pdf-invoices-packing-slips/using-custom-blocks/',
__( 'Learn more', 'woocommerce-pdf-invoices-packing-slips' )
),
'extensions' => array( 'templates', 'bundle' ),
),
array(
'label' => __( 'Additional PDF templates', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => __( 'Make use of our Business or Modern template designs.', 'woocommerce-pdf-invoices-packing-slips' ),
'extensions' => array( 'templates', 'bundle' ),
),
array(
'label' => __( 'Add styling', 'woocommerce-pdf-invoices-packing-slips' ),
'description' => __( 'Easily change the look and feel of your documents by adding some custom CSS.', 'woocommerce-pdf-invoices-packing-slips' ),
'extensions' => array( 'templates', 'bundle' ),
),
);
$extension_license_infos = $this->get_extension_license_infos();
include( WPO_WCPDF()->plugin_path() . '/includes/views/upgrade-table.php' );
}
}
/**
* Check if a PDF extension is enabled
*
* @param string $extension can be 'pro' or 'templates'
* @return boolean
*/
public function extension_is_enabled( $extension ) {
$is_enabled = false;
if ( ! empty( $extension ) || ! in_array( $extension, [ 'pro', 'templates' ] ) ) {
$extension_main_function = "WPO_WCPDF_".ucfirst( $extension );
if ( function_exists( $extension_main_function ) ) {
$is_enabled = true;
}
}
return $is_enabled;
}
/**
* Get PDF extensions license info
*
* @return array
*/
public function get_extension_license_infos() {
$extensions = [ 'pro', 'templates' ];
$license_info = [];
$bundle_upgrade_link = '';
$license_status = 'inactive';
foreach ( $extensions as $extension ) {
$license_info[$extension] = [];
$args = [];
$request = null;
$license_key = '';
$sidekick = false;
$updater = null;
if ( $this->extension_is_enabled( $extension ) ) {
$extension_main_function = "WPO_WCPDF_".ucfirst( $extension );
$updater = $extension_main_function()->updater;
if ( $extension == 'templates' && version_compare( $extension_main_function()->version, '2.20.0', '<=' ) ) { // 'updater' property had 'private' visibility
continue;
}
if ( is_null( $updater ) ) {
continue;
}
// built-in updater
if ( is_callable( [ $updater, 'get_license_key' ] ) ) {
$license_key = $updater->get_license_key();
// sidekick (legacy)
} elseif ( property_exists( $updater, 'license_key' ) ) {
$license_slug = "wpo_wcpdf_{$extension}_license";
$wpo_license_keys = get_option( 'wpocore_settings', array() );
$license_key = isset( $wpo_license_keys[$license_slug] ) ? $wpo_license_keys[$license_slug] : $license_key;
$sidekick = true;
}
if ( ! empty( $license_key ) ) {
$args['edd_action'] = 'check_license';
$args['license_key'] = trim( $license_key );
// legacy
if ( $sidekick ) {
if ( ! class_exists( 'WPO_Update_Helper' ) ) {
include_once( $extension_main_function()->plugin_path() . '/updater/update-helper.php' );
}
$item_name = 'PDF Invoices & Packing Slips for WooCommerce - ';
$file = $extension_main_function()->plugin_path();
$version = $extension_main_function()->version;
$author = 'WP Overnight';
switch ( $extension ) {
case 'pro':
$item_name = "{$item_name}Professional";
break;
case 'templates':
$item_name = "{$item_name}Premium Templates";
break;
}
$updater = new \WPO_Update_Helper( $item_name, $file, $license_slug, $version, $author );
}
} else {
continue;
}
if ( $updater && is_callable( [ $updater, 'remote_license_actions' ] ) && ! empty( $args ) ) {
$request = $updater->remote_license_actions( $args );
if ( is_object( $request ) && isset( $request->license ) ) {
$license_info[$extension]['status'] = $license_status = $request->license;
if ( empty( $bundle_upgrade_link ) && ! empty( $request->bundle_upgrade ) && is_string( $request->bundle_upgrade ) ) {
$bundle_upgrade_link = $request->bundle_upgrade; // https://github.com/wpovernight/woocommerce-pdf-invoices-packing-slips/pull/503#issue-1678203436
}
}
}
}
}
$extensions[] = 'bundle';
foreach ( $extensions as $extension ) {
if ( ! empty( $bundle_upgrade_link ) && $license_status == 'valid' ) {
$license_info[$extension]['url'] = $bundle_upgrade_link;
} else {
switch ( $extension ) {
case 'pro':
$license_info[$extension]['url'] = 'https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-professional/';
break;
case 'templates':
$license_info[$extension]['url'] = 'https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/';
break;
case 'bundle':
$license_info[$extension]['url'] = 'https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-bundle/';
break;
}
}
}
return $license_info;
}
}
endif; // class_exists