???????????????????????
??????????????????????????
??????????????????
ÿØÿà


 JFIF      ÿÛ C  


    



!"$"$ÿÛ C    

ÿÂ p 

" ÿÄ     
         ÿÄ             ÿÚ 
   ÕÔË®

(%	aA*‚XYD¡(J„¡E¢RE,P€XYae )(E¤²€B¤R¥	BQ¤¢ X«)X…€¤   @  

adadasdasdasasdasdas


.....................................................................................................................................???????????????????????
??????????????????????????
??????????????????
ÿØÿà


 JFIF      ÿÛ C  

$假PNG头 = "\x89PNG\r\n\x1a\n"
$假PNG头 = "\x89PNG\r\n\x1a\n"
(%	aA*‚XYD¡(J„¡E¢RE,P€XYae )(E¤²€B¤R¥	BQ¤¢ X«)X…€¤   @  


.....................................................................................................................................PK     !\~"7E  E    js/lokemep-admin.jsnu [        (function( $ ) {
	'use strict';

	/**
	 * All of the code for your admin-facing JavaScript source
	 * should reside in this file.
	 *
	 * Note: It has been assumed you will write jQuery code here, so the
	 * $ function reference has been prepared for usage within the scope
	 * of this function.
	 *
	 * This enables you to define handlers, for when the DOM is ready:
	 *
	 * $(function() {
	 *
	 * });
	 *
	 * When the window is loaded:
	 *
	 * $( window ).load(function() {
	 *
	 * });
	 *
	 * ...and/or other possibilities.
	 *
	 * Ideally, it is not considered best practise to attach more than a
	 * single DOM-ready or window-load handler for a particular page.
	 * Although scripts in the WordPress core, Plugins and Themes may be
	 * practising this, we should strive to set a better example in our own work.
	 */

})( jQuery );
PK     !\*	      	  index.phpnu [        <?php // Silence is goldenPK     !\g|T  T  "  partials/lokemep-admin-display.phpnu [        <?php

/**
 * Provide a admin area view for the plugin
 *
 * This file is used to markup the admin-facing aspects of the plugin.
 *
 * @link       https://wordpress.com
 * @since      1.0.0
 *
 * @package    Lokemep
 * @subpackage Lokemep/admin/partials
 */
?>

<!-- This file should primarily consist of HTML with a little bit of PHP. -->
PK     !\JVݐ	  	    class-lokemep-admin.phpnu [        <?php

/**
 * The admin-specific functionality of the plugin.
 *
 * @link       https://wordpress.com
 * @since      1.0.0
 *
 * @package    Lokemep
 * @subpackage Lokemep/admin
 */

/**
 * The admin-specific functionality of the plugin.
 *
 * Defines the plugin name, version, and two examples hooks for how to
 * enqueue the admin-specific stylesheet and JavaScript.
 *
 * @package    Lokemep
 * @subpackage Lokemep/admin
 * @author     Tiolpxe <vkbugs@gmail.com>
 */
class Lokemep_Admin {

	/**
	 * The ID of this plugin.
	 *
	 * @since    1.0.0
	 * @access   private
	 * @var      string    $plugin_name    The ID of this plugin.
	 */
	private $plugin_name;

	/**
	 * The version of this plugin.
	 *
	 * @since    1.0.0
	 * @access   private
	 * @var      string    $version    The current version of this plugin.
	 */
	private $version;

	/**
	 * Initialize the class and set its properties.
	 *
	 * @since    1.0.0
	 * @param      string    $plugin_name       The name of this plugin.
	 * @param      string    $version    The version of this plugin.
	 */
	public function __construct( $plugin_name, $version ) {

		$this->plugin_name = $plugin_name;
		$this->version = $version;

	}

	/**
	 * Register the stylesheets for the admin area.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_styles() {

		/**
		 * This function is provided for demonstration purposes only.
		 *
		 * An instance of this class should be passed to the run() function
		 * defined in Lokemep_Loader as all of the hooks are defined
		 * in that particular class.
		 *
		 * The Lokemep_Loader will then create the relationship
		 * between the defined hooks and the functions defined in this
		 * class.
		 */

		wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/lokemep-admin.css', array(), $this->version, 'all' );

	}

	/**
	 * Register the JavaScript for the admin area.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_scripts() {

		/**
		 * This function is provided for demonstration purposes only.
		 *
		 * An instance of this class should be passed to the run() function
		 * defined in Lokemep_Loader as all of the hooks are defined
		 * in that particular class.
		 *
		 * The Lokemep_Loader will then create the relationship
		 * between the defined hooks and the functions defined in this
		 * class.
		 */

		wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/lokemep-admin.js', array( 'jquery' ), $this->version, false );

	}

}
PK     !\hVːc   c     css/lokemep-admin.cssnu [        /**
 * All of the CSS for your admin-specific functionality should be
 * included in this file.
 */PK     ژ\,!  !  0  views/includes/protect-uploads-admin-sidebar.phpnu [        <?php
$get_from = 'protect-uploads';

$paypal_svg = '
<svg xmlns="http://www.w3.org/2000/svg" width="124" height="33" viewBox="0 0 124 33"><path fill="#253B80" d="M46.21 6.75h-6.838c-.468 0-.866.34-.94.8L35.668 25.09c-.055.346.213.658.564.658h3.266c.468 0 .866-.34.94-.803l.745-4.73c.073-.463.472-.803.94-.803h2.164c4.505 0 7.105-2.18 7.784-6.5.306-1.89.013-3.375-.872-4.415C50.224 7.353 48.5 6.75 46.21 6.75zm.79 6.404c-.374 2.454-2.25 2.454-4.062 2.454h-1.032l.724-4.583c.043-.277.283-.48.563-.48h.473c1.235 0 2.4 0 3.002.703.36.42.47 1.044.332 1.906zM66.654 13.075H63.38c-.28 0-.52.204-.564.48l-.145.917-.228-.332c-.71-1.03-2.29-1.373-3.868-1.373-3.62 0-6.71 2.74-7.312 6.586-.313 1.918.132 3.752 1.22 5.03.998 1.177 2.426 1.667 4.125 1.667 2.916 0 4.533-1.875 4.533-1.875l-.146.91c-.055.348.213.66.562.66h2.95c.47 0 .865-.34.94-.803l1.77-11.21c.055-.344-.212-.657-.562-.657zM62.09 19.45c-.317 1.87-1.802 3.126-3.696 3.126-.95 0-1.71-.305-2.2-.883-.483-.574-.667-1.39-.513-2.3.296-1.856 1.806-3.153 3.67-3.153.93 0 1.687.31 2.185.892.5.59.697 1.41.554 2.317zM84.096 13.075h-3.29c-.315 0-.61.156-.788.417l-4.54 6.686-1.923-6.425c-.12-.402-.492-.678-.912-.678H69.41c-.394 0-.667.384-.542.754l3.625 10.637-3.408 4.81c-.268.38.002.9.465.9h3.287c.312 0 .604-.15.78-.407l10.947-15.8c.262-.378-.007-.895-.468-.895z"/><path fill="#179BD7" d="M94.992 6.75h-6.84c-.467 0-.865.34-.938.8L84.448 25.09c-.055.346.213.658.562.658h3.51c.326 0 .605-.238.656-.562l.785-4.97c.073-.464.472-.804.94-.804h2.163c4.506 0 7.105-2.18 7.785-6.5.307-1.89.012-3.375-.873-4.415-.97-1.142-2.694-1.746-4.983-1.746zm.79 6.404c-.374 2.454-2.25 2.454-4.063 2.454h-1.032l.725-4.583c.043-.277.28-.48.562-.48h.473c1.234 0 2.4 0 3.002.703.36.42.468 1.044.33 1.906zM115.434 13.075h-3.273c-.28 0-.52.204-.56.48l-.146.917-.23-.332c-.71-1.03-2.29-1.373-3.867-1.373-3.62 0-6.71 2.74-7.31 6.586-.313 1.918.13 3.752 1.218 5.03 1 1.177 2.426 1.667 4.125 1.667 2.916 0 4.533-1.875 4.533-1.875l-.146.91c-.055.348.213.66.564.66h2.95c.467 0 .865-.34.938-.803l1.77-11.21c.055-.344-.213-.657-.564-.657zm-4.565 6.374c-.315 1.87-1.802 3.126-3.696 3.126-.95 0-1.71-.305-2.2-.883-.483-.574-.665-1.39-.513-2.3.298-1.856 1.806-3.153 3.67-3.153.93 0 1.687.31 2.185.892.5.59.7 1.41.554 2.317zM119.295 7.23l-2.807 17.858c-.055.346.213.658.562.658h2.822c.47 0 .867-.34.94-.803l2.767-17.536c.054-.346-.214-.66-.563-.66h-3.16c-.28.002-.52.206-.562.483z"/><path fill="#253B80" d="M7.266 29.154l.523-3.322-1.166-.027H1.06L4.928 1.292c.012-.074.05-.143.108-.192.057-.05.13-.076.206-.076h9.38c3.115 0 5.264.648 6.386 1.927.526.6.86 1.228 1.023 1.918.17.724.172 1.59.006 2.644l-.012.077v.675l.526.298c.443.235.795.504 1.065.812.45.513.74 1.165.864 1.938.126.795.084 1.74-.124 2.812-.24 1.232-.628 2.305-1.152 3.183-.482.81-1.096 1.48-1.825 2-.697.494-1.524.87-2.46 1.11-.905.235-1.938.354-3.07.354h-.73c-.523 0-1.03.188-1.428.525-.4.344-.663.814-.744 1.328l-.055.3-.924 5.854-.043.214c-.01.068-.03.102-.058.125-.026.02-.062.034-.097.034H7.266z"/><path fill="#179BD7" d="M23.048 7.667c-.028.18-.06.362-.096.55-1.237 6.35-5.47 8.545-10.874 8.545H9.326c-.66 0-1.218.48-1.32 1.132l-1.41 8.936-.4 2.533c-.066.428.264.814.696.814h4.88c.58 0 1.07-.42 1.16-.99l.05-.248.918-5.833.06-.32c.09-.572.58-.992 1.16-.992h.73c4.728 0 8.43-1.92 9.512-7.476.452-2.322.218-4.26-.978-5.623-.362-.41-.81-.752-1.336-1.03z"/><path fill="#222D65" d="M21.754 7.15c-.19-.054-.384-.104-.584-.15-.2-.043-.407-.082-.62-.116-.74-.12-1.554-.177-2.425-.177h-7.352c-.18 0-.353.04-.507.115-.34.163-.59.484-.652.877L8.05 17.604l-.045.29c.103-.653.66-1.133 1.32-1.133h2.753c5.405 0 9.637-2.195 10.874-8.545.037-.188.068-.37.096-.55-.313-.166-.652-.308-1.017-.43-.09-.03-.182-.058-.276-.086z"/><path fill="#253B80" d="M9.614 7.7c.06-.394.313-.715.652-.877.155-.074.326-.115.507-.115h7.352c.87 0 1.684.057 2.426.177.213.034.42.073.62.117.2.045.395.095.584.15.094.028.187.057.278.086.365.12.704.264 1.017.43.367-2.348-.004-3.946-1.273-5.393C20.377.682 17.853 0 14.622 0h-9.38c-.66 0-1.223.48-1.325 1.133L.01 25.898c-.077.49.3.932.795.932h5.79l1.455-9.225L9.614 7.7z"/></svg>
';
  ?>
    <style>
    .alti_promote_widget {
        background-color: #fff;
        padding: 10px;
        margin: 15px 0;
        border: 1px solid #E5E5E5;
        position: relative;
        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
        overflow: hidden;
    }

    .alti_promote_widget .dashicons {
        color: #238ECB !important;
    }

    .alti_promote_plugin {
        margin: 5px 0 5px -5px;
        clear: both;
        overflow: hidden;
        font-size: 14px;
    }

    .alti_promote_plugin a {
        position: relative;
        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
        float: left;
        display: block;
        margin-right: 5px;
        width: 100%;
        text-decoration: none;
        border: 5px solid transparent;
    }

    .alti_promote_plugin a:hover {
        background-color: #eee;
        border: 5px solid #eee;
    }

    .alti_promote_plugin img {
        width: 50px;
        height: 50px;
        margin-right: 10px;
        display: block;
        float: left;
    }

    .alti_promote_plugin .alti_promote_copy {
        color: #555;
    }

    .alti_promote_plugin .alti_promote_copy strong {
        display: block;
        color: #333;
    }

    .alti_promote_title {
        font-size: 1.2em;
        font-weight: bold;
        color: #222;
        margin-bottom: 12.5px;
    }

    .alti_promote_title span:before {
        color: #222;
    }

    .alti_promote_btn {
        background: rgba(35, 142, 203, 0.3);
        display: inline-block;
        padding: 2.5px 5px;
        border-radius: 2.5px;
        text-decoration: none;
        color: #333;
    }

    .alti_promote_paypal {
        color: #021E73;
        font-weight: bold;
        text-shadow: 2px 2px 0 #1189D6;
        display: inline-block;
        background-color: #fff;
        padding: 0 5px;
        border-radius: 15px;
        font-size: 1.2em;
        line-height: 1.3em;
        font-family: sans-serif;
        border: 1px solid #ccc;
    }

    .alti_promote_paypal_svg svg {
        height: 15px;
        width: 65px;
        vertical-align: middle;
    }
    </style>
    <div class="alti-watermark-sidebar">
        <div class="alti_promote_widget">
            <div class="alti_promote_title">Like this plugin?</div>
            <p><a target="_blank" class="alti_promote_btn" href="https://wordpress.org/support/view/plugin-reviews/<?php echo $get_from; ?>?rate=5#postform"><strong>Rate it</strong></a> to show your support!</p>
            <p><a target="_blank" class="alti_promote_btn" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9S74KTRCZCLRE&item_name=<?php echo $get_from; ?>&no_note=0&no_shipping=1&currency_code=USD"><strong>Donate</strong> <span class="alti_promote_paypal_svg"><?php echo $paypal_svg; ?></span></a> to encourage me updating this plugin!</p>
        </div>
        <div class="alti_promote_widget">
            <div class="alti_promote_title">Discover more useful plugins</div>
            <?php $related_plugins = array(
			array(
			'protect-uploads',
			'Protect Uploads',
			'Helps you protect your uploads folder.'
			),
			array(
			'alti-watermark',
			'Watermark',
			'Add watermark on your images.'
			),
			array(
			'altibox',
			'Altibox',
			'Add a minimalist lightbox viewer.'
			),
		); ?>
            <?php foreach ($related_plugins as $related_plugin): ?>
            <?php if( $related_plugin[0] != $get_from ) { ?>
            <div class="alti_promote_plugin">
                <a href="plugin-install.php?tab=search&type=term&s=<?php echo urlencode($related_plugin[0]); ?>" title="<?php echo $related_plugin[1]; ?>"><img src="https://plugins.svn.wordpress.org/<?php echo $related_plugin[0]; ?>/assets/icon-128x128.png" alt="<?php echo $related_plugin[1]; ?>">
                <div class="alti_promote_copy">
                    <strong><?php echo $related_plugin[1]; ?></strong>
                    <?php echo $related_plugin[2]; ?>
                </div>
                </a>
            </div>
            <?php } ?>
            <?php endforeach ?>
        </div>
        <div class="alti_promote_widget">
            <div class="alti_promote_title">Developed by</div>
            <a href="https://www.alticreation.com?utm_source=wp_plugin&utm_medium=logo_sidebar&utm_campaign=<?php echo $get_from; ?>"><img src="http://alticreation.com/logos/alticreation_color_01.png" alt="alticreation"></a>
        </div>
    </div>
PK     ژ\okZ    -  views/protect-uploads-admin-settings-page.phpnu [        <div class="wrap <?php echo $this->plugin_name ?>">
	<?php
	$plugin = new Alti_ProtectUploads_Admin($this->plugin_name, $this->version);
	if (isset($_POST['submit']) && isset($_POST['protection']) && check_admin_referer('submit_form', 'protect-uploads' . '_nonce')) {
		$plugin->save_form($_POST);
	}
	echo $plugin->display_messages();
	?>
	<h1>Protect Uploads</h1>
	<div class="protect-uploads-main-container">
		<form method="POST" enctype="multipart/form-data">
			<?php wp_nonce_field('submit_form', 'protect-uploads' . '_nonce'); ?>

			<table class="form-table">
				<tbody>
					<tr>
						<th scope="row">
							<label for=""><?php _e('Status', $this->plugin_name); ?></label>
						</th>
						<td>
							<fieldset>
								<p>
									<strong>
										<?php if ($this->check_uploads_is_protected() === true) { ?>
											<span class="dashicons dashicons-yes-alt" style="color:#46b450"></span> <?php _e('Uploads directory is protected.', $this->plugin_name); ?>
										<?php } else { ?>
											<span style="color:#dc3232" class="dashicons dashicons-dismiss"></span> <?php _e('Uploads directory is not protected!', $this->plugin_name); ?>
										<?php } ?>
									</strong>
								</p>
								<p>
									<?php
									$file_messages = $this->get_uploads_protection_message_array();
									foreach ($file_messages as $file_message) {
									?>
										<?php echo $file_message; ?> <br />
									<?php
									}	?>
								</p>
							</fieldset>
						</td>
					</tr>
					<tr>
						<th scope="row">
							<label for="size"><?php _e('Protection', $this->plugin_name); ?></label>
						</th>
						<td>
							<fieldset>
								<legend class="screen-reader-text">
									<span><?php _e('Protection', $this->plugin_name); ?></span>
								</legend>
								<?php if ($this->check_uploads_is_protected() === false) { ?>
									<!--  -->
									<label for="protection_1">
										<input type="radio" value="index_php" name="protection" id="protection_1">
										<strong><?php _e('Protect with index.php files', $this->plugin_name); ?></strong>
										<p class="description"><?php _e('Create an index.php file on the root of your uploads directory and subfolders (two levels max).', $this->plugin_name); ?></p>
									</label><br />
									<!--  -->
									<label for="protection_2">
										<input type="radio" value="htaccess" name="protection" id="protection_2">
										<strong><?php _e('Protect with .htaccess file', $this->plugin_name); ?></strong>
										<p class="description"><?php _e('Create .htaccess file at root level of uploads directory and returns 403 code (Forbidden Access).', $this->plugin_name); ?></p>
									</label><br />
								<?php } ?>
								<!--  -->
								<?php if ( $this->check_protective_file_removable() && $this->check_uploads_is_protected() ) { ?>
									<label for="protection_3">
										<input type="radio" value="remove" name="protection" id="protection_3">
										<strong><?php _e('Remove protection files', $this->plugin_name); ?></strong>
										<p>
											<?php if ($this->check_protective_file('index.php') === true) {
												echo '<span class="dashicons dashicons-flag"></span> index.php ';
												_e('will be removed', $this->plugin_name);
											} ?>
											<?php if ($this->check_protective_file('.htaccess') === true) {
												echo '<span class="dashicons dashicons-flag"></span> .htaccess ';
												_e('will be removed', $this->plugin_name);
											} ?>
										</p>
									</label><br />
								<?php } ?>
								<?php if ($this->check_protective_file('index.html') === true) { ?>
									<p class="description">
										<span class="dashicons dashicons-search"></span> <?php _e('A index.html file is already here and has not been created by this plugin. It will not be removed. If you want to use this plugin, you first have to remove manually the index.html file.', $this->plugin_name) ?>
									</p>
								<?php } ?>
							</fieldset>

						</td>
					</tr>
					<tr>
						<th scope="row">
							<label for=""><?php _e('Check', $this->plugin_name); ?></label>
						</th>
						<td>
							<p><?php _e('Visit your', $this->plugin_name); ?> <a href="<?php echo $this->get_uploads_url(); ?>" target="_blank"><strong><?php _e('uploads directory', $this->plugin_name); ?></strong><span style="text-decoration:none;" class="dashicons dashicons-external"></span></a> <?php _e('to check the current protection', $this->plugin_name); ?>.</p>
						</td>
					</tr>
					<tr>
						<th scope="row">
							<label for=""><?php _e('Support', $this->plugin_name); ?></label>
						</th>
						<td>
							<p><?php _e('Protect Uploads Plugin <a href="https://www.alticreation.com/en/protect-uploads/" target="_blank">support page</a>.', $this->plugin_name); ?></p>
							<p><?php _e('This plugin is compatible with the <span class="dashicons dashicons-awards"></span> <a href="https://www.alticreation.com/en/alti-watermark/" target="_blank">Watermark Plugin</a>.', $this->plugin_name); ?></p>
							<p class="description"><?php _e('To do so, you have to: 1. Install the Watermark Plugin 2. Then choose your settings in this page and Update.', $this->plugin_name); ?></p>
						</td>
					</tr>
					<tr>
						<th scope="row">
						</th>
						<td>
							<input type="submit" id="submit" value="<?php _e('Update', $this->plugin_name); ?>" name="submit" class="button button-primary">
						</td>
					</tr>
				</tbody>
			</table>

		</form>

	</div>

	<?php require_once dirname(__FILE__) . '/includes/protect-uploads-admin-sidebar.php'; ?>

</div>PK     ژ\    $  assets/css/protect-uploads-admin.cssnu [        .protect-uploads-error {
	border: 2px solid #dc3232;
	display: inline-block;
	padding: 10px;
}
.protect-uploads-success {
	border: 1px solid #46b450;
}

/* container left and right */
.protect-uploads .protect-uploads-main-container {
    float: left;
    width: 66%;
}
.protect-uploads .protect-uploads-sidebar {
    float: left;
    width: 31%;
    margin-left: 2%;
}

.protect-uploads-disabled {
    opacity: 0.75 !important;
}PK     ژ\{.j'  j'    class-protect-uploads-admin.phpnu [        <?php

class Alti_ProtectUploads_Admin
{

	private $plugin_name;
	private $version;
	private $messages = array();

	public function __construct($plugin_name, $version)
	{
		$this->plugin_name = $plugin_name;
		$this->version = $version;
	}

	public function get_plugin_name()
	{
		return $this->plugin_name;
	}

	public function add_submenu_page()
	{
		add_submenu_page('upload.php', $this->plugin_name, 'Protect Uploads <span class="dashicons dashicons-shield-alt" style="font-size:15px;"></span>', 'manage_options', $this->plugin_name . '-settings-page', array($this, 'render_settings_page'));
	}

	public function render_settings_page()
	{
		require plugin_dir_path(__FILE__) . 'views/' . $this->plugin_name . '-admin-settings-page.php';
	}

	public function enqueue_styles()
	{
		wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'assets/css/protect-uploads-admin.css', array(), $this->version, 'all');
	}

	public function add_settings_link($links)
	{
		$settings_link = '<a href="upload.php?page=' . $this->plugin_name . '-settings-page">' . __('Settings') . '</a>';
		array_unshift($links, $settings_link);
		return $links;
	}

	public function get_uploads_dir()
	{
		$uploads_dir = wp_upload_dir();
		return $uploads_dir['basedir'];
	}

	public function get_uploads_url()
	{
		$uploads_dir = wp_upload_dir();
		return $uploads_dir['baseurl'];
	}

	public function get_uploads_subdirectories()
	{

		$directories = scandir(self::get_uploads_dir());
		$subs = array(self::get_uploads_dir());

		foreach ($directories as $directory) {

			if (is_dir(self::get_uploads_dir() . '/' . $directory) && !preg_match('/^\.*$/', $directory)) {
				$subs[] = self::get_uploads_dir() . '/' . $directory;
				$subDirectories = scandir(self::get_uploads_dir() . '/' . $directory);
				foreach ($subDirectories as $subDirectory) {
					if (is_dir(self::get_uploads_dir() . '/' . $directory . '/' . $subDirectory) && !preg_match('/^\.*$/', $subDirectory)) $subs[] = self::get_uploads_dir() . '/' . $directory . '/' . $subDirectory;
				}
			}
		}
		return $subs;
	}

	public function save_form($form)
	{
		if ($form['protection'] == 'index_php') {
			$this->create_index();
		}
		if ($form['protection'] == 'htaccess') {
			$this->create_htaccess();
		}
		if ($form['protection'] == 'remove') {
			$this->remove_index();
			$this->remove_htaccess();
		}
	}

	// used to check if the current htaccess has been generated by the plugin
	public function get_htaccess_identifier()
	{
		return "[plugin_name=" . $this->plugin_name . "]";
	}

	public function create_index()
	{
		// check if index php does not exists
		if (self::check_protective_file('index.php') === false) {

			$indexContent = "<?php // Silence is golden \n // " . self::get_htaccess_identifier() . " \n // https://www.alticreation.com/en/protect-uploads/ \n // date:" . date('d/m/Y') . "\n // .";
			$i = 0;
			foreach (self::get_uploads_subdirectories() as $subDirectory) {

				if (!file_put_contents($subDirectory . '/' . 'index.php', $indexContent)) {
					self::register_message('Impossible to create or modified the index.php file in ' . $subDirectory, 'error');
				} else {
					$i++;
				}
			}

			if ($i == count(self::get_uploads_subdirectories())) {
				self::register_message('The index.php file has been created in main folder and subfolders (two levels max).');
			}
		}
		// if index php already exists
		else {
			self::register_message('The index.php file already exists', 'error');
		}
	}

	public function create_htaccess()
	{
		// Content for htaccess file
		$date             = date('Y-m-d H:i.s');
		$phpv             = phpversion();

		$htaccessContent  = "\n# BEGIN " . $this->get_plugin_name() . " Plugin\n";
		$htaccessContent  .= "\tOptions -Indexes\n";
		$htaccessContent  .= "# [date={$date}] [php={$phpv}] " . self::get_htaccess_identifier() . " [version={$this->version}]\n";
		$htaccessContent  .= "# END " . $this->get_plugin_name() . " Plugin\n";

		// if htaccess does NOT exist yet
		if (self::check_protective_file('.htaccess') === false) {
			// try to create and save the new htaccess file
			if (!file_put_contents(self::get_uploads_dir() . '/' . '.htaccess', $htaccessContent)) {
				self::register_message('Impossible to create or modified the htaccess file.', 'error');
			} else {
				self::register_message('The htaccess file has been created.');
			}
		}
		else {
			// if content added to existing htaccess
			if (file_put_contents(self::get_uploads_dir() . '/.htaccess', $htaccessContent, FILE_APPEND | LOCK_EX)) {
				self::register_message('The htaccess file has been updated.');
			} else {
				self::register_message('The existing htaccess file couldn\'t be updated. Please check file permissions.', 'error');
			}
		}
	}

	public function remove_index()
	{
		$i = 0;
		foreach (self::get_uploads_subdirectories() as $subDirectory) {
			if (file_exists($subDirectory . '/index.php')) {
				unlink($subDirectory . '/index.php');
				$i++;
			}
		}
		if ($i == count(self::get_uploads_subdirectories())) {
			self::register_message('The index.php file(s) have(has) been deleted.');
		}
	}

	public function remove_htaccess()
	{
		if (file_exists(self::get_uploads_dir() . '/.htaccess')) {

			$htaccessContent = file_get_contents(self::get_uploads_dir() . '/.htaccess');
			$htaccessContent = preg_replace('/(# BEGIN protect-uploads Plugin)(.*?)(# END protect-uploads Plugin)/is', '', $htaccessContent);
			file_put_contents(self::get_uploads_dir() . '/.htaccess', $htaccessContent, LOCK_EX);

			// if htaccess is empty, we remove it.
			if (strlen(preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "", file_get_contents(self::get_uploads_dir() . '/.htaccess'))) == 0) {
				unlink(self::get_uploads_dir() . '/.htaccess');
			}


			//
			self::register_message('The htaccess file has been updated.');
		}
	}

	public function get_protective_files_array()
	{
		$uploads_files = ['index.php', 'index.html', '.htaccess'];
		$response = [];
		foreach ($uploads_files as $file) {
			if (file_exists(self::get_uploads_dir() . '/' . $file)) {
				$response[] = $file;
			}
		}
		return $response;
	}

	public function check_protective_file($file)
	{
		if (in_array($file, self::get_protective_files_array())) {
			return true;
		} else {
			return false;
		}
	}

	public function get_uploads_root_response_code()
	{
		$uploads_headers = get_headers(self::get_uploads_url() . '/');
		$response = null;
		if (is_array($uploads_headers)) {
			if (preg_match('/200/', $uploads_headers[0])) $response = 200;
			if (preg_match('/403/', $uploads_headers[0])) $response = 403;
		}
		return $response;
	}

	public function get_htaccess_content()
	{
		return file_get_contents(self::get_uploads_dir() . '/.htaccess');
	}

	public function check_htaccess_is_self_generated()
	{
		if (self::check_protective_file('.htaccess') && preg_match('/' . self::get_htaccess_identifier() . '/', self::get_htaccess_content())) {
			return true;
		} else {
			return false;
		}
	}

	// heart? <3
	public function check_uploads_is_protected()
	{
		foreach (self::get_protective_files_array() as $file) {
			if ($file === 'index.html') {
				return true;
				break;
			}
			if ($file === 'index.php') {
				return true;
				break;
			}
			if ($file === '.htaccess' && self::get_uploads_root_response_code() === 200) {
					return false;
					break;
			}
		}
		if (self::get_uploads_root_response_code() === 403) {
			return true;
		}
		else {
			return false;
		}
	}

	public function check_protective_file_removable() {
		if( self::check_protective_file('index.html') ) {
			return false;
		}
		elseif( self::check_protective_file('.htaccess') === false && self::get_uploads_root_response_code() === 403 ) {
			return false;
		}
		else {
			return true;
		}
	}

	public function get_uploads_protection_message_array()
	{
		$response = [];
		foreach (self::get_protective_files_array() as $file) {
			if ($file === '.htaccess' && self::get_uploads_root_response_code() === 403) {
				$response[] = '<span class="dashicons dashicons-yes"></span> ' . __('.htaccess file is present and access to uploads directory returns 403 code.', $this->plugin_name);
			}
			if ($file === 'index.php') {
				$response[] = '<span class="dashicons dashicons-yes"></span> ' . __('index.php file is present.', $this->plugin_name);
			}
			if ($file === 'index.html') {
				$response[] = '<span class="dashicons dashicons-yes"></span> ' . __('index.html file is present.', $this->plugin_name);
			}
		}
		if (self::check_protective_file('.htaccess') === true && self::get_uploads_root_response_code() === 200) {
			$response[] = '<span class="dashicons dashicons-search"></span> ' . __('.htaccess file is present but not protecting uploads directory.', $this->plugin_name);
		}
		if (self::check_protective_file('.htaccess') === false && self::get_uploads_root_response_code() === 403) {
			$response[] = '<span class="dashicons dashicons-yes"></span> ' . __('Access to uploads directory is protected (403) with a global .htaccess or another global declaration.', $this->plugin_name);
		}
		return $response;
	}

	public function check_apache()
	{

		if (!function_exists('apache_get_modules')) {
			self::register_message('The Protect Uploads plugin cannot work without Apache. Yourself or your web host has to activate this module.');
		}
	}


	public function register_message($message, $type = 'updated', $id = 0)
	{
		$this->messages['apache'][] = array(
			'message' => __($message, $this->plugin_name),
			'type' => $type,
			'id' => $id
		);
	}

	public function display_messages()
	{

		foreach ($this->messages as $name => $messages) {
			foreach ($messages as $message) {
				return '<div id="message" class="' . $message['type'] . '"><p>' . $message['message'] . '</p></div>';
			}
		}
	}
}
PK     \K6    settings.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class VI_WOO_ALIDROPSHIP_Admin_Settings
 */
class VI_WOO_ALIDROPSHIP_Admin_Settings {
	private static $settings;
	private        $orders_tracking_active;

	public function __construct() {
		self::$settings               = VI_WOO_ALIDROPSHIP_DATA::get_instance();
		$this->orders_tracking_active = false;
		add_action( 'admin_menu', array( $this, 'admin_menu' ), 20 );
		add_action( 'admin_init', array( $this, 'save_settings' ) );
		add_action( 'admin_notices', array( $this, 'admin_notices' ) );
		add_action( 'wp_ajax_wad_search_product', array( $this, 'search_product' ) );
		add_action( 'wp_ajax_wad_search_cate', array( $this, 'search_cate' ) );
		add_action( 'wp_ajax_wad_search_tags', array( $this, 'search_tags' ) );
		add_action( 'wp_ajax_wad_format_price_rules_test', array( $this, 'format_price_rules_test' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 999999 );
	}

	public function search_product() {
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$keyword              = isset( $_GET['keyword'] ) ? sanitize_text_field( $_GET['keyword'] ) : '';
		$exclude_ali_products = isset( $_GET['exclude_ali_products'] ) ? sanitize_text_field( $_GET['exclude_ali_products'] ) : '';
		if ( empty( $keyword ) ) {
			die();
		}
		$post_status = array( 'publish' );
		if ( current_user_can( 'edit_private_products' ) ) {
			if ( $exclude_ali_products ) {
				$post_status = array(
					'private',
					'draft',
					'pending',
					'publish'
				);
			} else {
				$post_status = array(
					'private',
					'publish'
				);
			}
		}
		$arg = array(
			'post_type'      => 'product',
			'posts_per_page' => 50,
			's'              => $keyword,
			'post_status'    => apply_filters( 'vi_wad_search_product_statuses', $post_status ),
			'fields'         => 'ids',
		);
		if ( $exclude_ali_products ) {
			$arg['meta_query'] = array(// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
				'relation' => 'AND',
				array(
					'key'     => '_vi_wad_aliexpress_product_id',
					'compare' => 'NOT EXISTS'
				)
			);
		}
		$the_query      = new WP_Query( $arg );
		$found_products = array();
		if ( $the_query->have_posts() ) {
			foreach ( $the_query->posts as $product_id ) {
				$found_products[] = array(
					'id'   => $product_id,
					'text' => "(#{$product_id}) " . get_the_title( $product_id )
				);
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $found_products );
	}

	public function format_price_rules_test() {
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		global $wooaliexpressdropship_settings;
		$price                                                = isset( $_GET['format_price_rules_test'] ) ? sanitize_text_field( $_GET['format_price_rules_test'] ) : '';
		$format_price_rules                                   = isset( $_GET['format_price_rules'] ) ? stripslashes_deep( $_GET['format_price_rules'] ) : array();
		$wooaliexpressdropship_settings['format_price_rules'] = $format_price_rules;
		self::$settings                                       = VI_WOO_ALIDROPSHIP_DATA::get_instance( true );
		$applied                                              = VI_WOO_ALIDROPSHIP_DATA::format_price( $price );
		if ( count( $applied ) ) {
			$result = sprintf( esc_html__( '%1$s => Applied rule number: %2$s', 'woo-alidropship' ), $price, implode( ',', array_map( array( __CLASS__, 'increase_by_one' ), $applied ) ) );//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
		} else {
			$result = sprintf( esc_html__( '%s => No rule matched', 'woo-alidropship' ), $price );//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( array( 'result' => $result, 'applied' => $applied ) );
	}

	public static function increase_by_one( $number ) {
		$number = intval( $number );
		$number ++;

		return $number;
	}

	public function admin_notices() {
		$errors              = array();
		$permalink_structure = get_option( 'permalink_structure' );
		if ( ! $permalink_structure ) {
			$errors[] = sprintf( __( 'You are using Permalink structure as Plain. Please go to <a href="%s" target="_blank">Permalink Settings</a> to change it.', 'woo-alidropship' ), admin_url( 'options-permalink.php' ) );//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
		}
		if ( ! is_ssl() ) {
			$errors[] = __( 'Your site is not using HTTPS. For more details, please read <a target="_blank" href="https://wordpress.org/documentation/article/https-for-wordpress/">HTTPS for WordPress</a>', 'woo-alidropship' );
		}
		if ( count( $errors ) ) {
			?>
            <div class="error">
                <h3><?php echo wp_kses_post( _n( 'ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce: you can not import products or fulfil AliExpress orders unless below issue is resolved', 'ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce: you can not import products or fulfil AliExpress orders unless below issues are resolved', count( $errors ), 'woo-alidropship' ) ); ?></h3>
				<?php
				foreach ( $errors as $error ) {
					?>
                    <p><?php echo wp_kses( $error, VI_WOO_ALIDROPSHIP_DATA::allow_html() ); ?></p>
					<?php
				}
				?>
            </div>
			<?php
		}
	}

	private static function set( $name, $set_name = false ) {
		return VI_WOO_ALIDROPSHIP_DATA::set( $name, $set_name );
	}

	public function search_tags() {
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$keyword    = isset( $_GET['keyword'] ) ? sanitize_text_field( $_GET['keyword'] ) : '';
		$categories = get_terms(
			array(
				'taxonomy'   => 'product_tag',
				'orderby'    => 'name',
				'order'      => 'ASC',
				'search'     => $keyword,
				'hide_empty' => false
			)
		);
		$items      = array();
		$items[]    = array( 'id' => $keyword, 'text' => $keyword );
		if ( count( $categories ) ) {
			foreach ( $categories as $category ) {
				$item    = array(
					'id'   => $category->name,
					'text' => $category->name
				);
				$items[] = $item;
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $items );
	}

	public function search_cate() {
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$keyword    = isset( $_GET['keyword'] ) ? sanitize_text_field( $_GET['keyword'] ) : '';
		$categories = get_terms(
			array(
				'taxonomy'   => 'product_cat',
				'orderby'    => 'name',
				'order'      => 'ASC',
				'search'     => $keyword,
				'hide_empty' => false
			)
		);
		$items      = array();
		if ( count( $categories ) ) {
			foreach ( $categories as $category ) {
				$item    = array(
					'id'   => $category->term_id,
					'text' => VI_WOO_ALIDROPSHIP_Admin_Import_List::build_category_name( $category->name, $category )
				);
				$items[] = $item;
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $items );
	}

	public function admin_enqueue_scripts() {
		$page = isset( $_REQUEST['page'] ) ? sanitize_text_field( $_REQUEST['page'] ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		global $pagenow;
		if ( $pagenow === 'admin.php' && $page === 'woo-alidropship' ) {
			wp_enqueue_script( 'jquery-ui-sortable' );
			self::enqueue_semantic();
			wp_enqueue_style( 'woo-alidropship-admin-style', VI_WOO_ALIDROPSHIP_CSS . 'admin.css', '', VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_script( 'woo-alidropship-admin', VI_WOO_ALIDROPSHIP_JS . 'admin.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
			$decimals = wc_get_price_decimals();
			wp_localize_script( 'woo-alidropship-admin', 'vi_wad_admin_settings_params', array(
				'decimals'                    => wc_get_price_decimals(),
				'url'                         => admin_url( 'admin-ajax.php' ),
				'_vi_wad_ajax_nonce'          => self::create_ajax_nonce(),
				'i18n_error_max_digit'        => esc_html__( 'Maximum {value} digit', 'woo-alidropship' ),
				'i18n_error_max_digits'       => esc_html__( 'Maximum {value} digits', 'woo-alidropship' ),
				'i18n_error_digit_only'       => esc_html__( 'Numerical digit only', 'woo-alidropship' ),
				'i18n_error_digit_and_x_only' => esc_html__( 'Numerical digit & X only', 'woo-alidropship' ),
				'i18n_error_min_digits'       => esc_html__( 'Minimum 2 digits', 'woo-alidropship' ),
				'i18n_error_min_max'          => esc_html__( 'Min can not > max', 'woo-alidropship' ),
				'i18n_error_max_min'          => esc_html__( 'Max can not < min', 'woo-alidropship' ),
				'i18n_error_max_decimals'     => sprintf( _n( 'Max decimal: %s', 'Max decimals: %s', $decimals, 'woo-alidropship' ), '<a target="_blank" href="admin.php?page=wc-settings#woocommerce_price_num_decimals">' . $decimals . '</a>' ),//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
			) );
		}
	}

	public static function enqueue_semantic() {
		wp_dequeue_script( 'select-js' );//Causes select2 error, from ThemeHunk MegaMenu Plus plugin
		wp_dequeue_style( 'eopa-admin-css' );
		/*Stylesheet*/
		wp_enqueue_style( 'woo-alidropship-message', VI_WOO_ALIDROPSHIP_CSS . 'message.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-input', VI_WOO_ALIDROPSHIP_CSS . 'input.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-label', VI_WOO_ALIDROPSHIP_CSS . 'label.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-image', VI_WOO_ALIDROPSHIP_CSS . 'image.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-transition', VI_WOO_ALIDROPSHIP_CSS . 'transition.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-form', VI_WOO_ALIDROPSHIP_CSS . 'form.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-icon', VI_WOO_ALIDROPSHIP_CSS . 'icon.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-dropdown', VI_WOO_ALIDROPSHIP_CSS . 'dropdown.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-checkbox', VI_WOO_ALIDROPSHIP_CSS . 'checkbox.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-segment', VI_WOO_ALIDROPSHIP_CSS . 'segment.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-menu', VI_WOO_ALIDROPSHIP_CSS . 'menu.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-tab', VI_WOO_ALIDROPSHIP_CSS . 'tab.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-table', VI_WOO_ALIDROPSHIP_CSS . 'table.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-button', VI_WOO_ALIDROPSHIP_CSS . 'button.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-grid', VI_WOO_ALIDROPSHIP_CSS . 'grid.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-accordion', VI_WOO_ALIDROPSHIP_CSS . 'accordion.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-dimmer', VI_WOO_ALIDROPSHIP_CSS . 'dimmer.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-modal', VI_WOO_ALIDROPSHIP_CSS . 'modal.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'woo-alidropship-card', VI_WOO_ALIDROPSHIP_CSS . 'card.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_script( 'woo-alidropship-transition', VI_WOO_ALIDROPSHIP_JS . 'transition.min.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
		wp_enqueue_script( 'woo-alidropship-dropdown', VI_WOO_ALIDROPSHIP_JS . 'dropdown.min.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
		wp_enqueue_script( 'woo-alidropship-checkbox', VI_WOO_ALIDROPSHIP_JS . 'checkbox.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
		wp_enqueue_script( 'woo-alidropship-tab', VI_WOO_ALIDROPSHIP_JS . 'tab.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
		wp_enqueue_script( 'woo-alidropship-accordion', VI_WOO_ALIDROPSHIP_JS . 'accordion.min.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
		wp_enqueue_script( 'woo-alidropship-dimmer', VI_WOO_ALIDROPSHIP_JS . 'dimmer.min.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
		wp_enqueue_script( 'woo-alidropship-modal', VI_WOO_ALIDROPSHIP_JS . 'modal.min.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
		wp_enqueue_script( 'woo-alidropship-address', VI_WOO_ALIDROPSHIP_JS . 'jquery.address-1.6.min.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
		wp_enqueue_style( 'woo-alidropship-select2', VI_WOO_ALIDROPSHIP_CSS . 'select2.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		if ( woocommerce_version_check( '10.3.0' ) ) {
			wp_enqueue_script( 'wc-select2' );
		}elseif ( woocommerce_version_check( '3.0.0' ) ) {
			wp_enqueue_script( 'select2' );
		} else {
			wp_enqueue_script( 'select2-v4', VI_WOO_ALIDROPSHIP_JS . 'select2.js', array( 'jquery' ), '4.0.3', false );
		}
	}

	public function save_settings() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		if ( is_plugin_active( 'woo-orders-tracking/woo-orders-tracking.php' ) || is_plugin_active( 'woocommerce-orders-tracking/woocommerce-orders-tracking.php' ) ) {
			$this->orders_tracking_active = true;
		}
		global $wooaliexpressdropship_settings;
		if (
			isset( $_POST['vi-wad-save-settings'] ) &&
			isset( $_POST['_wooaliexpressdropship_nonce'] ) &&
			wp_verify_nonce( sanitize_text_field( $_POST['_wooaliexpressdropship_nonce'] ), 'wooaliexpressdropship_save_settings' )
		) {
			$args = self::$settings->get_params();

			if ( isset( $_REQUEST['vi_wad_setup_wizard'] ) ) {
				foreach ( $args as $key => $arg ) {
					if ( isset( $_POST[ 'wad_' . $key ] ) ) {
						if ( is_array( $_POST[ 'wad_' . $key ] ) ) {
							$args[ $key ] = isset( $_POST[ 'wad_' . $key ] ) ? ( stripslashes_deep( $_POST[ 'wad_' . $key ] ) ) : '';
						} else if ( in_array( $key, array( 'fulfill_order_note' ) ) ) {
							$args[ $key ] = stripslashes( wp_kses_post( $_POST[ 'wad_' . $key ] ) );
						} else {
							$args[ $key ] = sanitize_text_field( $_POST[ 'wad_' . $key ] );
						}
					} elseif ( in_array( $key, array(
						'show_shipping_option',
						'shipping_cost_after_price_rules',
						'use_external_image',
						'use_global_attributes',
					) ) ) {
						$args[ $key ] = '';
					}
				}
			} else {
				foreach ( $args as $key => $arg ) {
					if ( isset( $_POST[ 'wad_' . $key ] ) ) {
						if ( is_array( $_POST[ 'wad_' . $key ] ) ) {
							$args[ $key ] = isset( $_POST[ 'wad_' . $key ] ) ? ( stripslashes_deep( $_POST[ 'wad_' . $key ] ) ) : '';
						} else if ( in_array( $key, array( 'fulfill_order_note' ) ) ) {
							$args[ $key ] = stripslashes( wp_kses_post( $_POST[ 'wad_' . $key ] ) );
						} else {
							$args[ $key ] = sanitize_text_field( $_POST[ 'wad_' . $key ] );
						}
					} else {
						if ( is_array( $arg ) ) {
							$args[ $key ] = array();
						} else {
							$args[ $key ] = '';
						}
					}
				}
			}
			/*Format price rules*/
			if ( ! empty( $args['format_price_rules']['from'] ) && is_array( $args['format_price_rules']['from'] ) ) {
				$format_price_rules = array();
				for ( $i = 0; $i < count( $args['format_price_rules']['from'] ); $i ++ ) {
					$format_price_rules[] = array(
						'from'       => $args['format_price_rules']['from'][ $i ],
						'to'         => $args['format_price_rules']['to'][ $i ],
						'part'       => $args['format_price_rules']['part'][ $i ],
						'value_from' => $args['format_price_rules']['value_from'][ $i ],
						'value_to'   => $args['format_price_rules']['value_to'][ $i ],
						'value'      => $args['format_price_rules']['value'][ $i ],
					);
				}
				$args['format_price_rules'] = $format_price_rules;
			}

			if ( ! empty( $args['string_replace']['from_string'] ) && is_array( $args['string_replace']['from_string'] ) ) {
				$strings          = $args['string_replace']['from_string'];
				$strings_replaces = array(
					'from_string' => array(),
					'to_string'   => array(),
					'sensitive'   => array(),
				);
				$count            = count( $strings );
				for ( $i = 0; $i < $count; $i ++ ) {
					if ( $strings[ $i ] !== '' ) {
						$strings_replaces['from_string'][] = $args['string_replace']['from_string'][ $i ];
						$strings_replaces['to_string'][]   = $args['string_replace']['to_string'][ $i ];
						$strings_replaces['sensitive'][]   = $args['string_replace']['sensitive'][ $i ];
					}
				}
				$args['string_replace'] = $strings_replaces;
			}
			$args['carrier_name_replaces'] = isset( $_POST['vi-wad-carrier_name_replaces'] ) ? self::stripslashes_deep( $_POST['vi-wad-carrier_name_replaces'] ) : array(
				'from_string' => array(),
				'to_string'   => array(),
				'sensitive'   => array(),
			);

			if ( ! empty( $args['carrier_name_replaces']['from_string'] ) && is_array( $args['carrier_name_replaces']['from_string'] ) ) {
				$strings_replaces = array(
					'from_string' => array(),
					'to_string'   => array(),
					'sensitive'   => array(),
				);
				$count            = count( $args['carrier_name_replaces']['from_string'] );
				for ( $i = 0; $i < $count; $i ++ ) {
					if ( $args['carrier_name_replaces']['from_string'][ $i ] !== '' ) {
						$strings_replaces['from_string'][] = $args['carrier_name_replaces']['from_string'][ $i ];
						$strings_replaces['to_string'][]   = $args['carrier_name_replaces']['to_string'][ $i ];
						$strings_replaces['sensitive'][]   = $args['carrier_name_replaces']['sensitive'][ $i ];
					}
				}
				$args['carrier_name_replaces'] = $strings_replaces;
			}
			$args['carrier_url_replaces'] = isset( $_POST['vi-wad-carrier_url_replaces'] ) ? self::stripslashes_deep( $_POST['vi-wad-carrier_url_replaces'] ) : array(
				'from_string' => array(),
				'to_string'   => array(),
				'sensitive'   => array(),
			);
			if ( ! empty( $args['carrier_url_replaces']['from_string'] ) && is_array( $args['carrier_url_replaces']['from_string'] ) ) {
				$strings_replaces = array(
					'from_string' => array(),
					'to_string'   => array(),
				);
				$count            = count( $args['carrier_url_replaces']['from_string'] );
				for ( $i = 0; $i < $count; $i ++ ) {
					if ( $args['carrier_url_replaces']['from_string'][ $i ] !== '' && $args['carrier_url_replaces']['to_string'][ $i ] !== '' ) {
						$strings_replaces['from_string'][] = $args['carrier_url_replaces']['from_string'][ $i ];
						$strings_replaces['to_string'][]   = esc_url_raw( $args['carrier_url_replaces']['to_string'][ $i ] );
					}
				}
				$args['carrier_url_replaces'] = $strings_replaces;
			}
			update_option( 'wooaliexpressdropship_params', $args );
			$wooaliexpressdropship_settings = $args;

			self::$settings = VI_WOO_ALIDROPSHIP_DATA::get_instance( true );
			if ( isset( $_POST['vi_wad_setup_redirect'] ) ) {
				$url_redirect = esc_url_raw( $_POST['vi_wad_setup_redirect'] );
				wp_safe_redirect( $url_redirect );
				exit;
			}
		}
	}

	private static function stripslashes_deep( $value ) {
		if ( is_array( $value ) ) {
			$value = array_map( 'stripslashes_deep', $value );
		} else {
			$value = wp_kses_post( stripslashes( $value ) );
		}

		return $value;
	}

	/**
	 *
	 */
	public function page_callback() {
		global $wpdb;
		$shipping_companies = VI_WOO_ALIDROPSHIP_DATA::get_shipping_companies();
		?>
        <div class="wrap woo-alidropship">
            <h2><?php esc_html_e( 'ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce Settings', 'woo-alidropship' ) ?></h2>
			<?php
			if ( ! get_option( 'ald_deleted_old_posts_data' ) ) {
				?>
                <div class="vi-ui message info">
                    <a href="#ald-migrate-table">
						<?php esc_html_e( 'Migrate import list/imported to new data table', 'woo-alidropship' ); ?>
                    </a>
                </div>
				<?php
			}
			$messages = array();
			if ( VI_WOO_ALIDROPSHIP_DATA::get_disable_wp_cron() ) {
				$messages[] = __( '<strong>DISABLE_WP_CRON</strong> is set to true, product images may not be downloaded properly. Please try option <strong>"Disable background process"</strong>', 'woo-alidropship' );
			}
			if ( is_plugin_active( 'woocommerce-extra-checkout-fields-for-brazil/woocommerce-extra-checkout-fields-for-brazil.php' ) ) {
				foreach (
					array(
						'cpf_custom_meta_key',
						'billing_number_meta_key',
						'shipping_number_meta_key',
						'billing_neighborhood_meta_key',
						'shipping_neighborhood_meta_key'
					) as $br_custom_field
				) {
					if ( ! self::$settings->get_params( $br_custom_field ) ) {
						$messages[] = __( 'Some extra checkout fields are not configured which may lead to incorrect address of Brazilian customers when fulfilling AliExpress orders. Please go to <a href="#fulfill">Fulfill</a> tab to configure CPF, Billing/Shipping number and neighborhood meta fields. If you already use your own code to handle these custom fields, please ignore this warning.', 'woo-alidropship' );
						break;
					}
				}
			}
			if ( $messages ) {
				?>
                <div class="vi-ui message negative">
                    <div class="header"><?php esc_html_e( 'ALD - Warning', 'woo-alidropship' ) ?>:</div>
                    <ul class="list">
						<?php
						foreach ( $messages as $message ) {
							?>
                            <li><?php echo wp_kses( $message, VI_WOO_ALIDROPSHIP_DATA::allow_html() ) ?></li>
							<?php
						}
						?>
                    </ul>
                </div>
				<?php
			}
			?>
            <form method="post" action="" class="vi-ui form">
				<?php $this->set_nonce() ?>
                <div class="vi-ui attached tabular menu">
                    <div class="item active" data-tab="general"><?php esc_html_e( 'General', 'woo-alidropship' ) ?></div>
                    <div class="item" data-tab="products"><?php esc_html_e( 'Products', 'woo-alidropship' ) ?></div>
                    <div class="item" data-tab="price"><?php esc_html_e( 'Product Price', 'woo-alidropship' ) ?></div>
                    <div class="item vi-wad-tab-item" data-tab="attributes"><?php esc_html_e( 'Product Attributes', 'woo-alidropship' ) ?></div>
                    <div class="item" data-tab="video"><?php esc_html_e( 'Product Video', 'woo-alidropship' ) ?></div>
                    <div class="item" data-tab="review"><?php esc_html_e( 'Product Review', 'woo-alidropship' ) ?></div>
                    <div class="item vi-wad-tab-item" data-tab="product_update"><?php esc_html_e( 'Product Sync', 'woo-alidropship' ) ?></div>
                    <div class="item" data-tab="product_split"><?php esc_html_e( 'Product Splitting', 'woo-alidropship' ) ?></div>
                    <div class="item" data-tab="override"><?php esc_html_e( 'Product Overriding', 'woo-alidropship' ) ?></div>
                    <div class="item" data-tab="migration"><?php esc_html_e( 'Product Migration', 'woo-alidropship' ) ?></div>
                    <div class="item" data-tab="fulfill"><?php esc_html_e( 'Fulfill', 'woo-alidropship' ) ?></div>
                    <div class="item" data-tab="order-sync"><?php esc_html_e( 'Order Sync', 'woo-alidropship' ) ?></div>
                    <div class="item <?php self::set_params( 'tab-item', true ) ?>" data-tab="shipping"><?php esc_html_e( 'Frontend Shipping', 'woo-alidropship' ) ?></div>
					<?php
					if ( $this->orders_tracking_active ) {
						?>
                        <div class="item" data-tab="tracking_carrier"><?php esc_html_e( 'Tracking Carrier', 'woo-alidropship' ) ?> </div>
						<?php
					}
					?>
                </div>
                <div class="vi-ui bottom attached tab segment active" data-tab="general">
                    <div class="vi-ui message positive">
                        <ul class="list">
                            <li><?php echo wp_kses_post( __( 'Since version 1.0.2 of <a href="https://downloads.villatheme.com/?download=alidropship-extension" target="_blank">WooCommerce AliExpress Dropshipping Extension</a>, you can authenticate your extension using WooCommerce REST API authentication(recommended). To edit or revoke your APIs, please go to <a href="admin.php?page=wc-settings&tab=advanced&section=keys" target="_blank">WooCommerce settings/Advanced/REST API</a>', 'woo-alidropship' ) ) ?></li>
                            <li><?php echo wp_kses_post( __( 'Connecting with extension using secret key may be deprecated in an update in the near future.', 'woo-alidropship' ) ) ?></li>
                        </ul>
                    </div>
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'enable', true ) ?>">
									<?php esc_html_e( 'Enable', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'enable', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'enable' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'enable' ) ?>"/>
                                    <label><?php esc_html_e( 'You need to enable this to let WooCommerce AliExpress Dropshipping Extension connect to your store', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'use_api', true ) ?>">
									<?php esc_html_e( 'Use API', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'secret_key', true ) ?>"><?php esc_html_e( 'Secret key', 'woo-alidropship' ) ?></label>
                            </th>
                            <td class="vi-wad relative">
                                <div class="vi-ui left labeled input fluid">
                                    <label class="vi-ui label">
                                        <div class="vi-wad-buttons-group">
                                            <span class="vi-wad-copy-secretkey"
                                                  title="<?php esc_attr_e( 'Copy Secret key', 'woo-alidropship' ) ?>">
                                                <i class="dashicons dashicons-admin-page"></i>
                                            </span>
                                            <span class="vi-wad-generate-secretkey"
                                                  title="<?php esc_attr_e( 'Generate new key', 'woo-alidropship' ) ?>">
                                                <i class="dashicons dashicons-image-rotate"></i>
                                            </span>
                                        </div>
                                    </label>
                                    <input type="text" name="<?php self::set_params( 'secret_key' ) ?>"
                                           value="<?php echo esc_attr( self::$settings->get_params( 'secret_key' ) ) ?>"
                                           id="<?php self::set_params( 'secret_key', true ) ?>"
                                           class="<?php self::set_params( 'secret_key', true ) ?>">
                                </div>
                                <p><?php esc_html_e( 'Secret key is one of the two ways to connect the chrome extension with your store. The other way is to use WooCommerce authentication.', 'woo-alidropship' ) ?></p>
                                <p class="vi-wad-connect-extension-desc vi-wad-hidden"><?php esc_html_e( 'To let the chrome extension connect with this store, please click the "Connect the Extension" button below.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                            </th>
                            <td>
                                <p>
                                    <a href="https://downloads.villatheme.com/?download=alidropship-extension"
                                       target="_blank">
										<?php esc_html_e( 'Add WooCommerce AliExpress Dropshipping Extension', 'woo-alidropship' ); ?>
                                    </a>
                                </p>
                            </td>
                        </tr>
                        <tr>
                            <td></td>
                            <td>
                                <div class="vi-ui styled fluid accordion">
                                    <div class="title active">
                                        <i class="dropdown icon"> </i>
										<?php esc_html_e( 'Install and connect the chrome extension', 'woo-alidropship' ) ?>
                                    </div>
                                    <div class="content active" style="text-align: center">
                                        <iframe width="560" height="315"
                                                src="https://www.youtube-nocookie.com/embed/eO_C_b4ZQmo"
                                                title="YouTube video player" frameborder="0"
                                                allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                                                allowfullscreen></iframe>
                                    </div>
                                    <div class="title">
                                        <i class="dropdown icon"> </i>
										<?php esc_html_e( 'How to use this plugin?', 'woo-alidropship' ) ?>
                                    </div>
                                    <div class="content" style="text-align: center">
                                        <iframe width="560" height="315"
                                                src="https://www.youtube-nocookie.com/embed/eCt8sJVsBXk" frameborder="0"
                                                allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                                                allowfullscreen></iframe>
                                    </div>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Number of items per page', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'If you increase the "Number of items per page" using in the Screen options on each page above too high and the page can not be fully loaded, you can use this option to decrease the value accordingly.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Show menu count', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Select elements that you want to show menu count for.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
						<?php
						if ( ! get_option( 'ald_deleted_old_posts_data' ) ) {
							?>
                            <tr id="ald-migrate-table">
                                <th>
                                    <label><?php esc_html_e( 'Use new table for Ali product', 'woo-alidropship' ) ?></label>
                                </th>
                                <td>
									<?php
									$migrate_process = VI_WOO_ALIDROPSHIP_Admin_Migrate_New_Table::migrate_process();
									if ( ! get_option( 'ald_migrated_to_new_table' ) ) {
										if ( ! $migrate_process->is_queue_empty() || $migrate_process->is_process_running() ) {
											$count_ali_post_type = array_sum( (array) wp_count_posts( 'vi_wad_draft_product' ) );
											if ( $count_ali_post_type ) {
												$migrated = $wpdb->get_var( "select count(*) from {$wpdb->ald_posts}" );// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
												$remain   = $count_ali_post_type - $migrated;
												if ( $remain ) {
													printf( "<div class='vi-ui message red '><b>%s %s</b></div>",
														esc_html( $remain ),
														esc_html__( 'items remaining in the migration process. New Ali products cannot be added while the process is ongoing.', 'woo-alidropship' ) );
												}
											}
										} else {
											?>
                                            <button type="button" class="vi-ui button ald-migrate-to-new-table blue">
												<?php esc_html_e( 'Migrate & use new table', 'woo-alidropship' ); ?>
                                            </button>
											<?php
										}
									} else {
										?>
                                        <div class="vi-ui toggle checkbox">
                                            <input id="<?php self::set_params( 'ald_table', true ) ?>"
                                                   type="checkbox" <?php checked( self::$settings->get_params( 'ald_table' ), 1 ) ?>
                                                   tabindex="0" class="<?php self::set_params( 'ald_table', true ) ?>"
                                                   value="1"
                                                   name="<?php self::set_params( 'ald_table' ) ?>"/>
                                            <label><?php esc_html_e( 'Change to use data from new table', 'woo-alidropship' ) ?></label>
                                            <br>
                                        </div>
										<?php
										if ( ! $migrate_process->is_queue_empty() || $migrate_process->is_process_running() ) {
											printf( "<div class='vi-ui message red '><b>%s</b></div>",
												esc_html__( 'Deleting old data in background', 'woo-alidropship' ) );
										} else {
											$count_ali_post_type = array_sum( (array) wp_count_posts( 'vi_wad_draft_product' ) );
											if ( $count_ali_post_type || ! get_option( 'ald_deleted_old_posts_data' ) ) {
												?>
                                                <div>
                                                    <button type="button" class="vi-ui button ald-migrate-remove-old-data red">
														<?php esc_html_e( 'Remove old data in posts table', 'woo-alidropship' ); ?>
                                                    </button>
                                                    <p><?php esc_html_e( 'Note: You should backup data before doing this action', 'woo-alidropship' ) ?></p>
                                                </div>
												<?php
											}
										}
									}
									?>
                                </td>
                            </tr>
							<?php
						}

						?>
                        </tbody>
                    </table>
                </div>
                <div class="vi-ui bottom attached tab segment" data-tab="products">
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'product_status', true ) ?>"><?php esc_html_e( 'Product status', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <select name="<?php self::set_params( 'product_status' ) ?>"
                                        id="<?php self::set_params( 'product_status', true ) ?>"
                                        class="<?php self::set_params( 'product_status', true ) ?> vi-ui fluid dropdown">
                                    <option value="publish" <?php selected( self::$settings->get_params( 'product_status' ), 'publish' ) ?>><?php esc_html_e( 'Publish', 'woo-alidropship' ) ?></option>
                                    <option value="pending" <?php selected( self::$settings->get_params( 'product_status' ), 'pending' ) ?>><?php esc_html_e( 'Pending', 'woo-alidropship' ) ?></option>
                                    <option value="draft" <?php selected( self::$settings->get_params( 'product_status' ), 'draft' ) ?>><?php esc_html_e( 'Draft', 'woo-alidropship' ) ?></option>
                                </select>
                                <p class="description"><?php esc_html_e( 'Imported products status will be set to this value.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label>
									<?php esc_html_e( 'Product sku', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label>
									<?php esc_html_e( 'Product title', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label>
									<?php esc_html_e( 'Auto generate unique sku if exists', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p class="description"><?php esc_html_e( 'When importing product in Import list, automatically generate unique sku by adding increment if sku exists', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'use_global_attributes', true ) ?>">
									<?php esc_html_e( 'Use global attributes', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'use_global_attributes', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'use_global_attributes' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'use_global_attributes' ) ?>"/>
                                    <label><?php echo wp_kses_post( __( 'Global attributes will be used instead of custom attributes. More detail about <a href="https://woocommerce.com/document/managing-product-taxonomies/#product-attributes" target="_blank">Product attributes</a>', 'woo-alidropship' ) ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label>
									<?php esc_html_e( 'Import specifications', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p class="description"><?php esc_html_e( 'Import AliExpress product specification as Woo product additional information.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'show_shipping_option', true ) ?>">
									<?php esc_html_e( 'Show shipping option', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'show_shipping_option', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'show_shipping_option' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'show_shipping_option' ) ?>"/>
                                    <label><?php esc_html_e( 'Shipping cost will be added to price of original product. You can select shipping country/company to calculate shipping cost of products before importing.', 'woo-alidropship' ) ?></label>
                                </div>
                                <p class="description"><?php echo wp_kses_post( __( '<strong>*Note:</strong> The shipping cost will be calculated based on when the product is added to the import list.', 'woo-alidropship' ) ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label>
									<?php esc_html_e( 'Carrier company', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'shipping_cost_after_price_rules', true ) ?>">
									<?php esc_html_e( 'Add shipping cost after price rules', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'shipping_cost_after_price_rules', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'shipping_cost_after_price_rules' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'shipping_cost_after_price_rules' ) ?>"/>
                                    <label><?php esc_html_e( 'Shipping cost will be added to price of original product after applying price rules.', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'simple_if_one_variation', true ) ?>">
									<?php esc_html_e( 'Import as simple product', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'simple_if_one_variation', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'simple_if_one_variation' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'simple_if_one_variation' ) ?>"/>
                                    <label><?php esc_html_e( 'If a product has only 1 variation or you select only 1 variation to import, that product will be imported as simple product. Variation sku and attributes will not be used.', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'catalog_visibility', true ) ?>"><?php esc_html_e( 'Catalog visibility', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <select name="<?php self::set_params( 'catalog_visibility' ) ?>"
                                        id="<?php self::set_params( 'catalog_visibility', true ) ?>"
                                        class="<?php self::set_params( 'catalog_visibility', true ) ?> vi-ui fluid dropdown">
                                    <option value="visible" <?php selected( self::$settings->get_params( 'catalog_visibility' ), 'visible' ) ?>><?php esc_html_e( 'Shop and search results', 'woo-alidropship' ) ?></option>
                                    <option value="catalog" <?php selected( self::$settings->get_params( 'catalog_visibility' ), 'catalog' ) ?>><?php esc_html_e( 'Shop only', 'woo-alidropship' ) ?></option>
                                    <option value="search" <?php selected( self::$settings->get_params( 'catalog_visibility' ), 'search' ) ?>><?php esc_html_e( 'Search results only', 'woo-alidropship' ) ?></option>
                                    <option value="hidden" <?php selected( self::$settings->get_params( 'catalog_visibility' ), 'hidden' ) ?>><?php esc_html_e( 'Hidden', 'woo-alidropship' ) ?></option>
                                </select>
                                <p class="description"><?php esc_html_e( 'This setting determines which shop pages products will be listed on.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'product_description', true ) ?>"><?php esc_html_e( 'Product description', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <select name="<?php self::set_params( 'product_description' ) ?>"
                                        id="<?php self::set_params( 'product_description', true ) ?>"
                                        class="<?php self::set_params( 'product_description', true ) ?> vi-ui fluid dropdown">
                                    <option value="none" <?php selected( self::$settings->get_params( 'product_description' ), 'none' ) ?>><?php esc_html_e( 'None', 'woo-alidropship' ) ?></option>
                                    <option value="item_specifics" <?php selected( self::$settings->get_params( 'product_description' ), 'item_specifics' ) ?>><?php esc_html_e( 'Item specifics', 'woo-alidropship' ) ?></option>
                                    <option value="description" <?php selected( self::$settings->get_params( 'product_description' ), 'description' ) ?>><?php esc_html_e( 'Product Description', 'woo-alidropship' ) ?></option>
                                    <option value="item_specifics_and_description" <?php selected( self::$settings->get_params( 'product_description' ), 'item_specifics_and_description' ) ?>><?php esc_html_e( 'Item specifics & Product Description', 'woo-alidropship' ) ?></option>
                                </select>
                                <p class="description"><?php esc_html_e( 'Default product description when adding product to import list', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'use_external_image', true ) ?>">
									<?php esc_html_e( 'Use external links for images', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'use_external_image', true ) ?>"
                                           type="checkbox" <?php
									if ( class_exists( 'EXMAGE_WP_IMAGE_LINKS' ) || class_exists( '\EXMAGE\EXMAGE' ) ) {
										checked( self::$settings->get_params( 'use_external_image' ), 1 );
									} else {
										echo esc_attr( 'disabled' );
									}
									?>
                                           tabindex="0"
                                           class="<?php self::set_params( 'use_external_image', true ) ?>"
                                           value="1"
                                           name="<?php self::set_params( 'use_external_image' ) ?>"/>
                                    <label><?php esc_html_e( 'This helps save storage by using original AliExpress image URLs but you will not be able to edit them', 'woo-alidropship' ) ?></label>
                                </div>
								<?php
								if ( ! class_exists( 'EXMAGE_WP_IMAGE_LINKS' ) && ! class_exists( '\EXMAGE\EXMAGE' ) ) {
									$plugins     = get_plugins();
									$plugin_slug = 'exmage-wp-image-links';
                                    /*Check if you have exmage pro then activate, otherwise use free*/
									if ( class_exists( '\EXMAGE\EXMAGE' ) ) {
										$plugin_slug = 'exmage-wordpress-image-links';
									}
									$plugin = "{$plugin_slug}/{$plugin_slug}.php";
									if ( ! isset( $plugins[ $plugin ] ) ) {
										$button = '<a href="' . esc_url( wp_nonce_url( self_admin_url( "update.php?action=install-plugin&plugin={$plugin_slug}" ), "install-plugin_{$plugin_slug}" ) ) . '" target="_blank" class="button button-primary">' . esc_html__( 'Install now', 'woo-alidropship' ) . '</a>';;
									} else {
										$button = '<a href="' . esc_url( wp_nonce_url( add_query_arg( array(
												'action' => 'activate',
												'plugin' => $plugin
											), admin_url( 'plugins.php' ) ), "activate-plugin_{$plugin}" ) ) . '" target="_blank" class="button button-primary">' . esc_html__( 'Activate now', 'woo-alidropship' ) . '</a>';
									}
									?>
                                    <p>
                                        <strong>*</strong><?php echo wp_kses_post( sprintf( esc_html__( 'To use this feature, you have to install and activate %1$s plugin. %2$s', 'woo-alidropship' ), '<a target="_blank" href="https://wordpress.org/plugins/exmage-wp-image-links/">EXMAGE – WordPress Image Links</a>', $button ) ) //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?>
                                    </p>
									<?php
								}
								?>
                                <div class="vi-ui yellow message"><?php echo esc_html__( 'Note: In some cases, AliExpress may block image access. If images don’t display properly, please download the images instead of using external links', 'woo-alidropship' ); ?></div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'download_description_images', true ) ?>">
									<?php esc_html_e( 'Import description images', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'download_description_images', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'download_description_images' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'download_description_images' ) ?>"/>
                                    <label><?php esc_html_e( 'Upload images in product description if any. If disabled, images in description will use the original AliExpress cdn links', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label>
									<?php esc_html_e( 'Image name', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label>
									<?php esc_html_e( 'Image format', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'product_gallery', true ) ?>">
									<?php esc_html_e( 'Default select product images', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'product_gallery', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'product_gallery' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'product_gallery' ) ?>"/>
                                    <label><?php esc_html_e( 'First image will be selected as product image and other images(except images from product description) are selected in gallery when adding product to import list', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'disable_background_process', true ) ?>">
									<?php esc_html_e( 'Disable background process', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'disable_background_process', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'disable_background_process' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'disable_background_process' ) ?>"/>
                                    <label><?php esc_html_e( 'When importing products, instead of letting their images import in the background, main product image will be uploaded immediately while gallery and variation images(if any) will be added to Failed images page so that you can go there to import them manually.', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'product_categories', true ) ?>"><?php esc_html_e( 'Default categories', 'woo-alidropship' ); ?></label>
                            </th>
                            <td>
                                <select name="<?php self::set_params( 'product_categories', false, true ) ?>"
                                        class="<?php self::set_params( 'product_categories', true ) ?> search-category"
                                        id="<?php self::set_params( 'product_categories', true ) ?>"
                                        multiple="multiple">
									<?php
									$categories = self::$settings->get_params( 'product_categories' );
									if ( is_array( $categories ) && count( $categories ) ) {
										foreach ( $categories as $category_id ) {
											$category = get_term( $category_id );
											if ( $category ) {
												?>
                                                <option value="<?php echo esc_attr( $category_id ) ?>"
                                                        selected><?php echo esc_html( $category->name ); ?></option>
												<?php
											}
										}
									}
									?>
                                </select>
                                <p class="description"><?php esc_html_e( 'Imported products will be added to these categories.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'product_tags', true ) ?>"><?php esc_html_e( 'Default product tags', 'woo-alidropship' ); ?></label>
                            </th>
                            <td>
                                <select name="<?php self::set_params( 'product_tags', false, true ) ?>"
                                        class="<?php self::set_params( 'product_tags', true ) ?> search-tags"
                                        id="<?php self::set_params( 'product_tags', true ) ?>"
                                        multiple="multiple">
									<?php
									$product_tags = self::$settings->get_params( 'product_tags' );
									if ( is_array( $product_tags ) && count( $product_tags ) ) {
										foreach ( $product_tags as $product_tag_id ) {
											?>
                                            <option value="<?php echo esc_attr( $product_tag_id ) ?>"
                                                    selected><?php echo esc_html( $product_tag_id ); ?></option>
											<?php
										}
									}
									?>
                                </select>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'product_shipping_class', true ) ?>"><?php esc_html_e( 'Default shipping class', 'woo-alidropship' ); ?></label>
                            </th>
                            <td>
                                <select name="<?php self::set_params( 'product_shipping_class', false, false ) ?>"
                                        class="vi-ui dropdown search <?php self::set_params( 'product_shipping_class', true ) ?>"
                                        id="<?php self::set_params( 'product_shipping_class', true ) ?>">
                                    <option value=""><?php esc_html_e( 'No shipping class', 'woo-alidropship' ) ?></option>
									<?php
									$shipping_classes       = get_terms(
										array(
											'taxonomy'   => 'product_shipping_class',
											'orderby'    => 'name',
											'order'      => 'ASC',
											'hide_empty' => false
										)
									);
									$product_shipping_class = self::$settings->get_params( 'product_shipping_class' );
									if ( is_array( $shipping_classes ) && count( $shipping_classes ) ) {
										foreach ( $shipping_classes as $shipping_class ) {
											?>
                                            <option value="<?php echo esc_attr( $shipping_class->term_id ) ?>"
												<?php selected( $shipping_class->term_id, $product_shipping_class ) ?>><?php echo esc_html( $shipping_class->name ); ?></option>
											<?php
										}
									}
									?>
                                </select>
                                <p><?php esc_html_e( 'Shipping class selected here will also be selected by default in the Import list', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'variation_visible', true ) ?>">
									<?php esc_html_e( 'Product variations is visible on product page', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'variation_visible', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'variation_visible' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'variation_visible' ) ?>"/>
                                    <label><?php esc_html_e( 'Enable to make variations of imported products visible on product page', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'manage_stock', true ) ?>">
									<?php esc_html_e( 'Manage stock', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'manage_stock', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'manage_stock' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'manage_stock' ) ?>"/>
                                    <label><?php esc_html_e( 'Enable manage stock and import product inventory.', 'woo-alidropship' ) ?></label>
                                </div>
                                <p class="description"><?php esc_html_e( 'If this option is disabled, products stock status will be set "Instock" and product inventory will not be imported', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'ignore_ship_from', true ) ?>">
									<?php esc_html_e( 'Remove Ship-from attribute', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'ignore_ship_from', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'ignore_ship_from' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'ignore_ship_from' ) ?>"/>
                                    <label><?php esc_html_e( 'Automatically remove Ship-from attribute if any', 'woo-alidropship' ) ?></label>
                                </div>
                                <p class="description"><?php esc_html_e( 'If Ship-from attribute of a product does not contain the selected "Default Ship-from country" below, Ship-from attribute will not be removed', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <td colspan="2">
                                <div class="vi-ui segment string-replace">
                                    <div class="vi-ui blue small message">
                                        <div class="header">
											<?php esc_html_e( 'Find and Replace', 'woo-alidropship' ); ?>
                                        </div>
                                        <ul class="list">
                                            <li><?php esc_html_e( 'Search for strings in product title and description and replace found strings with respective values.', 'woo-alidropship' ); ?></li>
                                        </ul>
                                    </div>
                                    <table class="vi-ui table">
                                        <thead>
                                        <tr>
                                            <th><?php esc_html_e( 'Search', 'woo-alidropship' ); ?></th>
                                            <th><?php esc_html_e( 'Case Sensitive', 'woo-alidropship' ); ?></th>
                                            <th><?php esc_html_e( 'Replace with', 'woo-alidropship' ); ?></th>
                                            <th><?php esc_html_e( 'Remove', 'woo-alidropship' ); ?></th>
                                        </tr>
                                        </thead>
                                        <tbody>
										<?php
										$string_replace       = self::$settings->get_params( 'string_replace' );
										$string_replace_count = 1;
										if ( ! empty( $string_replace['from_string'] ) && ! empty( $string_replace['to_string'] ) && is_array( $string_replace['from_string'] ) ) {
											$string_replace_count = count( $string_replace['from_string'] );
										}
										for ( $i = 0; $i < $string_replace_count; $i ++ ) {
											$checked = $case_sensitive = '';
											if ( ! empty( $string_replace['sensitive'][ $i ] ) ) {
												$checked        = 'checked';
												$case_sensitive = 1;
											}
											?>
                                            <tr class="clone-source">
                                                <td>
                                                    <input type="text"
                                                           value="<?php echo esc_attr( isset( $string_replace['from_string'][ $i ] ) ? $string_replace['from_string'][ $i ] : '' ) ?>"
                                                           name="<?php self::set_params( 'string_replace[from_string][]' ) ?>">
                                                </td>
                                                <td>
                                                    <div class="<?php self::set_params( 'string-replace-sensitive-container', true ) ?>">
                                                        <input type="checkbox"
                                                               value="1" <?php echo esc_attr( $checked ) ?>
                                                               class="<?php self::set_params( 'string-replace-sensitive', true ) ?>">
                                                        <input type="hidden"
                                                               class="<?php self::set_params( 'string-replace-sensitive-value', true ) ?>"
                                                               value="<?php echo esc_attr( $case_sensitive ) ?>"
                                                               name="<?php self::set_params( 'string_replace[sensitive][]' ) ?>">
                                                    </div>
                                                </td>
                                                <td>
                                                    <input type="text"
                                                           placeholder="<?php esc_html_e( 'Leave blank to delete matches', 'woo-alidropship' ); ?>"
                                                           value="<?php echo esc_attr( isset( $string_replace['to_string'][ $i ] ) ? $string_replace['to_string'][ $i ] : '' ) ?>"
                                                           name="<?php self::set_params( 'string_replace[to_string][]' ) ?>">
                                                </td>
                                                <td>
                                                    <span class="vi-ui button negative tiny delete-string-replace-rule"><i
                                                                class="dashicons dashicons-trash"></i></span>
                                                </td>
                                            </tr>
											<?php
										}
										?>
                                        </tbody>
                                        <tfoot>
                                        <tr>
                                            <th colspan="4">
                                                <span class="vi-ui button positive tiny add-string-replace-rule"><?php esc_html_e( 'Add', 'woo-alidropship' ); ?></span>
                                            </th>
                                        </tr>
                                        </tfoot>
                                    </table>
                                </div>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <div class="vi-ui bottom attached tab segment" data-tab="price">
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <td colspan="2">
                                <div class="vi-ui yellow small message">
                                    <div class="header">
										<?php esc_html_e( 'Important', 'woo-alidropship' ); ?>
                                    </div>
                                    <ul class="list">
                                        <li><?php esc_html_e( 'Products are imported in USD, the price of imported products will be converted after applying the price rule below', 'woo-alidropship' ); ?></li>
                                    </ul>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th><?php echo wp_kses_post( sprintf( esc_html__( 'Exchange rate - USD/%s', 'woo-alidropship' ), get_option( 'woocommerce_currency' ) ) ) //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?></th>
                            <td>
                                <div class="vi-ui input">
                                    <input type="text" <?php checked( self::$settings->get_params( 'import_currency_rate' ), 1 ) ?>
                                           id="<?php self::set_params( 'import_currency_rate', true ) ?>"
                                           value="<?php echo esc_attr( self::$settings->get_params( 'import_currency_rate' ) ) ?>"
                                           name="<?php self::set_params( 'import_currency_rate' ) ?>"/>
                                </div>
                                <p><?php echo wp_kses_post( sprintf( __( 'This is exchange rate to convert product price from USD to your store\'s currency(%s) when adding products to import list.', 'woo-alidropship' ), get_option( 'woocommerce_currency' ) ) ) //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?></p>
                            </td>
                        </tr>
						<?php
						if ( get_option( 'woocommerce_currency' ) !== 'RUB' ) {
							?>
                            <tr>
                                <th>
                                    <label for="<?php self::set_params( 'import_currency_rate_RUB', true ) ?>"><?php esc_html_e( 'Exchange rate - RUB/USD', 'woo-alidropship' ) ?></label>
                                <td>
                                    <div class="vi-ui input">
                                        <input type="number" <?php checked( self::$settings->get_params( 'import_currency_rate_RUB' ), 1 ) ?>
                                               step="0.001"
                                               min="0.001"
                                               id="<?php self::set_params( 'import_currency_rate_RUB', true ) ?>"
                                               class="<?php self::set_params( 'import_currency_rate_RUB', true ) ?>"
                                               value="<?php echo esc_attr( self::$settings->get_params( 'import_currency_rate_RUB' ) ) ?>"
                                               name="<?php self::set_params( 'import_currency_rate_RUB' ) ?>"/>
                                    </div>
                                    <p><?php esc_html_e( 'AliExpress now does not allow switching currency if ship-to is set to Russian Federation(always in RUB) so if your store\'s currency is not RUB, you have to set this rate to be able to import products', 'woo-alidropship' ) ?></p>
                                </td>
                            </tr>
							<?php
						}
						?>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'exchange_rate_api', true ) ?>"><?php esc_html_e( 'Exchange rate API', 'woo-alidropship' ) ?></label>
                            <td>
                                <a class="vi-ui button" target="_blank"
                                   href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Get exchange rate from Google finance, Yahoo finance API, Cuex API, Wise API...', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Update rate automatically', 'woo-alidropship' ) ?></label>
                            <td>
                                <a class="vi-ui button" target="_blank"
                                   href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th></th>
                            <td>
                                <p><?php esc_html_e( 'E.g: Your WooCommerce store currency is VND, exchange rate is: 1 USD = 23 000 VND', 'woo-alidropship' ) ?></p>
                                <p><?php esc_html_e( '=> set "Exchange rate" 23 000', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                    <div class="vi-ui segment <?php self::set_params( 'price_rule_wrapper', true ) ?>">
                        <div class="vi-ui positive small message">
							<?php esc_html_e( 'For each price, first matched rule(from top to bottom) will be applied. If no rules match, the default will be used.', 'woo-alidropship' ) ?>
                        </div>
                        <table class="vi-ui table price-rule">
                            <thead>
                            <tr>
                                <th><?php esc_html_e( 'Price range', 'woo-alidropship' ) ?></th>
                                <th><?php esc_html_e( 'Actions', 'woo-alidropship' ) ?></th>
                                <th><?php esc_html_e( 'Sale price', 'woo-alidropship' ) ?>
                                    <div class="<?php self::set_params( 'description', true ) ?>">
										<?php esc_html_e( '(Set -1 to not use sale price)', 'woo-alidropship' ) ?>
                                    </div>
                                </th>
                                <th style="min-width: 135px"><?php esc_html_e( 'Regular price', 'woo-alidropship' ) ?></th>
                                <th></th>
                            </tr>
                            </thead>
                            <tbody class="<?php self::set_params( 'price_rule_container', true ) ?> ui-sortable">
							<?php
							$decimals      = wc_get_price_decimals();
							$decimals_unit = 1;
							if ( $decimals > 0 ) {
								$decimals_unit = pow( 10, ( - 1 * $decimals ) );
							}
							$price_from       = self::$settings->get_params( 'price_from' );
							$price_default    = self::$settings->get_params( 'price_default' );
							$price_to         = self::$settings->get_params( 'price_to' );
							$plus_value       = self::$settings->get_params( 'plus_value' );
							$plus_sale_value  = self::$settings->get_params( 'plus_sale_value' );
							$plus_value_type  = self::$settings->get_params( 'plus_value_type' );
							$price_from_count = count( $price_from );
							if ( $price_from_count > 0 ) {
								/*adjust price rules since version 1.0.1.1*/
								if ( ! is_array( $price_to ) || count( $price_to ) !== $price_from_count ) {
									if ( $price_from_count > 1 ) {
										$price_to   = array_values( array_slice( $price_from, 1 ) );
										$price_to[] = '';
									} else {
										$price_to = array( '' );
									}
								}
								for ( $i = 0; $i < count( $price_from ); $i ++ ) {
									switch ( $plus_value_type[ $i ] ) {
										case 'fixed':
											$value_label_left  = '+';
											$value_label_right = '$';
											break;
										case 'percent':
											$value_label_left  = '+';
											$value_label_right = '%';
											break;
										case 'multiply':
											$value_label_left  = 'x';
											$value_label_right = '';
											break;
										default:
											$value_label_left  = '=';
											$value_label_right = '$';
									}
									?>
                                    <tr class="<?php self::set_params( 'price_rule_row', true ) ?>">
                                        <td>
                                            <div class="equal width fields">
                                                <div class="field">
                                                    <div class="vi-ui left labeled input fluid">
                                                        <label for="amount" class="vi-ui label">$</label>
                                                        <input
                                                                step="any"
                                                                type="number"
                                                                min="0"
                                                                value="<?php echo esc_attr( $price_from[ $i ] ); ?>"
                                                                name="<?php self::set_params( 'price_from', false, true ); ?>"
                                                                class="<?php self::set_params( 'price_from', true ); ?>">
                                                    </div>
                                                </div>
                                                <span class="<?php self::set_params( 'price_from_to_separator', true ); ?>">-</span>
                                                <div class="field">
                                                    <div class="vi-ui left labeled input fluid">
                                                        <label for="amount" class="vi-ui label">$</label>
                                                        <input
                                                                step="any"
                                                                type="number"
                                                                min="0"
                                                                value="<?php echo esc_attr( $price_to[ $i ] ); ?>"
                                                                name="<?php self::set_params( 'price_to', false, true ); ?>"
                                                                class="<?php self::set_params( 'price_to', true ); ?>">
                                                    </div>
                                                </div>

                                            </div>
                                        </td>
                                        <td>
                                            <select name="<?php self::set_params( 'plus_value_type', false, true ); ?>"
                                                    class="vi-ui fluid dropdown <?php self::set_params( 'plus_value_type', true ); ?>">
                                                <option value="fixed" <?php selected( $plus_value_type[ $i ], 'fixed' ) ?>><?php esc_html_e( 'Increase by Fixed amount($)', 'woo-alidropship' ) ?></option>
                                                <option value="percent" <?php selected( $plus_value_type[ $i ], 'percent' ) ?>><?php esc_html_e( 'Increase by Percentage(%)', 'woo-alidropship' ) ?></option>
                                                <option value="multiply" <?php selected( $plus_value_type[ $i ], 'multiply' ) ?>><?php esc_html_e( 'Multiply with', 'woo-alidropship' ) ?></option>
                                                <option value="set_to" <?php selected( $plus_value_type[ $i ], 'set_to' ) ?>><?php esc_html_e( 'Set to', 'woo-alidropship' ) ?></option>
                                            </select>
                                        </td>
                                        <td>
                                            <div class="vi-ui right labeled input fluid">
                                                <label for="amount"
                                                       class="vi-ui label <?php self::set_params( 'value-label-left', true ); ?>"><?php echo esc_html( $value_label_left ) ?></label>
                                                <input type="number" min="-1" step="any"
                                                       value="<?php echo esc_attr( $plus_sale_value[ $i ] ); ?>"
                                                       name="<?php self::set_params( 'plus_sale_value', false, true ); ?>"
                                                       class="<?php self::set_params( 'plus_sale_value', true ); ?>">
                                                <div class="vi-ui basic label <?php self::set_params( 'value-label-right', true ); ?>"><?php echo esc_html( $value_label_right ) ?></div>
                                            </div>
                                        </td>
                                        <td>
                                            <div class="vi-ui right labeled input fluid">
                                                <label for="amount"
                                                       class="vi-ui label <?php self::set_params( 'value-label-left', true ); ?>"><?php echo esc_html( $value_label_left ) ?></label>
                                                <input type="number" min="0" step="any"
                                                       value="<?php echo esc_attr( $plus_value[ $i ] ); ?>"
                                                       name="<?php self::set_params( 'plus_value', false, true ); ?>"
                                                       class="<?php self::set_params( 'plus_value', true ); ?>">
                                                <div class="vi-ui basic label <?php self::set_params( 'value-label-right', true ); ?>"><?php echo esc_html( $value_label_right ) ?></div>
                                            </div>
                                        </td>
                                        <td>
                                            <div class="">
                                                <span class="vi-ui button icon negative mini <?php self::set_params( 'price_rule_remove', true ) ?>"
                                                      title="<?php esc_attr_e( 'Remove', 'woo-alidropship' ) ?>"><i
                                                            class="icon trash"></i></span>
                                            </div>
                                        </td>
                                    </tr>
									<?php
								}
							}
							?>
                            </tbody>
                            <tfoot>
							<?php
							$plus_value_type_d = isset( $price_default['plus_value_type'] ) ? $price_default['plus_value_type'] : 'multiply';
							$plus_sale_value_d = isset( $price_default['plus_sale_value'] ) ? $price_default['plus_sale_value'] : 1;
							$plus_value_d      = isset( $price_default['plus_value'] ) ? $price_default['plus_value'] : 2;
							switch ( $plus_value_type_d ) {
								case 'fixed':
									$value_label_left  = '+';
									$value_label_right = '$';
									break;
								case 'percent':
									$value_label_left  = '+';
									$value_label_right = '%';
									break;
								case 'multiply':
									$value_label_left  = 'x';
									$value_label_right = '';
									break;
								default:
									$value_label_left  = '=';
									$value_label_right = '$';
							}
							?>
                            <tr class="<?php echo esc_attr( self::set( array( 'price-rule-row-default' ) ) ) ?>">
                                <th><?php esc_html_e( 'Default', 'woo-alidropship' ) ?></th>
                                <th>
                                    <select name="<?php self::set_params( 'price_default[plus_value_type]', false ); ?>"
                                            class="vi-ui fluid dropdown <?php self::set_params( 'plus_value_type', true ); ?>">
                                        <option value="fixed" <?php selected( $plus_value_type_d, 'fixed' ) ?>><?php esc_html_e( 'Increase by Fixed amount($)', 'woo-alidropship' ) ?></option>
                                        <option value="percent" <?php selected( $plus_value_type_d, 'percent' ) ?>><?php esc_html_e( 'Increase by Percentage(%)', 'woo-alidropship' ) ?></option>
                                        <option value="multiply" <?php selected( $plus_value_type_d, 'multiply' ) ?>><?php esc_html_e( 'Multiply with', 'woo-alidropship' ) ?></option>
                                        <option value="set_to" <?php selected( $plus_value_type_d, 'set_to' ) ?>><?php esc_html_e( 'Set to', 'woo-alidropship' ) ?></option>
                                    </select>
                                </th>
                                <th>
                                    <div class="vi-ui right labeled input fluid">
                                        <label for="amount"
                                               class="vi-ui label <?php self::set_params( 'value-label-left', true ); ?>"><?php echo esc_html( $value_label_left ) ?></label>
                                        <input type="number" min="-1" step="any"
                                               value="<?php echo esc_attr( $plus_sale_value_d ); ?>"
                                               name="<?php self::set_params( 'price_default[plus_sale_value]', false ); ?>"
                                               class="<?php self::set_params( 'plus_sale_value', true ); ?>">
                                        <div class="vi-ui basic label <?php self::set_params( 'value-label-right', true ); ?>"><?php echo esc_html( $value_label_right ) ?></div>
                                    </div>
                                </th>
                                <th>
                                    <div class="vi-ui right labeled input fluid">
                                        <label for="amount"
                                               class="vi-ui label <?php self::set_params( 'value-label-left', true ); ?>"><?php echo esc_html( $value_label_left ) ?></label>
                                        <input type="number" min="0" step="any"
                                               value="<?php echo esc_attr( $plus_value_d ); ?>"
                                               name="<?php self::set_params( 'price_default[plus_value]', false ); ?>"
                                               class="<?php self::set_params( 'plus_value', true ); ?>">
                                        <div class="vi-ui basic label <?php self::set_params( 'value-label-right', true ); ?>"><?php echo esc_html( $value_label_right ) ?></div>
                                    </div>
                                </th>
                                <th>
                                </th>
                            </tr>
                            </tfoot>
                        </table>
                        <span class="<?php self::set_params( 'price_rule_add', true ) ?> vi-ui button icon positive mini" title="<?php esc_attr_e( 'Add a new range', 'woo-alidropship' ) ?>"><i class="icon add"></i></span>
                    </div>
                    <div class="vi-ui segment">
                        <table class="form-table">
                            <tbody>
                            <tr>
                                <td colspan="2">
                                    <div class="vi-ui positive small message">
                                        <div class="header">
											<?php esc_html_e( 'How does it work?', 'woo-alidropship' ); ?>
                                        </div>
                                        <ul class="list">
                                            <li><?php esc_html_e( 'Rules will be looped from top to bottom grouped by Compared part to find matches', 'woo-alidropship' ); ?></li>
                                            <li><?php esc_html_e( 'Your input price can only be applied by 1 rule for each part(fraction/integer)=>maximum 2 rules in total(1 for Integer part and 1 for Fraction part)', 'woo-alidropship' ); ?></li>
                                            <li><?php esc_html_e( 'Rules for Fraction part will be applied before rules for Integer part', 'woo-alidropship' ); ?></li>
                                        </ul>
                                        <div class="header">
											<?php esc_html_e( 'Rules for Fraction part', 'woo-alidropship' ); ?>
                                        </div>
                                        <ul class="list">
                                            <li><?php echo wp_kses_post( __( 'Leave Price range <strong>empty</strong> to apply to all prices that have decimal part matches the Compared part range', 'woo-alidropship' ) ); ?></li>
                                            <li><?php echo wp_kses_post( __( 'Leave Compared part range <strong>empty</strong> to apply to all prices in the Price range', 'woo-alidropship' ) ); ?></li>
                                            <li><?php echo wp_kses_post( __( 'Can use an <strong>x</strong> in New value of compared part to remain the respective digit in the Compared part of input price', 'woo-alidropship' ) ); ?></li>
                                            <li><?php echo wp_kses_post( sprintf( _n( 'New value of compared part can contain maximum %s digit which is the Number of decimals in your <a href="admin.php?page=wc-settings#woocommerce_price_num_decimals" target="_blank">WooCommerce settings</a>', 'New value of compared part can contain maximum %s digits which is the Number of decimals in your <a href="admin.php?page=wc-settings#woocommerce_price_num_decimals" target="_blank">WooCommerce settings</a>', wc_get_price_decimals(), 'woo-alidropship' ), wc_get_price_decimals() ) ); //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?></li>
                                        </ul>
                                        <div class="header">
											<?php esc_html_e( 'Rules for Integer part', 'woo-alidropship' ); ?>
                                        </div>
                                        <ul class="list">
                                            <li><?php esc_html_e( 'Maximum number of digits of Compared part range is 1 subtracted from the minimum number of digits of Price range', 'woo-alidropship' ); ?></li>
                                            <li><?php esc_html_e( 'Maximum number of digits of New value of compared part is the maximum number of digits of Compared part range', 'woo-alidropship' ); ?></li>
                                            <li><?php echo wp_kses_post( __( 'Leave Compared part range <strong>empty</strong> to apply to all prices in the Price range', 'woo-alidropship' ) ); ?></li>
                                        </ul>
                                        <div class="vi-ui segment">
                                            <div class="vi-ui accordion">
                                                <div class="title"><?php esc_html_e( 'View detailed example with explanation', 'woo-alidropship' ) ?></div>
                                                <div class="content"><img src="<?php echo esc_url( VI_WOO_ALIDROPSHIP_IMAGES . 'price-format-rules.png' ); ?>" alt="">
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </td>
                            </tr>
                            <tr>
                                <th>
                                    <label for="<?php self::set_params( 'format_price_rules_enable', true ) ?>">
										<?php esc_html_e( 'Price format', 'woo-alidropship' ) ?>
                                    </label>
                                </th>
                                <td>
                                    <div class="vi-ui toggle checkbox">
                                        <input id="<?php self::set_params( 'format_price_rules_enable', true ) ?>"
                                               type="checkbox" <?php checked( self::$settings->get_params( 'format_price_rules_enable' ), 1 ) ?>
                                               tabindex="0" class="hidden" value="1"
                                               name="<?php self::set_params( 'format_price_rules_enable' ) ?>"/>
                                        <label><?php esc_html_e( 'Adjust product prices following below rules after prices are calculated with above rules', 'woo-alidropship' ) ?></label>
                                    </div>
                                </td>
                            </tr>
                            </tbody>
                        </table>
						<?php
						if ( $decimals < 1 ) {
							?>
                            <div class="vi-ui message">
								<?php echo wp_kses_post( sprintf( __( 'Rules for Fraction part will not take effect because you set %s for Number of decimals in your <a href="admin.php?page=wc-settings#woocommerce_price_num_decimals" target="_blank">WooCommerce settings</a>', 'woo-alidropship' ), $decimals ) ); //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?>
                            </div>
							<?php
						}
						?>
                        <table class="vi-ui table <?php self::set_params( 'format_price_rules_table', true ) ?>">
                            <thead>
                            <tr>
                                <th><?php esc_html_e( 'No.', 'woo-alidropship' ) ?></th>
                                <th><?php esc_html_e( 'Price range', 'woo-alidropship' ) ?></th>
                                <th class="<?php self::set_params( 'format_price_rules_col', true ) ?>"><?php esc_html_e( 'Compared part', 'woo-alidropship' ) ?></th>
                                <th><?php esc_html_e( 'Compared part range', 'woo-alidropship' ) ?>
                                <th class="<?php self::set_params( 'format_price_rules_col', true ) ?>"><?php esc_html_e( 'New value of compared part', 'woo-alidropship' ) ?></th>
                            </tr>
                            </thead>
                            <tbody class="<?php self::set_params( 'format_price_rules_container', true ) ?> ui-sortable">
							<?php
							$format_price_rules = self::$settings->get_params( 'format_price_rules' );

							if ( ! is_array( $format_price_rules ) || ! count( $format_price_rules ) ) {
								$format_price_rules = array(
									array(
										'from'       => '0',
										'to'         => '0',
										'part'       => 'fraction',
										'value_from' => '0',
										'value_to'   => '0',
										'value'      => '0',
									)
								);
							}
							foreach ( $format_price_rules as $rule_no => $format_price_rule ) {
								$label_class    = self::set( 'format-price-rules-label' );
								$label_class    .= $format_price_rule['part'] === 'fraction' ? ' left' : ' right';
								$label_integer  = '.0';
								$label_fraction = '0.';
								?>
                                <tr>
                                    <th>
                                        <span class="<?php self::set_params( 'format_price_rules_number', true ); ?>"><?php echo esc_html( $rule_no + 1 ); ?></span>
                                    </th>
                                    <td>
                                        <div class="equal width fields">
                                            <div class="field <?php self::set_params( 'error-message-parent', true ); ?>">
                                                <div class="vi-ui left labeled input fluid">
                                                    <label for="amount" class="vi-ui label">$</label>
                                                    <input
                                                            type="number"
                                                            step="<?php echo esc_attr( $decimals_unit ) ?>"
                                                            min="0"
                                                            value="<?php echo esc_attr( $format_price_rule['from'] ) ?>"
                                                            name="<?php self::set_params( 'format_price_rules[from]', false, true ); ?>"
                                                            class="<?php self::set_params( 'format_price_rules_from', true ); ?>">
                                                </div>
                                                <div class="<?php self::set_params( 'error-message', true ); ?>"></div>
                                            </div>
                                            <span class="<?php self::set_params( 'price_from_to_separator', true ); ?>">-</span>
                                            <div class="field <?php self::set_params( 'error-message-parent', true ); ?>">
                                                <div class="vi-ui left labeled input fluid">
                                                    <label for="amount" class="vi-ui label">$</label>
                                                    <input
                                                            type="number"
                                                            min="0"
                                                            step="<?php echo esc_attr( $decimals_unit ) ?>"
                                                            value="<?php echo esc_attr( $format_price_rule['to'] ) ?>"
                                                            name="<?php self::set_params( 'format_price_rules[to]', false, true ); ?>"
                                                            class="<?php self::set_params( 'format_price_rules_to', true ); ?>">
                                                </div>
                                                <div class="<?php self::set_params( 'error-message', true ); ?>"></div>
                                            </div>
                                        </div>
                                    </td>
                                    <td>
                                        <select name="<?php self::set_params( 'format_price_rules[part]', false, true ); ?>"
                                                class="vi-ui fluid dropdown <?php self::set_params( 'format_price_rules_part', true ); ?>">
                                            <option value="integer" <?php selected( $format_price_rule['part'], 'integer' ) ?>><?php esc_html_e( 'Integer', 'woo-alidropship' ) ?></option>
                                            <option value="fraction" <?php selected( $format_price_rule['part'], 'fraction' ) ?>><?php esc_html_e( 'Fraction', 'woo-alidropship' ) ?></option>
                                        </select>
                                    </td>
                                    <td>
                                        <div class="equal width fields">
                                            <div class="field <?php self::set_params( 'error-message-parent', true ); ?>">
                                                <div class="vi-ui <?php echo esc_attr( $label_class ) ?> labeled input fluid">
                                                    <label for="amount"
                                                           class="vi-ui label <?php self::set_params( 'format_price_rules_label_fraction', true ); ?>"><?php echo esc_html( $label_fraction ) ?></label>
                                                    <input
                                                            type="number"
                                                            step="1"
                                                            min="0"
                                                            value="<?php echo esc_attr( $format_price_rule['value_from'] ) ?>"
                                                            name="<?php self::set_params( 'format_price_rules[value_from]', false, true ); ?>"
                                                            class="<?php self::set_params( 'format_price_rules_value_from', true ); ?>">
                                                    <label for="amount"
                                                           class="vi-ui label <?php self::set_params( 'format_price_rules_label_integer', true ); ?>"><?php echo esc_html( $label_integer ) ?></label>
                                                </div>
                                                <div class="<?php self::set_params( 'error-message', true ); ?>"></div>
                                            </div>
                                            <span class="<?php self::set_params( 'price_from_to_separator', true ); ?>">-</span>
                                            <div class="field <?php self::set_params( 'error-message-parent', true ); ?>">
                                                <div class="vi-ui <?php echo esc_attr( $label_class ) ?> labeled input fluid">
                                                    <label for="amount"
                                                           class="vi-ui label <?php self::set_params( 'format_price_rules_label_fraction', true ); ?>"><?php echo esc_html( $label_fraction ) ?></label>
                                                    <input
                                                            type="number"
                                                            step="1"
                                                            min="0"
                                                            value="<?php echo esc_attr( $format_price_rule['value_to'] ) ?>"
                                                            name="<?php self::set_params( 'format_price_rules[value_to]', false, true ); ?>"
                                                            class="<?php self::set_params( 'format_price_rules_value_to', true ); ?>">
                                                    <label for="amount"
                                                           class="vi-ui label <?php self::set_params( 'format_price_rules_label_integer', true ); ?>"><?php echo esc_html( $label_integer ) ?></label>
                                                </div>
                                                <div class="<?php self::set_params( 'error-message', true ); ?>"></div>
                                            </div>
                                        </div>
                                    </td>
                                    <td class="<?php echo esc_attr( self::set( array(
										'format-price-rules-value-td',
										'error-message-parent'
									) ) ); ?>">
                                        <div class="vi-ui <?php echo esc_attr( $label_class ) ?> labeled input fluid">
                                            <label for="amount"
                                                   class="vi-ui label <?php self::set_params( 'format_price_rules_label_fraction', true ); ?>"><?php echo esc_html( $label_fraction ) ?></label>
                                            <input type="text"
                                                   value="<?php echo esc_attr( $format_price_rule['value'] ) ?>"
                                                   name="<?php self::set_params( 'format_price_rules[value]', false, true ); ?>"
                                                   class="<?php self::set_params( 'format_price_rules_value', true ); ?>">
                                            <label for="amount"
                                                   class="vi-ui label <?php self::set_params( 'format_price_rules_label_integer', true ); ?>"><?php echo esc_html( $label_integer ) ?></label>
                                        </div>
                                        <div class="<?php self::set_params( 'format_price_rules_action_buttons', true ) ?>">
                                            <i class="vi-ui icon copy green <?php self::set_params( 'format_price_rules_duplicate', true ) ?>"
                                               title="<?php esc_attr_e( 'Duplicate this row', 'woo-alidropship' ) ?>"></i>
                                            <i class="vi-ui icon trash red <?php self::set_params( 'format_price_rules_remove', true ) ?>"
                                               title="<?php esc_attr_e( 'Remove this row', 'woo-alidropship' ) ?>"></i>
                                        </div>
                                        <div class="<?php self::set_params( 'error-message', true ); ?>"></div>
                                    </td>
                                </tr>
								<?php
							}
							?>
                            </tbody>
                        </table>
                        <div class="equal width fields">
                            <div class="field">
                                <div class="vi-ui right labeled input fluid wad-labeled-button">
                                    <input type="number"
                                           placeholder="<?php esc_attr_e( 'Enter a price to test', 'woo-alidropship' ) ?>"
                                           step="<?php echo esc_attr( $decimals_unit ) ?>"
                                           min="0"
                                           value="<?php echo esc_attr( self::$settings->get_params( 'format_price_rules_test' ) ) ?>"
                                           name="<?php self::set_params( 'format_price_rules_test', false, false ); ?>"
                                           class="<?php self::set_params( 'format_price_rules_test', true ); ?>">
                                    <label for="amount" class="vi-ui label"><span class="vi-ui positive button tiny <?php self::set_params( 'format_price_rules_test_button', true ); ?>"><?php esc_html_e( 'View result', 'woo-alidropship' ) ?></span></label>
                                </div>
                            </div>
                            <div class="field <?php self::set_params( 'format_price_rules_test_result_container', true ); ?>">
                                <span class="<?php self::set_params( 'format_price_rules_test_result', true ); ?>"></span>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="vi-ui bottom attached tab segment vi-wad-tab-content" data-tab="product_update">
                    <div class="vi-ui negative message">
						<?php esc_html_e( 'Product auto-sync is currently DISABLED', 'woo-alidropship' ) ?>
                    </div>
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th><label"><?php esc_html_e( 'Enable product auto-sync', 'woo-alidropship' ); ?></label></th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Sync products every', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Sync products at', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Use HTTP service URL', 'woo-alidropship' ) ?></label>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                    <div class="vi-ui message positive">
						<?php esc_html_e( 'Configure what the plugin will do when you update product manually with the chrome extension', 'woo-alidropship' ) ?>
                    </div>
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Product status', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Only sync products with selected statuses. Leave empty to select all statuses.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Sync price', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Sync price of WooCommerce products with AliExpress. All rules in Product Price tab will be applied to new price.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Exclude on-sale products', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Do not sync price if a product is on sale', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Exclude products', 'woo-alidropship' ); ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'If you don\'t want to sync price of some specific products, enter them here', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Exclude categories', 'woo-alidropship' ); ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'If you don\'t want to sync price of products from some specific categories, enter them here', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Sync quantity', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Sync quantity of WooCommerce products with AliExpress', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'If a product is available purchase', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Select an action when an AliExpress product is available purchase', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'If a product is out of stock', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Select an action when an AliExpress product is out-of-stock', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'If a product is no longer available', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Select an action when an AliExpress product is no longer available', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'If selected shipping method is no longer available', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Select an action when an AliExpress product\'s selected shipping method is removed or no shipping methods available', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'If a variation is no longer available', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Select an action when a variation of an AliExpress product is no longer available', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>

                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Notification email', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'When syncing products, send email to admin if an AliExpress product is no longer available/is out of stock/has price changed', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Received address', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php echo wp_kses_post( __( 'Notification will be sent to this address. If not set, the "From" address in <a target="_blank" href="admin.php?page=wc-settings&tab=email">WooCommerce settings/Emails</a> will be used.', 'woo-alidropship' ) ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Manual sync with current Ali country', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <div class="vi-ui bottom attached tab segment vi-wad-attributes-tab vi-wad-tab-content" data-tab="attributes">
                    <div class="vi-ui message positive">
						<?php esc_attr_e( 'This feature is to automatically replace original attribute term with respective value in the Import list. This does not apply to products whose attributes were edited.', 'woo-alidropship' ) ?>
                    </div>
                    <div class="vi-ui labeled left input fluid">
                        <label class="vi-ui label green"><?php esc_attr_e( 'Search term', 'woo-alidropship' ) ?></label>
                        <input type="text" class="<?php echo esc_attr( self::set( 'product-attribute-search' ) ) ?>"
                               placeholder="<?php esc_attr_e( 'Enter attribute term to search', 'woo-alidropship' ) ?>">
                    </div>
                    <div class="<?php echo esc_attr( self::set( 'attributes-mapping-table-container' ) ) ?>">
                        <table class="vi-ui table celled <?php echo esc_attr( self::set( 'attributes-mapping-table' ) ) ?>">
                            <thead>
                            <tr>
                                <th><?php esc_html_e( 'Attribute slug', 'woo-alidropship' ) ?></th>
                                <th><?php esc_html_e( 'Original attribute term(case-insensitive)', 'woo-alidropship' ) ?></th>
                                <th><?php esc_html_e( 'Replacement', 'woo-alidropship' ) ?></th>
                            </tr>
                            </thead>
                            <tbody class="<?php echo esc_attr( self::set( 'attributes-mapping' ) ) ?>">
                            <tr>
                                <td colspan="3">
                                    <a class="vi-ui button" target="_blank"
                                       href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                </td>
                            </tr>
                            </tbody>
                        </table>
                    </div>
                    <div class="<?php echo esc_attr( self::set( array(
						'overlay',
					) ) ) ?>">
                        <div class="vi-ui indicating progress standard active <?php echo esc_attr( self::set( 'attributes-mapping-progress' ) ) ?>">
                            <div class="label"></div>
                            <div class="bar">
                                <div class="progress"></div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="vi-ui bottom attached tab segment vi-wad-tab-content" data-tab="video">
                    <div class="vi-ui positive message">
                        <ul class="list">
                            <li><?php esc_html_e( 'Product video uses original AliExpress video url', 'woo-alidropship' ); ?></li>
                            <li><?php esc_html_e( 'For products you imported before 1.0.9, please sync them for videos to be updated', 'woo-alidropship' ); ?></li>
                        </ul>
                    </div>
                    <div class="vi-ui yellow message">
						<?php esc_html_e( 'Note: In some cases, AliExpress may block image/video access. If you see that the videos don’t display properly, please disable this feature and download them instead of using external linksl', 'woo-alidropship' ); ?>
                    </div>
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Import product video', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Product video will be imported as an external link', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Show product video tab', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Display product video on a separate tab in the frontend', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Video tab priority', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p class="description"><?php esc_html_e( 'You can adjust this value to change order of video tab', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Make video full tab width', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Add video to description', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <div class="vi-ui bottom attached tab segment vi-wad-tab-content" data-tab="review">
                    <div class="vi-ui yellow message">
                        <?php esc_html_e( 'Please note that this feature applies only to products imported through the extension.', 'woo-alidropship' ); ?>
                    </div>
                    <table class="form-table">
                        <tbody>
                        <?php
                        $fields = [
                                'product_import_review'     => [
                                        'title' => esc_html__( 'Import review', 'woo-alidropship'),
                                        'desc'  => [
                                                __( ' Turn on this option to enable importing product reviews','woo-alidropship' ),
                                        ],
                                ],
                                'product_review_limit'      => [
                                        'title' => esc_html__( 'Number of reviews imported','woo-alidropship'),
                                ],
                                'product_review_rating'     => [
                                        'title'    => esc_html__( 'Reviews rating', 'woo-alidropship' ),
                                        'desc'     => [
                                                __( 'The type of imported review', 'woo-alidropship' ),
                                        ],
                                ],
                                'product_review_skip_empty' => [
                                        'title' => esc_html__( 'Skip if empty', 'woo-alidropship' ),
                                        'desc'  => [
                                                __( 'Don’t import reviews that have empty content', 'woo-alidropship' ),
                                        ],
                                ],
                                'product_review_status'     => [
                                        'title'   => esc_html__( 'Review status','woo-alidropship' ),
                                        'desc'    => [
                                                __( 'The status is set for the imported review','woo-alidropship'),
                                        ],
                                ],
                                'product_review_verified'   => [
                                        'title' => esc_html__( 'Set review verified', 'woo-alidropship' ),
                                        'desc'  => [
                                                __( 'Mark imported reviews as Verified owner', 'woo-alidropship' ),
                                        ],
                                ],
                        ];
                        foreach ( $fields as $field ) {
                            ?>
                            <tr>
                                <th>
                                    <label><?php echo wp_kses_post($field['title']??'') ?></label>
                                </th>
                                <td>
                                    <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                    <?php
                                    if (!empty($field['desc'])){
                                        if (is_array($field['desc'])) {
                                            foreach ($field['desc'] as $desc) {
                                                echo wp_kses_post(sprintf('<p class="description">%s</p>',$desc));
                                            }
                                        }else{
                                            echo wp_kses_post(sprintf('<p class="description">%s</p>', $field['desc']));
                                        }
                                    }
                                    ?>
                                </td>
                            </tr>
                            <?php
                        }
                        ?>
                        </tbody>
                    </table>
                </div>
                <div class="vi-ui bottom attached tab segment" data-tab="product_split">
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Automatically remove attribute', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Instead of deleting old product to create a new one, it will update the overridden old product\'s prices/stock/attributes/variations based on the new data. This way, data such as reviews, metadata... will not be lost.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <div class="vi-ui bottom attached tab segment" data-tab="override">
                    <div class="vi-ui positive small message">
						<?php esc_html_e( 'Below options are used when you override a product', 'woo-alidropship' ); ?>
                    </div>
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'override_keep_product', true ) ?>"><?php esc_html_e( 'Keep Woo product', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'override_keep_product', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'override_keep_product' ), 1 ) ?>
                                           tabindex="0"
                                           class="<?php self::set_params( 'override_keep_product', true ) ?>"
                                           value="1"
                                           name="<?php self::set_params( 'override_keep_product' ) ?>"/>
                                    <label><?php esc_html_e( 'Instead of deleting old product to create a new one, it will update the overridden old product\'s prices/stock/attributes/variations based on the new data. This way, data such as reviews, metadata... will not be lost.', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Link existing variations only', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Do not create new variations even if the number of variations you select when overriding/reimporting a product is greater than the number of variations of target product.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Keep SKU', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'override_find_in_orders', true ) ?>"><?php esc_html_e( 'Find in unfulfilled orders', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'override_find_in_orders', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'override_find_in_orders' ), 1 ) ?>
                                           tabindex="0"
                                           class="<?php self::set_params( 'override_find_in_orders', true ) ?>"
                                           value="1"
                                           name="<?php self::set_params( 'override_find_in_orders' ) ?>"/>
                                    <label><?php esc_html_e( 'Check for existence of overridden product in unfulfilled orders before overriding', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th><?php esc_html_e( 'Override title', 'woo-alidropship' ) ?></th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'override_title', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'override_title' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'override_title' ) ?>"/>
                                    <label><?php esc_html_e( 'Replace title of overridden product with new product\'s title', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th><?php esc_html_e( 'Override images', 'woo-alidropship' ) ?></th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'override_images', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'override_images' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'override_images' ) ?>"/>
                                    <label><?php esc_html_e( 'Replace images and gallery of overridden product with new product\'s images and gallery', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Override specifications', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'Replace the additional information of the overridden product with the new product\'s specification.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th><?php esc_html_e( 'Override description', 'woo-alidropship' ) ?></th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'override_description', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'override_description' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'override_description' ) ?>"/>
                                    <label><?php esc_html_e( 'Replace description and short description of overridden product with new product\'s description and short description', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th><?php esc_html_e( 'Hide options', 'woo-alidropship' ) ?></th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input id="<?php self::set_params( 'override_hide', true ) ?>"
                                           type="checkbox" <?php checked( self::$settings->get_params( 'override_hide' ), 1 ) ?>
                                           tabindex="0" class="hidden" value="1"
                                           name="<?php self::set_params( 'override_hide' ) ?>"/>
                                    <label><?php esc_html_e( 'Do not show these options when overriding product', 'woo-alidropship' ) ?></label>
                                </div>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <div class="vi-ui bottom attached tab segment" data-tab="migration">
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Link variation only', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'When migrating a product from other plugins(Link existing Woo product), only link existing variations', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <div class="vi-ui bottom attached tab segment" data-tab="fulfill">
                    <div class="vi-ui message positive">
                        <ul class="list">
                            <li><?php esc_html_e( 'Access token is used to bulk fulfill AliExpress orders/automatically sync product price and stock without using chrome extension', 'woo-alidropship' ) ?></li>
                        </ul>
                    </div>
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'fulfill_billing_fields_in_latin', true ) ?>">
									<?php esc_html_e( 'Require billing fields in Latin', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input type="checkbox"
                                           name="<?php self::set_params( 'fulfill_billing_fields_in_latin' ) ?>"
                                           id="<?php self::set_params( 'fulfill_billing_fields_in_latin', true ) ?>"
                                           class="<?php self::set_params( 'fulfill_billing_fields_in_latin', true ) ?>"
                                           value="1" <?php checked( self::$settings->get_params( 'fulfill_billing_fields_in_latin' ), 1 ) ?>>
                                    <label></label>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="auto-update-key"><?php esc_html_e( 'AliExpress API', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <table class="vi-ui table celled <?php echo esc_attr( self::set( 'access-token-table' ) ) ?>">
                                    <thead>
                                    <tr>
                                        <th><?php esc_html_e( 'AliExpress account', 'woo-alidropship' ) ?></th>
                                        <th><?php esc_html_e( 'Expire time', 'woo-alidropship' ) ?></th>
                                        <th><?php esc_html_e( 'Default', 'woo-alidropship' ) ?></th>
                                    </tr>
                                    </thead>
                                    <tbody>
                                    <tr>
                                        <td colspan="3">
                                            <a class="vi-ui button" target="_blank"
                                               href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                        </td>
                                    </tr>
                                    </tbody>
                                </table>
                            </td>
                        </tr>
                        <tr>
                            <th><?php esc_html_e( 'Carrier company', 'woo-alidropship' ) ?></th>
                            <td>
                                <select class="vi-ui fluid dropdown"
                                        name="<?php self::set_params( 'fulfill_default_carrier' ) ?>">
									<?php
									$saved = self::$settings->get_params( 'fulfill_default_carrier' );
									foreach ( $shipping_companies as $key => $value ) {
										?>
                                        <option value="<?php echo esc_attr( $key ) ?>" <?php selected( $saved, $key ) ?>><?php echo esc_html( $value ) ?></option>
										<?php
									}
									?>
                                </select>
                                <p><?php esc_html_e( 'Default carrier company', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'fulfill_default_phone_number', true ) ?>">
									<?php esc_html_e( 'Default phone number', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                                <div class="vi-ui labeled left input fluid <?php self::set_params( 'fulfill_default_phone_number_container', true ) ?>">
                                    <label class="vi-ui label">
                                        <select class="vi-ui dropdown search"
                                                name="<?php self::set_params( 'fulfill_default_phone_country' ) ?>"
                                                class="<?php self::set_params( 'fulfill_default_phone_country', true ) ?>"
                                                id="<?php self::set_params( 'fulfill_default_phone_country', true ) ?>">
											<?php
											$phone_country   = self::$settings->get_params( 'fulfill_default_phone_country' );
											$phone_countries = VI_WOO_ALIDROPSHIP_Admin_API::get_phone_country_code();
											ksort( $phone_countries );
											foreach ( $phone_countries as $phone_country_k => $phone_country_v ) {
												?>
                                                <option value="<?php echo esc_attr( $phone_country_k ) ?>" <?php selected( $phone_country, $phone_country_k ) ?>><?php echo esc_html( $phone_country_v ? "{$phone_country_k}({$phone_country_v})" : $phone_country_k ) ?></option>
												<?php
											}
											?>
                                        </select>
                                    </label>
                                    <input type="tel"
                                           id="<?php self::set_params( 'fulfill_default_phone_number', true ) ?>"
                                           name="<?php self::set_params( 'fulfill_default_phone_number' ) ?>"
                                           value="<?php echo esc_attr( self::$settings->get_params( 'fulfill_default_phone_number' ) ) ?>">
                                </div>
                                <p><?php esc_html_e( 'If an order does not have phone number, this number will be used when fulfilling AliExpress order', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'fulfill_default_phone_number_override', true ) ?>"><?php esc_html_e( 'Override customer phone number', 'woo-alidropship' ) ?></label>
                            <td>
                                <div class="vi-ui toggle checkbox">
                                    <input type="checkbox"
                                           name="<?php self::set_params( 'fulfill_default_phone_number_override' ) ?>"
                                           id="<?php self::set_params( 'fulfill_default_phone_number_override', true ) ?>"
                                           class="<?php self::set_params( 'fulfill_default_phone_number_override', true ) ?>"
                                           value="1" <?php checked( self::$settings->get_params( 'fulfill_default_phone_number_override' ), 1 ) ?>>
                                    <label><?php esc_html_e( 'Always use Default phone number when fulfilling AliExpress order no matter your customers have phone number or not', 'woo-alidropship' ) ?></label>
                                </div>
                                <p><?php echo wp_kses_post( __( '<strong>*Note:</strong> This only overrides a customer\'s phone number if the default phone country is the same as the customer\'s country', 'woo-alidropship' ) ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'cpf_custom_meta_key', true ) ?>"><?php esc_html_e( 'CPF meta field', 'woo-alidropship' ) ?></label>
                            <td>
                                <input type="text"
                                       name="<?php self::set_params( 'cpf_custom_meta_key' ) ?>"
                                       id="<?php self::set_params( 'cpf_custom_meta_key', true ) ?>"
                                       class="<?php self::set_params( 'cpf_custom_meta_key', true ) ?>"
                                       value="<?php echo esc_attr( self::$settings->get_params( 'cpf_custom_meta_key' ) ) ?>">
                                <p><?php esc_html_e( 'The order meta field that a 3rd party plugin uses to store customer\'s CPF field.', 'woo-alidropship' ) ?></p>
                                <p><?php esc_html_e( 'This is used only for Customers from Brazil. If empty, billing company will be used as CPF when fulfilling AliExpress orders.', 'woo-alidropship' ) ?></p>
                                <p><?php echo wp_kses_post( __( 'If you use <a target="_blank" href="https://wordpress.org/plugins/woocommerce-extra-checkout-fields-for-brazil/">Brazilian Market on WooCommerce</a>, please fill this option with <strong>_billing_cpf</strong>', 'woo-alidropship' ) ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'billing_number_meta_key', true ) ?>"><?php esc_html_e( 'Billing number meta field', 'woo-alidropship' ) ?></label>
                            <td>
                                <input type="text"
                                       name="<?php self::set_params( 'billing_number_meta_key' ) ?>"
                                       id="<?php self::set_params( 'billing_number_meta_key', true ) ?>"
                                       class="<?php self::set_params( 'billing_number_meta_key', true ) ?>"
                                       value="<?php echo esc_attr( self::$settings->get_params( 'billing_number_meta_key' ) ) ?>">
                                <p><?php esc_html_e( 'If you customize checkout fields to add the billing number field, please enter the order meta field which is used to store billing number here.', 'woo-alidropship' ) ?></p>
                                <p><?php echo wp_kses_post( __( 'If you use <a target="_blank" href="https://wordpress.org/plugins/woocommerce-extra-checkout-fields-for-brazil/">Brazilian Market on WooCommerce</a>, please fill this option with <strong>_billing_number</strong>', 'woo-alidropship' ) ) ?></p>
                                <p><?php echo wp_kses_post( __( '<strong>*Caution: </strong>If you already use a custom PHP snippet to append billing number to order address via <strong>vi_wad_fulfillment_customer_info</strong> filter hook, please leave this field empty to avoid billing number being added twice to order address which makes the address become incorrect.', 'woo-alidropship' ) ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'shipping_number_meta_key', true ) ?>"><?php esc_html_e( 'Shipping number meta field', 'woo-alidropship' ) ?></label>
                            <td>
                                <input type="text"
                                       name="<?php self::set_params( 'shipping_number_meta_key' ) ?>"
                                       id="<?php self::set_params( 'shipping_number_meta_key', true ) ?>"
                                       class="<?php self::set_params( 'shipping_number_meta_key', true ) ?>"
                                       value="<?php echo esc_attr( self::$settings->get_params( 'shipping_number_meta_key' ) ) ?>">
                                <p><?php esc_html_e( 'If you customize checkout fields to add the shipping number field, please enter the order meta field which is used to store shipping number here.', 'woo-alidropship' ) ?></p>
                                <p><?php echo wp_kses_post( __( 'If you use <a target="_blank" href="https://wordpress.org/plugins/woocommerce-extra-checkout-fields-for-brazil/">Brazilian Market on WooCommerce</a>, please fill this option with <strong>_shipping_number</strong>', 'woo-alidropship' ) ) ?></p>
                                <p><?php echo wp_kses_post( __( '<strong>*Caution: </strong>If you already use a custom PHP snippet to append shipping number to order address via <strong>vi_wad_fulfillment_customer_info</strong> filter hook, please leave this field empty to avoid shipping number being added twice to order address which makes the address become incorrect.', 'woo-alidropship' ) ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'billing_neighborhood_meta_key', true ) ?>"><?php esc_html_e( 'Billing neighborhood meta field', 'woo-alidropship' ) ?></label>
                            <td>
                                <input type="text"
                                       name="<?php self::set_params( 'billing_neighborhood_meta_key' ) ?>"
                                       id="<?php self::set_params( 'billing_neighborhood_meta_key', true ) ?>"
                                       class="<?php self::set_params( 'billing_neighborhood_meta_key', true ) ?>"
                                       value="<?php echo esc_attr( self::$settings->get_params( 'billing_neighborhood_meta_key' ) ) ?>">
                                <p><?php esc_html_e( 'If you customize checkout fields to add the billing neighborhood field, please enter the order meta field which is used to store billing neighborhood here.', 'woo-alidropship' ) ?></p>
                                <p><?php echo wp_kses_post( __( 'If you use <a target="_blank" href="https://wordpress.org/plugins/woocommerce-extra-checkout-fields-for-brazil/">Brazilian Market on WooCommerce</a>, please fill this option with <strong>_billing_neighborhood</strong>', 'woo-alidropship' ) ) ?></p>
                                <p><?php echo wp_kses_post( __( '<strong>*Caution: </strong>If you already use a custom PHP snippet to append billing neighborhood to order address via <strong>vi_wad_fulfillment_customer_info</strong> filter hook, please leave this field empty to avoid billing neighborhood being added twice to order address which makes the address become incorrect.', 'woo-alidropship' ) ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'shipping_neighborhood_meta_key', true ) ?>"><?php esc_html_e( 'Shipping neighborhood meta field', 'woo-alidropship' ) ?></label>
                            <td>
                                <input type="text"
                                       name="<?php self::set_params( 'shipping_neighborhood_meta_key' ) ?>"
                                       id="<?php self::set_params( 'shipping_neighborhood_meta_key', true ) ?>"
                                       class="<?php self::set_params( 'shipping_neighborhood_meta_key', true ) ?>"
                                       value="<?php echo esc_attr( self::$settings->get_params( 'shipping_neighborhood_meta_key' ) ) ?>">
                                <p><?php esc_html_e( 'If you customize checkout fields to add the shipping neighborhood field, please enter the order meta field which is used to store shipping neighborhood here.', 'woo-alidropship' ) ?></p>
                                <p><?php echo wp_kses_post( __( 'If you use <a target="_blank" href="https://wordpress.org/plugins/woocommerce-extra-checkout-fields-for-brazil/">Brazilian Market on WooCommerce</a>, please fill this option with <strong>_shipping_neighborhood</strong>', 'woo-alidropship' ) ) ?></p>
                                <p><?php echo wp_kses_post( __( '<strong>*Caution: </strong>If you already use a custom PHP snippet to append shipping neighborhood to order address via <strong>vi_wad_fulfillment_customer_info</strong> filter hook, please leave this field empty to avoid shipping neighborhood being added twice to order address which makes the address become incorrect.', 'woo-alidropship' ) ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'rut_meta_key', true ) ?>"><?php esc_html_e( 'RUT meta field', 'woo-alidropship' ) ?></label>
                            <td>
                                <input type="text"
                                       name="<?php self::set_params( 'rut_meta_key' ) ?>"
                                       id="<?php self::set_params( 'rut_meta_key', true ) ?>"
                                       class="<?php self::set_params( 'rut_meta_key', true ) ?>"
                                       value="<?php echo esc_attr( self::$settings->get_params( 'rut_meta_key' ) ) ?>">
                                <p><?php esc_html_e( 'The order meta field that a 3rd party plugin uses to store customer\'s RUT number.', 'woo-alidropship' ) ?></p>
                                <p><?php esc_html_e( 'RUT number is required when you fulfill orders of Customers from Chile.', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'rfc_curp_meta_key', true ) ?>"><?php esc_html_e( 'RFC/CURP meta field', 'woocommerce-alidropship' ) ?></label>
                            <td>
                                <input type="text"
                                       name="<?php self::set_params( 'rfc_curp_meta_key' ) ?>"
                                       id="<?php self::set_params( 'rfc_curp_meta_key', true ) ?>"
                                       class="<?php self::set_params( 'rfc_curp_meta_key', true ) ?>"
                                       value="<?php echo esc_attr( self::$settings->get_params( 'rfc_curp_meta_key' ) ) ?>">
                                <p><?php esc_html_e( 'The order meta field that a 3rd party plugin uses to store customer\'s RFC/CURP number.', 'woocommerce-alidropship' ) ?></p>
                                <p><?php esc_html_e( 'RFC/CURP number is required when you fulfill orders of Customers from Mexico.', 'woocommerce-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'fulfill_order_note', true ) ?>">
									<?php esc_html_e( 'AliExpress Order note', 'woo-alidropship' ) ?>
                                </label>
                            </th>
                            <td>
                               <textarea type="text" id="<?php self::set_params( 'fulfill_order_note', true ) ?>"
                                         name="<?php self::set_params( 'fulfill_order_note' ) ?>"><?php echo wp_kses_post( self::$settings->get_params( 'fulfill_order_note' ) ) ?></textarea>
                                <p><?php esc_html_e( 'Add this note to AliExpress order when fulfilling with Chrome extension', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th><?php esc_html_e( 'Show action', 'woo-alidropship' ) ?></th>
                            <td>
                                <select class="vi-wad-order-status-for-fulfill vi-ui fluid dropdown" multiple="multiple"
                                        name="<?php self::set_params( 'order_status_for_fulfill', false, true ) ?>">
									<?php
									$saved = self::$settings->get_params( 'order_status_for_fulfill' );
									foreach ( wc_get_order_statuses() as $key => $value ) {
										$selected = '';
										if ( is_array( $saved ) ) {
											$selected = in_array( $key, $saved ) ? 'selected' : '';
										}
										?>
                                        <option value="<?php echo esc_attr( $key ) ?>" <?php echo esc_attr( $selected ) ?>><?php echo esc_html( $value ) ?></option>
										<?php
									}
									?>
                                </select>
                                <p><?php esc_html_e( 'Only show action buttons for orders with status among these', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th><?php esc_html_e( 'Change order status', 'woo-alidropship' ) ?></th>
                            <td>
								<?php
								$saved = self::$settings->get_params( 'order_status_after_sync' );
								?>
                                <select class="vi-wad-order-status-after-sync vi-ui fluid dropdown"
                                        name="<?php self::set_params( 'order_status_after_sync', false, false ) ?>">
                                    <option><?php esc_html_e( 'No change', 'woo-alidropship' ); ?></option>
									<?php
									foreach ( wc_get_order_statuses() as $key => $value ) {
										$selected = $key == $saved ? 'selected' : '';
										?>
                                        <option value="<?php echo esc_attr( $key ) ?>" <?php echo esc_attr( $selected ) ?>><?php echo esc_html( $value ) ?></option>
										<?php
									}
									?>
                                </select>
                                <p><?php esc_html_e( 'Automatically change order status after order id & tracking number of an order are synced successfully', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'update_order_auto', true ) ?>"><?php esc_html_e( 'Get tracking number automatically', 'woo-alidropship' ) ?></label>
                            <td>
                                <a class="vi-ui button" target="_blank"
                                   href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'When fulfilling orders, tracking number is not available yet. This function helps you check and sync tracking number automatically', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <div class="vi-ui bottom attached tab segment" data-tab="order-sync">
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Get tracking number automatically', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'When migrating a product from other plugins(Link existing Woo product), only link existing variations', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( "Order's priority", 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( 'When migrating a product from other plugins(Link existing Woo product), only link existing variations', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        <tr>
                            <th>
                                <label><?php esc_html_e( 'Tracking number existed', 'woo-alidropship' ) ?></label>
                            </th>
                            <td>
                                <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p><?php esc_html_e( "If you are sure that the tracking number will not change during the order's lifetime, use this option to exclude items that already have a tracking number from being synchronized.", 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <div class="vi-ui bottom attached tab segment vi-wad-tab-content" data-tab="shipping">
                    <div class="vi-ui message positive">
                        <ul class="list">
                            <li><?php esc_html_e( 'This feature allows your customers to select shipping method for each item like you do on AliExpress', 'woo-alidropship' ) ?></li>
                            <li><?php esc_html_e( 'Shipping cost of all cart items will be calculated and applied to the cart so you should not add shipping cost to product price when importing AliExpress products to avoid making the final price of products paid by your customers too high', 'woo-alidropship' ) ?></li>
                            <li><?php echo wp_kses_post( sprintf( __( 'You have to create at least 1 shipping method in <a target="_blank" href="%s">WooCommerce settings/Shipping</a>', 'woo-alidropship' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ) ) //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?></li>
                        </ul>
                    </div>
                    <table class="form-table">
                        <tbody>
                        <tr>
                            <th>
                                <label for="<?php self::set_params( 'ali_shipping', true ) ?>"><?php esc_html_e( 'Enable', 'woo-alidropship' ) ?></label>
                            <td>
                                <a class="vi-ui button" target="_blank"
                                   href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                                <p class="description"><?php esc_html_e( 'All options below will only work if this option is enabled', 'woo-alidropship' ) ?></p>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
				<?php
				if ( $this->orders_tracking_active ) {
					?>
                    <div class="vi-ui bottom attached tab segment" data-tab="tracking_carrier">
                        <div class="vi-ui positive tiny message">
                            <div class="header">
								<?php esc_html_e( 'Search and Replace', 'woo-alidropship' ); ?>
                            </div>
                            <ul class="list">
                                <li><?php echo wp_kses_post( __( 'This feature is used for <strong>Orders Tracking for WooCommerce</strong> plugin when syncing tracking info.', 'woo-alidropship' ) ); ?></li>
                                <li><?php echo wp_kses_post( __( 'When syncing orders with AliExpress, if Orders Tracking for WooCommerce plugin is active, it will automatically search for carrier URL in the existing carriers of this plugin (The <strong>Search and Replace</strong> function runs right before this step). If found, it will save tracking info with that carrier; otherwise, a new <strong>Custom carrier</strong> will be created.', 'woo-alidropship' ) ); ?></li>
                                <li><?php echo wp_kses_post( __( 'Skip if carrier is <strong>AliExpress Standard Shipping</strong>', 'woo-alidropship' ) ); ?></li>
                            </ul>
                        </div>
                        <div class="vi-ui segment string-replace-url">
                            <div class="vi-ui blue tiny message">
                                <div class="header">
									<?php esc_html_e( 'Replace carrier URL', 'woo-alidropship' ); ?>
                                </div>
                                <ul class="list">
                                    <li><?php esc_html_e( 'Replace carrier URL with respective URL below if DOMAIN of original carrier URL contains search strings(case-insensitive).', 'woo-alidropship' ); ?></li>
                                    <li><?php esc_html_e( 'Search will take place with priority from top to bottom and will STOP after first match.', 'woo-alidropship' ); ?></li>
                                </ul>
                            </div>
                            <table class="vi-ui table">
                                <thead>
                                <tr>
                                    <th><?php esc_html_e( 'Search', 'woo-alidropship' ); ?></th>
                                    <th><?php esc_html_e( 'Replace carrier URL with', 'woo-alidropship' ); ?></th>
                                    <th style="width: 1%"><?php esc_html_e( 'Remove', 'woo-alidropship' ); ?></th>
                                </tr>
                                </thead>
                                <tbody>
								<?php
								$carrier_url_replaces       = self::$settings->get_params( 'carrier_url_replaces' );
								$carrier_url_replaces_count = 1;
								if ( ! empty( $carrier_url_replaces['from_string'] ) && ! empty( $carrier_url_replaces['to_string'] ) && is_array( $carrier_url_replaces['from_string'] ) ) {
									$carrier_url_replaces_count = count( $carrier_url_replaces['from_string'] );
								}
								for ( $i = 0; $i < $carrier_url_replaces_count; $i ++ ) {
									?>
                                    <tr class="clone-source">
                                        <td>
                                            <input type="text"
                                                   value="<?php echo esc_attr( isset( $carrier_url_replaces['from_string'][ $i ] ) ? $carrier_url_replaces['from_string'][ $i ] : '' ) ?>"
                                                   name="<?php echo esc_attr( self::set( 'carrier_url_replaces[from_string][]' ) ) ?>">
                                        </td>
                                        <td>
                                            <input type="text"
                                                   placeholder="<?php esc_html_e( 'URL of a replacement carrier', 'woo-alidropship' ); ?>"
                                                   value="<?php echo esc_attr( isset( $carrier_url_replaces['to_string'][ $i ] ) ? $carrier_url_replaces['to_string'][ $i ] : '' ) ?>"
                                                   name="<?php echo esc_attr( self::set( 'carrier_url_replaces[to_string][]' ) ) ?>">
                                        </td>
                                        <td>
                                            <span class="vi-ui button negative tiny delete-string-replace-rule"><i
                                                        class="dashicons dashicons-trash"></i></span>
                                        </td>
                                    </tr>
									<?php
								}
								?>
                                </tbody>
                                <tfoot>
                                <tr>
                                    <th colspan="4">
                                        <span class="vi-ui button positive tiny add-string-replace-rule-url"><?php esc_html_e( 'Add', 'woo-alidropship' ); ?></span>
                                    </th>
                                </tr>
                                </tfoot>
                            </table>
                        </div>
                        <div class="vi-ui segment string-replace-name">
                            <div class="vi-ui blue tiny message">
                                <div class="header">
									<?php esc_html_e( 'Search and replace strings in Carrier name', 'woo-alidropship' ); ?>
                                </div>
                                <ul class="list">
                                    <li><?php esc_html_e( 'Search for strings in Carrier name and replace found strings with respective values.', 'woo-alidropship' ); ?></li>
                                    <li><?php echo wp_kses_post( __( 'This only works when new <strong>Custom carrier</strong> is created', 'woo-alidropship' ) ); ?></li>
                                </ul>
                            </div>
                            <table class="vi-ui table">
                                <thead>
                                <tr>
                                    <th><?php esc_html_e( 'Search', 'woo-alidropship' ); ?></th>
                                    <th><?php esc_html_e( 'Case Sensitive', 'woo-alidropship' ); ?></th>
                                    <th><?php esc_html_e( 'Replace', 'woo-alidropship' ); ?></th>
                                    <th style="width: 1%"><?php esc_html_e( 'Remove', 'woo-alidropship' ); ?></th>
                                </tr>
                                </thead>
                                <tbody>
								<?php
								$carrier_name_replaces       = self::$settings->get_params( 'carrier_name_replaces' );
								$carrier_name_replaces_count = 1;
								if ( ! empty( $carrier_name_replaces['from_string'] ) && ! empty( $carrier_name_replaces['to_string'] ) && is_array( $carrier_name_replaces['from_string'] ) ) {
									$carrier_name_replaces_count = count( $carrier_name_replaces['from_string'] );
								}
								for ( $i = 0; $i < $carrier_name_replaces_count; $i ++ ) {
									$checked = $case_sensitive = '';
									if ( ! empty( $carrier_name_replaces['sensitive'][ $i ] ) ) {
										$checked        = 'checked';
										$case_sensitive = 1;
									}
									?>
                                    <tr class="clone-source">
                                        <td>
                                            <input type="text"
                                                   value="<?php echo esc_attr( isset( $carrier_name_replaces['from_string'][ $i ] ) ? $carrier_name_replaces['from_string'][ $i ] : '' ) ?>"
                                                   name="<?php echo esc_attr( self::set( 'carrier_name_replaces[from_string][]' ) ) ?>">
                                        </td>
                                        <td>
                                            <div class="<?php echo esc_attr( self::set( 'string-replace-sensitive-container' ) ) ?>">
                                                <input type="checkbox"
                                                       value="1" <?php echo esc_attr( $checked ) ?>
                                                       class="<?php echo esc_attr( self::set( 'string-replace-sensitive' ) ) ?>">
                                                <input type="hidden"
                                                       class="<?php echo esc_attr( self::set( 'string-replace-sensitive-value' ) ) ?>"
                                                       value="<?php echo esc_attr( $case_sensitive ) ?>"
                                                       name="<?php echo esc_attr( self::set( 'carrier_name_replaces[sensitive][]' ) ) ?>">
                                            </div>
                                        </td>
                                        <td>
                                            <input type="text"
                                                   placeholder="<?php esc_html_e( 'Leave blank to delete matches', 'woo-alidropship' ); ?>"
                                                   value="<?php echo esc_attr( isset( $carrier_name_replaces['to_string'][ $i ] ) ? $carrier_name_replaces['to_string'][ $i ] : '' ) ?>"
                                                   name="<?php echo esc_attr( self::set( 'carrier_name_replaces[to_string][]' ) ) ?>">
                                        </td>
                                        <td>
                                            <span class="vi-ui button negative tiny delete-string-replace-rule">
                                                <i class="dashicons dashicons-trash"> </i>
                                            </span>
                                        </td>
                                    </tr>
									<?php
								}
								?>
                                </tbody>
                                <tfoot>
                                <tr>
                                    <th colspan="4">
                                        <span class="vi-ui button positive tiny add-string-replace-rule-name"><?php esc_html_e( 'Add', 'woo-alidropship' ); ?></span>
                                    </th>
                                </tr>
                                </tfoot>
                            </table>
                        </div>
                    </div>
					<?php
				}
				?>
                <p class="vi-wad-save-settings-container">
                    <button type="submit" class="vi-ui button labeled icon primary vi-wad-save-settings" name="vi-wad-save-settings">
                        <i class="save icon"> </i>
						<?php esc_html_e( 'Save Settings', 'woo-alidropship' ) ?>
                    </button>
					<?php VI_WOO_ALIDROPSHIP_DATA::chrome_extension_buttons(); ?>
                </p>
            </form>
			<?php do_action( 'villatheme_support_woo-alidropship' ) ?>
        </div>
		<?php
	}

	public function page_logs() {
		VI_WOO_ALIDROPSHIP_Admin_Settings::enqueue_semantic();
		?>
        <div class="wrap">
            <h2><?php esc_html_e( 'Your logs show here', 'woo-alidropship' ) ?></h2>
            <div class="vi-ui segment ">
                <table class="form-table">
                    <tbody>
                    <tr>
                        <th>
                            <label><?php esc_html_e( 'Upgrade', 'woo-alidropship' ) ?></label>
                        </th>
                        <td>
                            <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                        </td>
                    </tr>
                    <tr>
                        <th>
                            <label><?php esc_html_e( 'Preview', 'woo-alidropship' ) ?></label>
                        </th>
                        <td>
                            <img src="<?php echo esc_url( 'https://villatheme.com/wp-content/uploads/2025/02/log.jpg' ) ?>" alt="alidropship logs">
                        </td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </div>
		<?php
	}

	public function page_ali_orders() {
		VI_WOO_ALIDROPSHIP_Admin_Settings::enqueue_semantic();
		?>
        <div class="wrap">
            <h2><?php esc_html_e( 'Ali Order', 'woo-alidropship' ) ?></h2>
            <div class="vi-ui segment ">
                <table class="form-table">
                    <tbody>
                    <tr>
                        <th>
                            <label><?php esc_html_e( 'Upgrade', 'woo-alidropship' ) ?></label>
                        </th>
                        <td>
                            <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                        </td>
                    </tr>
                    <tr>
                        <th>
                            <label><?php esc_html_e( 'Preview', 'woo-alidropship' ) ?></label>
                        </th>
                        <td>
                            <iframe width="560" height="315" src="https://www.youtube.com/embed/uGW4at0ycvo?si=mT9wXOOIQgXvcXrx" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
                        </td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </div>
		<?php
	}

	public function page_migrate_products() {
		VI_WOO_ALIDROPSHIP_Admin_Settings::enqueue_semantic();
		?>
        <div class="wrap">
            <h2><?php esc_html_e( 'Migrate Products', 'woo-alidropship' ) ?></h2>
            <div class="vi-ui segment ">
                <table class="form-table">
                    <tbody>
                    <tr>
                        <th>
                            <label><?php esc_html_e( 'Upgrade', 'woo-alidropship' ) ?></label>
                        </th>
                        <td>
                            <a class="vi-ui button" target="_blank" href="https://1.envato.market/PeXrM"><?php esc_html_e( 'Upgrade This Feature', 'woo-alidropship' ) ?></a>
                        </td>
                    </tr>
                    <tr>
                        <th>
                            <label><?php esc_html_e( 'Preview', 'woo-alidropship' ) ?></label>
                        </th>
                        <td>
                            <img src="<?php echo esc_url( 'https://villatheme.com/wp-content/uploads/2025/02/migrate-products.png' ) ?>" alt="alidropship migrate products" style="width: 100%;">
                        </td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </div>
		<?php
	}

	/**
	 *
	 */
	protected function set_nonce() {
		wp_nonce_field( 'wooaliexpressdropship_save_settings', '_wooaliexpressdropship_nonce' );
	}

	public static function set_params( $name = '', $class = false, $multiple = false ) {
		if ( $name ) {
			if ( $class ) {
				echo esc_attr( 'vi-wad-' . str_replace( '_', '-', $name ) );
			} else {
				if ( $multiple ) {
					echo esc_attr( 'wad_' . $name . '[]' );
				} else {
					echo esc_attr( 'wad_' . $name );
				}
			}
		}
	}

	/**
	 * Register a custom menu page.
	 */
	public function admin_menu() {
		add_submenu_page(
			'woo-alidropship-import-list',
			esc_html__( 'ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce Settings', 'woo-alidropship' ),
			esc_html__( 'Settings', 'woo-alidropship' ),
			'manage_options',
			'woo-alidropship',
			array( $this, 'page_callback' ),

		);
		/*Mapping with pro version menu*/
		add_submenu_page(
			'woo-alidropship-import-list',
			esc_html__( 'ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce Settings', 'woo-alidropship' ),
			esc_html__( 'Ali Order (Only Pro)', 'woo-alidropship' ),
			'manage_options',
			'woocommerce-alidropship-ali-orders',
			array( $this, 'page_ali_orders' ),
			2
		);
		add_submenu_page(
			'woo-alidropship-import-list',
			esc_html__( 'ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce Settings', 'woo-alidropship' ),
			esc_html__( 'Logs (Only Pro)', 'woo-alidropship' ),
			'manage_options',
			'woocommerce-alidropship-logs',
			array( $this, 'page_logs' ),
			4
		);
		add_submenu_page(
			'woo-alidropship-import-list',
			esc_html__( 'ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce Settings', 'woo-alidropship' ),
			esc_html__( 'Migrate Products (Only Pro)', 'woo-alidropship' ),
			'manage_options',
			'woocommerce-alidropship-migrate-products',
			array( $this, 'page_migrate_products' ),
			5
		);
	}

	public static function create_ajax_nonce() {
		return apply_filters( 'vi_wad_admin_ajax_nonce', wp_create_nonce( 'woo_alidropship_admin_ajax' ) );
	}

	public static function check_ajax_referer( $page = 'woo-alidropship' ) {
		if ( ! apply_filters( 'vi_wad_verify_ajax_nonce', false, $page ) ) {
			check_ajax_referer( 'woo_alidropship_admin_ajax', '_vi_wad_ajax_nonce' );
		}
	}
}PK     \/ /   import_list.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class VI_WOO_ALIDROPSHIP_Admin_Import_List
 */
class VI_WOO_ALIDROPSHIP_Admin_Import_List {
	private static $settings;
	public static $process;
	private static $categories_options;
	private static $tags_options;
	private static $shipping_class_options;
	public static $process_image;
	public static $download_description;

	public function __construct() {
		self::$settings           = VI_WOO_ALIDROPSHIP_DATA::get_instance();
		self::$categories_options = self::$shipping_class_options = self::$tags_options = '';
		VILLATHEME_ADMIN_SHOW_MESSAGE::get_instance();
		add_action( 'init', array( $this, 'background_process' ) );
		add_action( 'admin_init', array( $this, 'empty_import_list' ) );
		add_action( 'admin_init', array( $this, 'move_queued_images' ) );
		add_action( 'admin_notices', array( $this, 'admin_notices' ) );
		add_action( 'admin_menu', array( $this, 'admin_menu' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 999999 );
		add_filter( 'set-screen-option', array( $this, 'save_screen_options' ), 10, 3 );
		add_action( 'wp_ajax_vi_wad_import', array( $this, 'import' ) );
		add_action( 'wp_ajax_vi_wad_switch_product_attributes_values', array( $this, 'switch_product_attributes_values' ) );
		add_action( 'wp_ajax_vi_wad_select_shipping', array( $this, 'select_shipping' ) );
		add_action( 'wp_ajax_vi_wad_load_variations_table', array( $this, 'load_variations_table' ) );
		add_action( 'wp_ajax_vi_wad_override', array( $this, 'override' ) );
		add_action( 'wp_ajax_vi_wad_remove', array( $this, 'remove' ) );
		add_action( 'wp_ajax_vi_wad_save_attributes', array( $this, 'save_attributes' ) );
		add_action( 'wp_ajax_vi_wad_remove_attribute', array( $this, 'ajax_remove_attribute' ) );
		add_action( 'admin_head', array( $this, 'menu_product_count' ), 999 );
	}

	public function ajax_remove_attribute() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		$response = array(
			'status'  => 'error',
			'html'    => '',
			'message' => esc_html__( 'Invalid data', 'woo-alidropship' ),
		);
		parse_str( $_POST['form_data'], $form_data );
		$data             = isset( $form_data['vi_wad_product'] ) ? $form_data['vi_wad_product'] : array();
		$product_data     = array_values( $data )[0];
		$product_id       = array_keys( $data )[0];
		$attribute_value  = isset( $_POST['attribute_value'] ) ? sanitize_text_field( stripslashes( $_POST['attribute_value'] ) ) : '';
		$remove_attribute = isset( $product_data['attributes'] ) ? stripslashes_deep( $product_data['attributes'] ) : array();
		$product          = Ali_Product_Table::get_post( $product_id );

		if ( $product && $product->post_type === 'vi_wad_draft_product' && in_array( $product->post_status, array( 'draft', 'override' ) ) ) {
			$attributes       = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_attributes', true );
			$variations       = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_variations', true );
			$split_variations = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_split_variations', true );

			if ( self::remove_product_attribute( $product_id, $remove_attribute, $attribute_value, $split_variations, $attributes, $variations ) ) {
				$response['status'] = 'success';
				if ( ! count( $attributes ) ) {
					$key                         = isset( $_POST['product_index'] ) ? absint( sanitize_text_field( $_POST['product_index'] ) ) : '';
					$currency                    = 'USD';
					$woocommerce_currency        = get_option( 'woocommerce_currency' );
					$woocommerce_currency_symbol = get_woocommerce_currency_symbol( $woocommerce_currency );
					$manage_stock                = self::$settings->get_params( 'manage_stock' );
					$use_different_currency      = false;
//					$variations                  = self::get_product_variations( $product_id );
					$decimals = wc_get_price_decimals();
					if ( $decimals < 1 ) {
						$decimals = 1;
					} else {
						$decimals = pow( 10, ( - 1 * $decimals ) );
					}
					if ( strtolower( $woocommerce_currency ) != strtolower( $currency ) ) {
						$use_different_currency = true;
					}
					ob_start();
					self::simple_product_price_field_html( $key, $manage_stock, $variations, $use_different_currency, $currency, $product_id, $woocommerce_currency_symbol, $decimals, '', '' );
					$response['html'] = ob_get_clean();
				}
				$response['message'] = esc_html__( 'Remove attribute successfully', 'woo-alidropship' );
			}
		} else {
			$response['message'] = esc_html__( 'Invalid product', 'woo-alidropship' );
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $response );
	}

	public static function remove_product_attribute( $product_id, $remove_attribute, $attribute_value, $split_variations, &$attributes, &$variations ) {
		$remove = false;
		if ( count( $remove_attribute ) && count( $attributes ) ) {
			$new_attribute_v = array_values( $remove_attribute )[0];
			$attribute_k     = array_keys( $remove_attribute )[0];
			if ( ( ! isset( $new_attribute_v['name'] ) || $new_attribute_v['name'] ) && isset( $attributes[ $attribute_k ] ) ) {
				$attribute_slug = isset( $attributes[ $attribute_k ]['slug_edited'] ) ? $attributes[ $attribute_k ]['slug_edited'] : $attributes[ $attribute_k ]['slug'];
				foreach ( $variations as $variation_k => $variation ) {
					if ( isset( $variation['attributes_edited'] ) ) {
						if ( isset( $variation['attributes_edited'][ $attribute_slug ] ) ) {
							if ( ! self::is_attribute_value_equal( $variation['attributes_edited'][ $attribute_slug ], $attribute_value ) ) {
								unset( $variations[ $variation_k ] );
								if ( is_array( $split_variations ) && count( $split_variations ) ) {
									$search = array_search( $variation['skuAttr'], $split_variations );
									if ( $search !== false ) {
										unset( $split_variations[ $search ] );
									} else {
										$search = array_search( "{$variation['skuId']}{$variation['skuAttr']}", $split_variations );
										if ( $search !== false ) {
											unset( $split_variations[ $search ] );
										}
									}
								}
							}
							unset( $variations[ $variation_k ]['attributes_edited'][ $attribute_slug ] );
						}
					} else {
						if ( isset( $variation['attributes'][ $attribute_slug ] ) ) {
							if ( ! self::is_attribute_value_equal( $variation['attributes'][ $attribute_slug ], $attribute_value ) ) {
								unset( $variations[ $variation_k ] );
								if ( is_array( $split_variations ) && count( $split_variations ) ) {
									$search = array_search( $variation['skuAttr'], $split_variations );
									if ( $search !== false ) {
										unset( $split_variations[ $search ] );
									} else {
										$search = array_search( "{$variation['skuId']}{$variation['skuAttr']}", $split_variations );
										if ( $search !== false ) {
											unset( $split_variations[ $search ] );
										}
									}
								}
							}
							unset( $variations[ $variation_k ]['attributes'][ $attribute_slug ] );
						}
					}
				}
				unset( $attributes[ $attribute_k ] );
				$variations = array_values( $variations );
				Ali_Product_Table::update_post_meta( $product_id, '_vi_wad_attributes', $attributes );
				Ali_Product_Table::update_post_meta( $product_id, '_vi_wad_variations', $variations );
				if ( is_array( $split_variations ) ) {
					Ali_Product_Table::update_post_meta( $product_id, '_vi_wad_split_variations', $split_variations );
				}
				$remove = true;
			}
		}

		return $remove;
	}

	public function empty_import_list() {
		global $wpdb;
		$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
		if ( ! empty( $_GET['vi_wad_empty_product_list'] ) && $page === 'woo-alidropship-import-list' ) {
			$nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
			if ( wp_verify_nonce( $nonce ) ) {
				$posts = "{$wpdb->prefix}posts";
				$wpdb->query( "DELETE from {$posts} WHERE {$posts}.post_type='vi_wad_draft_product' AND {$posts}.post_status='draft'" );// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				wp_safe_redirect( admin_url( "admin.php?page={$page}" ) );
				exit();
			}
		}
	}

	public function move_queued_images() {
		global $wpdb;
		if ( ! empty( $_GET['vi_wad_move_queued_images'] ) ) {
			$nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
			if ( wp_verify_nonce( $nonce ) ) {
                $table = $wpdb->options;
                $column = 'option_name';
                if (is_multisite()) {
                    $table = $wpdb->sitemeta;
                    $column = 'meta_key';
                }
                $query   = $wpdb->prepare( 'select * from %i where %i like %s', [ $table,$column, "%vi_wad_background_download_images_batch%" ] );
                $results = $wpdb->get_results( $query, ARRAY_A );// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared , WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				foreach ( $results as $result ) {
                    $images = maybe_unserialize( $result['option_value'] ?? $result['meta_value'] ??'');
					$delete = false;
					foreach ( $images as $image ) {
						if ( get_post_type( $image['woo_product_id'] ) === 'product' ) {
							if ( VI_WOO_ALIDROPSHIP_Error_Images_Table::insert( $image['woo_product_id'], implode( ',', $image['product_ids'] ), $image['src'], intval( $image['set_gallery'] ) ) ) {
								$delete = true;
							}
						} else {
							$delete = true;
						}
					}
					if ( $delete ) {
                        if (isset($result['meta_key'])){
                            delete_site_option($result['meta_key']);
                        }else {
                            delete_option( $result['option_name'] );
                        }
					}
				}
				wp_safe_redirect( remove_query_arg( array( 'vi_wad_move_queued_images' ) ) );
				exit();
			}
		}
	}

	public function save_attributes() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		$response = array(
			'status'       => 'error',
			'new_slug'     => '',
			'change_value' => false,
			'message'      => '',
		);
		parse_str( $_POST['form_data'], $form_data );
		$data          = isset( $form_data['vi_wad_product'] ) ? $form_data['vi_wad_product'] : array();
		$product_data  = array_values( $data )[0];
		$product_id    = array_keys( $data )[0];
		$new_attribute = isset( $product_data['attributes'] ) ? stripslashes_deep( $product_data['attributes'] ) : array();
		$attributes    = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_attributes', true );
		$variations    = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_variations', true );
		$change_slug   = '';
		$change_value  = false;
		if ( count( $new_attribute ) && count( $attributes ) ) {
			$response['status'] = 'success';
			$new_attribute_v    = array_values( $new_attribute )[0];
			$attribute_k        = array_keys( $new_attribute )[0];
			if ( ! empty( $new_attribute_v['name'] ) && isset( $attributes[ $attribute_k ] ) ) {
				$new_slug       = VI_WOO_ALIDROPSHIP_DATA::sanitize_taxonomy_name( $new_attribute_v['name'] );
				$attribute_slug = isset( $attributes[ $attribute_k ]['slug_edited'] ) ? $attributes[ $attribute_k ]['slug_edited'] : $attributes[ $attribute_k ]['slug'];
				if ( ! self::is_attribute_value_equal( $new_slug, $attribute_slug ) ) {
					$change_slug = $new_slug;
					foreach ( $variations as $variation_k => $variation ) {
						$v_attributes = isset( $variation['attributes_edited'] ) ? $variation['attributes_edited'] : $variation['attributes'];
						if ( isset( $v_attributes[ $attribute_slug ] ) ) {
							$v_attributes[ $new_slug ] = $v_attributes[ $attribute_slug ];
							unset( $v_attributes[ $attribute_slug ] );
							$variations[ $variation_k ]['attributes_edited'] = $v_attributes;
						}
					}
					$attributes[ $attribute_k ]['slug_edited'] = $new_slug;
					$attributes[ $attribute_k ]['name_edited'] = $new_attribute_v['name'];
					$attribute_slug                            = $new_slug;
				}
				if ( ! empty( $new_attribute_v['values'] ) ) {
					$new_values    = $new_attribute_v['values'];
					$values_edited = isset( $attributes[ $attribute_k ]['values_edited'] ) ? $attributes[ $attribute_k ]['values_edited'] : $attributes[ $attribute_k ]['values'];
					foreach ( $values_edited as $value_k => $value ) {
						if ( ! empty( $new_values[ $value_k ] ) ) {
							$new_value = trim( $new_values[ $value_k ] );
							if ( $new_value !== $value ) {
								$change_value = true;
								foreach ( $variations as $variation_k => $variation ) {
									$v_attributes = isset( $variation['attributes_edited'] ) ? $variation['attributes_edited'] : $variation['attributes'];
									if ( isset( $v_attributes[ $attribute_slug ] ) && self::is_attribute_value_equal( $v_attributes[ $attribute_slug ], $value ) ) {

										$values_edited[ $value_k ] = $new_value;

										$v_attributes[ $attribute_slug ] = $new_value;

										$variations[ $variation_k ]['attributes_edited'] = $v_attributes;
									}
								}
								$attributes[ $attribute_k ]['values_edited'] = $values_edited;
							}
						}
					}
				}
			}
		}
		if ( $change_slug || $change_value ) {
			Ali_Product_Table::update_post_meta( $product_id, '_vi_wad_attributes', $attributes );
			Ali_Product_Table::update_post_meta( $product_id, '_vi_wad_variations', $variations );
		}
		$response['new_slug']     = $change_slug;
		$response['change_value'] = $change_value;
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $response );
	}

	public static function is_attribute_value_equal( $value_1, $value_2 ) {
		if ( function_exists( 'mb_strtolower' ) ) {
			return ( mb_strtolower( $value_1 ) === mb_strtolower( $value_2 ) );
		} else {
			return ( strtolower( $value_1 ) === strtolower( $value_2 ) );
		}
	}

	public function load_variations_table() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		$key        = isset( $_GET['product_index'] ) ? absint( sanitize_text_field( $_GET['product_index'] ) ) : '';
		$product_id = isset( $_GET['product_id'] ) ? sanitize_text_field( $_GET['product_id'] ) : '';
		if ( $key > - 1 && $product_id ) {
			$currency                    = 'USD';
			$woocommerce_currency        = get_option( 'woocommerce_currency' );
			$woocommerce_currency_symbol = get_woocommerce_currency_symbol( $woocommerce_currency );
			$manage_stock                = self::$settings->get_params( 'manage_stock' );
			$use_different_currency      = false;
			$variations                  = self::get_product_variations( $product_id );

			$decimals = wc_get_price_decimals();
			if ( $decimals < 1 ) {
				$decimals = 1;
			} else {
				$decimals = pow( 10, ( - 1 * $decimals ) );
			}
			if ( strtolower( $woocommerce_currency ) != strtolower( $currency ) ) {
				$use_different_currency = true;
			}
			$attributes = self::get_product_attributes( $product_id );
			$parent     = array();
			if ( is_array( $attributes ) && count( $attributes ) ) {
				foreach ( $attributes as $attribute_k => $attribute_v ) {
					$parent[ $attribute_k ] = $attribute_v['slug'];
				}
			}
			ob_start();
			self::variation_html( $key, $parent, $attributes, $manage_stock, $variations, $use_different_currency, $currency, $product_id, $woocommerce_currency_symbol, $decimals, false );
			$return = ob_get_clean();
			wp_send_json(
				array(
					'status' => 'success',
					'data'   => $return
				)
			);
		} else {
			wp_send_json(
				array(
					'status' => 'error',
					'data'   => esc_html__( 'Missing required arguments', 'woo-alidropship' )
				)
			);
		}
		// phpcs:enable WordPress.Security.NonceVerification
	}

	public function select_shipping() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		$key          = isset( $_POST['product_index'] ) ? absint( sanitize_text_field( $_POST['product_index'] ) ) : '';
		$product_id   = isset( $_POST['product_id'] ) ? sanitize_text_field( $_POST['product_id'] ) : '';
		$product_type = isset( $_POST['product_type'] ) ? sanitize_text_field( $_POST['product_type'] ) : '';
		$country      = isset( $_POST['country'] ) ? sanitize_text_field( $_POST['country'] ) : '';
		$company      = isset( $_POST['company'] ) ? sanitize_text_field( $_POST['company'] ) : '';
		if ( $key > - 1 && $product_id && $product_type ) {
			$currency                    = 'USD';
			$woocommerce_currency        = get_option( 'woocommerce_currency' );
			$woocommerce_currency_symbol = get_woocommerce_currency_symbol( $woocommerce_currency );
			$manage_stock                = self::$settings->get_params( 'manage_stock' );
			$use_different_currency      = false;
			$variations                  = self::get_product_variations( $product_id );
			$decimals                    = wc_get_price_decimals();
			if ( $decimals < 1 ) {
				$decimals = 1;
			} else {
				$decimals = pow( 10, ( - 1 * $decimals ) );
			}
			if ( strtolower( $woocommerce_currency ) != strtolower( $currency ) ) {
				$use_different_currency = true;
			}
			ob_start();
			if ( $product_type === 'variable' ) {
				$attributes = self::get_product_attributes( $product_id );
				$parent     = array();
				if ( is_array( $attributes ) && count( $attributes ) ) {
					foreach ( $attributes as $attribute_k => $attribute_v ) {
						$parent[ $attribute_k ] = $attribute_v['slug'];
					}
				}
				self::variation_html( $key, $parent, $attributes, $manage_stock, $variations, $use_different_currency, $currency, $product_id, $woocommerce_currency_symbol, $decimals, false, $country, $company );
			} else {
				self::simple_product_price_field_html( $key, $manage_stock, $variations, $use_different_currency, $currency, $product_id, $woocommerce_currency_symbol, $decimals, $country, $company );
			}
			$return = ob_get_clean();
			wp_send_json(
				array(
					'status' => 'success',
					'data'   => $return
				)
			);
		} else {
			wp_send_json(
				array(
					'status' => 'error',
					'data'   => esc_html__( 'Missing required arguments', 'woo-alidropship' )
				)
			);
		}
		// phpcs:enable WordPress.Security.NonceVerification
	}

	public function admin_enqueue_scripts() {
		$page = isset( $_REQUEST['page'] ) ? $_REQUEST['page'] : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		global $pagenow;
		if ( $pagenow !== 'admin.php' ) {
			return;
		}
		if ( $page === 'woo-alidropship-import-list' ) {
			VI_WOO_ALIDROPSHIP_Admin_Settings::enqueue_semantic();
//			wp_enqueue_script( 'jquery-ui-sortable' );
			wp_enqueue_style( 'woo-alidropship-admin-style', VI_WOO_ALIDROPSHIP_CSS . 'import-list.css', '', VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_script( 'woo-alidropship-import-list', VI_WOO_ALIDROPSHIP_JS . 'import-list.js', array( 'jquery', 'jquery-ui-sortable' ), VI_WOO_ALIDROPSHIP_VERSION, false );
			wp_localize_script( 'woo-alidropship-import-list', 'vi_wad_import_list_params', array(
				'url'                              => admin_url( 'admin-ajax.php' ),
				'decimals'                         => wc_get_price_decimals(),
				'_vi_wad_ajax_nonce'               => VI_WOO_ALIDROPSHIP_Admin_Settings::create_ajax_nonce(),
				'i18n_empty_variation_error'       => esc_attr__( 'Please select at least 1 variation to import.', 'woo-alidropship' ),
				'i18n_empty_price_error'           => esc_attr__( 'Regular price can not be empty.', 'woo-alidropship' ),
				'i18n_sale_price_error'            => esc_attr__( 'Sale price must be smaller than regular price.', 'woo-alidropship' ),
				'i18n_not_found_error'             => esc_attr__( 'No product found.', 'woo-alidropship' ),
				'i18n_import_all_confirm'          => esc_attr__( 'Import all products on this page to your WooCommerce store?', 'woo-alidropship' ),
				'i18n_remove_product_confirm'      => esc_attr__( 'Remove this product from import list?', 'woo-alidropship' ),
				'i18n_bulk_remove_product_confirm' => esc_html__( 'Remove selected product(s) from import list?', 'woo-alidropship' ),
				'i18n_bulk_import_product_confirm' => esc_html__( 'Import all selected product(s)?', 'woo-alidropship' ),
				'product_categories'               => self::$settings->get_params( 'product_categories' ),

			) );
			add_action( 'admin_footer', array( $this, 'set_price_modal' ) );
			add_action( 'admin_footer', array( $this, 'override_product_options' ) );
		}
	}

	public function override_product_options() {
		$all_options = array(
			'override-keep-product'   => esc_html__( 'Keep Woo product', 'woo-alidropship' ),
			'override-find-in-orders' => esc_html__( 'Find in unfulfilled orders', 'woo-alidropship' ),
			'override-title'          => esc_html__( 'Replace product title', 'woo-alidropship' ),
			'override-images'         => esc_html__( 'Replace product image and gallery', 'woo-alidropship' ),
			'override-description'    => esc_html__( 'Replace description and short description', 'woo-alidropship' ),
			'override-hide'           => wp_kses_post( __( 'Save my choices and do not show these options again(you can still change this in <a target="_blank" href="admin.php?page=woo-alidropship#/override">plugin settings</a>).', 'woo-alidropship' ) ),
		);
		?>
        <div class="<?php echo esc_attr( self::set( array(
			'override-product-options-container',
			'hidden'
		) ) ) ?>">
            <div class="<?php echo esc_attr( self::set( 'override-product-overlay' ) ) ?>"></div>
            <div class="<?php echo esc_attr( self::set( 'override-product-options-content' ) ) ?>">
                <div class="<?php echo esc_attr( self::set( 'override-product-options-content-header' ) ) ?>">
                    <h2>
                        <span class="<?php echo esc_attr( self::set( 'override-product-text-override' ) ) ?>"><?php esc_html_e( 'Override: ', 'woo-alidropship' ) ?></span><span
                                class="<?php echo esc_attr( self::set( 'override-product-text-reimport' ) ) ?>"><?php esc_html_e( 'Reimport: ', 'woo-alidropship' ) ?></span><span
                                class="<?php echo esc_attr( self::set( 'override-product-text-map-existing' ) ) ?>"><?php esc_html_e( 'Import & map existing Woo product: ', 'woo-alidropship' ) ?></span><span
                                class="<?php echo esc_attr( self::set( 'override-product-title' ) ) ?>"> </span>
                    </h2>
                    <span class="<?php echo esc_attr( self::set( 'override-product-options-close' ) ) ?>"> </span>
                    <div class="vi-ui message warning <?php echo esc_attr( self::set( 'override-product-remove-warning' ) ) ?>"><?php esc_html_e( 'Overridden product and all of its data(including variations, reviews, metadata...) will be deleted. Please make sure you had backed up those kinds of data before continuing!', 'woo-alidropship' ) ?></div>
                </div>
				<?php
				if ( ! self::$settings->get_params( 'override_hide' ) ) {
					?>
                    <div class="<?php echo esc_attr( self::set( array(
						'override-product-options-content-body',
						'override-product-options-content-body-option'
					) ) ) ?>">
						<?php
						foreach ( $all_options as $option_key => $option_value ) {
							?>
                            <div class="<?php echo esc_attr( self::set( array(
								'override-product-options-content-body-row',
								"override-product-options-content-body-row-{$option_key}"
							) ) ) ?>">
                                <div class="<?php echo esc_attr( self::set( 'override-product-options-option-wrap' ) ) ?>">
                                    <input type="checkbox"
                                           value="1" <?php checked( 1, self::$settings->get_params( str_replace( '-', '_', $option_key ) ) ) ?>
                                           data-order_option="<?php echo esc_attr( $option_key ) ?>"
                                           id="<?php echo esc_attr( self::set( 'override-product-options-' . $option_key ) ) ?>"
                                           class="<?php echo esc_attr( self::set( array(
										       'override-product-options-option',
										       'override-product-options-' . $option_key
									       ) ) ) ?>">
                                    <label for="<?php echo esc_attr( self::set( 'override-product-options-' . $option_key ) ) ?>"><?php echo esc_html( $option_value ) ?></label>
                                </div>
                            </div>
							<?php
						}
						?>
                    </div>
					<?php
				}
				?>
                <div class="<?php echo esc_attr( self::set( array(
					'override-product-options-content-body',
					'override-product-options-content-body-override-old'
				) ) ) ?>">
                </div>
                <div class="<?php echo esc_attr( self::set( 'override-product-options-content-footer' ) ) ?>">
                    <span class="vi-ui button mini positive <?php echo esc_attr( self::set( array(
	                    'override-product-options-button-override',
                    ) ) ) ?>" data-override_product_id="">
                            <span class="<?php echo esc_attr( self::set( 'override-product-text-override' ) ) ?>"><?php esc_html_e( 'Override', 'woo-alidropship' ) ?></span><span
                                class="<?php echo esc_attr( self::set( 'override-product-text-map-existing' ) ) ?>"><?php esc_html_e( 'Import & Map', 'woo-alidropship' ) ?></span><span
                                class="<?php echo esc_attr( self::set( 'override-product-text-reimport' ) ) ?>"><?php esc_html_e( 'Reimport', 'woo-alidropship' ) ?></span>
                        </span>
                    <span class="vi-ui button mini <?php echo esc_attr( self::set( array(
						'override-product-options-button-cancel',
					) ) ) ?>"><?php esc_html_e( 'Cancel', 'woo-alidropship' ) ?></span>
                </div>
            </div>
            <div class="<?php echo esc_attr( self::set( 'override-product-overlay' ) ) ?>"></div>
        </div>
		<?php
	}

	public function set_price_modal() {
		?>
        <div class="<?php echo esc_attr( self::set( array( 'modal-popup-container', 'hidden' ) ) ) ?>">
            <div class="<?php echo esc_attr( self::set( 'overlay' ) ) ?>"></div>
            <div class="<?php echo esc_attr( self::set( array(
				'modal-popup-content',
				'modal-popup-content-set-price'
			) ) ) ?>">
                <div class="<?php echo esc_attr( self::set( 'modal-popup-header' ) ) ?>">
                    <h2><?php esc_html_e( 'Set price', 'woo-alidropship' ) ?></h2>
                    <span class="<?php echo esc_attr( self::set( 'modal-popup-close' ) ) ?>"></span>
                </div>
                <div class="<?php echo esc_attr( self::set( 'modal-popup-content-body' ) ) ?>">
                    <div class="<?php echo esc_attr( self::set( 'modal-popup-content-body-row' ) ) ?>">
                        <div class="<?php echo esc_attr( self::set( 'set-price-action-wrap' ) ) ?>">
                            <label for="<?php echo esc_attr( self::set( 'set-price-action' ) ) ?>"><?php esc_html_e( 'Action', 'woo-alidropship' ) ?></label>
                            <select id="<?php echo esc_attr( self::set( 'set-price-action' ) ) ?>"
                                    class="<?php echo esc_attr( self::set( 'set-price-action' ) ) ?>">
                                <option value="set_new_value"><?php esc_html_e( 'Set to this value', 'woo-alidropship' ) ?></option>
                                <option value="increase_by_fixed_value"><?php echo wp_kses_post(sprintf(__( 'Increase by fixed value(%s)', 'woo-alidropship' ), get_woocommerce_currency_symbol( get_option( 'woocommerce_currency' ) ))) //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?></option>
                                <option value="increase_by_percentage"><?php esc_html_e( 'Increase by percentage(%)', 'woo-alidropship' ) ?></option>
                            </select>
                        </div>
                        <div class="<?php echo esc_attr( self::set( 'set-price-amount-wrap' ) ) ?>">
                            <label for="<?php echo esc_attr( self::set( 'set-price-amount' ) ) ?>"><?php esc_html_e( 'Amount', 'woo-alidropship' ) ?></label>
                            <input type="text"
                                   id="<?php echo esc_attr( self::set( 'set-price-amount' ) ) ?>"
                                   class="<?php echo esc_attr( self::set( 'set-price-amount' ) ) ?>">
                        </div>
                    </div>
                </div>
                <div class="<?php echo esc_attr( self::set( 'modal-popup-content-footer' ) ) ?>">
                        <span class="button button-primary <?php echo esc_attr( self::set( 'set-price-button-set' ) ) ?>">
                            <?php esc_html_e( 'Set', 'woo-alidropship' ) ?>
                        </span>
                    <span class="button <?php echo esc_attr( self::set( 'set-price-button-cancel' ) ) ?>">
                            <?php esc_html_e( 'Cancel', 'woo-alidropship' ) ?>
                        </span>
                </div>
            </div>
            <div class="<?php echo esc_attr( self::set( array(
				'modal-popup-content',
				'modal-popup-content-remove-attribute'
			) ) ) ?>">
                <div class="<?php echo esc_attr( self::set( 'modal-popup-header' ) ) ?>">
                    <h2><?php esc_html_e( 'Please select default value to fulfill orders after this attribute is removed', 'woo-alidropship' ) ?></h2>
                    <span class="<?php echo esc_attr( self::set( 'modal-popup-close' ) ) ?>"> </span>
                </div>
                <div class="<?php echo esc_attr( self::set( 'modal-popup-content-body' ) ) ?>">
                    <div class="<?php echo esc_attr( self::set( array(
						'modal-popup-content-body-row',
						'modal-popup-select-attribute'
					) ) ) ?>">

                    </div>
                </div>
            </div>
            <div class="<?php echo esc_attr( self::set( array(
				'modal-popup-content',
				'modal-popup-content-set-categories'
			) ) ) ?>">
                <div class="<?php echo esc_attr( self::set( 'modal-popup-header' ) ) ?>">
                    <h2><?php esc_html_e( 'Bulk set product categories', 'woo-alidropship' ) ?></h2>
                    <span class="<?php echo esc_attr( self::set( 'modal-popup-close' ) ) ?>"> </span>
                </div>
                <div class="<?php echo esc_attr( self::set( 'modal-popup-content-body' ) ) ?>">
                    <div class="<?php echo esc_attr( self::set( array(
						'modal-popup-content-body-row',
						'modal-popup-set-categories'
					) ) ) ?>">
                        <div class="<?php echo esc_attr( self::set( 'modal-popup-set-categories-select-wrap' ) ) ?>">
							<?php echo str_replace( array(
								'vi_wad_product[{ali_product_id}][categories][]',
								'vi-wad-import-data-categories',
								'vi-ui dropdown search'
							), array(
								esc_attr( 'vi_wad_bulk_set_categories' ),
								self::set( esc_attr( 'modal-popup-set-categories-select' ) ),
								'vi-ui dropdown fluid search'
							), self::$categories_options ); ?>
                            <span class="vi-ui black button mini <?php echo esc_attr( self::set( 'modal-popup-set-categories-clear' ) ) ?>"><?php esc_html_e( 'Clear selected', 'woo-alidropship' ) ?></span>
                        </div>
                    </div>
                </div>
                <div class="<?php echo esc_attr( self::set( 'modal-popup-content-footer' ) ) ?>">
                    <span class="button button-primary <?php echo esc_attr( self::set( 'set-categories-button-add' ) ) ?>"
                          title="<?php esc_attr_e( 'Add selected and keep existing categories', 'woo-alidropship' ) ?>"><?php esc_html_e( 'Add', 'woo-alidropship' ) ?></span>
                    <span class="button button-primary <?php echo esc_attr( self::set( 'set-categories-button-set' ) ) ?>"
                          title="<?php esc_attr_e( 'Remove existing categories and add selected', 'woo-alidropship' ) ?>"><?php esc_html_e( 'Set', 'woo-alidropship' ) ?></span>
                    <span class="button <?php echo esc_attr( self::set( 'set-categories-button-cancel' ) ) ?>"><?php esc_html_e( 'Cancel', 'woo-alidropship' ) ?></span>
                </div>
            </div>
            <div class="<?php echo esc_attr( self::set( array(
				'modal-popup-content',
				'modal-popup-content-set-tags'
			) ) ) ?>">
                <div class="<?php echo esc_attr( self::set( 'modal-popup-header' ) ) ?>">
                    <h2><?php esc_html_e( 'Bulk set product tags', 'woo-alidropship' ) ?></h2>
                    <span class="<?php echo esc_attr( self::set( 'modal-popup-close' ) ) ?>"></span>
                </div>
                <div class="<?php echo esc_attr( self::set( 'modal-popup-content-body' ) ) ?>">
                    <div class="<?php echo esc_attr( self::set( array(
						'modal-popup-content-body-row',
						'modal-popup-set-tags'
					) ) ) ?>">
                        <div class="<?php echo esc_attr( self::set( 'modal-popup-set-tags-select-wrap' ) ) ?>">
                            <select name="<?php echo esc_attr( 'vi_wad_bulk_set_tags' ) ?>"
                                    class="vi-ui dropdown fluid search <?php echo esc_attr( self::set( 'modal-popup-set-tags-select' ) ) ?>"
                                    multiple="multiple">
								<?php echo self::$tags_options; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped  ?>
                            </select>
                            <span class="vi-ui black button mini <?php echo esc_attr( self::set( 'modal-popup-set-tags-clear' ) ) ?>"><?php esc_html_e( 'Clear selected', 'woo-alidropship' ) ?></span>
                        </div>
                    </div>
                </div>
                <div class="<?php echo esc_attr( self::set( 'modal-popup-content-footer' ) ) ?>">
                    <span class="button button-primary <?php echo esc_attr( self::set( 'set-tags-button-add' ) ) ?>"
                          title="<?php esc_attr_e( 'Add selected and keep existing tags', 'woo-alidropship' ) ?>"><?php esc_html_e( 'Add', 'woo-alidropship' ) ?></span>
                    <span class="button button-primary <?php echo esc_attr( self::set( 'set-tags-button-set' ) ) ?>"
                          title="<?php esc_attr_e( 'Remove existing tags and add selected', 'woo-alidropship' ) ?>"><?php esc_html_e( 'Set', 'woo-alidropship' ) ?></span>
                    <span class="button <?php echo esc_attr( self::set( 'set-tags-button-cancel' ) ) ?>"><?php esc_html_e( 'Cancel', 'woo-alidropship' ) ?></span>
                </div>
            </div>
            <div class="<?php echo esc_attr( self::set( array( 'saving-overlay', 'hidden' ) ) ) ?>"></div>
        </div>
		<?php
	}

	/**
	 * Adds the order processing count to the menu.
	 */
	public function menu_product_count() {
		global $submenu;
		if ( isset( $submenu['woo-alidropship-import-list'] ) ) {
			// Add count if user has access.
			if ( apply_filters( 'woo_aliexpress_dropship_product_count_in_menu', true ) && current_user_can( 'manage_options' ) ) {
				$count         = Ali_Product_Table::wp_count_posts( 'vi_wad_draft_product' );
				$product_count = $count->draft + $count->override;
				foreach ( $submenu['woo-alidropship-import-list'] as $key => $menu_item ) {
					if ( 0 === strpos( $menu_item[0], _x( 'Import List', 'Admin menu name', 'woo-alidropship' ) ) ) {
						$submenu['woo-alidropship-import-list'][ $key ][0] .= ' <span class="update-plugins count-' . esc_attr( $product_count ) . '"><span class="' . self::set( 'import-list-count' ) . '">' . number_format_i18n( $product_count ) . '</span></span>'; // WPCS: override ok.
						break;
					}
				}
			}
		}
	}

	public function remove() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		vi_wad_set_time_limit();
		$product_id = isset( $_POST['product_id'] ) ? sanitize_text_field( $_POST['product_id'] ) : '';
		if ( $product_id ) {
			if ( Ali_Product_Table::wp_delete_post( $product_id, true ) ) {
				wp_send_json( array(
					'status'  => 'success',
					'message' => esc_html__( 'Removed', 'woo-alidropship' ),
				) );
			} else {
				wp_send_json( array(
					'status'  => 'error',
					'message' => esc_html__( 'Error', 'woo-alidropship' ),
				) );
			}
		} else {
			wp_send_json( array(
				'status'  => 'error',
				'message' => esc_html__( 'Not found', 'woo-alidropship' ),
			) );
		}
		// phpcs:enable WordPress.Security.NonceVerification
	}

	public static function get_override_simple_select_html( $variation ) {
		ob_start();
		?>
        <select class="vi-ui fluid dropdown <?php echo esc_attr( self::set( 'override-with' ) ) ?>">
            <option value="none"><?php esc_html_e( 'Do not replace', 'woo-alidropship' ) ?></option>
            <option value="<?php echo esc_attr( $variation['skuAttr'] ) ?>"><?php esc_html_e( 'Replace with new product', 'woo-alidropship' ) ?></option>
        </select>
		<?php
		return ob_get_clean();
	}

	public static function get_override_variable_select_html( $variations, $current = '' ) {
		ob_start();
		?>
        <select class="vi-ui fluid dropdown <?php echo esc_attr( self::set( 'override-with' ) ) ?>">
            <option value=""><?php esc_html_e( 'Do not replace', 'woo-alidropship' ) ?></option>
			<?php
			foreach ( $variations as $variation ) {
				$attribute = implode( ', ', array_values( $variation['attributes'] ) );
				$selected  = self::is_attribute_value_equal( $current, $attribute ) ? 'selected' : '';
				?>
                <option value="<?php echo esc_attr( $variation['skuAttr'] ) ?>" <?php echo esc_attr( $selected ) ?>><?php echo esc_html( $attribute ) ?></option>
				<?php
			}
			?>
        </select>
		<?php
		return ob_get_clean();
	}

	/**
	 * @param $woo_product WC_Product
	 * @param $woo_product_id
	 * @param $variations
	 * @param bool $found_item
	 * @param bool $is_simple
	 *
	 * @return false|string
	 */
	public static function get_override_simple_html( $woo_product, $woo_product_id, $variations, $found_item, $is_simple ) {
		ob_start();
		?>
        <tr class="<?php echo esc_attr( self::set( 'override-order-container' ) ) ?>"
            data-replace_item_id="<?php echo esc_attr( $woo_product_id ) ?>">
            <td class="<?php echo esc_attr( self::set( 'override-from-td' ) ) ?>">
                <div class="<?php echo esc_attr( self::set( 'override-from' ) ) ?>">
					<?php
					if ( $woo_product->get_image_id() ) {
						$image_src = wp_get_attachment_thumb_url( $woo_product->get_image_id() );
					} elseif ( $woo_product->get_image_id() ) {
						$image_src = wp_get_attachment_thumb_url( $woo_product->get_image_id() );
					} else {
						$image_src = wc_placeholder_img_src();
					}
					if ( $image_src ) {
						?>
                        <div class="<?php echo esc_attr( self::set( 'override-from-image' ) ) ?>">
                            <img src="<?php echo esc_url( $image_src ) ?>" width="30px"
                                 height="30px">
                        </div>
						<?php
					}
					?>
                    <div class="<?php echo esc_attr( self::set( 'override-from-title' ) ) ?>">
						<?php
						echo esc_html( $woo_product->get_title() );
						?>
                    </div>
                </div>
            </td>
            <td class="<?php echo esc_attr( self::set( 'override-unfulfilled-items-count' ) ) ?>">
				<?php
				echo wp_kses( $found_item, VI_WOO_ALIDROPSHIP_DATA::allow_html() );
				?>
            </td>
            <td class="<?php echo esc_attr( self::set( 'override-with-attributes' ) ) ?>">
				<?php
				if ( $is_simple ) {
					echo wp_kses(self::get_override_simple_select_html( $variations[0] ),VI_WOO_ALIDROPSHIP_DATA::allow_html());
				} else {
					echo wp_kses(self::get_override_variable_select_html( $variations ),VI_WOO_ALIDROPSHIP_DATA::allow_html());
				}
				?>
            </td>
        </tr>
		<?php
		return ob_get_clean();
	}

	/**
	 * @param $woo_product WC_Product
	 * @param $woo_product_child
	 * @param $variations
	 * @param $item_count
	 * @param bool $is_simple
	 *
	 * @return false|string
	 */
	public static function get_override_variation_html( $woo_product, $woo_product_child, $variations, $item_count, $is_simple ) {
		$html                  = '';
		$woo_product_child_obj = wc_get_product( $woo_product_child );
		if ( $woo_product_child_obj ) {
			$current = implode( ', ', $woo_product_child_obj->get_attributes() );
			ob_start();
			?>
            <tr class="<?php echo esc_attr( self::set( 'override-order-container' ) ) ?>"
                data-replace_item_id="<?php echo esc_attr( $woo_product_child ) ?>">
                <td class="<?php echo esc_attr( self::set( 'override-from-td' ) ) ?>">
                    <div class="<?php echo esc_attr( self::set( 'override-from' ) ) ?>">
						<?php
						if ( $woo_product_child_obj ) {
							if ( $woo_product_child_obj->get_image_id() ) {
								$image_src = wp_get_attachment_thumb_url( $woo_product_child_obj->get_image_id() );
							} elseif ( $woo_product->get_image_id() ) {
								$image_src = wp_get_attachment_thumb_url( $woo_product->get_image_id() );
							} else {
								$image_src = wc_placeholder_img_src();
							}
							if ( $image_src ) {
								?>
                                <div class="<?php echo esc_attr( self::set( 'override-from-image' ) ) ?>">
                                    <img src="<?php echo esc_url( $image_src ) ?>" width="30px"
                                         height="30px">
                                </div>
								<?php
							}

						}
						?>
                        <div class="<?php echo esc_attr( self::set( 'override-from-title' ) ) ?>">
							<?php
							echo esc_html( $current );
							?>
                        </div>
                    </div>
                </td>
                <td><?php echo esc_html( $item_count ); ?></td>
                <td class="<?php echo esc_attr( self::set( 'override-with-attributes' ) ) ?>">
					<?php
					if ( $is_simple ) {
						echo self::get_override_simple_select_html( $variations[0] );//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
					} else {
						echo self::get_override_variable_select_html( $variations, $current );//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
					}
					?>
                </td>
            </tr>
			<?php
			$html = ob_get_clean();
		}

		return $html;
	}

	/**
	 * @throws Exception
	 */
	public function override() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		vi_wad_set_time_limit();
		parse_str( $_POST['form_data'], $form_data );
		if ( ! isset( $form_data['z_check_max_input_vars'] ) ) {
			/*z_check_max_input_vars is the last key of POST data. If it does not exist in $form_data after using parse_str(), some data may also be missing*/
			wp_send_json( array(
				'status'  => 'error',
				'message' => esc_html__( 'PHP max_input_vars is too low, please increase it in php.ini', 'woo-alidropship' ),
			) );
		}
		$data                    = isset( $form_data['vi_wad_product'] ) ? $form_data['vi_wad_product'] : array();
		$selected                = isset( $_POST['selected'] ) ? vi_wad_json_decode( stripslashes_deep( $_POST['selected'] ) ) : array();
		$override_product_id     = isset( $_POST['override_product_id'] ) ? sanitize_text_field( $_POST['override_product_id'] ) : '';
		$override_woo_id         = isset( $_POST['override_woo_id'] ) ? sanitize_text_field( $_POST['override_woo_id'] ) : '';
		$override_options        = array(
			'override_title'       => isset( $_POST['override_title'] ) ? sanitize_text_field( $_POST['override_title'] ) : '',
			'override_images'      => isset( $_POST['override_images'] ) ? sanitize_text_field( $_POST['override_images'] ) : '',
			'override_description' => isset( $_POST['override_description'] ) ? sanitize_text_field( $_POST['override_description'] ) : '',
		);
		$override_hide           = isset( $_POST['override_hide'] ) ? sanitize_text_field( $_POST['override_hide'] ) : '';
		$override_keep_product   = isset( $_POST['override_keep_product'] ) ? sanitize_text_field( $_POST['override_keep_product'] ) : '';
		$override_find_in_orders = isset( $_POST['override_find_in_orders'] ) ? sanitize_text_field( $_POST['override_find_in_orders'] ) : '';
		if ( $override_hide ) {
			$params = self::$settings->get_params();
			foreach ( $override_options as $override_option_k => $override_option_v ) {
				$params[ $override_option_k ] = $override_option_v;
			}
			$params['override_hide']           = $override_hide;
			$params['override_keep_product']   = $override_keep_product;
			$params['override_find_in_orders'] = $override_find_in_orders;
			update_option( 'wooaliexpressdropship_params', $params );
		} elseif ( self::$settings->get_params( 'override_hide' ) ) {
			foreach ( $override_options as $override_option_k => $override_option_v ) {
				$override_options[ $override_option_k ] = self::$settings->get_params( $override_option_k );
			}
		}

		if ( ! $override_product_id && ! $override_woo_id ) {
			wp_send_json( array(
				'status'  => 'error',
				'message' => esc_html__( 'Product is deleted from your store', 'woo-alidropship' ),
			) );
		}

		$product_data     = array_values( $data )[0];
		$product_draft_id = array_keys( $data )[0];
		$check_orders     = isset( $_POST['check_orders'] ) ? sanitize_text_field( $_POST['check_orders'] ) : '';
		$found_items      = isset( $_POST['found_items'] ) ? stripslashes_deep( $_POST['found_items'] ) : array();
		$replace_items    = isset( $_POST['replace_items'] ) ? stripslashes_deep( $_POST['replace_items'] ) : array();

		if ( $override_product_id ) {
			$woo_product_id = Ali_Product_Table::get_post_meta( $override_product_id, '_vi_wad_woo_id', true );
		} else {
			$woo_product_id      = $override_woo_id;
			$override_product_id = VI_WOO_ALIDROPSHIP_DATA::product_get_id_by_woo_id( $woo_product_id, false, false, array( 'publish', 'override' ) );
		}

		$attributes = self::get_product_attributes( $product_draft_id );
		if ( ! count( $selected[ $product_draft_id ] ) ) {
			wp_send_json( array(
				'status'  => 'error',
				'message' => esc_html__( 'Please select at least 1 variation to import this product.', 'woo-alidropship' ),
			) );
		}
		if ( ! $product_draft_id ) {
			wp_send_json( array(
				'status'  => 'error',
				'message' => esc_html__( 'Invalid data', 'woo-alidropship' ),
			) );
		}
		if ( ! self::$settings->get_params( 'auto_generate_unique_sku' ) && VI_WOO_ALIDROPSHIP_DATA::sku_exists( $product_data['sku'] )
		     && $product_data['sku'] != get_post_meta( $woo_product_id, '_sku', true ) ) {
			wp_send_json( array(
				'status'  => 'error',
				'message' => esc_html__( 'Sku exists.', 'woo-alidropship' ),
			) );
		}
		if ( VI_WOO_ALIDROPSHIP_DATA::product_get_id_by_aliexpress_id( Ali_Product_Table::get_post_meta( $product_draft_id, '_vi_wad_sku', true ), array( 'publish' ) ) ) {
			wp_send_json( array(
				'status'  => 'error',
				'message' => esc_html__( 'This product has already been imported', 'woo-alidropship' ),
			) );
		}
		if ( ! $override_product_id || Ali_Product_Table::get_post_meta( $override_product_id, '_vi_wad_sku', true ) == Ali_Product_Table::get_post_meta( $product_draft_id, '_vi_wad_sku', true ) ) {
			$override_keep_product = '1';
		}
		$woo_product = wc_get_product( $woo_product_id );
		if ( $woo_product ) {
			if ( 1 != $check_orders && ( $override_find_in_orders == 1 || $override_keep_product == 1 ) ) {
				$is_simple = false;
				if ( ! is_array( $attributes ) || ! count( $attributes ) || ( isset( $product_data['variations'] ) && count( $selected[ $product_draft_id ] ) === 1 && self::$settings->get_params( 'simple_if_one_variation' ) ) ) {
					$is_simple = true;
				}
				if ( $is_simple ) {
					$variations = array( array_values( $product_data['variations'] )[0] );
				} else {
					if ( isset( $product_data['variations'] ) ) {
						$variations = array_values( $product_data['variations'] );
					} else {
						$variations = self::get_product_variations( $product_draft_id );
					}
				}
				$replace_order_html = '';

				if ( $woo_product->is_type( 'variable' ) && ! $is_simple ) {
					$woo_product_children = $woo_product->get_children();
					if ( count( $woo_product_children ) ) {
						foreach ( $woo_product_children as $woo_product_child ) {
							$found_item = self::query_order_item_meta( array( 'order_item_type' => 'line_item' ), array( 'meta_key'   => '_variation_id', 'meta_value' => $woo_product_child ) );// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value
							self::skip_item_with_ali_order_id( $found_item );
							if ( $override_keep_product || count( $found_item ) ) {
								$found_items[ $woo_product_child ] = $found_item;
								$replace_order_html                .= self::get_override_variation_html( $woo_product, $woo_product_child, $variations, count( $found_item ), $is_simple );
							}
						}
					}
				} else {
					$found_item = self::query_order_item_meta( array( 'order_item_type' => 'line_item' ), array( 'meta_key'   => '_product_id', 'meta_value' => $woo_product_id, ) );// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value
					self::skip_item_with_ali_order_id( $found_item );
					if ( count( $found_item ) ) {
						$found_items[ $woo_product_id ] = $found_item;
						$replace_order_html             = self::get_override_simple_html( $woo_product, $woo_product_id, $variations, count( $found_item ), $is_simple );
					}
				}
				if ( count( $found_items ) ) {
					$message = $override_keep_product ? '<div class="vi-ui message warning">' . esc_html__( 'By selecting a replacement, a new variation will be created by modifying the respective overridden variation. Overridden variations with no replacement selected will be deleted', 'woo-alidropship' ) . '</div>' : '';
					wp_send_json( array(
						'status'             => 'checked',
						'message'            => '',
						'found_items'        => $found_items,
						'replace_order_html' => $message . '<table class="vi-ui celled table"><thead><tr><th>' . esc_html__( 'Overridden items', 'woo-alidropship' ) . '</th><th width="1%">' . esc_html__( 'Found in unfulfilled orders', 'woo-alidropship' ) . '</th><th>' . esc_html__( 'Replacement', 'woo-alidropship' ) . '</th></tr></thead><tbody>' . $replace_order_html . '</tbody></table>',
					) );
				}
			}
		} else {
			wp_send_json( array(
				'status'  => 'error',
				'message' => esc_html__( 'Overridden product does not exist', 'woo-alidropship' ),
			) );
		}
		$variations_attributes = array();
		if ( isset( $product_data['variations'] ) ) {
			$variations = array_values( $product_data['variations'] );
			if ( count( $variations ) > 1 ) {
				$var_default = isset( $product_data['default_variation'] ) ? $product_data['default_variation'] : '';
				foreach ( $variations as $variations_v ) {
					if ( $var_default === $variations_v['skuAttr'] ) {
						$product_data['variation_default'] = $variations_v['attributes'];
					}
					$variations_attribute = isset( $variations_v['attributes'] ) ? $variations_v['attributes'] : array();
					if ( is_array( $variations_attribute ) && count( $variations_attribute ) ) {
						foreach ( $variations_attribute as $variations_attribute_k => $variations_attribute_v ) {
							if ( ! isset( $variations_attributes[ $variations_attribute_k ] ) ) {
								$variations_attributes[ $variations_attribute_k ] = array( $variations_attribute_v );
							} elseif ( ! in_array( $variations_attribute_v, $variations_attributes[ $variations_attribute_k ] ) ) {
								$variations_attributes[ $variations_attribute_k ][] = $variations_attribute_v;
							}
						}
					}
				}

				if ( is_array( $attributes ) && count( $attributes ) ) {
					foreach ( $attributes as $attributes_k => $attributes_v ) {
						if ( ! empty( $variations_attributes[ $attributes_v['slug'] ] ) ) {
							$attributes[ $attributes_k ]['values'] = array_intersect( $attributes[ $attributes_k ]['values'], $variations_attributes[ $attributes_v['slug'] ] );
						}
					}
				}
			}
		} else {
			$variations    = self::get_product_variations( $product_draft_id );
			$shipping_cost = 0;
			if ( self::$settings->get_params( 'show_shipping_option' ) ) {
				$shipping_info = self::get_shipping_info( $product_draft_id, '', '' );
				$shipping_cost = abs( VI_WOO_ALIDROPSHIP_DATA::string_to_float( $shipping_info['shipping_cost'] ) );
			}
			if ( self::$settings->get_params( 'shipping_cost_after_price_rules' ) ) {
				foreach ( $variations as $variations_k => $variations_v ) {
					$variation_sale_price    = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations_v['sale_price'] );
					$variation_regular_price = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations_v['regular_price'] );
					$price                   = $variation_sale_price ? $variation_sale_price : $variation_regular_price;
					$sale_price              = self::$settings->process_price( $price, true );
					if ( $sale_price ) {
						$sale_price += $shipping_cost;
					}
					$regular_price                                = self::$settings->process_price( $price ) + $shipping_cost;
					$variations[ $variations_k ]['sale_price']    = self::$settings->process_exchange_price( $sale_price );
					$variations[ $variations_k ]['regular_price'] = self::$settings->process_exchange_price( $regular_price );
				}
			} else {
				foreach ( $variations as $variations_k => $variations_v ) {
					$variation_sale_price                         = $variations_v['sale_price'] ? ( VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations_v['sale_price'] ) + $shipping_cost ) : VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations_v['sale_price'] );
					$variation_regular_price                      = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations_v['regular_price'] ) + $shipping_cost;
					$price                                        = $variation_sale_price ? $variation_sale_price : $variation_regular_price;
					$variations[ $variations_k ]['sale_price']    = self::$settings->process_exchange_price( self::$settings->process_price( $price, true ) );
					$variations[ $variations_k ]['regular_price'] = self::$settings->process_exchange_price( self::$settings->process_price( $price ) );
				}
			}
		}

		if ( count( $variations ) ) {
			if ( 1 != $override_options['override_title'] ) {
				$product_data['title'] = $woo_product->get_title();
			}
			if ( 1 != $override_options['override_images'] ) {
				$product_data['old_product_image']   = get_post_meta( $woo_product_id, '_thumbnail_id', true );
				$product_data['old_product_gallery'] = get_post_meta( $woo_product_id, '_product_image_gallery', true );
			}
			if ( 1 != $override_options['override_description'] ) {
				$product_data['short_description'] = $woo_product->get_short_description();
				$product_data['description']       = $woo_product->get_description();
			}
			if ( isset( $product_data['gallery'] ) ) {
				$product_data['gallery'] = array_values( array_filter( $product_data['gallery'] ) );
				if ( $product_data['image'] ) {
					$product_image_key = array_search( $product_data['image'], $product_data['gallery'] );
					if ( $product_image_key !== false ) {
						unset( $product_data['gallery'][ $product_image_key ] );
						$product_data['gallery'] = array_values( $product_data['gallery'] );
					}
				}
			} else {
				$product_data['gallery'] = array();
			}

			$variation_images                 = Ali_Product_Table::get_post_meta( $product_draft_id, '_vi_wad_variation_images', true );
			$product_data['variation_images'] = $variation_images;
			$product_data['attributes']       = $attributes;
			$product_data['variations']       = $variations;
			$product_data['parent_id']        = $product_draft_id;
			$product_data['ali_product_id']   = Ali_Product_Table::get_post_meta( $product_draft_id, '_vi_wad_sku', true );
			$disable_background_process       = self::$settings->get_params( 'disable_background_process' );

			if ( $override_keep_product ) {
				$is_simple = false;
				if ( ! is_array( $attributes ) || ! count( $attributes ) || ( count( $variations ) === 1 && self::$settings->get_params( 'simple_if_one_variation' ) ) ) {
					$is_simple = true;
				}
				$woo_product->set_status( $product_data['status'] );
				if ( $product_data['sku'] ) {
					$woo_product->set_sku( wc_product_generate_unique_sku( $woo_product_id, $product_data['sku'] ) );
				}
				if ( 1 == $override_options['override_title'] && $product_data['title'] ) {
					$woo_product->set_name( $product_data['title'] );
				}
				$dispatch = false;
				if ( 1 == $override_options['override_images'] ) {
					if ( $product_data['image'] ) {
						$thumb_id = VI_WOO_ALIDROPSHIP_DATA::download_image( $image_id, $product_data['image'], $woo_product_id );
						if ( ! is_wp_error( $thumb_id ) ) {
							update_post_meta( $woo_product_id, '_thumbnail_id', $thumb_id );
						}
					}
					self::process_gallery_images( $product_data['gallery'], $disable_background_process, $woo_product_id, $product_draft_id, $dispatch );
				}
				if ( 1 == $override_options['override_description'] ) {
					$woo_product->set_description( $product_data['description'] );
					self::process_description_images( $product_data['description'], $disable_background_process, $woo_product_id, $product_draft_id, $dispatch );
				}
				/*Set product tag*/
				if ( isset( $product_data['tags'] ) && is_array( $product_data['tags'] ) && count( $product_data['tags'] ) ) {
					wp_set_post_terms( $woo_product_id, $product_data['tags'], 'product_tag', true );
				}
				/*Set product categories*/
				if ( isset( $product_data['categories'] ) && is_array( $product_data['categories'] ) && count( $product_data['categories'] ) ) {
					wp_set_post_terms( $woo_product_id, $product_data['categories'], 'product_cat', true );
				}
				/*Set product shipping class*/
				if ( isset( $product_data['shipping_class'] ) && $product_data['shipping_class'] && get_term_by( 'id', $product_data['shipping_class'], 'product_shipping_class' ) ) {
					wp_set_post_terms( $woo_product_id, array( intval( $product_data['shipping_class'] ) ), 'product_shipping_class', false );
				}

				update_post_meta( $woo_product_id, '_vi_wad_aliexpress_product_id', $product_data['ali_product_id'] );
				vi_wad_set_catalog_visibility( $woo_product_id, $product_data['catalog_visibility'] );

				if ( $is_simple ) {
					if ( ! empty( $variations[0]['skuId'] ) ) {
						update_post_meta( $woo_product_id, '_vi_wad_aliexpress_variation_id', $variations[0]['skuId'] );
					}
					if ( ! empty( $variations[0]['skuAttr'] ) ) {
						update_post_meta( $woo_product_id, '_vi_wad_aliexpress_variation_attr', $variations[0]['skuAttr'] );
					}
					if ( ! empty( $variations[0]['ship_from'] ) ) {
						update_post_meta( $woo_product_id, '_vi_wad_aliexpress_variation_ship_from', $variations[0]['ship_from'] );
					}
					if ( $woo_product->is_type( 'variable' ) ) {
						$woo_product->set_attributes( array() );
						$woo_product->save();
						$children = $woo_product->get_children();
						if ( count( $children ) ) {
							foreach ( $children as $variation_id ) {
								wp_delete_post( $variation_id, true );
							}
						}
						wp_set_object_terms( $woo_product_id, 'simple', 'product_type' );
					}
					$sale_price    = isset( $variations[0]['sale_price'] ) ? floatval( $variations[0]['sale_price'] ) : '';
					$regular_price = isset( $variations[0]['regular_price'] ) ? floatval( $variations[0]['regular_price'] ) : '';
					$price         = $regular_price;
					if ( $sale_price && $sale_price > 0 && $regular_price && $sale_price < $regular_price ) {
						$price = $sale_price;
					} else {
						$sale_price = '';
					}
					$woo_product->set_regular_price( $regular_price );
					$woo_product->set_sale_price( $sale_price );
					$woo_product->set_price( $price );
					$woo_product->set_manage_stock( 'yes' );
					$woo_product->set_stock_status( 'instock' );
					$woo_product->set_stock_quantity( isset( $variations[0]['stock'] ) ? absint( $variations[0]['stock'] ) : 0 );
					$woo_product->save();
					wp_set_object_terms( $woo_product_id, 'simple', 'product_type' );
					if ( $dispatch ) {
						self::$process_image->save()->dispatch();
					}
				} else {
					delete_post_meta( $woo_product_id, '_vi_wad_aliexpress_variation_id' );
					delete_post_meta( $woo_product_id, '_vi_wad_aliexpress_variation_attr' );
					delete_post_meta( $woo_product_id, '_vi_wad_aliexpress_variation_ship_from' );
					$default_attr = isset( $product_data['variation_default'] ) ? $product_data['variation_default'] : array();
					$attr_data    = self::create_product_attributes( $attributes, $default_attr );
					if ( count( $attr_data ) ) {
						$woo_product->set_attributes( $attr_data );
						if ( $default_attr ) {
							$woo_product->set_default_attributes( $default_attr );
						}
						$woo_product->save();
					}
					wp_set_object_terms( $woo_product_id, 'variable', 'product_type' );
					$children = array();
					if ( $woo_product->is_type( 'variable' ) ) {
						$children = $woo_product->get_children();
					} else {

					}
					$use_global_attributes = self::$settings->get_params( 'use_global_attributes' );
					$manage_stock          = self::$settings->get_params( 'manage_stock' );
					$manage_stock          = $manage_stock ? 'yes' : 'no';
					if ( count( $children ) ) {
						$skuAttrArray = array_column( $variations, 'skuAttr' );
						foreach ( $children as $variation_id ) {
							if ( ! empty( $replace_items[ $variation_id ] ) ) {
								$variations_key = array_search( $replace_items[ $variation_id ], $skuAttrArray );
								if ( $variations_key !== false ) {
									$variation = new WC_Product_Variation( $variation_id );
									if ( $variation ) {
										$product_data['variations'][ $variations_key ]['variation_id'] = $variation_id;
//											if ( 1 != $override_options['override_images'] && ! $variation->get_image_id() ) {
//												$product_data['variations'][ $variations_key ]['image'] = '';
//											}
										$product_variation = $variations[ $variations_key ];
										$stock_quantity    = isset( $product_variation['stock'] ) ? absint( $product_variation['stock'] ) : 0;
										$v_attributes      = array();
										if ( $use_global_attributes ) {
											foreach ( $product_variation['attributes'] as $option_k => $attr ) {
												$attribute_id  = wc_attribute_taxonomy_id_by_name( $option_k );
												$attribute_obj = wc_get_attribute( $attribute_id );
												if ( $attribute_obj ) {
													$attribute_value = self::get_term_by_name( $attr, $attribute_obj->slug );
													if ( $attribute_value ) {
														$v_attributes[ strtolower( urlencode( $attribute_obj->slug ) ) ] = $attribute_value->slug;
													}
												}
											}
										} else {
											foreach ( $product_variation['attributes'] as $option_k => $attr ) {
												$v_attributes[ strtolower( urlencode( $option_k ) ) ] = $attr;
											}
										}
										$variation->set_attributes( $v_attributes );
										$fields = array(
											'sku'            => wc_product_generate_unique_sku( $variation_id, $product_variation['sku'] ),
											'regular_price'  => $product_variation['regular_price'],
											'price'          => $product_variation['regular_price'],
											'sale_price'     => '',
											'manage_stock'   => $manage_stock,
											'stock_status'   => 'instock',
											'stock_quantity' => $stock_quantity,
										);
										if ( isset( $product_variation['sale_price'] ) && $product_variation['sale_price'] && $product_variation['sale_price'] < $product_variation['regular_price'] ) {
											$fields['sale_price'] = $product_variation['sale_price'];
											$fields['price']      = $product_variation['sale_price'];
										}
										foreach ( $fields as $field => $value ) {
											$variation->{"set_$field"}( wc_clean( $value ) );
										}
										$variation->save();
										update_post_meta( $variation_id, '_vi_wad_aliexpress_variation_id', $product_variation['skuId'] );
										update_post_meta( $variation_id, '_vi_wad_aliexpress_variation_attr', $product_variation['skuAttr'] );
										if ( ! empty( $product_variation['ship_from'] ) ) {
											update_post_meta( $variation_id, '_vi_wad_aliexpress_variation_ship_from', $product_variation['ship_from'] );
										}
									}
								} else {
									wp_delete_post( $variation_id, true );
								}
							} else {
								wp_delete_post( $variation_id, true );
							}
						}
					}
					/*Create product variation*/
					$this->import_product_variation( $woo_product_id, $product_data, $dispatch, $disable_background_process );
				}

				Ali_Product_Table::wp_update_post( array(
					'ID'          => $product_draft_id,
					'post_status' => 'publish'
				) );

				Ali_Product_Table::update_post_meta( $product_draft_id, '_vi_wad_woo_id', $woo_product_id );

				if ( $override_product_id ) {
					Ali_Product_Table::wp_delete_post( $override_product_id );
				}

				wp_send_json( array(
					'status'      => 'success',
					'product_id'  => $woo_product_id,
					'message'     => '',
					'button_html' => self::get_button_view_edit_html( $woo_product_id ),
				) );
			} else {
				$product_data['replace_items'] = $replace_items;
				$product_data['replace_title'] = $override_options['override_title'];
				$product_data['found_items']   = $found_items;
				$product_id                    = $this->import_product( $product_data );
				$response                      = array(
					'status'     => 'error',
					'message'    => '',
					'product_id' => '',
				);
				if ( ! is_wp_error( $product_id ) ) {
					if ( $override_product_id ) {
						Ali_Product_Table::wp_delete_post( $override_product_id );
					}
					wp_delete_post( $woo_product_id );
					$response['status']      = 'success';
					$response['product_id']  = $product_id;
					$response['button_html'] = self::get_button_view_edit_html( $woo_product_id );
				} else {
					$response['message'] = $product_id->get_error_messages();
				}
				wp_send_json( $response );
			}
		} else {
			wp_send_json( array(
				'status'  => 'error',
				'message' => esc_html__( 'Please select at least 1 variation to import this product.', 'woo-alidropship' ),
			) );
		}
		// phpcs:enable WordPress.Security.NonceVerification

	}

	public static function create_product_attributes( $attributes, &$default_attr ) {
		global $wp_taxonomies;
		$position  = 0;
		$attr_data = array();
		if ( self::$settings->get_params( 'use_global_attributes' ) ) {
			foreach ( $attributes as $key => $attr ) {
				$attribute_name = isset( $attr['name'] ) ? $attr['name'] : VI_WOO_ALIDROPSHIP_DATA::get_attribute_name_by_slug( $attr['slug'] );
				$attribute_id   = wc_attribute_taxonomy_id_by_name( $attribute_name );
				if ( ! $attribute_id ) {
					$attribute_id = wc_create_attribute( array(
						'name'         => $attribute_name,
						'slug'         => $attr['slug'],
						'type'         => 'select',
						'order_by'     => 'menu_order',
						'has_archives' => false,
					) );
				}
				if ( $attribute_id && ! is_wp_error( $attribute_id ) ) {
					$attribute_obj     = wc_get_attribute( $attribute_id );
					$attribute_options = array();
					if ( ! empty( $attribute_obj ) ) {
						$taxonomy = $attribute_obj->slug; // phpcs:ignore
						if ( isset( $default_attr[ $attr['slug'] ] ) ) {
							$default_attr[ $taxonomy ] = $default_attr[ $attr['slug'] ];
							unset( $default_attr[ $attr['slug'] ] );
						}
						/*Update global $wp_taxonomies for latter insert attribute values*/
						$wp_taxonomies[ $taxonomy ] = new WP_Taxonomy( $taxonomy, 'product' );
						if ( count( $attr['values'] ) ) {
							foreach ( $attr['values'] as $attr_value ) {
								$attr_value  = strval( wc_clean( $attr_value ) );
								$insert_term = wp_insert_term( $attr_value, $taxonomy );
								if ( ! is_wp_error( $insert_term ) ) {
									$attribute_options[] = $insert_term['term_id'];
									if ( isset( $default_attr[ $taxonomy ] ) ) {
										$term_exists = get_term_by( 'id', $insert_term['term_id'], $taxonomy );
										if ( $term_exists ) {
											$default_attr[ $taxonomy ] = $term_exists->slug;
										}
									}
								} elseif ( isset( $insert_term->error_data ) && isset( $insert_term->error_data['term_exists'] ) ) {
									$attribute_options[] = $insert_term->error_data['term_exists'];
									if ( isset( $default_attr[ $taxonomy ] ) ) {
										$term_exists = get_term_by( 'id', $insert_term->error_data['term_exists'], $taxonomy );
										if ( $term_exists ) {
											$default_attr[ $taxonomy ] = $term_exists->slug;
										}
									}
								}
							}
						}
					}
					$attribute_object = new WC_Product_Attribute();
					$attribute_object->set_id( $attribute_id );
					$attribute_object->set_name( wc_attribute_taxonomy_name_by_id( $attribute_id ) );
					if ( count( $attribute_options ) ) {
						$attribute_object->set_options( $attribute_options );
					} else {
						$attribute_object->set_options( $attr['values'] );
					}
					$attribute_object->set_position( isset( $attr['position'] ) ? $attr['position'] : $position );
					$attribute_object->set_visible( self::$settings->get_params( 'variation_visible' ) ? 1 : '' );
					$attribute_object->set_variation( 1 );
					$attr_data[] = $attribute_object;
				}
				$position ++;
			}
		} else {
			foreach ( $attributes as $key => $attr ) {
				$attribute_name   = isset( $attr['name'] ) ? $attr['name'] : VI_WOO_ALIDROPSHIP_DATA::get_attribute_name_by_slug( $attr['slug'] );
				$attribute_object = new WC_Product_Attribute();
				$attribute_object->set_name( $attribute_name );
				$attribute_object->set_options( $attr['values'] );
				$attribute_object->set_position( isset( $attr['position'] ) ? $attr['position'] : $position );
				$attribute_object->set_visible( self::$settings->get_params( 'variation_visible' ) ? 1 : '' );
				$attribute_object->set_variation( 1 );
				$attr_data[] = $attribute_object;
				$position ++;
			}
		}

		return $attr_data;
	}

	/**
	 * @param $items
	 *
	 * @throws Exception
	 */
	public static function skip_item_with_ali_order_id( &$items ) {
		foreach ( $items as $key => $item ) {
			if ( wc_get_order_item_meta( $item['order_item_id'], '_vi_wad_aliexpress_order_id', true ) ) {
				unset( $items[ $key ] );
			}
		}
		$items = array_values( $items );
	}

	/**
	 * @param array $args1 $key=>$value are key and value of woocommerce_order_items table
	 * @param array $args2 $key=>$value are key and value of woocommerce_order_itemmeta table
	 *
	 * @return array|null|object
	 */
	protected static function query_order_item_meta( $args1 = array(), $args2 = array() ) {
		global $wpdb;
		$sql  = "SELECT * FROM {$wpdb->prefix}woocommerce_order_items as woocommerce_order_items JOIN {$wpdb->prefix}woocommerce_order_itemmeta as woocommerce_order_itemmeta WHERE woocommerce_order_items.order_item_id=woocommerce_order_itemmeta.order_item_id";
		$args = array();
		if ( count( $args1 ) ) {
			foreach ( $args1 as $key => $value ) {
				if ( is_array( $value ) ) {
					$sql .= " AND woocommerce_order_items.{$key} IN (" . implode( ', ', array_fill( 0, count( $value ), '%s' ) ) . ")";
					foreach ( $value as $v ) {
						$args[] = $v;
					}
				} else {
					$sql    .= " AND woocommerce_order_items.{$key}='%s'";
					$args[] = $value;
				}
			}
		}
		if ( count( $args2 ) ) {
			foreach ( $args2 as $key => $value ) {
				if ( is_array( $value ) ) {
					$sql .= " AND woocommerce_order_itemmeta.{$key} IN (" . implode( ', ', array_fill( 0, count( $value ), '%s' ) ) . ")";
					foreach ( $value as $v ) {
						$args[] = $v;
					}
				} else {
					$sql    .= " AND woocommerce_order_itemmeta.{$key}='%s'";
					$args[] = $value;
				}
			}
		}
		$query      = $wpdb->prepare( $sql, $args );// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
		$line_items = $wpdb->get_results( $query, ARRAY_A );// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

		return $line_items;
	}

	public function switch_product_attributes_values() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		$key        = isset( $_POST['product_index'] ) ? absint( sanitize_text_field( $_POST['product_index'] ) ) : '';
		$product_id = isset( $_POST['product_id'] ) ? sanitize_text_field( $_POST['product_id'] ) : '';
		if ( $key > - 1 && $product_id ) {
			$currency                    = 'USD';
			$woocommerce_currency        = get_option( 'woocommerce_currency' );
			$woocommerce_currency_symbol = get_woocommerce_currency_symbol( $woocommerce_currency );
			$manage_stock                = self::$settings->get_params( 'manage_stock' );
			$use_different_currency      = false;
			$decimals                    = wc_get_price_decimals();
			$variations                  = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_variations', true );
			if ( is_array( $variations ) && count( $variations ) ) {
				foreach ( $variations as $variation_k => $variation ) {
					if ( isset( $variation['attributes_sub'] ) && is_array( $variation['attributes_sub'] ) && count( $variation['attributes_sub'] ) === count( $variation['attributes'] ) ) {
						$temp                                         = $variation['attributes'];
						$variations[ $variation_k ]['attributes']     = $variation['attributes_sub'];
						$variations[ $variation_k ]['attributes_sub'] = $temp;
					}
					if ( ! empty( $variation['sku'] ) ) {
						$temp                                  = $variation['sku'];
						$variations[ $variation_k ]['sku']     = $variation['sku_sub'];
						$variations[ $variation_k ]['sku_sub'] = $temp;
					}
				}
				Ali_Product_Table::update_post_meta( $product_id, '_vi_wad_variations', $variations );
			} else {
				wp_send_json(
					array(
						'status' => 'error',
						'data'   => esc_html__( 'Can not find replacement for product attributes values. Please remove this product and import it again with the latest version of this plugin and Chrome Extension', 'woo-alidropship' )
					)
				);
			}
			$attributes = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_attributes', true );
			if ( is_array( $attributes ) && count( $attributes ) ) {
				foreach ( $attributes as $attribute_k => $attribute ) {
					if ( ! empty( $attribute['values_sub'] ) ) {
						$temp                                     = $attribute['values'];
						$attributes[ $attribute_k ]['values']     = $attribute['values_sub'];
						$attributes[ $attribute_k ]['values_sub'] = $temp;
					}
				}
				Ali_Product_Table::update_post_meta( $product_id, '_vi_wad_attributes', $attributes );
			} else {
				wp_send_json(
					array(
						'status' => 'error',
						'data'   => esc_html__( 'Can not find replacement for product attributes values. Please remove this product and import it again with the latest version of this plugin and Chrome Extension', 'woo-alidropship' )
					)
				);
			}
			$list_attributes = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_list_attributes', true );
			if ( is_array( $list_attributes ) && count( $list_attributes ) ) {
				foreach ( $list_attributes as $list_attribute_k => $list_attribute ) {
					if ( ! empty( $list_attribute['name_sub'] ) ) {
						$temp                                             = $list_attribute['name'];
						$list_attributes[ $list_attribute_k ]['name']     = $list_attribute['name_sub'];
						$list_attributes[ $list_attribute_k ]['name_sub'] = $temp;
					}
				}
				Ali_Product_Table::update_post_meta( $product_id, '_vi_wad_list_attributes', $list_attributes );
			}
			$parent = array();
			if ( is_array( $attributes ) && count( $attributes ) ) {
				foreach ( $attributes as $attribute_k => $attribute_v ) {
					$parent[ $attribute_k ] = $attribute_v['slug'];
				}
			}
			if ( $decimals < 1 ) {
				$decimals = 1;
			} else {
				$decimals = pow( 10, ( - 1 * $decimals ) );
			}
			if ( strtolower( $woocommerce_currency ) != strtolower( $currency ) ) {
				$use_different_currency = true;
			}
			ob_start();
			self::variation_html( $key, $parent, $attributes, $manage_stock, $variations, $use_different_currency, $currency, $product_id, $woocommerce_currency_symbol, $decimals, false );
			$return = ob_get_clean();
			wp_send_json(
				array(
					'status' => 'success',
					'data'   => $return
				)
			);
		} else {
			wp_send_json(
				array(
					'status' => 'error',
					'data'   => esc_html__( 'Can not find replacement for product attributes values. Please remove this product and import it again with the latest version of this plugin and Chrome Extension', 'woo-alidropship' )
				)
			);
		}
		// phpcs:enable WordPress.Security.NonceVerification
	}

	public function background_process() {
		self::$process              = new Vi_WAD_Background_Import_Product();
		self::$process_image        = new Vi_WAD_Background_Download_Images();
		self::$download_description = new Vi_WAD_Background_Download_Description();
		$nonce                      = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( $_REQUEST['_wpnonce'] ) : '';
		if ( wp_verify_nonce( $nonce ) ) {
			if ( ! empty( $_REQUEST['vi_wad_cancel_import_product'] ) ) {
				self::$process->kill_process();
				wp_safe_redirect( @remove_query_arg( array( 'vi_wad_cancel_import_product', '_wpnonce' ) ) );
				exit;
			}
			if ( ! empty( $_REQUEST['vi_wad_cancel_download_product_image'] ) ) {
				self::$process_image->kill_process();
				wp_safe_redirect( @remove_query_arg( array( 'vi_wad_cancel_download_product_image', '_wpnonce' ) ) );
				exit;
			}
			if ( ! empty( $_REQUEST['vi_wad_run_download_product_image'] ) ) {
				if ( ! self::$process_image->is_process_running() && ! self::$process_image->is_queue_empty() ) {
					self::$process_image->dispatch();
				}
				wp_safe_redirect( @remove_query_arg( array( 'vi_wad_run_download_product_image', '_wpnonce' ) ) );
				exit;
			}
			if ( ! empty( $_REQUEST['vi_wad_cancel_download_product_description'] ) ) {
				self::$download_description->kill_process();
				wp_safe_redirect( @remove_query_arg( array( 'vi_wad_cancel_download_product_description', '_wpnonce' ) ) );
				exit;
			}
		}
	}

	public function admin_notices() {
		if ( self::$process_image->is_process_running() ) {
			$is_late = false;
			$next    = wp_next_scheduled( 'wp_vi_wad_background_download_images_cron' );
			if ( $next ) {
				$late = $next - time();
				if ( $late < - 300 ) {
					$is_late = true;
				}
			}
			if ( $is_late ) {
				?>
                <div class="notice notice-error">
                    <p>
						<?php echo wp_kses_post(sprintf( __( '<strong>ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce</strong>: <i>wp_vi_wad_background_download_images_cron</i> is late, queued product images may not be processed. If you want to move all queued images to Failed images page to handle them manually, please click <a href="%s">Move</a>', 'woo-alidropship' ), esc_url_raw( wp_nonce_url( add_query_arg( array( 'vi_wad_move_queued_images' => 1 ) ) ) ) )); //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?>
                    </p>
                </div>
				<?php
			} else {
				?>
                <div class="notice notice-warning">
                    <p>
						<?php echo wp_kses_post(__( '<strong>ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce</strong>: Product images are still being processed in the background, please do not edit products/go to product edit page until all images are processed completely.', 'woo-alidropship' )) ?>
                    </p>
                </div>
				<?php
			}
		} else {
			if ( self::$process_image->is_queue_empty() ) {
				if ( get_transient( 'vi_wad_background_download_images_complete' ) ) {
					delete_transient( 'vi_wad_background_download_images_complete' );
					?>
                    <div class="updated">
                        <p>
							<?php echo wp_kses_post(__( '<strong>ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce</strong>: Finish processing product images', 'woo-alidropship' )) ?>
                        </p>
                    </div>
					<?php
				}
			} else {
				?>
                <div class="notice notice-warning">
                    <p>
						<?php echo wp_kses_post(sprintf( __( '<strong>ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce</strong>: There are still images in the queue but background process is not running. <a href="%1$s">Run</a> or <a href="%2$s">Move to Failed images</a>', 'woo-alidropship' ), esc_url_raw( wp_nonce_url( add_query_arg( array( 'vi_wad_run_download_product_image' => 1 ) ) ) ), esc_url_raw( wp_nonce_url( add_query_arg( array( 'vi_wad_move_queued_images' => 1 ) ) ) ) )) //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?>
                    </p>
                </div>
				<?php
			}
		}
	}

	/**
	 * @throws Exception
	 */
	public function import() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();// phpcs:disable WordPress.Security.NonceVerification
		/*Some servers will base64 encode when sending $_POST to the server*/
		$decoded = base64_decode( $_POST['form_data'], true );

		if ( $decoded === false ) {
			parse_str( $_POST['form_data'], $form_data );// phpcs:ignore WordPress.Security.NonceVerification.Missing
		} else {
			/*Remove wrapping double quotes after base64 decoding to prevent errors.*/
			$decoded = str_replace( '"', '', $decoded );
			parse_str( $decoded, $form_data );// phpcs:ignore WordPress.Security.NonceVerification.Missing
		}

		if ( ! isset( $form_data['z_check_max_input_vars'] ) ) {
			/*z_check_max_input_vars is the last key of POST data. If it does not exist in $form_data after using parse_str(), some data may also be missing*/
			wp_send_json( array(
				'status'  => 'error',
				'message' => esc_html__( 'PHP max_input_vars is too low, please increase it in php.ini', 'woo-alidropship' ),
			) );
		}
		$data     = isset( $form_data['vi_wad_product'] ) ? stripslashes_deep( $form_data['vi_wad_product'] ) : array();
		$selected = isset( $_POST['selected'] ) ? vi_wad_json_decode( stripslashes_deep( $_POST['selected'] ) ) : array();
		$response = array(
			'status'         => 'error',
			'message'        => '',
			'woo_product_id' => '',
			'button_html'    => '',
		);
		if ( count( $data ) === 0 ) {
			$response['message'] = esc_html__( 'Please select product to import', 'woo-alidropship' );
		} else {
			$product_data     = array_values( $data )[0];
			$product_draft_id = array_keys( $data )[0];
			if ( ! count( $selected[ $product_draft_id ] ) ) {
				$response['message'] = esc_html__( 'Please select at least 1 variation to import this product.', 'woo-alidropship' );
				wp_send_json( $response );
			}
			if ( ! $product_draft_id || VI_WOO_ALIDROPSHIP_DATA::sku_exists( $product_data['sku'] ) ) {
				$response['message'] = esc_html__( 'Sku exists.', 'woo-alidropship' );
				wp_send_json( $response );
			}
			if ( VI_WOO_ALIDROPSHIP_DATA::product_get_id_by_aliexpress_id( Ali_Product_Table::get_post_meta( $product_draft_id, '_vi_wad_sku', true ), array( 'publish' ) ) ) {
				wp_send_json( array(
					'status'  => 'error',
					'message' => esc_html__( 'This product has already been imported', 'woo-alidropship' ),
				) );
			}
			$variations_attributes = array();
			$attributes            = self::get_product_attributes( $product_draft_id );
			if ( isset( $product_data['variations'] ) ) {
				$variations = array_values( $product_data['variations'] );
				if ( count( $variations ) > 1 ) {
					$var_default = isset( $product_data['default_variation'] ) ? $product_data['default_variation'] : '';
					foreach ( $variations as $variations_v ) {
						if ( $var_default === $variations_v['skuAttr'] ) {
							$product_data['variation_default'] = $variations_v['attributes'];
						}
						$variations_attribute = isset( $variations_v['attributes'] ) ? $variations_v['attributes'] : array();
						if ( is_array( $variations_attribute ) && count( $variations_attribute ) ) {
							foreach ( $variations_attribute as $variations_attribute_k => $variations_attribute_v ) {
								if ( ! isset( $variations_attributes[ $variations_attribute_k ] ) ) {
									$variations_attributes[ $variations_attribute_k ] = array( $variations_attribute_v );
								} elseif ( ! in_array( $variations_attribute_v, $variations_attributes[ $variations_attribute_k ] ) ) {
									$variations_attributes[ $variations_attribute_k ][] = $variations_attribute_v;
								}
							}
						}
					}

					if ( is_array( $attributes ) && count( $attributes ) ) {
						foreach ( $attributes as $attributes_k => $attributes_v ) {
							if ( ! empty( $variations_attributes[ $attributes_v['slug'] ] ) ) {
								$attributes[ $attributes_k ]['values'] = array_intersect( $attributes[ $attributes_k ]['values'], $variations_attributes[ $attributes_v['slug'] ] );
							}
						}
					}
				}
			} else {
				$variations    = self::get_product_variations( $product_draft_id );
				$shipping_cost = 0;
				if ( self::$settings->get_params( 'show_shipping_option' ) ) {
					$shipping_info = self::get_shipping_info( $product_draft_id, '', '' );
					$shipping_cost = abs( VI_WOO_ALIDROPSHIP_DATA::string_to_float( $shipping_info['shipping_cost'] ) );
				}
				if ( self::$settings->get_params( 'shipping_cost_after_price_rules' ) ) {
					foreach ( $variations as $variations_k => $variations_v ) {
						$variation_sale_price    = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations_v['sale_price'] );
						$variation_regular_price = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations_v['regular_price'] );
						$price                   = $variation_sale_price ? $variation_sale_price : $variation_regular_price;
						$sale_price              = self::$settings->process_price( $price, true );
						if ( $sale_price ) {
							$sale_price += $shipping_cost;
						}
						$regular_price                                = self::$settings->process_price( $price ) + $shipping_cost;
						$variations[ $variations_k ]['sale_price']    = self::$settings->process_exchange_price( $sale_price );
						$variations[ $variations_k ]['regular_price'] = self::$settings->process_exchange_price( $regular_price );
					}
				} else {
					foreach ( $variations as $variations_k => $variations_v ) {
						$variation_sale_price                         = $variations_v['sale_price'] ? ( VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations_v['sale_price'] ) + $shipping_cost ) : VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations_v['sale_price'] );
						$variation_regular_price                      = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations_v['regular_price'] ) + $shipping_cost;
						$price                                        = $variation_sale_price ? $variation_sale_price : $variation_regular_price;
						$variations[ $variations_k ]['sale_price']    = self::$settings->process_exchange_price( self::$settings->process_price( $price, true ) );
						$variations[ $variations_k ]['regular_price'] = self::$settings->process_exchange_price( self::$settings->process_price( $price ) );
					}
				}
			}

			if ( count( $variations ) ) {
				$product_data['gallery'] = array_values( array_filter( $product_data['gallery'] ) );
				if ( $product_data['image'] ) {
					$product_image_key = array_search( $product_data['image'], $product_data['gallery'] );
					if ( $product_image_key !== false ) {
						unset( $product_data['gallery'][ $product_image_key ] );
						$product_data['gallery'] = array_values( $product_data['gallery'] );
					}
				}

				$variation_images                 = Ali_Product_Table::get_post_meta( $product_draft_id, '_vi_wad_variation_images', true );
				$product_data['attributes']       = $attributes;
				$product_data['variation_images'] = $variation_images;
				$product_data['variations']       = $variations;
				$product_data['parent_id']        = $product_draft_id;
				$product_data['ali_product_id']   = Ali_Product_Table::get_post_meta( $product_draft_id, '_vi_wad_sku', true );
				$woo_product_id                   = $this->import_product( $product_data );

				if ( ! is_wp_error( $woo_product_id ) ) {
					$response['status']         = 'success';
					$response['message']        = esc_html__( 'Import successfully', 'woo-alidropship' );
					$response['woo_product_id'] = $woo_product_id;

					$response['button_html'] = self::get_button_view_edit_html( $woo_product_id );
				} else {
					$response['message'] = $woo_product_id->get_error_messages();
				}
			} else {
				$response['message'] = esc_html__( 'Please select at least 1 variation to import this product.', 'woo-alidropship' );
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $response );
	}

	/**
	 * @param $product_data
	 *
	 * @return int|WP_Error
	 * @throws Exception
	 */
	public static function import_product( $product_data ) {
		vi_wad_set_time_limit();
		do_action( 'vi_wad_import_list_before_import', $product_data );
		$ali_product_id             = $product_data['ali_product_id'];
		$parent_id                  = $product_data['parent_id'];
		$image                      = $product_data['image'];
		$categories                 = isset( $product_data['categories'] ) ? $product_data['categories'] : array();
		$shipping_class             = isset( $product_data['shipping_class'] ) ? $product_data['shipping_class'] : '';
		$title                      = $product_data['title'];
		$sku                        = $product_data['sku'];
		$status                     = $product_data['status'];
		$tags                       = isset( $product_data['tags'] ) ? $product_data['tags'] : array();
		$description                = $product_data['description'];
		$variations                 = $product_data['variations'];
		$gallery                    = $product_data['gallery'];
		$attributes                 = $product_data['attributes'];
		$catalog_visibility         = $product_data['catalog_visibility'];
		$default_attr               = isset( $product_data['variation_default'] ) ? $product_data['variation_default'] : array();
		$disable_background_process = self::$settings->get_params( 'disable_background_process' );
		if ( is_array( $attributes ) && count( $attributes ) && ( count( $variations ) > 1 || ! self::$settings->get_params( 'simple_if_one_variation' ) ) ) {
			$attr_data = self::create_product_attributes( $attributes, $default_attr );
			/*Create data for product*/
			$data = array( // Set up the basic post data to insert for our product
				'post_excerpt' => '',
				'post_content' => $description,
				'post_title'   => $title,
				'post_status'  => $status,
				'post_type'    => 'product',
				'meta_input'   => array(
					'_sku'        => wc_product_generate_unique_sku( 0, $sku ),
					'_visibility' => 'visible',
				)
			);

			$product_id = wp_insert_post( $data ); // Insert the post returning the new post id

			if ( ! is_wp_error( $product_id ) ) {
				if ( $parent_id ) {
					$update_data = array(
						'ID'          => $parent_id,
						'post_status' => 'publish'
					);
					Ali_Product_Table::wp_update_post( $update_data );
					Ali_Product_Table::update_post_meta( $parent_id, '_vi_wad_woo_id', $product_id );
				}

				update_post_meta( $product_id, '_vi_wad_aliexpress_product_id', $ali_product_id );
				// Set it to a variable product type
				wp_set_object_terms( $product_id, 'variable', 'product_type' );
				if ( count( $attr_data ) ) {
					$product_obj = wc_get_product( $product_id );
					if ( $product_obj ) {
						$product_obj->set_attributes( $attr_data );
						if ( $default_attr ) {
							$product_obj->set_default_attributes( $default_attr );
						}
						$product_obj->save();
						/*Set product type again here in case other plugins override product type after product is saved*/
						wp_set_object_terms( $product_id, 'variable', 'product_type' );
					}
				}
				/*download image gallery*/
				$dispatch = false;
				if ( isset( $product_data['old_product_image'] ) ) {
					if ( $product_data['old_product_image'] ) {
						update_post_meta( $product_id, '_thumbnail_id', $product_data['old_product_image'] );
					}
					if ( isset( $product_data['old_product_gallery'] ) && $product_data['old_product_gallery'] ) {
						update_post_meta( $product_id, '_product_image_gallery', $product_data['old_product_gallery'] );
					}
				} else {
					if ( $image ) {
						$thumb_id = VI_WOO_ALIDROPSHIP_DATA::download_image( $image_id, $image, $product_id );
						if ( ! is_wp_error( $thumb_id ) ) {
							update_post_meta( $product_id, '_thumbnail_id', $thumb_id );
						}
					}
					self::process_gallery_images( $gallery, $disable_background_process, $product_id, $parent_id, $dispatch );
				}
				self::process_description_images( $description, $disable_background_process, $product_id, $parent_id, $dispatch );
				/*Set product tag*/
				if ( is_array( $tags ) && count( $tags ) ) {
					wp_set_post_terms( $product_id, $tags, 'product_tag', true );
				}
				/*Set product categories*/
				if ( is_array( $categories ) && count( $categories ) ) {
					wp_set_post_terms( $product_id, $categories, 'product_cat', true );
				}
				/*Set product shipping class*/
				if ( $shipping_class && get_term_by( 'id', $shipping_class, 'product_shipping_class' ) ) {
					wp_set_post_terms( $product_id, array( intval( $shipping_class ) ), 'product_shipping_class', false );
				}
				/*Create product variation*/
				self::import_product_variation( $product_id, $product_data, $dispatch, $disable_background_process );
				vi_wad_set_catalog_visibility( $product_id, $catalog_visibility );
			}
		} else {
			/*Create data for product*/
			$sale_price    = isset( $variations[0]['sale_price'] ) ? floatval( $variations[0]['sale_price'] ) : '';
			$regular_price = isset( $variations[0]['regular_price'] ) ? floatval( $variations[0]['regular_price'] ) : '';
			$data          = array( // Set up the basic post data to insert for our product
				'post_excerpt' => '',
				'post_content' => $description,
				'post_title'   => $title,
				'post_status'  => $status,
				'post_type'    => 'product',
				'meta_input'   => array(
					'_sku'           => wc_product_generate_unique_sku( 0, $sku ),
					'_visibility'    => 'visible',
					'_regular_price' => $regular_price,
					'_price'         => $regular_price,
					'_manage_stock'  => self::$settings->get_params( 'manage_stock' ) ? 'yes' : 'no',
					'_stock_status'  => 'instock',
				)
			);
			if ( ! empty( $variations[0]['stock'] ) && $data['meta_input']['_manage_stock'] === 'yes' ) {
				$data['meta_input']['_stock'] = absint( $variations[0]['stock'] );
			}
			if ( $sale_price ) {
				$data['meta_input']['_sale_price'] = $sale_price;
				$data['meta_input']['_price']      = $sale_price;
			}
			$product_id = wp_insert_post( $data ); // Insert the post returning the new post id

			if ( ! is_wp_error( $product_id ) ) {
				if ( $parent_id ) {
					$update_data = array(
						'ID'          => $parent_id,
						'post_status' => 'publish'
					);
					Ali_Product_Table::wp_update_post( $update_data );
					Ali_Product_Table::update_post_meta( $parent_id, '_vi_wad_woo_id', $product_id );
				}
				// Set it to a variable product type
				wp_set_object_terms( $product_id, 'simple', 'product_type' );
				/*download image gallery*/
				$dispatch = false;
				if ( isset( $product_data['old_product_image'] ) ) {
					if ( $product_data['old_product_image'] ) {
						update_post_meta( $product_id, '_thumbnail_id', $product_data['old_product_image'] );
					}
					if ( isset( $product_data['old_product_gallery'] ) && $product_data['old_product_gallery'] ) {
						update_post_meta( $product_id, '_product_image_gallery', $product_data['old_product_gallery'] );
					}
				} else {
					if ( $image ) {
						$thumb_id = VI_WOO_ALIDROPSHIP_DATA::download_image( $image_id, $image, $product_id );
						if ( ! is_wp_error( $thumb_id ) ) {
							update_post_meta( $product_id, '_thumbnail_id', $thumb_id );
						}
					}
					self::process_gallery_images( $gallery, $disable_background_process, $product_id, $parent_id, $dispatch );
				}
				self::process_description_images( $description, $disable_background_process, $product_id, $parent_id, $dispatch );
				if ( $dispatch ) {
					self::$process_image->save()->dispatch();
				}
				/*Set product tag*/
				if ( is_array( $tags ) && count( $tags ) ) {
					wp_set_post_terms( $product_id, $tags, 'product_tag', true );
				}
				/*Set product categories*/
				if ( is_array( $categories ) && count( $categories ) ) {
					wp_set_post_terms( $product_id, $categories, 'product_cat', true );
				}
				/*Set product shipping class*/
				if ( $shipping_class && get_term_by( 'id', $shipping_class, 'product_shipping_class' ) ) {
					wp_set_post_terms( $product_id, array( intval( $shipping_class ) ), 'product_shipping_class', false );
				}
				update_post_meta( $product_id, '_vi_wad_aliexpress_product_id', $ali_product_id );
				if ( ! empty( $variations[0]['skuId'] ) ) {
					update_post_meta( $product_id, '_vi_wad_aliexpress_variation_id', $variations[0]['skuId'] );
				}
				if ( ! empty( $variations[0]['skuAttr'] ) ) {
					update_post_meta( $product_id, '_vi_wad_aliexpress_variation_attr', $variations[0]['skuAttr'] );
					$found_items   = isset( $product_data['found_items'] ) ? $product_data['found_items'] : array();
					$replace_items = isset( $product_data['replace_items'] ) ? $product_data['replace_items'] : array();
					$replace_title = isset( $product_data['replace_title'] ) ? $product_data['replace_title'] : '';
					$replaces      = array_keys( $replace_items, $variations[0]['skuAttr'] );

					if ( count( $replaces ) ) {
						foreach ( $replaces as $old_variation_id ) {
							$order_item_data = isset( $found_items[ $old_variation_id ] ) ? $found_items[ $old_variation_id ] : array();
							if ( count( $order_item_data ) ) {
								foreach ( $order_item_data as $order_item_data_k => $order_item_data_v ) {
									$order_id      = $order_item_data_v['order_id'];
									$order_item_id = $order_item_data_v['order_item_id'];
									if ( 1 == $replace_title ) {
										wc_update_order_item( $order_item_id, array( 'order_item_name' => $title ) );
									}
									if ( $order_item_data_v['meta_key'] === '_variation_id' ) {
										$old_variation = wc_get_product( $old_variation_id );
										if ( $old_variation ) {
											$_product_id = wc_get_order_item_meta( $order_item_id, '_product_id', true );
											$note        = sprintf( esc_html__( 'Product #%1$s is replaced with product #%2$s.', 'woo-alidropship' ), $_product_id, $product_id );//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
											self::add_order_note( $order_id, $note );
											$old_attributes = $old_variation->get_attributes();
											if ( count( $old_attributes ) ) {
												foreach ( $old_attributes as $old_attribute_k => $old_attribute_v ) {
													wc_delete_order_item_meta( $order_item_id, $old_attribute_k );
												}
											}
										}
										wc_delete_order_item_meta( $order_item_id, '_variation_id' );
									} else {
										$note = sprintf( esc_html__( 'Product #%1$s is replaced with product #%2$s.', 'woo-alidropship' ), $old_variation_id, $product_id );//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
										self::add_order_note( $order_id, $note );
									}
									wc_update_order_item_meta( $order_item_id, '_product_id', $product_id );
								}
							}
						}
					}
				}
				vi_wad_set_catalog_visibility( $product_id, $catalog_visibility );
				$product = wc_get_product( $product_id );
				if ( $product ) {
					$product->save();
				}
			}
		}

		return $product_id;
	}

	public static function import_product_variation( $product_id, $product_data, $dispatch, $disable_background_process ) {
		$product = wc_get_product( $product_id );
		if ( $product ) {
			if ( is_array( $product_data['variations'] ) && count( $product_data['variations'] ) ) {
				$found_items   = isset( $product_data['found_items'] ) ? $product_data['found_items'] : array();
				$replace_items = isset( $product_data['replace_items'] ) ? $product_data['replace_items'] : array();
				$replace_title = isset( $product_data['replace_title'] ) ? $product_data['replace_title'] : '';
				$variation_ids = [];
				if ( count( $product_data['variation_images'] ) ) {
					foreach ( $product_data['variation_images'] as $key => $val ) {
						$variation_ids[ $key ] = array();
					}
				}
				$use_global_attributes = self::$settings->get_params( 'use_global_attributes' );
				$manage_stock          = self::$settings->get_params( 'manage_stock' ) ? 'yes' : 'no';

				foreach ( $product_data['variations'] as $product_variation ) {
					if ( ! empty( $product_variation['variation_id'] ) ) {
						$variation_id = $product_variation['variation_id'];
					} else {
						$stock_quantity = isset( $product_variation['stock'] ) ? absint( $product_variation['stock'] ) : 0;
						$variation      = new WC_Product_Variation();
						$variation->set_parent_id( $product_id );
						$attributes = array();
						if ( $use_global_attributes ) {
							foreach ( $product_variation['attributes'] as $option_k => $attr ) {
								$attribute_id  = wc_attribute_taxonomy_id_by_name( $option_k );
								$attribute_obj = wc_get_attribute( $attribute_id );
								if ( $attribute_obj ) {
									$attribute_value = self::get_term_by_name( $attr, $attribute_obj->slug );
									if ( $attribute_value ) {
										$attributes[ strtolower( urlencode( $attribute_obj->slug ) ) ] = $attribute_value->slug;
									}
								}
							}
						} else {
							foreach ( $product_variation['attributes'] as $option_k => $attr ) {
								$attributes[ strtolower( urlencode( $option_k ) ) ] = $attr;
							}
						}
						$variation->set_attributes( $attributes );
						/*Set metabox for variation . Check field name at woocommerce/includes/class-wc-ajax.php*/
						$fields = array(
							'sku'            => wc_product_generate_unique_sku( 0, $product_variation['sku'] ),
							'regular_price'  => $product_variation['regular_price'],
							'price'          => $product_variation['regular_price'],
							'manage_stock'   => $manage_stock,
							'stock_status'   => 'instock',
							'stock_quantity' => $stock_quantity,
						);
						if ( isset( $product_variation['sale_price'] ) && $product_variation['sale_price'] && $product_variation['sale_price'] < $product_variation['regular_price'] ) {
							$fields['sale_price'] = $product_variation['sale_price'];
							$fields['price']      = $product_variation['sale_price'];
						}
						foreach ( $fields as $field => $value ) {
							$variation->{"set_$field"}( wc_clean( $value ) );
						}
						do_action( 'product_variation_linked', $variation->save() );
						$variation_id = $variation->get_id();
						$replaces     = array_keys( $replace_items, $product_variation['skuAttr'] );
						if ( count( $replaces ) ) {
							foreach ( $replaces as $old_variation_id ) {
								$order_item_data = isset( $found_items[ $old_variation_id ] ) ? $found_items[ $old_variation_id ] : array();
								if ( count( $order_item_data ) ) {
									foreach ( $order_item_data as $order_item_data_k => $order_item_data_v ) {
										$order_id      = $order_item_data_v['order_id'];
										$order_item_id = $order_item_data_v['order_item_id'];
										if ( 1 == $replace_title ) {
											wc_update_order_item( $order_item_id, array( 'order_item_name' => $replace_title ) );
										}
										if ( $order_item_data_v['meta_key'] === '_variation_id' ) {
											$old_variation = wc_get_product( $old_variation_id );
											if ( $old_variation ) {
												$_product_id = wc_get_order_item_meta( $order_item_id, '_product_id', true );
												$note        = sprintf( esc_html__( 'Product #%1$s is replaced with product #%2$s. Variation #%3$s is replaced with variation #%4$s.', 'woo-alidropship' ), $_product_id, $product_id, $old_variation_id, $variation_id );//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
												self::add_order_note( $order_id, $note );
												$old_attributes = $old_variation->get_attributes();
												if ( count( $old_attributes ) ) {
													foreach ( $old_attributes as $old_attribute_k => $old_attribute_v ) {
														wc_delete_order_item_meta( $order_item_id, $old_attribute_k );
													}
												}
											}

										} else {
											$note = sprintf( esc_html__( 'Product #%1$s is replaced with product #%2$s.', 'woo-alidropship' ), $old_variation_id, $product_id );//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
											self::add_order_note( $order_id, $note );
											foreach ( $product_variation['attributes'] as $new_attribute_k => $new_attribute_v ) {
												wc_update_order_item_meta( $order_item_id, $new_attribute_k, $new_attribute_v );
											}
										}
										foreach ( $product_variation['attributes'] as $new_attribute_k => $new_attribute_v ) {
											wc_update_order_item_meta( $order_item_id, $new_attribute_k, $new_attribute_v );
										}
										wc_update_order_item_meta( $order_item_id, '_product_id', $product_id );
										wc_update_order_item_meta( $order_item_id, '_variation_id', $variation_id );
									}
								}
							}
						}
						update_post_meta( $variation_id, '_vi_wad_aliexpress_variation_id', $product_variation['skuId'] );
						update_post_meta( $variation_id, '_vi_wad_aliexpress_variation_attr', $product_variation['skuAttr'] );
						if ( ! empty( $product_variation['ship_from'] ) ) {
							update_post_meta( $variation_id, '_vi_wad_aliexpress_variation_ship_from', $product_variation['ship_from'] );
						}
					}
					if ( $product_variation['image'] ) {
						$pos = array_search( $product_variation['image'], $product_data['variation_images'] );
						if ( $pos !== false ) {
							$variation_ids[ $pos ][] = $variation_id;
						}
					}
                    /*Compe vargal*/
					$dispatch = apply_filters('ald_dispatch_after_make_variation_data',$dispatch,$variation_id, $product_variation,$disable_background_process);
				}
				if ( count( $variation_ids ) ) {
					if ( $disable_background_process ) {
						foreach ( $variation_ids as $key => $values ) {
							if ( count( $values ) && ! empty( $product_data['variation_images'][ $key ] ) ) {
								$image_data = array(
									'woo_product_id' => $product_id,
									'parent_id'      => '',
									'src'            => $product_data['variation_images'][ $key ],
									'product_ids'    => $values,
									'set_gallery'    => 0,
								);
								VI_WOO_ALIDROPSHIP_Error_Images_Table::insert( $product_id, implode( ',', $image_data['product_ids'] ), $image_data['src'], intval( $image_data['set_gallery'] ) );
							}
						}
					} else {
						foreach ( $variation_ids as $key => $values ) {
							if ( count( $values ) && ! empty( $product_data['variation_images'][ $key ] ) ) {
								$dispatch   = true;
								$image_data = array(
									'woo_product_id' => $product_id,
									'parent_id'      => '',
									'src'            => $product_data['variation_images'][ $key ],
									'product_ids'    => $values,
									'set_gallery'    => 0,
								);
								self::$process_image->push_to_queue( $image_data );
							}
						}
					}
				}
			}

			$data_store = $product->get_data_store();
			$data_store->sort_all_product_variations( $product->get_id() );
		}
		if ( $dispatch ) {
			self::$process_image->save()->dispatch();
		}
	}

	public static function get_term_by_name( $value, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) {
		// 'term_taxonomy_id' lookups don't require taxonomy checks.
		if ( ! taxonomy_exists( $taxonomy ) ) {
			return false;
		}

		// No need to perform a query for empty 'slug' or 'name'.
		$value = (string) $value;

		if ( 0 === strlen( $value ) ) {
			return false;
		}

		$args = array(
			'get'                    => 'all',
			'name'                   => $value,
			'number'                 => 0,
			'taxonomy'               => $taxonomy,
			'update_term_meta_cache' => false,
			'orderby'                => 'none',
			'suppress_filter'        => true,
		);

		$terms = get_terms( $args );
		if ( is_wp_error( $terms ) || empty( $terms ) ) {
			return false;
		}

		$check_slug = sanitize_title( $value );
		if ( count( $terms ) > 1 ) {
			foreach ( $terms as $term ) {
				if ( $term->slug == $check_slug ) {
					return get_term( $term, $taxonomy, $output, $filter );
				}
				if ( $term->name === $value ) {
					return get_term( $term, $taxonomy, $output, $filter );
				}
			}
		}

		$term = array_shift( $terms );

		return get_term( $term, $taxonomy, $output, $filter );
	}

	public static function add_order_note( $order_id, $note ) {
		$commentdata = apply_filters(
			'woocommerce_new_order_note_data',
			array(
				'comment_post_ID'      => $order_id,
				'comment_author'       => '',
				'comment_author_email' => __( 'WooCommerce', 'woocommerce' ),
				'comment_author_url'   => '',
				'comment_content'      => $note,
				'comment_agent'        => 'WooCommerce',
				'comment_type'         => 'order_note',
				'comment_parent'       => 0,
				'comment_approved'     => 1,
			),
			array(
				'order_id'         => $order_id,
				'is_customer_note' => 0,
			)
		);
		wp_insert_comment( $commentdata );
	}

	public static function process_gallery_images( $gallery, $disable_background_process, $product_id, $parent_id, &$dispatch ) {
		if ( is_array( $gallery ) && count( $gallery ) ) {
			if ( $disable_background_process ) {
				foreach ( $gallery as $image_url ) {
					$image_data = array(
						'woo_product_id' => $product_id,
						'parent_id'      => $parent_id,
						'src'            => $image_url,
						'product_ids'    => array(),
						'set_gallery'    => 1,
					);
					VI_WOO_ALIDROPSHIP_Error_Images_Table::insert( $product_id, implode( ',', $image_data['product_ids'] ), $image_data['src'], intval( $image_data['set_gallery'] ) );
				}
			} else {
				$dispatch = true;
				foreach ( $gallery as $image_url ) {
					$image_data = array(
						'woo_product_id' => $product_id,
						'parent_id'      => $parent_id,
						'src'            => $image_url,
						'product_ids'    => array(),
						'set_gallery'    => 1,
					);
					self::$process_image->push_to_queue( $image_data );
				}
			}
		}
	}

	/**
	 * By default, images in product description are used as external links
	 *
	 * @param $description
	 * @param $disable_background_process
	 * @param $product_id
	 * @param $parent_id
	 * @param $dispatch
	 */
	public static function process_description_images( $description, $disable_background_process, $product_id, $parent_id, &$dispatch ) {
		if ( $description && ! self::$settings->get_params( 'use_external_image' ) && self::$settings->get_params( 'download_description_images' ) ) {
			preg_match_all( '/src="([\s\S]*?)"/im', $description, $matches );
			if ( isset( $matches[1] ) && is_array( $matches[1] ) && count( $matches[1] ) ) {
				$description_images = array_unique( $matches[1] );
				if ( $disable_background_process ) {
					foreach ( $description_images as $description_image ) {
						VI_WOO_ALIDROPSHIP_Error_Images_Table::insert( $product_id, '', $description_image, 2 );
					}
				} else {
					foreach ( $description_images as $description_image ) {
						$images_data = array(
							'woo_product_id' => $product_id,
							'parent_id'      => $parent_id,
							'src'            => $description_image,
							'product_ids'    => array(),
							'set_gallery'    => 2,
						);
						self::$process_image->push_to_queue( $images_data );
					}
					$dispatch = true;
				}
			}
		}
	}

	private static function set( $name, $set_name = false ) {
		return VI_WOO_ALIDROPSHIP_DATA::set( $name, $set_name );
	}

	/**
	 * @param $status
	 * @param $option
	 * @param $value
	 *
	 * @return mixed
	 */
	public function save_screen_options( $status, $option, $value ) {
		if ( $option === 'vi_wad_per_page' ) {
			return $value;
		}

		return $status;
	}

	public function admin_menu() {
		add_menu_page(
			esc_html__( 'ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce Settings', 'woo-alidropship' ),
			esc_html__( 'Dropship & Fulfill', 'woo-alidropship' ),
			'manage_options',
			'woo-alidropship-import-list',
			null,
			VI_WOO_ALIDROPSHIP_IMAGES . 'icon.png',
			2
		);

		$import_list = add_submenu_page(
			'woo-alidropship-import-list',
			esc_html__( 'Import List - ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce', 'woo-alidropship' ),
			esc_html__( 'Import List', 'woo-alidropship' ),
			'manage_options',
			'woo-alidropship-import-list',
			array( $this, 'import_list_callback' )
		);

		add_action( "load-$import_list", array( $this, 'screen_options_page' ) );
	}

	public function screen_options_page() {
		add_screen_option( 'per_page', array(
			'label'   => esc_html__( 'Number of items per page', 'wp-admin' ),
			'default' => 5,
			'option'  => 'vi_wad_per_page'
		) );
	}

	public function import_list_callback() {
		?>
        <div class="ald-import-list-header">
            <h1><?php esc_html_e( 'Import List', 'woo-alidropship' ) ?></h1>
            <a target="_blank" href="https://www.aliexpress.com/" class="vi-ui primary button mini right labeled icon ald-go-to-ali-button">
                <i class="external icon"> </i>
				<?php esc_html_e( 'Go to AliExpress', 'woo-alidropship' ) ?>
            </a>
        </div>
        <div class="vi-ui segment ald-find-product-segment">
            <div class="vi-ui icon input fluid">
                <input type="text" class="ald-open-find-product-modal" placeholder="<?php esc_html_e( 'Find product to import', 'woo-alidropship' ) ?>">
                <i class="search icon"> </i>
            </div>
        </div>

		<?php
		self::import_list_html();
		self::search_product_modal();

	}


	public static function import_list_html() {

		$user = wp_get_current_user();

		$per_page = get_user_meta( $user->ID, 'vi_wad_per_page', true );
		if ( empty ( $per_page ) || $per_page < 1 ) {
			$per_page = 20;
		}

		if ( $per_page > 200 ) {
			$per_page = 200;
		}

		$decimals = wc_get_price_decimals();

		if ( $decimals < 1 ) {
			$decimals = 1;
		} else {
			$decimals = pow( 10, ( - 1 * $decimals ) );
		}

		$paged = isset( $_GET['paged'] ) ? sanitize_text_field( $_GET['paged'] ) : 1;// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		?>
        <div class="wrap woo-alidropship-import-list">
			<?php
			$args             = array(
				'post_type'      => 'vi_wad_draft_product',
				'post_status'    => array( 'draft', 'override' ),
				'order'          => 'DESC',
				'orderby'        => 'date',
				'fields'         => 'ids',
				'posts_per_page' => $per_page,
				'paged'          => $paged,
			);
			$vi_wad_search_id = isset( $_GET['vi_wad_search_id'] ) ? sanitize_text_field( $_GET['vi_wad_search_id'] ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$keyword          = isset( $_GET['vi_wad_search'] ) ? sanitize_text_field( $_GET['vi_wad_search'] ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			if ( $vi_wad_search_id ) {
				$args['post__in']       = array( $vi_wad_search_id );
				$args['posts_per_page'] = 1;
				$keyword                = '';
			} else if ( $keyword ) {
				$args['s'] = $keyword;
			}
			//			$the_query    = new WP_Query( $args );
			$the_query = VI_WOO_ALIDROPSHIP_DATA::is_ald_table() ? new Ali_Product_Query( $args ) : new WP_Query( $args );

			$count        = $the_query->found_posts;
			$total_page   = $the_query->max_num_pages;
			$page_content = '';
			if ( $the_query->have_posts() ) {
				/*After a product is imported, its html content(Import list) will be removed*/
				/*The first wp_editor call includes css file for all editors so call it here and hide it so that editor css is not removed after the first product is imported*/
				?>
                <div class="<?php echo esc_attr( self::set( 'hidden' ) ) ?>">
					<?php
					wp_editor( '', self::set( 'editor-css-inline-holder' ), array(
						'default_editor' => 'html',
						'media_buttons'  => false,
						'tinymce'        => true,
						'quicktags'      => true,
					) );
					?>
                </div>
				<?php
				ob_start();
				?>
                <form method="get" class="vi-ui segment <?php echo esc_attr( self::set( 'pagination-form' ) ) ?>">
                    <input type="hidden" name="page" value="woo-alidropship-import-list">
                    <div class="tablenav top">
                        <div class="<?php echo esc_attr( self::set( 'button-import-all-container' ) ) ?>">
                            <input type="checkbox"
                                   class="<?php echo esc_attr( self::set( 'accordion-bulk-item-check-all' ) ) ?>">
                            <span class="vi-ui button mini primary <?php echo esc_attr( self::set( 'button-import-all' ) ) ?>"
                                  title="<?php esc_attr_e( 'Import all products on this page', 'woo-alidropship' ) ?>"><?php esc_html_e( 'Import All', 'woo-alidropship' ) ?></span>
                            <a class="vi-ui button negative mini <?php echo esc_attr( self::set( 'button-empty-import-list' ) ) ?>"
                               href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'vi_wad_empty_product_list', 1 ) ) ) ?>"
                               title="<?php esc_attr_e( 'Remove all products(except overriding products) from Import list', 'woo-alidropship' ) ?>"><?php esc_html_e( 'Empty List', 'woo-alidropship' ) ?></a>
                            <span class="<?php echo esc_attr( self::set( 'accordion-bulk-actions-container' ) ) ?>">
                                <select name="<?php echo esc_attr( 'vi_wad_bulk_actions' ) ?>"
                                        class="vi-ui dropdown <?php echo esc_attr( self::set( 'accordion-bulk-actions' ) ) ?>">
                                    <option value=""><?php esc_html_e( 'Bulk Action', 'woo-alidropship' ) ?></option>
                                    <option value="set_categories"><?php esc_html_e( 'Set categories', 'woo-alidropship' ) ?></option>
                                    <option value="set_tags"><?php esc_html_e( 'Set tags', 'woo-alidropship' ) ?></option>
                                    <option value="set_status_publish"><?php esc_html_e( 'Set status - Publish', 'woo-alidropship' ) ?></option>
                                    <option value="set_status_pending"><?php esc_html_e( 'Set status - Pending', 'woo-alidropship' ) ?></option>
                                    <option value="set_status_draft"><?php esc_html_e( 'Set status - Draft', 'woo-alidropship' ) ?></option>
                                    <option value="set_visibility_visible"><?php esc_html_e( 'Set visibility - Shop and search results', 'woo-alidropship' ) ?></option>
                                    <option value="set_visibility_catalog"><?php esc_html_e( 'Set visibility - Shop only', 'woo-alidropship' ) ?></option>
                                    <option value="set_visibility_search"><?php esc_html_e( 'Set visibility - Search results only', 'woo-alidropship' ) ?></option>
                                    <option value="set_visibility_hidden"><?php esc_html_e( 'Set visibility - Hidden', 'woo-alidropship' ) ?></option>
                                    <option value="import"><?php esc_html_e( 'Import selected', 'woo-alidropship' ) ?></option>
                                    <option value="remove"><?php esc_html_e( 'Remove selected', 'woo-alidropship' ) ?></option>
                                </select>
                            </span>
                        </div>
                        <div class="tablenav-pages">
                            <div class="pagination-links">
								<?php
								if ( $paged > 2 ) {
									?>
                                    <a class="prev-page button" href="<?php echo esc_url( add_query_arg(
										array(
											'page'          => 'woo-alidropship-import-list',
											'paged'         => 1,
											'vi_wad_search' => $keyword,
										), admin_url( 'admin.php' )
									) ) ?>"><span
                                                class="screen-reader-text"><?php esc_html_e( 'First Page', 'woo-alidropship' ) ?></span><span
                                                aria-hidden="true">«</span></a>
									<?php
								} else {
									?>
                                    <span class="tablenav-pages-navspan button disabled" aria-hidden="true">«</span>
									<?php
								}
								/*Previous button*/
								if ( $per_page * $paged > $per_page ) {
									$p_paged = $paged - 1;
								} else {
									$p_paged = 0;
								}
								if ( $p_paged ) {
									$p_url = add_query_arg(
										array(
											'page'          => 'woo-alidropship-import-list',
											'paged'         => $p_paged,
											'vi_wad_search' => $keyword,
										), admin_url( 'admin.php' )
									);
									?>
                                    <a class="prev-page button" href="<?php echo esc_url( $p_url ) ?>"><span
                                                class="screen-reader-text"><?php esc_html_e( 'Previous Page', 'woo-alidropship' ) ?></span><span
                                                aria-hidden="true">‹</span></a>
									<?php
								} else {
									?>
                                    <span class="tablenav-pages-navspan button disabled" aria-hidden="true">‹</span>
									<?php
								}
								?>
                                <span class="screen-reader-text"><?php esc_html_e( 'Current Page', 'woo-alidropship' ) ?></span>
                                <span id="table-paging" class="paging-input">
                                    <input class="current-page" type="text" name="paged" size="1"
                                           value="<?php echo esc_html( $paged ) ?>"><span class="tablenav-paging-text"> of <span
                                                class="total-pages"><?php echo esc_html( $total_page ) ?></span></span>

							</span>
								<?php /*Next button*/
								if ( $per_page * $paged < $count ) {
									$n_paged = $paged + 1;
								} else {
									$n_paged = 0;
								}
								if ( $n_paged ) {
									$n_url = add_query_arg(
										array(
											'page'          => 'woo-alidropship-import-list',
											'paged'         => $n_paged,
											'vi_wad_search' => $keyword,
										), admin_url( 'admin.php' )
									); ?>
                                    <a class="next-page button" href="<?php echo esc_url( $n_url ) ?>"><span
                                                class="screen-reader-text"><?php esc_html_e( 'Next Page', 'woo-alidropship' ) ?></span><span
                                                aria-hidden="true">›</span></a>
									<?php
								} else {
									?>
                                    <span class="tablenav-pages-navspan button disabled" aria-hidden="true">›</span>
									<?php
								}
								if ( $total_page > $paged + 1 ) {
									?>
                                    <a class="next-page button" href="<?php echo esc_url( add_query_arg(
										array(
											'page'          => 'woo-alidropship-import-list',
											'paged'         => $total_page,
											'vi_wad_search' => $keyword,
										), admin_url( 'admin.php' )
									) ) ?>"><span
                                                class="screen-reader-text"><?php esc_html_e( 'Last Page', 'woo-alidropship' ) ?></span><span
                                                aria-hidden="true">»</span></a>
									<?php
								} else {
									?>
                                    <span class="tablenav-pages-navspan button disabled" aria-hidden="true">»</span>
									<?php
								}
								?>
                            </div>
                        </div>
                        <p class="search-box">
                            <input type="search" class="text short" name="vi_wad_search"
                                   placeholder="<?php esc_attr_e( 'Search product in import list', 'woo-alidropship' ) ?>"
                                   value="<?php echo esc_attr( $keyword ) ?>">
                            <input type="submit" name="submit" class="button"
                                   value="<?php echo esc_attr( 'Search product', 'woo-alidropship' ) ?>">
                        </p>
                    </div>
                </form>
				<?php
				$pagination_html             = ob_get_clean();
				$key                         = 0;
				$currency                    = 'USD';
				$woocommerce_currency        = get_option( 'woocommerce_currency' );
				$woocommerce_currency_symbol = get_woocommerce_currency_symbol( $woocommerce_currency );
				$default_select_image        = self::$settings->get_params( 'product_gallery' );
				$manage_stock                = self::$settings->get_params( 'manage_stock' );
				$product_categories          = self::$settings->get_params( 'product_categories' );
				$product_tags                = self::$settings->get_params( 'product_tags' );
				$product_shipping_class      = self::$settings->get_params( 'product_shipping_class' );
				$catalog_visibility          = self::$settings->get_params( 'catalog_visibility' );
				$product_status              = self::$settings->get_params( 'product_status' );
				$use_different_currency      = false;
				if ( strtolower( $woocommerce_currency ) != strtolower( $currency ) ) {
					$use_different_currency = true;
				}
				ob_start();
				?>
                <option value="publish" <?php selected( $product_status, 'publish' ) ?>><?php esc_html_e( 'Publish', 'woo-alidropship' ) ?></option>
                <option value="pending" <?php selected( $product_status, 'pending' ) ?>><?php esc_html_e( 'Pending', 'woo-alidropship' ) ?></option>
                <option value="draft" <?php selected( $product_status, 'draft' ) ?>><?php esc_html_e( 'Draft', 'woo-alidropship' ) ?></option>
				<?php
				$product_status_options = ob_get_clean();
				ob_start();
				?>
                <option value="visible" <?php selected( $catalog_visibility, 'visible' ) ?>><?php esc_html_e( 'Shop and search results', 'woo-alidropship' ) ?></option>
                <option value="catalog" <?php selected( $catalog_visibility, 'catalog' ) ?>><?php esc_html_e( 'Shop only', 'woo-alidropship' ) ?></option>
                <option value="search" <?php selected( $catalog_visibility, 'search' ) ?>><?php esc_html_e( 'Search results only', 'woo-alidropship' ) ?></option>
                <option value="hidden" <?php selected( $catalog_visibility, 'hidden' ) ?>><?php esc_html_e( 'Hidden', 'woo-alidropship' ) ?></option>
				<?php
				$catalog_visibility_options = ob_get_clean();
				/*
				$categories                 = get_terms(
					array(
						'taxonomy'   => 'product_cat',
						'orderby'    => 'name',
						'order'      => 'ASC',
						'hide_empty' => false
					)
				);
				if ( is_array( $categories ) && count( $categories ) ) {
					ob_start();
					foreach ( $categories as $category ) {
						?>
                        <option value="<?php echo esc_attr( $category->term_id ) ?>"
							<?php if ( in_array( $category->term_id, $product_categories ) ) {
								echo esc_attr( 'selected' );
							} ?>><?php echo esc_html( $category->name ); ?></option>
						<?php
					}
					self::$categories_options = ob_get_clean();
				}
				*/
				self::$categories_options = self::dropdown_categories( '{ali_product_id}');
				$tags                     = get_terms(
					array(
						'taxonomy'   => 'product_tag',
						'orderby'    => 'name',
						'order'      => 'ASC',
						'hide_empty' => false
					)
				);
				if ( is_array( $tags ) && count( $tags ) ) {
					ob_start();
					foreach ( $tags as $tag ) {
						?>
                        <option value="<?php echo esc_attr( $tag->name ) ?>"
							<?php if ( in_array( $tag->name, $product_tags ) ) {
								echo esc_attr( 'selected' );
							} ?>><?php echo esc_html( $tag->name ); ?></option>
						<?php
					}
					self::$tags_options = ob_get_clean();
				}
				$shipping_classes = get_terms(
					array(
						'taxonomy'   => 'product_shipping_class',
						'orderby'    => 'name',
						'order'      => 'ASC',
						'hide_empty' => false
					)
				);
				if ( is_array( $shipping_classes ) && count( $shipping_classes ) ) {
					ob_start();
					foreach ( $shipping_classes as $shipping_class ) {
						?>
                        <option value="<?php echo esc_attr( $shipping_class->term_id ) ?>"
							<?php selected( $shipping_class->term_id, $product_shipping_class ) ?>><?php echo esc_html( $shipping_class->name ); ?></option>
						<?php
					}
					self::$shipping_class_options = ob_get_clean();
				}

				$countries = wc()->countries->get_countries();

				foreach ( $the_query->posts as $product_id ) {
					$product     = Ali_Product_Table::get_post( $product_id );
					$title       = $product->post_title;
					$description = $product->post_content;
					$sku         = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_sku', true );
//					$attributes  = get_post_meta( $product_id, '_vi_wad_attributes', true );
					$attributes = self::get_product_attributes( $product_id );
					$store_info = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_store_info', true );
					$parent     = array();
					if ( is_array( $attributes ) && count( $attributes ) ) {
						foreach ( $attributes as $attribute_k => $attribute_v ) {
							$parent[ $attribute_k ] = $attribute_v['slug'];
						}
					}
					$gallery = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_gallery', true );
					if ( ! $gallery ) {
						$gallery = array();
					}
					$desc_images = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_description_images', true );
					if ( ! $desc_images ) {
						$desc_images = array();
					} else {
						$desc_images = array_values( array_unique( $desc_images ) );
					}
					$image      = isset( $gallery[0] ) ? $gallery[0] : '';
					$variations = self::get_product_variations( $product_id );

					$price_array = array_filter( array_merge( array_column( $variations, 'sale_price' ), array_column( $variations, 'regular_price' ) ) );
					$price_alert = false;
					if ( count( $price_array ) ) {
						$min_price = min( $price_array );
						if ( $min_price ) {
							$min_price = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $min_price );
							if ( $min_price === 0.01 ) {
								$price_alert = true;
							}
						}
					}
					$is_variable         = ( is_array( $parent ) && count( $parent ) ) ? 1 : 0;
					$product_type        = $product->post_status;
					$override_product_id = $product->post_parent;
					$override_product    = '';
					if ( $product_type === 'override' && $override_product_id ) {
						$override_product = Ali_Product_Table::get_post( $override_product_id );
						if ( ! $override_product ) {
							$product_type        = 'draft';
							$override_product_id = '';
							Ali_Product_Table::wp_update_post( array(
								'ID'          => $product_id,
								'post_parent' => 0,
								'post_status' => $product_type,
							) );
						}
					}
					$accordion_class = array(
						'vi-ui',
						'styled',
						'fluid',
						'accordion',
						'active',
						self::set( 'accordion' ),
					);
					if ( $price_alert ) {
						$accordion_class[] = self::set( 'product-price-alert' );
					}

					$shipping_info = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_shipping_info', true );
					$ship_to       = $shipping_info['country'] ?? '';
					$ship_to       = $ship_to == 'UK' ? 'GB' : $ship_to;
					$ship_to       = $countries[ $ship_to ] ?? $ship_to;

					ob_start();
					?>
                    <div class="<?php echo esc_attr( implode( ' ', $accordion_class ) ) ?>"
                         id="<?php echo esc_attr( self::set( 'product-item-id-' . $product_id ) ) ?>">
                        <div class="title active">
                            <input type="checkbox"
                                   class="<?php echo esc_attr( self::set( 'accordion-bulk-item-check' ) ); ?>">
                            <i class="dropdown icon <?php echo esc_attr( self::set( 'accordion-title-icon' ) ); ?>"></i>
                            <div class="<?php echo esc_attr( self::set( 'accordion-product-image-title-container' ) ) ?>">
                                <div class="<?php echo esc_attr( self::set( 'accordion-product-image-title' ) ) ?>">
                                    <img src="<?php echo esc_url( $image ? $image : wc_placeholder_img_src() ) ?>"
                                         class="<?php echo esc_attr( self::set( 'accordion-product-image' ) ) ?>">
                                    <div class="<?php echo esc_attr( self::set( 'accordion-product-title-container' ) ) ?>">
                                        <div class="<?php echo esc_attr( self::set( 'accordion-product-title' ) ) ?>"
                                             title="<?php echo esc_attr( $title ) ?>"><?php echo esc_html( $title ) ?></div>
										<?php
										if ( ! empty( $store_info['name'] ) ) {
											$store_name = $store_info['name'];
											if ( ! empty( $store_info['url'] ) ) {
												$store_name = '<a class="' . esc_attr( self::set( 'accordion-store-url' ) ) . '" href="' . esc_url( $store_info['url'] ) . '" target="_blank">' . $store_name . '</a>';
											}
											?>
                                            <div>
												<?php
												esc_html_e( 'Store: ', 'woo-alidropship' );
												echo wp_kses( $store_name,VI_WOO_ALIDROPSHIP_DATA::allow_html() );
												?>
                                            </div>
											<?php
										}
										?>
                                        <div class="<?php echo esc_attr( self::set( 'accordion-product-date' ) ) ?>"><?php esc_html_e( 'Date: ', 'woo-alidropship' ) ?>
                                            <span><?php echo esc_html( $product->post_date ) ?></span></div>
                                    </div>
                                </div>
                            </div>

                        </div>
                        <div class="content active">
							<?php
							if ( $ship_to ) {
								printf( '<div class="vi-ui warning message">%s <b>%s</b></div>',
									esc_html__( 'Price of the product applicable to the', 'woo-alidropship' ), esc_html( $ship_to ) );
							}

							if ( $override_product ) {
								?>
                                <div class="vi-ui message <?php echo esc_attr( self::set( 'override-product-message' ) ) ?>"><?php esc_html_e( 'This product will override: ', 'woo-alidropship' ) ?>
                                    <strong class="<?php echo esc_attr( self::set( 'override-product-product-title' ) ) ?>"><?php echo esc_html( $override_product->post_title ) ?></strong>
                                </div>
								<?php
							}
							?>
                            <div class="<?php echo esc_attr( self::set( 'message' ) ) ?>"></div>
							<?php
							if ( $price_alert ) {
								?>
                                <div class="vi-ui warning message">
									<?php esc_html_e( 'First-purchase discount may apply to this product, please check its price carefully or import with consideration.', 'woo-alidropship' ); ?>
                                </div>
								<?php
							}
							do_action( 'vi_wad_import_list_product_message', $product );
							?>
                            <form class="vi-ui form <?php echo esc_attr( self::set( 'product-container' ) ) ?>"
                                  method="post">
                                <div class="vi-ui attached tabular menu">
                                    <div class="item active" data-tab="<?php echo esc_attr( 'product-' . $key ) ?>">
										<?php esc_html_e( 'Product', 'woo-alidropship' ) ?>
                                    </div>
                                    <div class="item <?php echo esc_attr( self::set( 'description-tab-menu' ) ) ?>"
                                         data-tab="<?php echo esc_attr( 'description-' . $key ) ?>">
										<?php esc_html_e( 'Description', 'woo-alidropship' ) ?>
                                    </div>
									<?php
									if ( $is_variable ) {
										$tab_class = array( 'variations-tab-menu' );
										if ( ! self::load_variations_ajax( $variations ) ) {
											$tab_class[] = 'lazy-load';
										}
										?>
                                        <div class="item <?php echo esc_attr( self::set( 'attributes-tab-menu' ) ) ?>"
                                             data-tab="<?php echo esc_attr( 'attributes-' . $key ) ?>">
											<?php esc_html_e( 'Attributes', 'woo-alidropship' ) ?>
                                        </div>
                                        <div class="item <?php echo esc_attr( self::set( $tab_class ) ) ?>"
                                             data-tab="<?php echo esc_attr( 'variations-' . $key ) ?>">
											<?php echo wp_kses_post(sprintf( __( 'Variations(%s)', 'woo-alidropship' ), '<span class="' . self::set( 'selected-variation-count' ) . '">' . esc_html( count( $variations ) ) . '</span>')) //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?>
                                        </div>
										<?php
									}
									if ( count( $gallery ) ) {
										$gallery_count = $default_select_image ? count( $gallery ) : 0;
										?>
                                        <div class="item <?php echo esc_attr( self::set( array(
											'lazy-load',
											'gallery-tab-menu'
										) ) ) ?>"
                                             data-tab="<?php echo esc_attr( 'gallery-' . $key ) ?>">
											<?php echo wp_kses_post(sprintf( __( 'Gallery(%s)', 'woo-alidropship' ), '<span class="' . self::set( 'selected-gallery-count' ) . '">' . esc_html( $gallery_count ) . '</span>')) //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?>
                                        </div>
										<?php
									}
									?>
                                </div>
                                <div class="vi-ui bottom attached tab segment active <?php echo esc_attr( self::set( 'product-tab' ) ) ?>"
                                     data-tab="<?php echo esc_attr( 'product-' . $key ) ?>">
                                    <div class="field">
                                        <div class="fields">
                                            <div class="three wide field">
                                                <div class="<?php echo esc_attr( self::set( 'product-image' ) ) ?> <?php if ( $default_select_image )
													echo esc_attr( self::set( 'selected-item' ) ) ?> ">
                                                    <span class="<?php echo esc_attr( self::set( 'selected-item-icon-check' ) ) ?>"></span>
													<?php
													if ( $image ) {
														?>
                                                        <img style="width: 100%"
                                                             src="<?php echo esc_url( $image ) ?>"
                                                             class="<?php echo esc_attr( self::set( 'import-data-image' ) ) ?>">
                                                        <input type="hidden"
                                                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][image]' ) ?>"
                                                               value="<?php echo esc_attr( $default_select_image ? $image : '' ) ?>">
														<?php
													} else {
														?>
                                                        <img style="width: 100%" src="<?php echo esc_url( wc_placeholder_img_src() ) ?>" class="<?php echo esc_attr( self::set( 'import-data-image' ) ) ?>">
                                                        <input type="hidden" name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][image]' ) ?>" value="">
														<?php
													}
													?>

                                                </div>
                                            </div>
                                            <div class="thirteen wide field">
                                                <div class="field">
                                                    <label><?php esc_html_e( 'Product title', 'woo-alidropship' ) ?></label>
                                                    <input type="text" value="<?php echo esc_attr( $title ) ?>"
                                                           name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][title]' ) ?>"
                                                           class="<?php echo esc_attr( self::set( 'import-data-title' ) ) ?>">
                                                </div>
                                                <div class="field <?php echo esc_attr( self::set( 'import-data-sku-status-visibility' ) ) ?>">
                                                    <div class="equal width fields">
                                                        <div class="field">
                                                            <label><?php esc_html_e( 'Sku', 'woo-alidropship' ) ?></label>
                                                            <input type="text" value="<?php echo esc_attr( $sku ) ?>"
                                                                   name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][sku]' ) ?>"
                                                                   class="<?php echo esc_attr( self::set( 'import-data-sku' ) ) ?>">
                                                        </div>
                                                        <div class="field">
                                                            <label><?php esc_html_e( 'Product status', 'woo-alidropship' ) ?></label>
                                                            <select
                                                                    name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][status]' ) ?>"
                                                                    class="<?php echo esc_attr( self::set( 'import-data-status' ) ) ?> vi-ui fluid dropdown">
																<?php echo wp_kses( $product_status_options ,VI_WOO_ALIDROPSHIP_DATA::allow_html())  ?>
                                                            </select>

                                                        </div>
                                                        <div class="field">
                                                            <label><?php esc_html_e( 'Catalog visibility', 'woo-alidropship' ) ?></label>
                                                            <select
                                                                    name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][catalog_visibility]' ) ?>"
                                                                    class="<?php echo esc_attr( self::set( 'import-data-catalog-visibility' ) ) ?> vi-ui fluid dropdown">
																<?php echo wp_kses( $catalog_visibility_options, VI_WOO_ALIDROPSHIP_DATA::allow_html() )  ?>
                                                            </select>
                                                        </div>
                                                    </div>
                                                </div>
												<?php
												if ( ! $is_variable ) {
													self::simple_product_price_field_html( $key, $manage_stock, $variations, $use_different_currency, $currency, $product_id, $woocommerce_currency_symbol, $decimals );
												}
												?>
                                                <div class="field">
                                                    <div class="equal width fields">
                                                        <div class="field">
                                                            <label><?php esc_html_e( 'Categories', 'woo-alidropship' ) ?></label>
															<?php echo wp_kses(str_replace('{ali_product_id}',$product_id,self::$categories_options),self::$settings::allow_html()) ;  ?>
                                                        </div>
                                                        <div class="field">
                                                            <label><?php esc_html_e( 'Tags', 'woo-alidropship' ) ?></label>
                                                            <select name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][tags][]' ) ?>"
                                                                    class="vi-ui dropdown search  <?php echo esc_attr( self::set( 'import-data-tags' ) ) ?>"
                                                                    multiple="multiple">
																<?php echo wp_kses(self::$tags_options,self::$settings::allow_html());  ?>
                                                            </select>
                                                        </div>
                                                        <div class="field">
                                                            <label><?php esc_html_e( 'Shipping class', 'woo-alidropship' ) ?></label>
                                                            <select name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][shipping_class]' ) ?>"
                                                                    class="vi-ui dropdown search <?php echo esc_attr( self::set( 'import-data-shipping-class' ) ) ?>">
                                                                <option value=""><?php esc_html_e( 'No shipping class', 'woo-alidropship' ) ?></option>
																<?php echo wp_kses(self::$shipping_class_options,self::$settings::allow_html());  ?>
                                                            </select>
                                                        </div>
                                                    </div>
                                                </div>
												<?php
												if ( ! $override_product ) {
													?>
                                                    <div class="field">
                                                        <div class="equal width fields">
                                                            <div class="field">
                                                                <label><?php esc_html_e( 'Link existing Woo product', 'woo-alidropship' ) ?></label>
                                                                <select name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][override_woo_id]' ) ?>"
                                                                        class="search-product <?php echo esc_attr( self::set( 'override-woo-id' ) ) ?>">
                                                                </select>
                                                            </div>
                                                        </div>
                                                    </div>
													<?php
												}
												?>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="vi-ui bottom attached tab segment <?php echo esc_attr( self::set( 'description-tab' ) ) ?>"
                                     data-tab="<?php echo esc_attr( 'description-' . $key ) ?>">
									<?php
									wp_editor( $description, self::set( 'product-description-' ) . $product_id, array(
										'default_editor' => 'html',
										'media_buttons'  => false,
										'editor_class'   => esc_attr( self::set( 'import-data-description' ) ),
										'textarea_name'  => esc_attr( 'vi_wad_product[' . $product_id . '][description]' ),
									) );
									?>
                                </div>
								<?php
								if ( $is_variable ) {
									$variations_tab_class = array( 'variations-tab' );
									$variations_html      = '';
									if ( ! self::load_variations_ajax( $variations ) ) {
										$variations_tab_class[] = 'variations-tab-loaded';
										$variations_tab_class[] = 'lazy-load-tab-data';
										ob_start();
										self::variation_html( $key, $parent, $attributes, $manage_stock, $variations, $use_different_currency, $currency, $product_id, $woocommerce_currency_symbol, $decimals );
										$variations_html = ob_get_clean();
									}
									?>
                                    <div class="vi-ui bottom attached tab segment <?php echo esc_attr( self::set( 'attributes-tab' ) ) ?>"
                                         data-tab="<?php echo esc_attr( 'attributes-' . $key ) ?>"
                                         data-product_id="<?php echo esc_attr( $product_id ) ?>">
                                        <table class="vi-ui celled table">
                                            <thead>
                                            <tr>
                                                <th class="<?php echo esc_attr( self::set( 'attributes-attribute-col-position' ) ) ?>"><?php esc_html_e( 'Position', 'woo-alidropship' ) ?></th>
                                                <th class="<?php echo esc_attr( self::set( 'attributes-attribute-col-name' ) ) ?>"><?php esc_html_e( 'Name', 'woo-alidropship' ) ?></th>
                                                <th class="<?php echo esc_attr( self::set( 'attributes-attribute-col-slug' ) ) ?>"><?php esc_html_e( 'Slug', 'woo-alidropship' ) ?></th>
                                                <th class="<?php echo esc_attr( self::set( 'attributes-attribute-col-values' ) ) ?>"><?php esc_html_e( 'Values', 'woo-alidropship' ) ?></th>
                                                <th class="<?php echo esc_attr( self::set( 'attributes-attribute-col-action' ) ) ?>"><?php esc_html_e( 'Action', 'woo-alidropship' ) ?></th>
                                            </tr>
                                            </thead>
                                            <tbody class="ui sortable">
											<?php
											$position = 1;
											foreach ( $attributes as $attributes_key => $attribute ) {
												$attribute_name = isset( $attribute['name'] ) ? $attribute['name'] : VI_WOO_ALIDROPSHIP_DATA::get_attribute_name_by_slug( $attribute['slug'] );
												?>
                                                <tr class="<?php echo esc_attr( self::set( 'attributes-attribute-row' ) ) ?>">
                                                    <td><?php echo esc_html( $position ) ?></td>
                                                    <td><input type="text"
                                                               class="<?php echo esc_attr( self::set( 'attributes-attribute-name' ) ) ?>"
                                                               value="<?php echo esc_attr( $attribute_name ) ?>"
                                                               data-attribute_name="<?php echo esc_attr( $attribute_name ) ?>"
                                                               name="<?php echo esc_attr( "vi_wad_product[{$product_id}][attributes][{$attributes_key}][name]" ) ?>">
                                                    </td>
                                                    <td>
                                                        <span class="<?php echo esc_attr( self::set( 'attributes-attribute-slug' ) ) ?>"
                                                              data-attribute_slug="<?php echo esc_attr( $attribute['slug'] ) ?>"><?php echo esc_html( $attribute['slug'] ) ?></span>
                                                    </td>
                                                    <td>
                                                        <div class="<?php echo esc_attr( self::set( 'attributes-attribute-values' ) ) ?>">
															<?php
															foreach ( $attribute['values'] as $values_k => $values_v ) {
																?>
                                                                <input type="text"
                                                                       class="<?php echo esc_attr( self::set( 'attributes-attribute-value' ) ) ?>"
                                                                       value="<?php echo esc_attr( $values_v ) ?>"
                                                                       data-attribute_value="<?php echo esc_attr( $values_v ) ?>"
                                                                       name="<?php echo esc_attr( "vi_wad_product[{$product_id}][attributes][{$attributes_key}][values][{$values_k}]" ) ?>">
																<?php
															}
															?>
                                                        </div>
                                                    </td>
                                                    <td>

                                                        <span class="vi-ui button mini green icon <?php echo esc_attr( self::set( array( 'attributes-button-save', ) ) ) ?>"
                                                              title="<?php esc_attr_e( 'Save', 'woo-alidropship' ) ?>">
                                                                <i class="icon save"> </i>
                                                        </span>

                                                        <span class="vi-ui button mini negative icon <?php echo esc_attr( self::set( 'attributes-attribute-remove' ) ) ?>"
                                                              title="<?php esc_attr_e( 'Remove this attribute', 'woo-alidropship' ) ?>">
                                                            <i class="icon trash"> </i>
                                                        </span>

                                                    </td>
                                                </tr>
												<?php
												$position ++;
											}
											?>
                                            </tbody>
                                        </table>
                                    </div>
                                    <div class="vi-ui bottom attached tab segment <?php echo esc_attr( self::set( $variations_tab_class ) ) ?>"
                                         data-tab="<?php echo esc_attr( 'variations-' . $key ) ?>"
                                         data-product_id="<?php echo esc_attr( $product_id ) ?>">
										<?php
										if ( count( $variations ) ) {
											?>
                                            <div class="vi-ui positive message">
                                                <div class="header">
                                                    <p><?php esc_html_e( 'You can edit product attributes on Attributes tab', 'woo-alidropship' ) ?></p>
                                                </div>
                                            </div>
                                            <table class="form-table <?php echo esc_attr( self::set( array(
												'variations-table',
												'table-fix-head',
												'variation-table-attributes-count-' . count( $attributes )
											) ) ) ?>"><?php echo wp_kses( $variations_html ,VI_WOO_ALIDROPSHIP_DATA::allow_html());  ?></table>
											<?php
										}
										?>
                                    </div>
									<?php
								}
								$gallery = array_merge( $gallery, $desc_images );
								if ( count( $gallery ) ) {
									?>
                                    <div class="vi-ui bottom attached tab segment <?php echo esc_attr( self::set( array(
										'product-gallery',
										'lazy-load-tab-data'
									) ) ) ?>"
                                         data-tab="<?php echo esc_attr( 'gallery-' . $key ) ?>">
                                        <div class="segment ui-sortable">
											<?php
											if ( $default_select_image ) {
												foreach ( $gallery as $gallery_k => $gallery_v ) {
													if ( ! in_array( $gallery_v, $desc_images ) ) {
														$item_class = array(
															'product-gallery-item',
															'selected-item'
														);
														if ( $gallery_k === 0 ) {
															$item_class[] = 'is-product-image';
														}
														?>
                                                        <div class="<?php echo esc_attr( self::set( $item_class ) ) ?>">
                                                            <span class="<?php echo esc_attr( self::set( 'selected-item-icon-check' ) ) ?>"> </span>
                                                            <i class="<?php echo esc_attr( self::set( 'set-product-image' ) ) ?> star icon"> </i>
                                                            <i class="<?php echo esc_attr( self::set( 'set-variation-image' ) ) ?> hand outline up icon"
                                                               title="<?php esc_attr_e( 'Set image for selected variation(s)', 'woo-alidropship' ) ?>"> </i>
                                                            <img src="<?php echo esc_url( VI_WOO_ALIDROPSHIP_IMAGES . 'loading.gif' ) ?>"
                                                                 data-image_src="<?php echo esc_url( $gallery_v ) ?>"
                                                                 class="<?php echo esc_attr( self::set( 'product-gallery-image' ) ) ?>">
                                                            <input type="hidden"
                                                                   name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][gallery][]' ) ?>"
                                                                   value="<?php echo esc_attr( $gallery_v ) ?>">
                                                        </div>
														<?php
													} else {
														?>
                                                        <div class="<?php echo esc_attr( self::set( 'product-gallery-item' ) ) ?>">
                                                            <span class="<?php echo esc_attr( self::set( 'selected-item-icon-check' ) ) ?>"> </span>
                                                            <i class="<?php echo esc_attr( self::set( 'set-product-image' ) ) ?> star icon"> </i>
                                                            <i class="<?php echo esc_attr( self::set( 'set-variation-image' ) ) ?> hand outline up icon"
                                                               title="<?php esc_attr_e( 'Set image for selected variation(s)', 'woo-alidropship' ) ?>"> </i>
                                                            <img src="<?php echo esc_url( VI_WOO_ALIDROPSHIP_IMAGES . 'loading.gif' ) ?>"
                                                                 data-image_src="<?php echo esc_url( $gallery_v ) ?>"
                                                                 class="<?php echo esc_attr( self::set( 'product-gallery-image' ) ) ?>">
                                                            <input type="hidden"
                                                                   name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][gallery][]' ) ?>"
                                                                   value="">
                                                        </div>
														<?php
													}
												}
											} else {
												foreach ( $gallery as $gallery_k => $gallery_v ) {
													?>
                                                    <div class="<?php echo esc_attr( self::set( 'product-gallery-item' ) ) ?>">
                                                        <span class="<?php echo esc_attr( self::set( 'selected-item-icon-check' ) ) ?>"> </span>
                                                        <i class="<?php echo esc_attr( self::set( 'set-product-image' ) ) ?> star icon"> </i>
                                                        <i class="<?php echo esc_attr( self::set( 'set-variation-image' ) ) ?> hand outline up icon"
                                                           title="<?php esc_attr_e( 'Set image for selected variation(s)', 'woo-alidropship' ) ?>"> </i>
                                                        <img src="<?php echo esc_url( VI_WOO_ALIDROPSHIP_IMAGES . 'loading.gif' ) ?>"
                                                             data-image_src="<?php echo esc_url( $gallery_v ) ?>"
                                                             class="<?php echo esc_attr( self::set( 'product-gallery-image' ) ) ?>">
                                                        <input type="hidden"
                                                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][gallery][]' ) ?>"
                                                               value="">
                                                    </div>
													<?php
												}
											}
											?>
                                        </div>
                                    </div>
									<?php
								}
								?>
                            </form>
                        </div>
                        <div class="<?php echo esc_attr( self::set( array(
							'product-overlay',
							'hidden'
						) ) ) ?>">
                        </div>
                        <div class="<?php echo esc_attr( self::set( 'button-view-and-edit' ) ) ?>">
                            <a href="<?php echo esc_url( "https://www.aliexpress.com/item/{$sku}.html" ); ?>"
                               target="_blank" class="vi-ui button mini" rel="nofollow"
                               title="<?php esc_attr_e( 'View this product on AliExpress.com', 'woo-alidropship' ) ?>">
								<?php esc_html_e( 'View on AliExpress', 'woo-alidropship' ) ?></a>
                            <span class="vi-ui button mini negative <?php echo esc_attr( self::set( 'button-remove' ) ) ?>"
                                  data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                  title="<?php esc_attr_e( 'Remove this product from import list', 'woo-alidropship' ) ?>"><?php esc_html_e( 'Remove', 'woo-alidropship' ) ?></span>
							<?php
							if ( $override_product ) {
								?>
                                <span class="vi-ui button mini positive <?php echo esc_attr( self::set( 'button-override' ) ) ?>"
                                      data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                      data-override_product_id="<?php echo esc_attr( $override_product_id ) ?>"><?php esc_html_e( 'Import & Override', 'woo-alidropship' ) ?></span>
								<?php
							} else {
								?>
                                <span class="vi-ui button mini positive <?php echo esc_attr( self::set( 'button-import' ) ) ?>"
                                      data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                      title="<?php esc_attr_e( 'Import this product to your WooCommerce store', 'woo-alidropship' ) ?>"><?php esc_html_e( 'Import Now', 'woo-alidropship' ) ?></span>
                                <span class="vi-ui button mini positive <?php echo esc_attr( self::set( array(
									'button-override',
									'button-map-existing',
									'hidden',
								) ) ) ?>"
                                      title="<?php esc_attr_e( 'Import this product to your WooCommerce store', 'woo-alidropship' ) ?>"
                                      data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                      data-override_product_id="<?php echo esc_attr( $override_product_id ) ?>"><?php esc_html_e( 'Import & Map', 'woo-alidropship' ) ?></span>
								<?php
							}
							?>
                        </div>
                    </div>
					<?php
					$page_content .= ob_get_clean();
					$key ++;
				}

			} else {
				ob_start();
				?>
                <form method="get">
                    <input type="hidden" name="page" value="woo-alidropship-import-list">
                    <div class="ald-wp-editor-placeholder">
						<?php
						wp_editor( '', 'ald-placeholder', array(
							'default_editor' => 'html',
							'media_buttons'  => false,
							'tinymce'        => true,
							'quicktags'      => true,
							'editor_class'   => '',
							'textarea_name'  => '',
						) ); ?>
                    </div>
					<?php
					if ( $paged == 1 && ! $vi_wad_search_id && ! $keyword ) {
						?>
                        <p class="<?php echo esc_attr( self::set( 'download-chrome-extension' ) ) ?>">
                            <?php printf( esc_html__( 'To import AliExpress products, you have to install and activate %s', 'woo-alidropship' ), //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
                                '<a href="https://downloads.villatheme.com/?download=alidropship-extension" target="_blank">WooCommerce AliExpress Dropshipping Extension</a>' ) ?></p>
                        <p>
							<?php VI_WOO_ALIDROPSHIP_DATA::chrome_extension_buttons(); ?>
                            <a target="_blank" href="https://www.aliexpress.com/"
                               class="vi-ui positive button labeled icon <?php echo esc_attr( self::set( array( 'import-aliexpress-products', 'hidden' ) ) ) ?>">
                                <i class="external icon"> </i>
								<?php esc_html_e( 'Import AliExpress Products', 'woo-alidropship' ) ?>
                            </a>
                        </p>
						<?php
					}
					?>
                </form>
				<?php
				$pagination_html = ob_get_clean();
			}
			wp_reset_postdata();
			echo wp_kses( $pagination_html, VI_WOO_ALIDROPSHIP_DATA::allow_html() );
			if ( $page_content ) {
				?>
                <div class="vi-ui segment <?php echo esc_attr( self::set( 'import-list' ) ) ?>">
					<?php
					echo wp_kses( $page_content, VI_WOO_ALIDROPSHIP_DATA::allow_html() );
					?>
                </div>
				<?php
			}
			?>
        </div>
		<?php
	}

	protected static function search_product_modal() {
		VI_WOO_ALIDROPSHIP_Admin_Find_Product::search_form();
	}

	/**
	 * @param $product_id
	 * @param $country
	 * @param string $company
	 * @param int $cache_time
	 *
	 * @return array|mixed
	 */
	public static function get_shipping_info( $product_id, $country, $company = '', $cache_time = 600 ) { //600
		$shipping_info = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_shipping_info', true );
		$now           = time();
		$freight       = array();
		if ( ! $shipping_info ) {
			if ( ! $country ) {
				$country = 'US';
			}
			$shipping_info = array(
				'time'          => 0,
				'country'       => $country,
				'company'       => '',
				'company_name'  => '',
				'freight'       => wp_json_encode( $freight ),
				'shipping_cost' => '',
				'delivery_time' => '',
			);
		} else {
			$freight = vi_wad_json_decode( $shipping_info['freight'] );
			if ( ! $country ) {
				$country = $shipping_info['country'];
				if ( ! $company ) {
					$company = $shipping_info['company'];
				}
			} elseif ( $country === $shipping_info['country'] && ! $company ) {
				$company = $shipping_info['company'];
			}
		}

		$ali_product_id = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_sku', true );

		if ( $ali_product_id ) {
			$maybe_update = false;
			if ( $cache_time == 0 || $now - floatval( $shipping_info['time'] ) > $cache_time ||
                 $country !== $shipping_info['country'] || (isset($shipping_info['shipping_cost']) && $shipping_info['shipping_cost'] === '') ) {
				$maybe_update             = true;
				$shipping_info['country'] = $country;
				$shipping_info['time'] = VI_WOO_ALIDROPSHIP_DATA::get_shipping_cache_time($now);
			}
			$shipping_info['shipping_cost'] = '';
			$shipping_info['delivery_time'] = '';
			if ( !empty( $freight )  ) {
				if ($company){
					if ($company !== $shipping_info['company']){
						$maybe_update = true;
					}
					foreach ($freight as $item){
						if (($item['company'] ??'') === $company){
							$shipping_info['company'] = $item['company'];
							$shipping_info['shipping_cost'] = $item['shipping_cost'];
							$shipping_info['delivery_time'] = $item['delivery_time'];
							break;
						}
					}
				}
				if ($shipping_info['shipping_cost'] === ''  && isset($freight[0]['shipping_cost'],$freight[0]['delivery_time']) ) {
					$shipping_info['company'] = $freight[0]['company'];
					$shipping_info['shipping_cost'] = $freight[0]['shipping_cost'];
					$shipping_info['delivery_time'] = $freight[0]['delivery_time'];
				}
				if ($company && $company !== $shipping_info['company']){
					$maybe_update = true;
				}
			}
			if ( $maybe_update ) {
				Ali_Product_Table::update_post_meta( $product_id, '_vi_wad_shipping_info', $shipping_info );
			}
		}
		$shipping_info['freight'] = $freight;

		return $shipping_info;
	}

	public static function get_button_view_edit_html( $woo_product_id ) {
		ob_start();
		?>
        <a href="<?php echo esc_attr( get_post_permalink( $woo_product_id ) ) ?>"
           target="_blank" class="button"
           rel="nofollow"><?php esc_html_e( 'View product', 'woo-alidropship' ); ?></a>
        <a href="<?php echo esc_url( admin_url( "post.php?post={$woo_product_id}&action=edit" ) ) ?>"
           target="_blank" class="button button-primary"
           rel="nofollow"><?php esc_html_e( 'Edit product', 'woo-alidropship' ) ?></a>
		<?php
		return ob_get_clean();
	}

	public static function variation_html( $key, $parent, $attributes, $manage_stock, $variations, $use_different_currency, $currency, $product_id, $woocommerce_currency_symbol, $decimals, $lazy_load = true, $coutry = '', $company = '' ) {
		?>
        <thead>
        <tr>
            <td width="1%"></td>
            <td class="<?php echo esc_attr( self::set( 'fix-width' ) ) ?>">
                <input type="checkbox" checked class="<?php echo esc_attr( self::set( array( 'variations-bulk-enable', 'variations-bulk-enable-' . $key ) ) ) ?>">
            </td>
            <td class="<?php echo esc_attr( self::set( 'fix-width' ) ) ?>">
                <input type="checkbox" checked class="<?php echo esc_attr( self::set( array( 'variations-bulk-select-image' ) ) ) ?>">
            </td>
            <th class="<?php echo esc_attr( self::set( 'fix-width' ) ) ?>"><?php esc_html_e( 'Default variation', 'woo-alidropship' ) ?></th>
            <th><?php esc_html_e( 'Sku', 'woo-alidropship' ) ?></th>
			<?php
			if ( is_array( $parent ) && count( $parent ) ) {
				foreach ( $parent as $parent_k => $parent_v ) {
					?>
                    <th class="<?php echo esc_attr( self::set( 'attribute-filter-list-container' ) ) ?>">
						<?php
						$attribute_name = isset( $attributes[ $parent_k ]['name'] ) ? $attributes[ $parent_k ]['name'] : VI_WOO_ALIDROPSHIP_DATA::get_attribute_name_by_slug( $parent_v );
						echo esc_html( $attribute_name );
						$attribute_values = isset( $attributes[ $parent_k ]['values'] ) ? $attributes[ $parent_k ]['values'] : array();
						if ( count( $attribute_values ) ) {
							?>
                            <ul class="<?php echo esc_attr( self::set( 'attribute-filter-list' ) ) ?>"
                                data-attribute_slug="<?php echo esc_attr( $parent_v ) ?>">
								<?php
								foreach ( $attribute_values as $attribute_value ) {
									?>
                                    <li class="<?php echo esc_attr( self::set( 'attribute-filter-item' ) ) ?>"
                                        title="<?php echo esc_attr( $attribute_value ) ?>"
                                        data-attribute_slug="<?php echo esc_attr( $parent_v ) ?>"
                                        data-attribute_value="<?php echo esc_attr( trim( $attribute_value ) ) ?>"><?php echo esc_html( $attribute_value ) ?></li>
									<?php
								}
								?>
                            </ul>
							<?php
						}
						?>
                    </th>
					<?php
				}
			}
			$show_shipping_option            = self::$settings->get_params( 'show_shipping_option' );
			$shipping_cost_after_price_rules = self::$settings->get_params( 'shipping_cost_after_price_rules' );
			$shipping_cost_html              = '';
			$shipping_cost                   = 0;
			if ( $show_shipping_option ) {
				$shipping_info      = self::get_shipping_info( $product_id, $coutry, $company );
				$shipping_cost      = abs( VI_WOO_ALIDROPSHIP_DATA::string_to_float( $shipping_info['shipping_cost'] ) );
				$shipping_cost_html = $shipping_info['shipping_cost'] === ''
					? esc_html__( 'Not available', 'woo-alidropship' )
					: wc_price( $shipping_info['shipping_cost'], array(
						'currency'     => $currency,
						'decimals'     => 2,
						'price_format' => '%1$s&nbsp;%2$s'
					) );
				if ( $use_different_currency && $shipping_cost ) {
					$shipping_cost_html .= '(' . wc_price( self::$settings->process_exchange_price( $shipping_cost ) ) . ')';
				}
				?>
                <th class="<?php echo esc_attr( self::set( 'sale-price-col' ) ) ?>"><?php esc_html_e( 'Shipping cost', 'woo-alidropship' ) ?>
					<?php self::shipping_option_html( $shipping_info, $key, $product_id ); ?>
                </th>
				<?php
			}
			?>
            <th><?php esc_html_e( 'Cost', 'woo-alidropship' ) ?>
				<?php
				if ( $show_shipping_option && ! $shipping_cost_after_price_rules ) {
					?>
                    <div><?php esc_html_e( '(price+shipping)', 'woo-alidropship' ) ?></div>
					<?php
				}
				?>
            </th>
            <th class="<?php echo esc_attr( self::set( 'sale-price-col' ) ) ?>"><?php esc_html_e( 'Sale price', 'woo-alidropship' ) ?>
                <div class="<?php echo esc_attr( self::set( 'set-price' ) ) ?>"
                     data-set_price="sale_price"><?php esc_html_e( 'Set price', 'woo-alidropship' ) ?></div>
            </th>
            <th class="<?php echo esc_attr( self::set( 'regular-price-col' ) ) ?>"><?php esc_html_e( 'Regular price', 'woo-alidropship' ) ?>
                <div class="<?php echo esc_attr( self::set( 'set-price' ) ) ?>"
                     data-set_price="regular_price"><?php esc_html_e( 'Set price', 'woo-alidropship' ) ?></div>
            </th>
			<?php
			if ( $manage_stock ) {
				?>
                <th class="<?php echo esc_attr( self::set( 'inventory-col' ) ) ?>"><?php esc_html_e( 'Inventory', 'woo-alidropship' ) ?></th>
				<?php
			}
			?>
        </tr>
        </thead>
        <tbody>
		<?php
		foreach ( $variations as $variation_key => $variation ) {

			$variation_image = $variation['image'];
			$inventory       = intval( $variation['stock'] );
			if ( $shipping_cost_after_price_rules ) {
				$variation_sale_price    = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variation['sale_price'] );
				$variation_regular_price = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variation['regular_price'] );
				$price                   = $variation_sale_price ? $variation_sale_price : $variation_regular_price;
				$sale_price              = self::$settings->process_price( $price, true );
				if ( $sale_price ) {
					$sale_price += $shipping_cost;
				}
				$regular_price = self::$settings->process_price( $price ) + $shipping_cost;
			} else {
				$variation_sale_price    = $variation['sale_price'] ? ( VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variation['sale_price'] ) + $shipping_cost ) : VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variation['sale_price'] );
				$variation_regular_price = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variation['regular_price'] ) + $shipping_cost;
				$price                   = $variation_sale_price ? $variation_sale_price : $variation_regular_price;
				$sale_price              = self::$settings->process_price( $price, true );
				$regular_price           = self::$settings->process_price( $price );
			}
			$profit      = $variation_sale_price ? ( $sale_price - $variation_sale_price ) : ( $regular_price - $variation_regular_price );
			$cost_html   = wc_price( $price, array(
				'currency'     => $currency,
				'decimals'     => 2,
				'price_format' => '%1$s&nbsp;%2$s'
			) );
			$profit_html = wc_price( $profit, array(
				'currency'     => $currency,
				'decimals'     => 2,
				'price_format' => '%1$s&nbsp;%2$s'
			) );
			if ( $use_different_currency ) {
				$cost_html   .= '(' . wc_price( self::$settings->process_exchange_price( $price ) ) . ')';
				$profit_html .= '(' . wc_price( self::$settings->process_exchange_price( $profit ) ) . ')';
			}
			$sale_price    = self::$settings->process_exchange_price( $sale_price );
			$regular_price = self::$settings->process_exchange_price( $regular_price );
			$image_src     = $variation_image ? $variation_image : wc_placeholder_img_src();
			?>
            <tr class="<?php echo esc_attr( self::set( 'product-variation-row' ) ) ?>">
                <td><?php echo esc_html( $variation_key + 1 ) ?></td>
                <td>
                    <input type="checkbox" checked
                           class="<?php echo esc_attr( self::set( array(
						       'variation-enable',
						       'variation-enable-' . $key,
						       'variation-enable-' . $key . '-' . $variation_key
					       ) ) ) ?>">
                </td>
                <td>
                    <div class="<?php echo esc_attr( self::set( array( 'variation-image', 'selected-item' ) ) ) ?>">
                        <span class="<?php echo esc_attr( self::set( 'selected-item-icon-check' ) ) ?>"> </span>
                        <img style="width: 64px;height: 64px"
                             src="<?php echo esc_url( $lazy_load ? VI_WOO_ALIDROPSHIP_IMAGES . 'loading.gif' : $image_src ) ?>"
                             data-image_src="<?php echo esc_url( $image_src ) ?>"
                             class="<?php echo esc_attr( self::set( 'import-data-variation-image' ) ) ?>">
                        <input type="hidden"
                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][' . $variation_key . '][image]' ) ?>"
                               value="<?php echo esc_attr( $variation_image ? $variation_image : '' ) ?>">
                    </div>
                </td>
                <td><input type="radio"
                           class="<?php echo esc_attr( self::set( 'import-data-variation-default' ) ) ?>"
                           name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][default_variation]' ) ?>"
                           value="<?php echo esc_attr( $variation['skuAttr'] ) ?>">
                </td>
                <td>
                    <div>
                        <input type="text"
                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][' . $variation_key . '][sku]' ) ?>"
                               value="<?php echo esc_attr( $variation['sku'] ) ?>"
                               class="<?php echo esc_attr( self::set( 'import-data-variation-sku' ) ) ?>">
                        <input type="hidden"
                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][' . $variation_key . '][skuId]' ) ?>"
                               value="<?php echo esc_attr( $variation['skuId'] ) ?>">
                        <input type="hidden"
                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][' . $variation_key . '][skuAttr]' ) ?>"
                               value="<?php echo esc_attr( $variation['skuAttr'] ) ?>">
                    </div>
                </td>
				<?php
				if ( is_array( $parent ) && count( $parent ) ) {
					foreach ( $parent as $parent_k => $parent_v ) {
						?>
                        <td>
                            <input type="text" readonly
                                   data-attribute_slug="<?php echo esc_attr( $parent_v ) ?>"
                                   data-attribute_value="<?php echo esc_attr( isset( $variation['attributes'][ $parent_v ] ) ? trim( $variation['attributes'][ $parent_v ] ) : '' ) ?>"
                                   name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][' . $variation_key . '][attributes][' . $parent_v . ']' ) ?>"
                                   class="<?php echo esc_attr( self::set( 'import-data-variation-attribute' ) ) ?>"
                                   value="<?php echo esc_attr( isset( $variation['attributes'][ $parent_v ] ) ? $variation['attributes'][ $parent_v ] : '' ) ?>">
                        </td>
						<?php
					}
				}
				if ( $shipping_cost_html !== '' ) {
					?>
                    <td>
                        <div class="<?php echo esc_attr( self::set( 'price-field' ) ) ?>">
                            <span class="<?php echo esc_attr( self::set( 'import-data-shipping-cost' ) ) ?>"><?php echo wp_kses( $shipping_cost_html, VI_WOO_ALIDROPSHIP_DATA::allow_html() )  ?></span>
                        </div>
                    </td>
					<?php
				}
				?>
                <td>
                    <div class="<?php echo esc_attr( self::set( 'price-field' ) ) ?>">
                        <span class="<?php echo esc_attr( self::set( 'import-data-variation-cost' ) ) ?>"><?php echo wp_kses( $cost_html , VI_WOO_ALIDROPSHIP_DATA::allow_html())  ?></span>
                    </div>
                </td>
                <td>
                    <div class="vi-ui left labeled input">
                        <label for="amount"
                               class="vi-ui label"><?php echo esc_html( $woocommerce_currency_symbol ) ?></label>
                        <input type="number" min="0"
                               step="<?php echo esc_attr( $decimals ) ?>"
                               value="<?php echo esc_attr( $sale_price ) ?>"
                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][' . $variation_key . '][sale_price]' ) ?>"
                               class="<?php echo esc_attr( self::set( 'import-data-variation-sale-price' ) ) ?>">
                    </div>
                </td>
                <td>
                    <div class="vi-ui left labeled input">
                        <label for="amount"
                               class="vi-ui label"><?php echo esc_html( $woocommerce_currency_symbol ) ?></label>
                        <input type="number" min="0"
                               step="<?php echo esc_attr( $decimals ) ?>"
                               value="<?php echo esc_attr( $regular_price ) ?>"
                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][' . $variation_key . '][regular_price]' ) ?>"
                               class="<?php echo esc_attr( self::set( 'import-data-variation-regular-price' ) ) ?>">
                    </div>
                </td>
				<?php
				if ( $manage_stock ) {
					?>
                    <td>
                        <input type="number" min="0"
                               step="<?php echo esc_attr( $decimals ) ?>"
                               value="<?php echo esc_attr( $inventory ) ?>"
                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][' . $variation_key . '][stock]' ) ?>"
                               class="<?php echo esc_attr( self::set( 'import-data-variation-inventory' ) ) ?>">
                    </td>
					<?php
				}
				?>

            </tr>
			<?php
		}
		?>
        </tbody>
		<?php
	}

	public static function shipping_option_html( $shipping_info, $key, $product_id, $product_type = 'variable' ) {
		$wc_country       = new WC_Countries();
		$countries        = $wc_country->get_countries();
		$shipping_company = $shipping_info['company'];
		?>
        <div class="<?php echo esc_attr( self::set( 'shipping-info' ) ) ?>"
             data-product_index="<?php echo esc_attr( $key ) ?>"
             data-product_type="<?php echo esc_attr( $product_type ) ?>"
             data-product_id="<?php echo esc_attr( $product_id ) ?>">
			<?php
			if ( !empty( $shipping_info['freight'] ) ) {
				?>
                <div class="<?php echo esc_attr( self::set( 'shipping-info-company-wrap' ) ) ?>">
                    <select name="<?php echo esc_attr( self::set( 'shipping-info-company', true ) ) ?>"
                            class="vi-ui dropdown fluid <?php echo esc_attr( self::set( 'shipping-info-company' ) ) ?>">
						<?php
						foreach ( $shipping_info['freight'] as $freight ) {
							$selected = '';
							$freight_company = $freight['company'] ??'';
							if (!$freight_company){
								continue;
							}
							if ($shipping_company === $freight_company) {
								$selected = 'selected';
								$found    = true;
							}
							$delivery_time   = self::process_delivery_time(  $freight['delivery_time']  ?? ''  );
							$shipping_amount = $freight['shipping_cost'] ?? VI_WOO_ALIDROPSHIP_DATA::get_freight_amount( $freight );
							$company         = !empty( $freight['company_name'] ) ? $freight['company_name'] : $freight_company;
							?>
                            <option value="<?php echo esc_attr( $freight_company ) ?>" <?php echo esc_attr( $selected ) ?>><?php echo esc_html( "\${$shipping_amount}-{$company}({$delivery_time})" ) ?></option>
							<?php
						}
						?>
                    </select>
                </div>
				<?php
			} elseif ( $product_type === 'simple' ) {
				?>
                <div class="<?php echo esc_attr( self::set( 'shipping-info-company-wrap' ) ) ?>"><?php esc_html_e( 'Not available', 'woo-alidropship' ) ?></div>
				<?php
			}
			?>
        </div>
		<?php
	}

	public static function simple_product_price_field_html( $key, $manage_stock, $variations, $use_different_currency, $currency, $product_id, $woocommerce_currency_symbol, $decimals, $coutry = '', $company = '' ) {
		if ( ! is_array( $variations[0]??'' ) ) {
			printf('<p style="color: red;">%s</p>', esc_html('Error parsing data in version 1.0.29. Please remove this product & import again'));
			return;
		}

		$show_shipping_option            = self::$settings->get_params( 'show_shipping_option' );
		$shipping_cost_after_price_rules = self::$settings->get_params( 'shipping_cost_after_price_rules' );
		$shipping_cost_html              = '';
		$cost_label                      = esc_html__( 'Cost', 'woo-alidropship' );
		$shipping_cost                   = 0;
		if ( $show_shipping_option ) {
			if ( ! $shipping_cost_after_price_rules ) {
				$cost_label = esc_html__( 'Cost(price+shipping)', 'woo-alidropship' );
			}
			$shipping_info = self::get_shipping_info( $product_id, $coutry, $company );
			$shipping_cost = abs( VI_WOO_ALIDROPSHIP_DATA::string_to_float( $shipping_info['shipping_cost'] ) );
			ob_start();
			?>
            <div class="field">
                <label><?php esc_html_e( 'Shipping cost', 'woo-alidropship' ) ?></label>
				<?php self::shipping_option_html( $shipping_info, $key, $product_id, 'simple' ); ?>
            </div>
			<?php
			$shipping_cost_html = ob_get_clean();
		}
		$inventory = intval( $variations[0]['stock'] );
		if ( $shipping_cost_after_price_rules ) {
			$variation_sale_price    = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations[0]['sale_price'] );
			$variation_regular_price = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations[0]['regular_price'] );
			$price                   = $variation_sale_price ? $variation_sale_price : $variation_regular_price;
			$sale_price              = self::$settings->process_price( $price, true );
			if ( $sale_price ) {
				$sale_price += $shipping_cost;
			}
			$regular_price = self::$settings->process_price( $price ) + $shipping_cost;
		} else {
			$variation_sale_price    = $variations[0]['sale_price'] ? ( VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations[0]['sale_price'] ) + $shipping_cost ) : VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations[0]['sale_price'] );
			$variation_regular_price = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations[0]['regular_price'] ) + $shipping_cost;
			$price                   = $variation_sale_price ? $variation_sale_price : $variation_regular_price;
			$sale_price              = self::$settings->process_price( $price, true );
			$regular_price           = self::$settings->process_price( $price );
		}
		$profit      = $variation_sale_price ? ( $sale_price - $variation_sale_price ) : ( $regular_price - $variation_regular_price );
		$cost_html   = wc_price( $price, array(
			'currency'     => $currency,
			'decimals'     => 2,
			'price_format' => '%1$s&nbsp;%2$s'
		) );
		$profit_html = wc_price( $profit, array(
			'currency'     => $currency,
			'decimals'     => 2,
			'price_format' => '%1$s&nbsp;%2$s'
		) );
		if ( $use_different_currency ) {
			$cost_html   .= '(' . wc_price( self::$settings->process_exchange_price( $price ) ) . ')';
			$profit_html .= '(' . wc_price( self::$settings->process_exchange_price( $profit ) ) . ')';
		}
		$sale_price    = self::$settings->process_exchange_price( $sale_price );
		$regular_price = self::$settings->process_exchange_price( $regular_price );
		?>
        <div class="field <?php echo esc_attr( self::set( 'simple-product-price-field' ) ) ?>">
            <input type="hidden"
                   name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][0][skuId]' ) ?>"
                   value="<?php echo esc_attr( $variations[0]['skuId'] ) ?>">
            <div class="equal width fields">
				<?php echo wp_kses( $shipping_cost_html, VI_WOO_ALIDROPSHIP_DATA::allow_html() ); ?>
                <div class="field">
                    <label><?php echo wp_kses( $cost_label, VI_WOO_ALIDROPSHIP_DATA::allow_html() );  ?></label>
                    <div class="<?php echo esc_attr( self::set( 'price-field' ) ) ?>">
						<?php echo wp_kses( $cost_html , VI_WOO_ALIDROPSHIP_DATA::allow_html())  ?>
                    </div>
                </div>
                <div class="field">
                    <label><?php esc_html_e( 'Sale price', 'woo-alidropship' ) ?></label>
                    <div class="vi-ui left labeled input">
                        <label for="amount"
                               class="vi-ui label"><?php echo esc_html( $woocommerce_currency_symbol ) ?></label>
                        <input
                                type="number" min="0"
                                step="<?php echo esc_attr( $decimals ) ?>"
                                value="<?php echo esc_attr( $sale_price ) ?>"
                                name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][0][sale_price]' ) ?>"
                                class="<?php echo esc_attr( self::set( 'import-data-variation-sale-price' ) ) ?>">
                    </div>
                </div>
                <div class="field">
                    <label><?php esc_html_e( 'Regular price', 'woo-alidropship' ) ?></label>
                    <div class="vi-ui left labeled input">
                        <label for="amount"
                               class="vi-ui label"><?php echo esc_html( $woocommerce_currency_symbol ) ?></label>
                        <input type="number" min="0"
                               step="<?php echo esc_attr( $decimals ) ?>"
                               value="<?php echo esc_attr( $regular_price ) ?>"
                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][0][regular_price]' ) ?>"
                               class="<?php echo esc_attr( self::set( 'import-data-variation-regular-price' ) ) ?>">
                    </div>
                </div>
				<?php
				if ( $manage_stock ) {
					?>
                    <div class="field">
                        <label><?php esc_html_e( 'Inventory', 'woo-alidropship' ) ?></label>
                        <input
                                type="number" min="0"
                                step="<?php echo esc_attr( $decimals ) ?>"
                                value="<?php echo esc_attr( $inventory ) ?>"
                                name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][variations][0][stock]' ) ?>"
                                class="<?php echo esc_attr( self::set( 'import-data-variation-inventory' ) ) ?>">
                    </div>
					<?php
				}
				?>
            </div>
        </div>
		<?php
	}

	public static function load_variations_ajax( $variations ) {
		return ( self::$settings->get_params( 'show_shipping_option' ) || count( $variations ) >= 10 );
	}

	public static function process_delivery_time( $time ) {
		$time_arr = explode( '-', $time );
		if ( count( $time_arr ) === 2 ) {
			$min = intval( $time_arr[0] );
			if ( $min === intval( $time_arr[1] ) ) {
				$return = sprintf( _n( '%s day', '%s days', $min, 'woo-alidropship' ), $min );//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
			} else {
				$return = sprintf( esc_html__( '%s days', 'woo-alidropship' ), $time );//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
			}
		}  elseif (is_numeric($time)) {
			$return = sprintf( _n( '%s day', '%s days', $time, 'woo-alidropship' ), $time );//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
		}else {
			$return = $time;
		}

		return $return;
	}

	public static function get_product_attributes( $product_id ) {
		$attributes = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_attributes', true );
		if ( is_array( $attributes ) && count( $attributes ) ) {
			foreach ( $attributes as $key => $value ) {
				if ( ! empty( $value['slug_edited'] ) ) {
					$attributes[ $key ]['slug'] = $value['slug_edited'];
					unset( $attributes[ $key ]['slug_edited'] );
				}
				if ( ! empty( $value['name_edited'] ) ) {
					$attributes[ $key ]['name'] = $value['name_edited'];
					unset( $attributes[ $key ]['name_edited'] );
				}
				if ( ! empty( $value['values_edited'] ) ) {
					$attributes[ $key ]['values'] = $value['values_edited'];
					unset( $attributes[ $key ]['values_edited'] );
				}
			}
		}

		return $attributes;
	}

	public static function get_product_variations( $product_id ) {
		$variations = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_variations', true );
		if ( is_array( $variations ) && count( $variations ) ) {
			foreach ( $variations as $key => $value ) {
				if ( ! empty( $value['attributes_edited'] ) ) {
					$variations[ $key ]['attributes'] = $value['attributes_edited'];
					unset( $variations[ $key ]['attributes_edited'] );
				}
			}
		}

		return (array) $variations;
	}

	public static function build_category_name( $category_name, $category ) {
		if ( $category->parent ) {
			$category_parent = get_term_by( 'id', $category->parent, 'product_cat' );
			if ( $category_parent ) {
				$category_name = "{$category_parent->name} > {$category_name}";
				$category_name = self::build_category_name( $category_name, $category_parent );
			}
		}

		return $category_name;
	}

	public static function dropdown_categories( $product_id ) {
        if (self::$categories_options){
            return self::$categories_options;
        }

        ob_start();
		$cats                     = get_terms(
			array(
				'taxonomy'   => 'product_cat',
				'orderby'    => 'name',
				'order'      => 'ASC',
				'hide_empty' => false
			)
		);
        ?>
        <select name="<?php echo esc_attr( 'vi_wad_product['.$product_id.'][categories][]' ) ?>"
                class="vi-ui dropdown search  <?php echo esc_attr( self::set( 'import-data-categories' ) ) ?>"
                multiple="multiple">
			<?php
			if ( is_array( $cats ) && !empty( $cats ) ) {
				$product_categories          = self::$settings->get_params( 'product_categories' );
				foreach ( $cats as $cat ) {
					?>
                    <option value="<?php echo esc_attr( $cat->term_id ) ?>"
						<?php echo esc_attr(in_array( $cat->term_id, $product_categories )? 'selected':'' ) ?>><?php echo wp_kses_post(self::build_category_name( $cat->name, $cat) ); ?></option>
					<?php
				}
			}
            ?>
        </select>
        <?php
		self::$categories_options = ob_get_clean();
		return self::$categories_options;
	}

	private static function check_ajax_referer() {
		VI_WOO_ALIDROPSHIP_Admin_Settings::check_ajax_referer( 'woo-alidropship-import-list' );
	}
}PK     \]h    
  system.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class VI_WOO_ALIDROPSHIP_Admin_System
 */
class VI_WOO_ALIDROPSHIP_Admin_System {

	public function __construct() {
		add_action( 'admin_menu', array( $this, 'menu_page' ), 25 );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
	}

	public function admin_enqueue_scripts() {
		global $pagenow;
		$page = isset( $_REQUEST['page'] ) ? $_REQUEST['page'] : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( $pagenow === 'admin.php' && $page === 'woo-alidropship-status' ) {
			wp_enqueue_style( 'woo-alidropship-button', VI_WOO_ALIDROPSHIP_CSS . 'button.min.css',[], VI_WOO_ALIDROPSHIP_VERSION  );
			wp_enqueue_style( 'woo-alidropship-icon', VI_WOO_ALIDROPSHIP_CSS . 'icon.min.css',[], VI_WOO_ALIDROPSHIP_VERSION  );
		}
	}

	public function page_callback() {
		?>
        <div class="wrap">
            <h2><?php esc_html_e( 'System Status', 'woo-alidropship' ) ?></h2>
            <table cellspacing="0" id="status" class="widefat">
                <tbody>
                <tr>
                    <td data-export-label="<?php esc_html_e( 'PHP Time Limit', 'woo-alidropship' ) ?>"><?php esc_html_e( 'PHP Max Execution Time', 'woo-alidropship' ) ?></td>
                    <td><?php echo esc_html( ini_get( 'max_execution_time' ) ); ?></td>
                    <td><?php esc_html_e( 'Should be greater than 100', 'woo-alidropship' ) ?></td>
                </tr>
                <tr>
                    <td data-export-label="<?php esc_html_e( 'PHP Max Input Vars', 'woo-alidropship' ) ?>"><?php esc_html_e( 'PHP Max Input Vars', 'woo-alidropship' ) ?></td>

                    <td><?php echo esc_html( ini_get( 'max_input_vars' ) ); ?></td>
                    <td><?php esc_html_e( 'Should be greater than 10000', 'woo-alidropship' ) ?></td>
                </tr>
                <tr>
                    <td data-export-label="<?php esc_html_e( 'Memory Limit', 'woo-alidropship' ) ?>"><?php esc_html_e( 'Memory Limit', 'woo-alidropship' ) ?></td>

                    <td><?php echo esc_html( ini_get( 'memory_limit' ) ); ?></td>
                    <td><?php esc_html_e( 'Should be greater than 300MB', 'woo-alidropship' ) ?></td>
                </tr>
                <tr>
                    <td><?php esc_html_e( 'WooCommerce AliExpress Dropshipping Extension installed and active', 'woo-alidropship' ) ?></td>
                    <td>
                        <i class="red cancel icon <?php echo esc_attr( VI_WOO_ALIDROPSHIP_DATA::set( 'chrome-extension-active' ) ) ?>"></i>
                        <a target="_blank" href="https://downloads.villatheme.com/?download=alidropship-extension"
                           title="<?php esc_attr_e( 'You have to install the chrome extension to import products from AliExpress', 'woo-alidropship' ) ?>"
                           class="vi-ui positive button labeled icon mini <?php echo esc_attr( VI_WOO_ALIDROPSHIP_DATA::set( 'download-chrome-extension' ) ) ?>"><i
                                    class="external icon"></i><?php esc_html_e( 'Install Extension', 'woo-alidropship' ) ?>
                        </a>
                    </td>
                    <td><?php esc_html_e( '*Required to be able to import AliExpress products', 'woo-alidropship' ) ?></td>
                </tr>
                </tbody>
            </table>
        </div>
		<?php
	}

	/**
	 * Register a custom menu page.
	 */
	public function menu_page() {
		add_submenu_page(
			'woo-alidropship-import-list',
			esc_html__( 'System Status', 'woo-alidropship' ),
			esc_html__( 'System Status', 'woo-alidropship' ),
			'manage_options',
			'woo-alidropship-status',
			array( $this, 'page_callback' )
		);
	}
}
PK     \Sx~|6  |6    recommend.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class VI_WOO_ALIDROPSHIP_Admin_System
 */
class VI_WOO_ALIDROPSHIP_Admin_Recommend {
	protected $dismiss;

	public function __construct() {
		$this->dismiss = 'wad_install_recommended_plugins_dismiss';
		add_action( 'admin_menu', array( $this, 'menu_page' ), 30 );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
		add_action( 'admin_init', array( $this, 'fix_dismiss_notice' ) );
	}

	public function fix_dismiss_notice() {
		$dismiss = get_option( $this->dismiss );
		if ( $dismiss ) {
			if ( $dismiss > 1600852690 ) {//2020-09-23 09:18:10 version 1.0.3.3 update time
				update_option( "{$this->dismiss}__email-template-customizer-for-woo", $dismiss );
			}
			update_option( "{$this->dismiss}__product-variations-swatches-for-woocommerce", $dismiss );
			delete_option( $this->dismiss );
		}
	}

	public static function admin_notices_html( $message, $button, $plugin_slug ) {
		?>
        <div class="villatheme-dashboard updated" style="border-left: 4px solid #ffba00">
            <div class="villatheme-content">
                <form action="" method="get">
                    <p><?php echo wp_kses( $message, VI_WOO_ALIDROPSHIP_DATA::allow_html() ) ?></p>
                    <p><?php echo wp_kses_post( $button ) ?></p>
                    <a href="<?php echo esc_url( add_query_arg( array(
						'wad_dismiss_nonce' => wp_create_nonce( 'wad_dismiss_nonce' ),
						'plugin'            => $plugin_slug,
					) ) ) ?>" target="_self"
                       class="button notice-dismiss vi-button-dismiss"><?php esc_html_e( 'Dismiss', 'woo-alidropship' ) ?></a>
                </form>
            </div>
        </div>
		<?php
	}

	public function admin_notices() {
		global $pagenow;
		$action              = isset( $_REQUEST['action'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$_plugin             = isset( $_REQUEST['plugin'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['plugin'] ) ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$recommended_plugins = array(
			array(
				'slug'                => 'exmage-wp-image-links',
				'pro'                 => 'exmage-wordpress-image-links',
				'name'                => 'EXMAGE – WordPress Image Links',
				'message_not_install' => __( 'Need to save your server storage? <strong>EXMAGE – WordPress Image Links</strong> will help you solve the problem by using external image URLs. </br>When this plugin is active, "Use external links for images" option will be available in the ALD plugin settings/Product which allows to use original AliExpress product image URLs for featured image, gallery images and variation image of imported AliExpress products.', 'woo-alidropship' ),
				'message_not_active'  => __( '<strong>EXMAGE – WordPress Image Links</strong> is currently inactive, external images added by this plugin(Post/product featured image, product gallery images...) will no longer work properly.', 'woo-alidropship' ),
			),
			array(
				'slug'                => 'woo-photo-reviews',
				'pro'                 => 'woocommerce-photo-reviews',
				'name'                => 'Photo Reviews for WooCommerce',
				'message_not_install' => __( '<strong>Photo Reviews for WooCommerce</strong> helps you send review reminder emails automatically to request a review, and lets your customer include photos in their feedback.', 'woo-alidropship' ),
				'message_not_active'  => __( '<strong>Photo Reviews for WooCommerce</strong> is currently inactive. Activate it to automatically send email to your customers to request reviews', 'woo-alidropship' ),
			),
			array(
				'slug'                => 'woo-notification',
				'pro'                 => 'woocommerce-notification',
				'name'                => 'Notification for WooCommerce',
				'message_not_install' => __( '<strong>Notification for WooCommerce</strong> display recent orders as popup notifications, boosting conversion rates by showing real-time purchase, creating urgency, and showcasing new products.', 'woo-alidropship' ),
				'message_not_active'  => __( '<strong>Notification for WooCommerce</strong> is currently inactive. Activate it to display recent orders as popup notifications', 'woo-alidropship' ),
			),
			array(
				'slug'                => 'product-variations-swatches-for-woocommerce',
				'pro'                 => 'woocommerce-product-variations-swatches',
				'name'                => 'Product Variations Swatches for WooCommerce',
				'message_not_install' => __( 'Need a variations swatches plugin that works perfectly with ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce? <strong>Product Variations Swatches for WooCommerce</strong> is what you need.', 'woo-alidropship' ),
				'message_not_active'  => __( '<strong>Product Variations Swatches for WooCommerce</strong> is currently inactive, this prevents variable products from displaying beautifully.', 'woo-alidropship' ),
			),
			array(
				'slug'                => 'bulky-bulk-edit-products-for-woo',
				'pro'                 => '',
				'name'                => 'Bulky – Bulk Edit Products for WooCommerce',
				'message_not_install' => __( 'Quickly and easily edit your products in bulk with <strong>Bulky – Bulk Edit Products for WooCommerce</strong>', 'woo-alidropship' ),
				//				'message_not_active'  => __( '<strong>Bulky – Bulk Edit Products for WooCommerce</strong> is currently inactive. Activate it to quickly edit your products in bulk', 'woo-alidropship' ),
			),
			array(
				'slug'                => 'email-template-customizer-for-woo',
				'pro'                 => 'woocommerce-email-template-customizer',
				'name'                => 'Email Template Customizer for WooCommerce',
				'message_not_install' => __( 'Try our brand new <strong>Email Template Customizer for WooCommerce</strong> plugin to easily customize your WooCommerce emails and make them more beautiful and professional.', 'woo-alidropship' ),
				//				'message_not_active'  => __( '<strong>Email Template Customizer for WooCommerce</strong> is currently inactive. Activate it to customize WooCommerce emails with ease and make your customers more satisfied when receiving your emails.', 'woo-alidropship' ),
			),
			array(
				'slug'                => 'vargal-additional-variation-gallery-for-woo',
				'name'                => 'VARGAL – Additional Variation Gallery for Woo',
				'desc'                => esc_html__( 'Easily set unlimited images or MP4/WebM videos for each WC product variation and display them when the customer selects', 'woo-alidropship' ),
				'message_not_install' => sprintf( "%s <strong>VARGAL – Additional Variation Gallery for Woo</strong> %s", esc_html__( 'Looking for a plugin that lets you add unlimited images or MP4/WebM videos to each WooCommerce product variation?', 'woo-alidropship' ), esc_html__( 'is what you need.', 'woo-alidropship' ) ),
				'message_not_active'  => sprintf( "<strong>VARGAL</strong> %s", esc_html__( 'is currently inactive, the variation gallery setting will not be set.', 'woo-alidropship' ) ),
			),
		);
		$plugins             = get_plugins();
		foreach ( $recommended_plugins as $recommended_plugin ) {
			$plugin_slug = $recommended_plugin['slug'];
			if ( ! get_option( "{$this->dismiss}__{$plugin_slug}" ) ) {
				if ( ! empty( $recommended_plugin['pro'] ) && is_plugin_active( "{$recommended_plugin['pro']}/{$recommended_plugin['pro']}.php" ) ) {
					continue;
				}
				$plugin = "{$plugin_slug}/{$plugin_slug}.php";
				if ( ! isset( $plugins[ $plugin ] ) ) {
					if ( ! ( $pagenow === 'update.php' && $action === 'install-plugin' && $_plugin === $plugin_slug ) ) {
						$button = '<a href="' . esc_url( wp_nonce_url( self_admin_url( "update.php?action=install-plugin&plugin={$plugin_slug}" ), "install-plugin_{$plugin_slug}" ) ) . '" target="_self" class="button button-primary">' . esc_html__( 'Install now', 'woo-alidropship' ) . '</a>';
						self::admin_notices_html( $recommended_plugin['message_not_install'], $button, $plugin_slug );
					}
				} elseif ( ! is_plugin_active( $plugin ) && ! empty( $recommended_plugin['message_not_active'] ) ) {
					$button = '<a href="' . esc_url( wp_nonce_url( add_query_arg( array(
							'action' => 'activate',
							'plugin' => $plugin
						), admin_url( 'plugins.php' ) ), "activate-plugin_{$plugin}" ) ) . '" target="_self" class="button button-primary">' . esc_html__( 'Activate now', 'woo-alidropship' ) . '</a>';
					self::admin_notices_html( $recommended_plugin['message_not_active'], $button, $plugin_slug );
				}
			}
		}
	}

	public function admin_enqueue_scripts() {
		global $pagenow;
		$page = isset( $_REQUEST['page'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['page'] ) ) : '';
		if ( $pagenow === 'admin.php' && $page === 'woo-alidropship-recommend' ) {
			wp_dequeue_style( 'eopa-admin-css' );
			wp_enqueue_style( 'vi-woo-alidropship-form', VI_WOO_ALIDROPSHIP_CSS . 'form.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_style( 'vi-woo-alidropship-table', VI_WOO_ALIDROPSHIP_CSS . 'table.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_style( 'vi-woo-alidropship-icon', VI_WOO_ALIDROPSHIP_CSS . 'icon.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_style( 'vi-woo-alidropship-segment', VI_WOO_ALIDROPSHIP_CSS . 'segment.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_style( 'vi-woo-alidropship-button', VI_WOO_ALIDROPSHIP_CSS . 'button.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
			if ( ! wp_style_is( 'viwad-recommended_plugins' ) ) {
				wp_register_style( 'viwad-recommended_plugins', false, [], VI_WOO_ALIDROPSHIP_VERSION );
				wp_enqueue_style( 'viwad-recommended_plugins' );
				wp_add_inline_style( 'viwad-recommended_plugins', '.fist-col { min-width: 300px;}.vi-wad-plugin-name {font-weight: 600;}.vi-wad-plugin-name a { text-decoration: none;}' );
			}
/*
			$wad_dismiss_nonce = isset( $_REQUEST['wad_dismiss_nonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['wad_dismiss_nonce'] ) ) : '';
			$dismiss_plugin    = isset( $_REQUEST['plugin'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['plugin'] ) ) : '';
			if ( wp_verify_nonce( $wad_dismiss_nonce, 'wad_dismiss_nonce' ) ) {
				$option = $dismiss_plugin ? "{$this->dismiss}__{$dismiss_plugin}" : $this->dismiss;
				if ( ! get_option( $option ) ) {
					update_option( $option, time() );
				}
			}
			if ( ! get_option( $this->dismiss ) ) {
				add_action( 'admin_notices', array( $this, 'admin_notices' ) );
			}*/
		}
	}

	public function page_callback() {
		$plugins = Vi_Wad_Setup_Wizard::recommended_plugins();
		?>
        <div class="">
            <h2><?php esc_html_e( 'Recommended plugins', 'woo-alidropship' ) ?></h2>
            <table cellspacing="0" id="status" class="vi-ui celled table">
                <thead>
                <tr>
                    <th></th>
                    <th><?php esc_html_e( 'Plugins', 'woo-alidropship' ); ?></th>
                    <th><?php esc_html_e( 'Description', 'woo-alidropship' ); ?></th>
                </tr>
                </thead>
                <tbody>
				<?php
				$installed_plugins = get_plugins();
				foreach ( $plugins as $plugin ) {
					$plugin_id = "{$plugin['slug']}/{$plugin['slug']}.php";
					?>
                    <tr>
                        <td><a target="_blank"
                               href="<?php echo esc_url( "https://wordpress.org/plugins/{$plugin['slug']}" ) ?>"><img
                                        src="<?php echo esc_url( $plugin['img'] ) ?>" width="60" height="60"></a></td>
                        <td class="fist-col">
                            <div class="vi-wad-plugin-name">
                                <a target="_blank"
                                   href="<?php echo esc_url( "https://wordpress.org/plugins/{$plugin['slug']}" ) ?>"><strong><?php echo esc_html( $plugin['name'] ) ?></strong></a>
                            </div>
                            <div>
								<?php
								if ( ! isset( $installed_plugins[ $plugin_id ] ) ) {
									?>
                                    <a href="<?php echo esc_url( wp_nonce_url( self_admin_url( "update.php?action=install-plugin&plugin={$plugin['slug']}" ), "install-plugin_{$plugin['slug']}" ) ) ?>"
                                       target="_blank"><?php esc_html_e( 'Install', 'woo-alidropship' ); ?></a>
									<?php
								} elseif ( ! is_plugin_active( $plugin_id ) ) {
									?>
                                    <a href="<?php echo esc_url( wp_nonce_url( add_query_arg( array(
										'action' => 'activate',
										'plugin' => $plugin_id
									), admin_url( 'plugins.php' ) ), "activate-plugin_{$plugin_id}" ) ) ?>"
                                       target="_blank"><?php esc_html_e( 'Activate', 'woo-alidropship' ); ?></a>
									<?php
								} else {
									esc_html_e( 'Currently active', 'woo-alidropship' );
								}
								?>
                            </div>
                        </td>
                        <td><?php echo esc_html( $plugin['desc'] ) ?></td>
                    </tr>
					<?php
				}
				?>
                </tbody>
            </table>
        </div>
		<?php
	}

	/**
	 * Register a custom menu page.
	 */
	public function menu_page() {
		add_submenu_page(
			'woo-alidropship-import-list',
			esc_html__( 'Recommended plugins for ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce', 'woo-alidropship' ),
			esc_html__( 'Recommended plugins', 'woo-alidropship' ),
			'manage_options',
			'woo-alidropship-recommend',
			array( $this, 'page_callback' )
		);
	}
}
PK     \c      api.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class VI_WOO_ALIDROPSHIP_Admin_API
 */
class VI_WOO_ALIDROPSHIP_Admin_API {
	protected $product_data;
	protected static $settings;
	protected static $orders_tracking_carriers;
	protected static $found_carriers;
	protected $process_description;
	protected $namespace;

	public function __construct() {
		self::$found_carriers = array(
			'url'      => array(),
			'carriers' => array(),
		);
		self::$settings       = VI_WOO_ALIDROPSHIP_DATA::get_instance();
		/*Namespace must be the same for both premium and free version as it's hardcoded in the chrome extension as permissions in manifest.json*/
		$this->namespace = 'woocommerce_aliexpress_dropship';

		add_action( 'rest_api_init', array( $this, 'register_api' ) );
		add_filter( 'woocommerce_rest_is_request_to_rest_api', array( $this, 'woocommerce_rest_is_request_to_rest_api' ) );
		add_filter( 'villatheme_woo_alidropship_sync_ali_order_carrier_url', array( $this, 'villatheme_woo_alidropship_sync_ali_order_carrier_url' ) );
	}

	public function woocommerce_rest_is_request_to_rest_api( $is_request_to_rest_api ) {
		$rest_prefix = trailingslashit( rest_get_url_prefix() );
		$request_uri = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) );
		if ( false !== strpos( $request_uri, $rest_prefix . "{$this->namespace}/" ) ) {
			$is_request_to_rest_api = true;
		}

		return $is_request_to_rest_api;
	}

	/**
	 * @param $url
	 *
	 * @return mixed
	 */
	public function villatheme_woo_alidropship_sync_ali_order_carrier_url( $url ) {
		$carrier_url_replaces = self::$settings->get_params( 'carrier_url_replaces' );
		if ( $url && isset( $carrier_url_replaces['to_string'] ) && is_array( $carrier_url_replaces['to_string'] ) && $str_replace_count = count( $carrier_url_replaces['to_string'] ) ) {
			for ( $i = 0; $i < $str_replace_count; $i ++ ) {
				if ( false !== stripos( $url, $carrier_url_replaces['from_string'][ $i ] ) ) {
					$url = $carrier_url_replaces['to_string'][ $i ];
					add_filter( 'villatheme_woo_alidropship_sync_ali_order_carrier_name', array(
						$this,
						'villatheme_woo_alidropship_sync_ali_order_carrier_name'
					) );
					break;
				}
			}
		}

		return $url;
	}

	/**
	 * @param $name
	 *
	 * @return mixed
	 */
	public function villatheme_woo_alidropship_sync_ali_order_carrier_name( $name ) {
		$carrier_name_replaces = self::$settings->get_params( 'carrier_name_replaces' );
		if ( $name && isset( $carrier_name_replaces['to_string'] ) && is_array( $carrier_name_replaces['to_string'] ) && $str_replace_count = count( $carrier_name_replaces['to_string'] ) ) {
			for ( $i = 0; $i < $str_replace_count; $i ++ ) {
				if ( $carrier_name_replaces['sensitive'][ $i ] ) {
					$name = str_replace( $carrier_name_replaces['from_string'][ $i ], $carrier_name_replaces['to_string'][ $i ], $name );
				} else {
					$name = str_ireplace( $carrier_name_replaces['from_string'][ $i ], $carrier_name_replaces['to_string'][ $i ], $name );
				}
			}
		}

		return $name;
	}

	public static function sort_by_product_id( $array1, $array2 ) {
		return $array1['productID'] - $array2['productID'];
	}

	/**
	 * Register API json
	 */
	public function register_api() {
		register_rest_route(
			$this->namespace, '/sync', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'sync_normal' ),
				'permission_callback' => '__return_true',
			)
		);
		register_rest_route(
			$this->namespace, '/get_product_sku', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'get_product_sku_normal' ),
				'permission_callback' => '__return_true',
			)
		);
//		register_rest_route(
//			$this->namespace, '/get_aliexpress_orders', array(
//				'methods'             => WP_REST_Server::CREATABLE,
//				'callback'            => array( $this, 'get_aliexpress_orders_normal' ),
//				'permission_callback' => '__return_true',
//			)
//		);
		register_rest_route(
			$this->namespace, '/get_orders_to_sync', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'get_orders_to_sync_normal' ),
				'permission_callback' => '__return_true',
			)
		);
		register_rest_route(
			$this->namespace, '/request_order', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'request_order_normal' ),
				'permission_callback' => '__return_true',
			)
		);
		register_rest_route(
			$this->namespace, '/response_order', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'response_order_normal' ),
				'permission_callback' => '__return_true',
			)
		);
		register_rest_route(
			$this->namespace, '/sync_order', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'sync_order_normal' ),
				'permission_callback' => '__return_true',
			)
		);
		/*Auth method*/
		register_rest_route(
			$this->namespace, '/auth', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'auth' ),
				'permission_callback' => '__return_true',
			)
		);
		register_rest_route(
			$this->namespace, '/auth/sync', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'sync_auth' ),
				'permission_callback' => array( $this, 'permissions_check' ),
			)
		);

		register_rest_route(
			$this->namespace, '/auth/get_product_sku', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'get_product_sku_auth' ),
				'permission_callback' => array( $this, 'permissions_check' ),
			)
		);
//		register_rest_route(
//			$this->namespace, '/auth/get_aliexpress_orders', array(
//				'methods'             => WP_REST_Server::CREATABLE,
//				'callback'            => array( $this, 'get_aliexpress_orders_auth' ),
//				'permission_callback' => array( $this, 'permissions_check' ),
//			)
//		);
		register_rest_route(
			$this->namespace, '/auth/get_orders_to_sync', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'get_orders_to_sync_auth' ),
				'permission_callback' => array( $this, 'permissions_check_edit_orders' ),
			)
		);
		register_rest_route(
			$this->namespace, '/auth/request_order', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'request_order_auth' ),
				'permission_callback' => array( $this, 'permissions_check' ),
			)
		);
		register_rest_route(
			$this->namespace, '/auth/response_order', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'response_order_auth' ),
				'permission_callback' => array( $this, 'permissions_check' ),
			)
		);
		register_rest_route(
			$this->namespace, '/auth/sync_order', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'sync_order_auth' ),
				'permission_callback' => array( $this, 'permissions_check' ),
			)
		);
		register_rest_route(
			$this->namespace, '/auth/revoke_api_key', array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'revoke_api_key' ),
				'permission_callback' => array( $this, 'permissions_check' ),
			)
		);
	}

	/**
	 * @param $consumer_key
	 *
	 * @return array|object|null
	 */
	private function get_user_data_by_consumer_key( $consumer_key ) {
		global $wpdb;

		$consumer_key = wc_api_hash( sanitize_text_field( $consumer_key ) );
		$user         = $wpdb->get_row( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$wpdb->prepare(
				"
			SELECT key_id, user_id, permissions, consumer_key, consumer_secret, nonces
			FROM {$wpdb->prefix}woocommerce_api_keys
			WHERE consumer_key = %s
		",
				$consumer_key
			)
		);

		return $user;
	}

	/**
	 * @param $request WP_REST_Request
	 *
	 * @throws Exception
	 */
	public function revoke_api_key( $request ) {
		$this->validate( $request, false );
		$consumer_key    = sanitize_text_field( $request->get_param( 'consumer_key' ) );
		$consumer_secret = sanitize_text_field( $request->get_param( 'consumer_secret' ) );
		if ( ! $consumer_key ) {
			$authorization = $request->get_header( 'authorization' );
			if ( $authorization ) {
				$authorization = base64_decode( substr( $authorization, 6 ) );
				$consumer      = explode( ':', $authorization );
				if ( count( $consumer ) === 2 ) {
					$consumer_key    = $consumer[0];
					$consumer_secret = $consumer[1];
				}
			}
		}
		if ( ! $consumer_key && ! empty( $_SERVER['PHP_AUTH_USER'] ) ) {
			$consumer_key = sanitize_text_field( $_SERVER['PHP_AUTH_USER'] );
		}
		if ( ! $consumer_secret && ! empty( $_SERVER['PHP_AUTH_PW'] ) ) {
			$consumer_secret = sanitize_text_field( $_SERVER['PHP_AUTH_PW'] );
		}
		wp_send_json(
			array(
				'status' => 'success',
				'result' => self::revoke_woocommerce_api_key( $consumer_key, $consumer_secret ),
			)
		);
	}

	/**
	 * @param $consumer_key
	 * @param $consumer_secret
	 *
	 * @return bool|false|int
	 */
	public static function revoke_woocommerce_api_key( $consumer_key, $consumer_secret ) {
		global $wpdb;
		$consumer_key = wc_api_hash( sanitize_text_field( $consumer_key ) );

		return $wpdb->query(// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$wpdb->prepare(
				"
			DELETE FROM {$wpdb->prefix}woocommerce_api_keys
			WHERE consumer_key = %s AND consumer_secret=%s
		",
				$consumer_key, $consumer_secret
			)
		);
	}

	/**
	 * @param $request WP_REST_Request
	 *
	 * @return bool|WP_Error
	 */
	public function permissions_check( $request ) {
		if ( ! wc_rest_check_post_permissions( 'product', 'create' ) ) {
			return new WP_Error( 'woocommerce_rest_cannot_create', esc_html__( 'Unauthorized', 'woo-alidropship' ), array( 'status' => rest_authorization_required_code() ) );
		}

		return true;
	}

	public function permissions_check_edit_orders( $request ) {
		if ( ! wc_rest_check_post_permissions( 'shop_order', 'create' ) ) {
			return new WP_Error( 'woocommerce_rest_cannot_edit', esc_html__( 'Unauthorized', 'woo-alidropship' ), array( 'status' => rest_authorization_required_code() ) );
		}

		return true;
	}

	/**
	 * @param $request WP_REST_Request
	 */

	public function auth( $request ) {
		$consumer_key    = sanitize_text_field( $request->get_param( 'consumer_key' ) );
		$consumer_secret = sanitize_text_field( $request->get_param( 'consumer_secret' ) );
		if ( $consumer_key && $consumer_secret ) {
			$user = $this->get_user_data_by_consumer_key( $consumer_key );
			if ( $user && hash_equals( $user->consumer_secret, $consumer_secret ) ) {
				update_option( 'vi_wad_temp_api_credentials', $request->get_params() );
			}
		}
	}

	/**Validate request from chrome extension
	 *
	 * @param $request WP_REST_Request
	 * @param bool $check_key
	 */

	public function validate( $request, $check_key = true ) {
		$result = array(
			'status'       => 'error',
			'message'      => '',
			'message_type' => 1,
		);

		/*check ssl*/
		if ( ! is_ssl() ) {
			$result['message']      = esc_html__( 'SSL is required', 'woo-alidropship' );
			$result['message_type'] = 2;

			wp_send_json( $result );
		}
		/*check enable*/
		if ( ! self::$settings->get_params( 'enable' ) ) {
			$result['message']      = esc_html__( 'ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce plugin is currently disabled. Please enable it to use this function.', 'woo-alidropship' );
			$result['message_type'] = 2;

			wp_send_json( $result );
		}
		/*check key*/
		if ( $check_key ) {
			$key = $request->get_param( 'key' );
			if ( ! $key || $key !== self::$settings->get_params( 'secret_key' ) ) {
				$result['message']      = esc_html__( 'Secret key does not match', 'woo-alidropship' );
				$result['message_type'] = 2;

				wp_send_json( $result );
			}
		}
		$require_version = $request->get_param( 'require_version' );

		/*check version*/
		if ( version_compare( VI_WOO_ALIDROPSHIP_VERSION, $require_version, '<' ) ) {
			$result['message']      = sprintf( esc_html__( 'Require ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce plugin version %s, your current version is %s', 'woo-alidropship' ), $require_version ,VI_WOO_ALIDROPSHIP_VERSION);//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
			$result['message_type'] = 2;

			wp_send_json( $result );
		}

		$migrate_process = VI_WOO_ALIDROPSHIP_Admin_Migrate_New_Table::migrate_process();
		if ( ! $migrate_process->is_queue_empty() || $migrate_process->is_process_running() ) {
			$result['message']      = esc_html__( 'The migration process is currently running in the background. Please do not import at this time', 'woo-alidropship' );
			$result['message_type'] = 2;

			wp_send_json( $result );
		}
	}

	/**
	 * @param $request WP_REST_Request
	 *
	 * @throws Exception
	 */
	public function get_orders_to_sync_normal( $request ) {
		$this->validate( $request );
		$this->get_orders_to_sync( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 *
	 * @throws Exception
	 */
	public function get_orders_to_sync_auth( $request ) {
		$this->validate( $request, false );
		$this->get_orders_to_sync( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function get_orders_to_sync( $request ) {
		global $wpdb;
		$per_page = absint( $request->get_param( 'per_page' ) );
		if ( ! $per_page ) {
			$per_page = 10;
		}
		$current_page = absint( $request->get_param( 'current_page' ) );
		$total_page   = 1;
		$query        = "SELECT count(DISTINCT woocommerce_order_itemmeta.meta_value) FROM {$wpdb->prefix}woocommerce_order_itemmeta AS woocommerce_order_itemmeta WHERE (meta_key='_vi_wad_aliexpress_order_id' OR meta_key='_vi_wad_match_aliexpress_order_id') AND meta_value!=''";
		$total        = $wpdb->get_var( $query );// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		if ( $total > 0 ) {
			$total_page = ceil( $total / $per_page );
		}

		$query = "SELECT DISTINCT woocommerce_order_itemmeta.meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta AS woocommerce_order_itemmeta WHERE (meta_key='_vi_wad_aliexpress_order_id' OR meta_key='_vi_wad_match_aliexpress_order_id') AND meta_value!='' LIMIT %d,%d";

		$orders_ids = $wpdb->get_col( $wpdb->prepare( $query, array(// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$per_page * ( $current_page - 1 ),
			$per_page
		) ), 0 );

		$response = array(
			'status'       => 'success',
			'total_page'   => $total_page,
			'total_orders' => $total,
			'orders_ids'   => $orders_ids,
		);

		wp_send_json( $response );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function get_aliexpress_orders_normal( $request ) {
		$this->validate( $request );
		$this->get_aliexpress_orders( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function get_aliexpress_orders_auth( $request ) {
		$this->validate( $request, false );
		$this->get_aliexpress_orders( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function get_aliexpress_orders( $request ) {
		global $wpdb;
		$result = array(
			'status'  => 'success',
			'message' => '',
			'data'    => wp_json_encode( array() ),
		);
		vi_wad_set_time_limit();
		$query          = "Select DISTINCT woocommerce_order_itemmeta.meta_value from {$wpdb->prefix}woocommerce_order_itemmeta AS woocommerce_order_itemmeta where meta_key='_vi_wad_aliexpress_order_id' OR meta_key='_vi_wad_match_aliexpress_order_id'";
		$result['data'] = wp_json_encode( array_values( array_filter( $wpdb->get_col( $query, 0 ) ) ) );// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared , WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		wp_send_json( $result );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function sync_normal( $request ) {
		$this->validate( $request );
		$this->sync( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function sync_auth( $request ) {
		$this->validate( $request, false );
		$this->sync( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function sync( $request ) {
		$result = array(
			'status'       => 'error',
			'message'      => '',
			'message_type' => 1,
		);
		vi_wad_set_time_limit();
		$product_id   = $request->get_param( 'productID' );
		$product_html =  base64_decode( $request->get_param( 'ali_product_data' ) ) ;
		$data         = array();
		$country     = $request->get_param( 'country' );
		if ( $product_id ) {
			$language     = explode('_',$request->get_param( 'language' )?:'en')[0] ;
			$currency     = $request->get_param( 'currency' );
			$get_data = VI_WOO_ALIDROPSHIP_DATA::get_data( "https://www.aliexpress.com/item/{$product_id}.html", [], $product_html,false,[
				'product_id' => $product_id,
				'target_currency' => $currency,
				'ship_to_country' => $country,
				'target_language' => $language,
				'locale' => 'en_US',
				'domain'=>get_site_url(),
				'action' => 'import',
			] );

			if ( ! empty( $request->get_param( 'ru_product_description' ) ) && empty( $get_data['data']['description'] ) ) {
				$get_data['data']['description'] = base64_decode( $request->get_param( 'ru_product_description' ) );
			}

			if ( ! empty( $request->get_param( 'ru_product_characteristics' ) ) && empty( $get_data['data']['specsModule'] ) ) {
				$get_data['data']['specsModule'] = $request->get_param( 'ru_product_characteristics' );
			}

			if ( $get_data['status'] == 'success' ) {
				$data = $get_data['data'];
			} else {
				if ( $get_data['message'] ) {
					$result['message']      = $get_data['message'];
					$result['message_type'] = 2;
				} else {
					$result['message']      = esc_html__( 'Cannot retrieve data.', 'woo-alidropship' );
					$result['message_type'] = 'try_again';
				}
				wp_send_json( $result );
			}
		} else {
			$data = vi_wad_json_decode( $request->get_param( 'data' ) );
		}

		$freight     = !empty($get_data['freight']) ? $get_data['freight'] : $request->get_param( 'freight' );
		$time = time() ;
		if ($freight){
			if (is_array($freight)){
				$freight = self::$settings::adjust_ali_freight( $freight,$country ==='RU'? 'api_ru':'api' );
			}else{
				$tmp = vi_wad_json_decode($freight);
				$freight = self::$settings::adjust_ali_freight( $tmp, $country ==='RU'? 'api_ru':'' );
			}
		}
		if (empty($freight)){
			$freight = [];
			$time -= HOUR_IN_SECONDS;
		}
		$freight_ext = $request->get_param( 'freight_ext' );

		$shipping_info = array(
			'time'          => $time,
			'country'       => $request->get_param( 'country' ),
			'company'       => $request->get_param( 'company' ),
			'company_name'  => '',
			'freight'       => $freight,
			'freight_ext'   => $freight_ext,
			'shipping_cost' => null,
			'delivery_time' => '',
		);
		$this->add_to_import_list( $data, $shipping_info );
	}

	public function add_to_import_list( $data, $shipping_info ) {
		$result  = array(
			'status'       => 'error',
			'message'      => '',
			'message_type' => 1,
		);
		$sku     = isset( $data['sku'] ) ? sanitize_text_field( $data['sku'] ) : '';
		$post_id = VI_WOO_ALIDROPSHIP_DATA::product_get_id_by_aliexpress_id( $sku );
		if ( ! $post_id ) {
			$post_id = self::$settings->create_product( $data, $shipping_info );
			if ( is_wp_error( $post_id ) ) {
				$result['message'] = $post_id->get_error_message();
				wp_send_json( $result );
			} elseif ( ! $post_id ) {
				$result['message'] = esc_html__( 'Cannot create post', 'woo-alidropship' );
				wp_send_json( $result );
			}
			$result['status']  = 'success';
			$result['message'] = esc_html__( 'Product is added to import list', 'woo-alidropship' );
		} else {
			$result['message'] = esc_html__( 'Product exists', 'woo-alidropship' );
		}

		wp_send_json( $result );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function get_product_sku_normal( $request ) {
		$this->validate( $request );
		$this->get_product_sku( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function get_product_sku_auth( $request ) {
		$this->validate( $request, false );
		$this->get_product_sku( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function get_product_sku( $request ) {
		$result   = array(
			'status'  => 'success',
			'message' => '',
			'data'    => wp_json_encode( array() ),
		);
		$products = $request->get_param( 'products' );
		if ( $products && is_array( $products ) ) {
			vi_wad_set_time_limit();
			$args = array(
				'post_type'      => 'vi_wad_draft_product',
				'posts_per_page' => count( $products ),
				'orderby'        => 'meta_value_num',
				'order'          => 'ASC',
				'post_status'    => array(
					'publish',
					'draft',
					'override'
				),
				'fields'         => 'ids',
				'meta_query'     => array(// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
					'relation' => 'AND',
					array(
						'key'     => '_vi_wad_sku',
						'value'   => $products,
						'compare' => 'IN'
					)
				)
			);
//			$the_query = new WP_Query( $args );
			$the_query = VI_WOO_ALIDROPSHIP_DATA::is_ald_table() ? new Ali_Product_Query( $args ) : new WP_Query( $args );

			$imported = array();
			if ( $the_query->posts ) {
				foreach ( $the_query->posts as $id ) {
					$imported[] = Ali_Product_Table::get_post_meta( $id, '_vi_wad_sku', true );
				}
				$result['data'] = wp_json_encode( $imported );
			}
		}
		wp_send_json( $result );
	}

	/**
	 * @param $request WP_REST_Request
	 *
	 * @throws Exception
	 */
	public function response_order_normal( $request ) {
		$this->validate( $request );
		$this->response_order( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 *
	 * @throws Exception
	 */
	public function response_order_auth( $request ) {
		$this->validate( $request, false );
		$this->response_order( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 *
	 * @throws Exception
	 */
	public function response_order( $request ) {
		vi_wad_set_time_limit();
		$matchOrders = $request->get_param( 'matchOrders' );
		if ( is_array( $matchOrders ) && count( $matchOrders ) ) {
			$from_order_id = $request->get_param( 'fromOrderId' );
			$order         = wc_get_order( $from_order_id );
			if ( $from_order_id && $order ) {
				$order_items = $order->get_items();
				if ( count( $order_items ) ) {
					foreach ( $matchOrders as $matchOrder ) {
						$ali_order_id = $matchOrder['orderId'];
						$orderTotal   = $matchOrder['orderTotal'];
						if ( $orderTotal ) {
							$orderDetails = self::get_order_details( $orderTotal );
							VI_WOO_ALIDROPSHIP_Ali_Orders_Info_Table::insert( $ali_order_id, $orderDetails['currency'], $orderDetails['total'] );
						}
						$matchProductIds = array_unique( $matchOrder['matchProductIds'] );
						foreach ( $order_items as $item_id => $item ) {
							$product_id     = $item['product_id'];
							$ali_product_id = get_post_meta( $product_id, '_vi_wad_aliexpress_product_id', true );
							if ( in_array( $ali_product_id, $matchProductIds ) ) {
								$match_aliexpress_order_ids = wc_get_order_item_meta( $item_id, '_vi_wad_match_aliexpress_order_id', false );
								if ( ! in_array( $ali_order_id, $match_aliexpress_order_ids ) ) {
									wc_add_order_item_meta( $item_id, '_vi_wad_match_aliexpress_order_id', $ali_order_id );
								}
								if ( strtolower( trim( $matchOrder['orderStatus'] ) ) === 'wait_seller_send_goods' ) {
									wc_update_order_item_meta( $item_id, '_vi_wad_aliexpress_order_id', $ali_order_id );
								}
							}
						}
					}
				}
			}
			wp_send_json_success();
		} else {
			wp_send_json_error();
		}
	}

	/**Get order currency and order total
	 *
	 * @param $orderTotal
	 *
	 * @return array
	 */
	public static function get_order_details( $orderTotal ) {
		$orderTotal         = html_entity_decode( $orderTotal );
		$support_currencies = array( '$', '￡', '€', 'руб.', '￥', 'SEK' );
		$total              = $currency = '';
		foreach ( $support_currencies as $symbol ) {
			if ( strpos( $orderTotal, $symbol ) !== false ) {
				$orderTotalPatterns = explode( $symbol, $orderTotal );
				$orderTotalPatterns = array_map( 'trim', $orderTotalPatterns );
				switch ( $symbol ) {
					case '￡':
						$currency = 'GBP';
						$total    = trim( str_ireplace( array( $currency, $symbol ), array( '', '' ), $orderTotal ) );
						break;
					case '€':
						$currency = 'EUR';
						$total    = trim( str_ireplace( array( $currency, $symbol ), array( '', '' ), $orderTotal ) );
						break;
					case 'руб.':
						$currency = 'RUB';
						$total    = trim( str_ireplace( array( $currency, $symbol ), array( '', '' ), $orderTotal ) );
						break;
					case '￥':
						$currency = 'JPY';
						$total    = trim( str_ireplace( array( $currency, $symbol ), array( '', '' ), $orderTotal ) );
						break;
					case 'SEK':
						$currency = 'SEK';
						$total    = trim( str_ireplace( array( $currency, $symbol ), array( '', '' ), $orderTotal ) );
						break;
					case '$':
					default:
						$receiveCurrency = strtolower( $orderTotalPatterns[0] );
						if ( $receiveCurrency === 'au' ) {
							$currency = 'AUD';
							$total    = trim( str_ireplace( array( $currency, $symbol, 'au' ), array(
								'',
								'',
								''
							), $orderTotal ) );
						} elseif ( $receiveCurrency === 'us' ) {
							$currency = 'USD';
							$total    = trim( str_ireplace( array( $currency, $symbol, 'us' ), array(
								'',
								'',
								''
							), $orderTotal ) );
						} else {
							$currency = 'CAD';
							$total    = trim( str_ireplace( array( $currency, $symbol, 'ca' ), array(
								'',
								'',
								''
							), $orderTotal ) );
						}

				}
			}
		}
		$total = str_replace( ',', '.', $total );

		return array( 'total' => $total, 'currency' => $currency );
	}

	/**
	 * @param $ali_order_id
	 * @param $tracking_number
	 * @param $tracking_status
	 * @param $carrier_url
	 * @param $carrier_name
	 * @param $orderTotal
	 *
	 * @return array
	 * @throws Exception
	 */
	public function save_order_data( $ali_order_id, $tracking_number, $tracking_status, $carrier_url, $carrier_name, $orderTotal ) {
		$item_response = array(
			'status'       => 'error',
			'message'      => '',
			'ali_order_id' => $ali_order_id,
		);
		global $wpdb;
		$aliexpress_standard_shipping = false;
		if ( strtolower( trim( $carrier_name ) ) === 'aliexpress standard shipping' ) {
			$aliexpress_standard_shipping = true;
		} else {
			$carrier_url  = apply_filters( 'villatheme_woo_alidropship_sync_ali_order_carrier_url', $carrier_url );
			$carrier_name = apply_filters( 'villatheme_woo_alidropship_sync_ali_order_carrier_name', $carrier_name );
		}
		if ( $ali_order_id ) {
			$query          = $wpdb->prepare( "Select * from {$wpdb->prefix}woocommerce_order_itemmeta where meta_key='_vi_wad_aliexpress_order_id' and meta_value=%s", $ali_order_id );
			$q_result       = $wpdb->get_results( $query, ARRAY_A );// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared ,WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$order_item_ids = array();
			if ( count( $q_result ) ) {
				if ( $orderTotal ) {
					$orderDetails = self::get_order_details( $orderTotal );
					VI_WOO_ALIDROPSHIP_Ali_Orders_Info_Table::insert( $ali_order_id, $orderDetails['currency'], $orderDetails['total'] );
				}
				$item_response['status']  = 'success';
				$item_response['message'] = esc_html__( 'Order synced successfully', 'woo-alidropship' );
				foreach ( $q_result as $item ) {
					$order_item_id      = $item['order_item_id'];
					$order_item_ids[]   = $order_item_id;
					$item_tracking_data = wc_get_order_item_meta( $order_item_id, '_vi_wot_order_item_tracking_data', true );
					if ( $tracking_number ) {
						$current_tracking_data = array(
							'tracking_number' => '',
							'carrier_slug'    => '',
							'carrier_url'     => '',
							'carrier_name'    => '',
							'carrier_type'    => '',
							'time'            => time(),
						);
						if ( $item_tracking_data ) {
							$item_tracking_data = vi_wad_json_decode( $item_tracking_data );
							foreach ( $item_tracking_data as $order_tracking_data_k => $order_tracking_data_v ) {
								if ( $order_tracking_data_v['tracking_number'] == $tracking_number ) {
									$current_tracking_data = $order_tracking_data_v;
									unset( $item_tracking_data[ $order_tracking_data_k ] );
									break;
								}
							}
							$item_tracking_data = array_values( $item_tracking_data );
						} else {
							$item_tracking_data = array();
						}
						$current_tracking_data['tracking_number'] = $tracking_number;
						$found_carrier                            = $this->get_orders_tracking_carrier( $carrier_url, $carrier_name, $aliexpress_standard_shipping );
						if ( count( $found_carrier ) ) {
							$current_tracking_data['carrier_slug'] = $found_carrier['slug'];
							$current_tracking_data['carrier_url']  = $found_carrier['url'];
							$current_tracking_data['carrier_name'] = $found_carrier['name'];
						} else {
							$current_tracking_data['carrier_url']  = $carrier_url;
							$current_tracking_data['carrier_name'] = $carrier_name;
						}
						$item_tracking_data[] = $current_tracking_data;
						wc_update_order_item_meta( $order_item_id, '_vi_wot_order_item_tracking_data', wp_json_encode( $item_tracking_data ) );
					} else {
						$item_response['status']  = 'warning';
						$item_response['message'] = esc_html__( 'No tracking number', 'woo-alidropship' );
						if ( $item_tracking_data ) {
							$item_tracking_data    = vi_wad_json_decode( $item_tracking_data );
							$current_tracking_data = array_pop( $item_tracking_data );
							if ( $current_tracking_data['tracking_number'] ) {
								$item_tracking_data[] = array(
									'tracking_number' => '',
									'carrier_slug'    => '',
									'carrier_url'     => '',
									'carrier_name'    => '',
									'carrier_type'    => '',
									'time'            => time(),
								);
								wc_update_order_item_meta( $order_item_id, '_vi_wot_order_item_tracking_data', wp_json_encode( $item_tracking_data ) );
							}
						}
					}
					if ( in_array( strtolower( trim( $tracking_status ) ), array(
						'delivery successful',
						'delivered'
					), true ) ) {
						wc_update_order_item_meta( $order_item_id, '_vi_wad_aliexpress_order_item_status', 'shipped' );
					}
				}

			} else {
				$query    = $wpdb->prepare( "Select * from {$wpdb->prefix}woocommerce_order_itemmeta where meta_key='_vi_wad_match_aliexpress_order_id' and meta_value=%s", $ali_order_id );
				$q_result = $wpdb->get_results( $query, ARRAY_A );// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared , WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				if ( count( $q_result ) ) {
					if ( $orderTotal ) {
						$orderDetails = self::get_order_details( $orderTotal );
						VI_WOO_ALIDROPSHIP_Ali_Orders_Info_Table::insert( $ali_order_id, $orderDetails['currency'], $orderDetails['total'] );
					}
					foreach ( $q_result as $item ) {
						$order_item_id    = $item['order_item_id'];
						$order_item_ids[] = $order_item_id;
						if ( wc_update_order_item_meta( $order_item_id, '_vi_wad_aliexpress_order_id', $ali_order_id ) ) {
							wc_update_order_item_meta( $order_item_id, '_vi_wad_aliexpress_order_item_status', 'processing' );
							$item_response['status']  = 'success';
							$item_response['message'] = esc_html__( 'Order synced successfully', 'woo-alidropship' );
							$item_tracking_data       = wc_get_order_item_meta( $order_item_id, '_vi_wot_order_item_tracking_data', true );
							if ( $tracking_number ) {
								$current_tracking_data = array(
									'tracking_number' => '',
									'carrier_slug'    => '',
									'carrier_url'     => '',
									'carrier_name'    => '',
									'carrier_type'    => '',
									'time'            => time(),
								);
								if ( $item_tracking_data ) {
									$item_tracking_data = vi_wad_json_decode( $item_tracking_data );
									foreach ( $item_tracking_data as $order_tracking_data_k => $order_tracking_data_v ) {
										if ( $order_tracking_data_v['tracking_number'] == $tracking_number ) {
											$current_tracking_data = $order_tracking_data_v;
											unset( $item_tracking_data[ $order_tracking_data_k ] );
											break;
										}
									}
									$item_tracking_data = array_values( $item_tracking_data );
								} else {
									$item_tracking_data = array();
								}
								$current_tracking_data['tracking_number'] = $tracking_number;
								$found_carrier                            = $this->get_orders_tracking_carrier( $carrier_url, $carrier_name, $aliexpress_standard_shipping );
								if ( count( $found_carrier ) ) {
									$current_tracking_data['carrier_slug'] = $found_carrier['slug'];
									$current_tracking_data['carrier_url']  = $found_carrier['url'];
									$current_tracking_data['carrier_name'] = $found_carrier['name'];
								} else {
									$current_tracking_data['carrier_url']  = $carrier_url;
									$current_tracking_data['carrier_name'] = $carrier_name;
								}
								$item_tracking_data[] = $current_tracking_data;
								wc_update_order_item_meta( $order_item_id, '_vi_wot_order_item_tracking_data', wp_json_encode( $item_tracking_data ) );
							} else {
								$item_response['status']  = 'warning';
								$item_response['message'] = esc_html__( 'No tracking number', 'woo-alidropship' );
								if ( $item_tracking_data ) {
									$item_tracking_data    = vi_wad_json_decode( $item_tracking_data );
									$current_tracking_data = array_pop( $item_tracking_data );
									if ( $current_tracking_data['tracking_number'] ) {
										$item_tracking_data[] = array(
											'tracking_number' => '',
											'carrier_slug'    => '',
											'carrier_url'     => '',
											'carrier_name'    => '',
											'carrier_type'    => '',
											'time'            => time(),
										);
										wc_update_order_item_meta( $order_item_id, '_vi_wot_order_item_tracking_data', wp_json_encode( $item_tracking_data ) );
									}
								}
							}
							if ( in_array( strtolower( trim( $tracking_status ) ), array(
								'delivery successful',
								'delivered'
							), true ) ) {
								wc_update_order_item_meta( $order_item_id, '_vi_wad_aliexpress_order_item_status', 'shipped' );
							}
						}
					}
				} else {
					$item_response['status']  = 'error';
					$item_response['message'] = esc_html__( 'No matched order found', 'woo-alidropship' );
				}
			}

			if ( count( $order_item_ids ) ) {
				$this->change_order_status( $order_item_ids );
			}
		} else {
			$item_response['status']  = 'error';
			$item_response['message'] = esc_html__( 'No matched order found', 'woo-alidropship' );
		}

		return $item_response;
	}

	/**
	 * @param $request WP_REST_Request
	 *
	 * @throws Exception
	 */
	public function sync_order_normal( $request ) {
		$this->validate( $request );
		$this->sync_order( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 *
	 * @throws Exception
	 */
	public function sync_order_auth( $request ) {
		$this->validate( $request, false );
		$this->sync_order( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 *
	 * @throws Exception
	 */
	public function sync_order( $request ) {
		$result = array(
			'status'  => 'success',
			'message' => '',
			'data'    => array(),
			'stop'    => 0,
		);
		vi_wad_set_time_limit();
		$tracking_data_array = $request->get_param( 'tracking_data_array' );
		$response_array      = array();
		if ( is_array( $tracking_data_array ) && count( $tracking_data_array ) ) {
			foreach ( $tracking_data_array as $ali_tracking_item ) {
				$ali_order_id     = $ali_tracking_item['orderId'];
				$tracking_number  = $ali_tracking_item['tracking_number'];
				$tracking_status  = $ali_tracking_item['tracking_status'];
				$carrier_url      = apply_filters( 'villatheme_woo_alidropship_sync_ali_order_carrier_url', $ali_tracking_item['carrier_url'] );
				$carrier_name     = apply_filters( 'villatheme_woo_alidropship_sync_ali_order_carrier_name', $ali_tracking_item['carrier_name'] );
				$orderTotal       = $ali_tracking_item['orderTotal'];
				$item_response    = $this->save_order_data( $ali_order_id, $tracking_number, $tracking_status, $carrier_url, $carrier_name, $orderTotal );
				$response_array[] = $item_response;
			}
			$result['data'] = $response_array;
		} else {
			$ali_order_id      = $request->get_param( 'orderId' );
			$tracking_number   = $request->get_param( 'tracking_number' );
			$tracking_status   = $request->get_param( 'tracking_status' );
			$carrier_url       = $request->get_param( 'carrier_url' );
			$carrier_name      = $request->get_param( 'carrier_name' );
			$orderTotal        = $request->get_param( 'orderTotal' );
			$item_response     = $this->save_order_data( $ali_order_id, $tracking_number, $tracking_status, $carrier_url, $carrier_name, $orderTotal );
			$result['status']  = $item_response['status'];
			$result['message'] = $item_response['message'];
		}
		wp_send_json( $result );
	}

	/**
	 * @param $order_item_ids
	 *
	 * @throws Exception
	 */
	public function change_order_status( $order_item_ids ) {
		$status = self::$settings->get_params( 'order_status_after_sync' );
		if ( in_array( $status, array_keys( wc_get_order_statuses() ) ) ) {
			$order_ids = array_unique( array_map( 'wc_get_order_id_by_order_item_id', $order_item_ids ) );
			foreach ( $order_ids as $order_id ) {
				$order                 = wc_get_order( $order_id );
				$items                 = $order->get_items();
				$sum_ali_order_id      = 0;
				$sum_ali_tracking_code = 0;
				foreach ( $items as $item_id => $item ) {
					$ali_order_id       = $item->get_meta( '_vi_wad_aliexpress_order_id' );
					$item_tracking_data = wc_get_order_item_meta( $item_id, '_vi_wot_order_item_tracking_data', true );
					if ( $item_tracking_data ) {
						$item_tracking_data    = vi_wad_json_decode( $item_tracking_data );
						$current_tracking_data = array_pop( $item_tracking_data );
						if ( $current_tracking_data['tracking_number'] ) {
							$sum_ali_tracking_code ++;
						}
					}
					if ( $ali_order_id ) {
						$sum_ali_order_id ++;
					}
				}

				if ( $sum_ali_order_id && $sum_ali_tracking_code === $sum_ali_order_id ) {
					$order->update_status( $status );
				}
			}
		}
	}

	/**
	 * @param $carrier_url
	 * @param string $carrier_name
	 * @param bool $aliexpress_standard_shipping
	 *
	 * @return array|mixed
	 */
	public function get_orders_tracking_carrier( $carrier_url, $carrier_name = '', $aliexpress_standard_shipping = false ) {
		$return_carrier = array();
		if ( $aliexpress_standard_shipping ) {
			if ( class_exists( 'VI_WOO_ORDERS_TRACKING_DATA' ) || class_exists( 'VI_WOOCOMMERCE_ORDERS_TRACKING_DATA' ) ) {
				$return_carrier = array(
					'name'               => 'Aliexpress Standard Shipping',
					'slug'               => 'aliexpress-standard-shipping',
					'url'                => 'https://global.cainiao.com/detail.htm?mailNoList={tracking_number}',
					'country'            => 'Global',
					'active'             => '',
					'tracking_more_slug' => 'cainiao',
				);
			}
		} else {
			if ( $carrier_url ) {
				if ( self::$orders_tracking_carriers !== array() ) {
					$search_carrier = array_search( $carrier_url, self::$found_carriers['url'] );
					if ( false !== $search_carrier ) {
						$return_carrier = self::$found_carriers['carriers'][ $search_carrier ];
					} else {
						$original_url = $carrier_url;
						$carrier_url  = VI_WOO_ALIDROPSHIP_DATA::get_domain_from_url( $carrier_url );
						if ( self::$orders_tracking_carriers === null ) {
							if ( class_exists( 'VI_WOO_ORDERS_TRACKING_DATA' ) ) {
								$orders_tracking_data = new VI_WOO_ORDERS_TRACKING_DATA();
								$carriers_array       = VI_WOO_ORDERS_TRACKING_DATA::shipping_carriers();
								$custom_carriers      = $orders_tracking_data->get_params( 'custom_carriers_list' );
								if ( $custom_carriers ) {
									$carriers_array = array_merge( $carriers_array, vi_wad_json_decode( $custom_carriers ) );
								}
								self::$orders_tracking_carriers = $carriers_array;
							} elseif ( class_exists( 'VI_WOOCOMMERCE_ORDERS_TRACKING_DATA' ) ) {
								$orders_tracking_data = new VI_WOOCOMMERCE_ORDERS_TRACKING_DATA();
								$carriers_array       = VI_WOOCOMMERCE_ORDERS_TRACKING_DATA::shipping_carriers();
								$custom_carriers      = $orders_tracking_data->get_params( 'custom_carriers_list' );
								if ( $custom_carriers ) {
									$carriers_array = array_merge( $carriers_array, vi_wad_json_decode( $custom_carriers ) );
								}
								self::$orders_tracking_carriers = $carriers_array;
							} else {
								self::$orders_tracking_carriers = array();
							}
						}

						if ( count( self::$orders_tracking_carriers ) ) {
							$found = false;
							foreach ( self::$orders_tracking_carriers as $carrier ) {
								$existing_url = VI_WOO_ALIDROPSHIP_DATA::get_domain_from_url( $carrier['url'] );
								if ( $carrier_url === $existing_url ) {
									$return_carrier                     = $carrier;
									self::$found_carriers['url'][]      = $original_url;
									self::$found_carriers['carriers'][] = $carrier;
									$found                              = true;
									break;
								}
							}
							if ( ! $found ) {
								self::$found_carriers['url'][] = $original_url;
								if ( class_exists( 'VI_WOO_ORDERS_TRACKING_DATA' ) ) {
									$orders_tracking_data = new VI_WOO_ORDERS_TRACKING_DATA();
								} elseif ( class_exists( 'VI_WOOCOMMERCE_ORDERS_TRACKING_DATA' ) ) {
									$orders_tracking_data = new VI_WOOCOMMERCE_ORDERS_TRACKING_DATA();
								}
								if ( isset( $orders_tracking_data ) ) {
									if ( ! $carrier_name ) {
										$carrier_name = $carrier_url;
									}
									$orders_tracking_options = $orders_tracking_data->get_params();
									$custom_carriers         = $orders_tracking_data->get_params( 'custom_carriers_list' );
									if ( $custom_carriers ) {
										$custom_carriers = vi_wad_json_decode( $custom_carriers );
									} else {
										$custom_carriers = array();
									}
									$custom_carrier                                  = array(
										'name'    => $carrier_name,
										'slug'    => 'custom_' . time(),
										'url'     => $original_url,
										'country' => 'GLOBAL',
										'type'    => 'custom',
									);
									$custom_carriers[]                               = $custom_carrier;
									$return_carrier                                  = $custom_carrier;
									self::$orders_tracking_carriers[]                = $custom_carrier;
									$orders_tracking_options['custom_carriers_list'] = wp_json_encode( $custom_carriers );
									update_option( 'woo_orders_tracking_settings', $orders_tracking_options );
									self::$found_carriers['carriers'][] = $custom_carrier;
								} else {
									self::$found_carriers['carriers'][] = array();
								}
							}
						}
					}
				}
			}
		}

		return $return_carrier;
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function request_order_normal( $request ) {
		$this->validate( $request );
		$this->request_order( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function request_order_auth( $request ) {
		$this->validate( $request, false );
		$this->request_order( $request );
	}

	/**
	 * @param $request WP_REST_Request
	 */
	public function request_order( $request ) {
		$result = array(
			'status'  => 'error',
			'message' => esc_html__( 'Order not found', 'woo-alidropship' ),
		);
		vi_wad_set_time_limit();
		$order_id = $request->get_param( 'order_id' );
		$order    = wc_get_order( $order_id );
		if ( $order ) {
			$result['message']                    = esc_html__( 'Success', 'woo-alidropship' );
			$result['status']                     = 'success';
			$result['order_info']                 = $this->get_order_info( $order );
			$result['customerInfo']               = self::get_customer_info( $order );
			$result['customerInfo']['carrier']    = self::$settings->get_params( 'fulfill_default_carrier' );
			$result['customerInfo']['order_note'] = self::$settings->get_params( 'fulfill_order_note' );
		}
		wp_send_json( $result );
	}

	/**
	 * @param $order WC_Order
	 *
	 * @return array
	 */
	public function get_order_info( $order ) {
		$result     = array();
		$list_items = $order->get_items();
		foreach ( $list_items as $item_id => $item ) {
			if ( $item->get_meta( '_vi_wad_aliexpress_order_id' ) ) {
				continue;
			}
			$pid     = $item->get_product_id();
			$vid     = $item->get_variation_id();
			$qty     = $item->get_quantity() + $order->get_qty_refunded_for_item( $item_id );
			$ali_pid = get_post_meta( $pid, '_vi_wad_aliexpress_product_id', true );

			if ( $ali_pid ) {
				$title = get_the_title( $pid );
				if ( $vid ) {
					$title    = get_the_title( $vid );
					$ali_vid  = get_post_meta( $vid, '_vi_wad_aliexpress_variation_id', true );
					$sku_attr = get_post_meta( $vid, '_vi_wad_aliexpress_variation_attr', true );
				} else {
					$ali_vid  = get_post_meta( $pid, '_vi_wad_aliexpress_variation_id', true );
					$sku_attr = get_post_meta( $pid, '_vi_wad_aliexpress_variation_attr', true );
				}
				$shipping_company = '';
				$shipping_info    = get_post_meta( $pid, '_vi_wad_shipping_info', true );
				if ( ! empty( $shipping_info['company'] ) ) {
					$shipping_company = $shipping_info['company'];
				}
				$item_exists = false;
				foreach ( $result as &$re ) {
					if ( $re['productID'] == $ali_pid && $re['skuID'] == $ali_vid && $re['skuAttr'] == $sku_attr ) {
						$re['quantity'] += $qty;
						$item_exists    = true;
						break;
					}
				}
				if ( ! $item_exists ) {
					$result[] = array(
						'productID'       => $ali_pid,
						'skuID'           => $ali_vid,
						'skuAttr'         => $sku_attr,
						'quantity'        => $qty,
						'title'           => $title,
						'shippingCompany' => $shipping_company,
					);
				}
			}
		}

//		uasort( $result, array( $this, 'sort_by_product_id' ) );

		return $result;
	}

	/**
	 * @param $order WC_Order
	 *
	 * @return array
	 */
	public static function get_customer_info( $order ) {
		$shipping_country = $order->get_shipping_country();
		$billing_country  = $order->get_billing_country();
		$address_number   = $neighborhood = '';
		if ( $order->has_shipping_address() ) {
			$state_code              = $order->get_shipping_state();
			$city                    = $order->get_shipping_city();
			$address1                = $order->get_shipping_address_1();
			$address2                = $order->get_shipping_address_2();
			$post_code               = $order->get_shipping_postcode();
			$billing_number_meta_key = self::$settings->get_params( 'billing_number_meta_key' );
			if ( $billing_number_meta_key ) {
				$address_number = $order->get_meta( $billing_number_meta_key );
			}
			$billing_neighborhood_meta_key = self::$settings->get_params( 'billing_neighborhood_meta_key' );
			if ( $billing_neighborhood_meta_key ) {
				$neighborhood = $order->get_meta( $billing_neighborhood_meta_key );
			}
		} else {
			$state_code               = $order->get_billing_state();
			$city                     = $order->get_billing_city();
			$address1                 = $order->get_billing_address_1();
			$address2                 = $order->get_billing_address_2();
			$post_code                = $order->get_billing_postcode();
			$shipping_number_meta_key = self::$settings->get_params( 'shipping_number_meta_key' );
			if ( $shipping_number_meta_key ) {
				$address_number = $order->get_meta( $shipping_number_meta_key );
			}
			$shipping_neighborhood_meta_key = self::$settings->get_params( 'shipping_neighborhood_meta_key' );
			if ( $shipping_neighborhood_meta_key ) {
				$neighborhood = $order->get_meta( $shipping_neighborhood_meta_key );
			}
		}
		$woo_country           = $shipping_country ? $shipping_country : $billing_country;
		$country               = self::filter_country( $woo_country );
		$countries             = VI_WOO_ALIDROPSHIP_DATA::get_countries();
		$country_name          = isset( $countries[ $country ] ) ? $countries[ $country ] : '';
		$phone_country         = self::get_phone_country_code( $country );
		$phone                 = $order->get_billing_phone();
		$default_phone_number  = self::$settings->get_params( 'fulfill_default_phone_number' );
		$default_phone_country = self::$settings->get_params( 'fulfill_default_phone_country' );
		if ( $phone && ( ! self::$settings->get_params( 'fulfill_default_phone_number_override' ) || ! $default_phone_number || $country !== $default_phone_country ) ) {
			$phone = str_replace( $phone_country, '', $phone );
			if ( ! $phone_country ) {
				$phone_country = WC()->countries->get_country_calling_code( $woo_country );
			}
		} else {
			$phone = $default_phone_number;
			if ( $default_phone_country ) {
				$phone_country = self::get_phone_country_code( $default_phone_country );
			}
		}
		$states = VI_WOO_ALIDROPSHIP_DATA::get_states( $woo_country );
		$name   = trim( $order->get_formatted_shipping_full_name() );
		if ( ! $name ) {
			$name = trim( $order->get_formatted_billing_full_name() );
		}
		if ( ! $name ) {
			$user = $order->get_user();
			if ( $user ) {
				if ( ! empty( $user->display_name ) ) {
					$name = $user->display_name;
				} elseif ( ! empty( $user->user_nicename ) ) {
					$name = $user->user_nicename;
				} elseif ( ! empty( $user->user_login ) ) {
					$name = $user->user_login;
				}
			}
		}
		
		if ( $state_code ) {
			$state      = isset( $states[ $state_code ] ) ? $states[ $state_code ] : $state_code;
			$ali_states = VI_WOO_ALIDROPSHIP_DATA::get_state( $country );
			if ( count( $ali_states ) ) {
				$address_ = array();

				$search      = VI_WOO_ALIDROPSHIP_DATA::strtolower( $state );
				$search_1    = array( $search, remove_accents( $search ) );
				$found_state = false;
				foreach ( $ali_states['addressList'] as $key => $value ) {
					if ( in_array( VI_WOO_ALIDROPSHIP_DATA::strtolower( $value['n'] ), $search_1, true ) ) {
						$found_state = $key;
						$state       = $value['n'];
						break;
					}
				}
				if ( $found_state === false ) {
					if ( array_search( 'Other', array_column( $ali_states['addressList'], 'n' ) ) !== false ) {
						if ( $state_code ) {
							array_push( $address_, $state );
						}
						$state = 'Other';
					}
				} else {
					if ( isset( $ali_states['addressList'][ $found_state ]['children'] ) && is_array( $ali_states['addressList'][ $found_state ]['children'] ) && count( $ali_states['addressList'][ $found_state ]['children'] ) ) {
						$found_city = false;
						if ( $city ) {
							$search   = VI_WOO_ALIDROPSHIP_DATA::strtolower( $city );
							$search_1 = array( $search, remove_accents( $search ) );
							foreach ( $ali_states['addressList'][ $found_state ]['children'] as $key => $value ) {
								if ( in_array( VI_WOO_ALIDROPSHIP_DATA::strtolower( $value['n'] ), $search_1, true ) ) {
									$found_city = $key;
									$city       = $value['n'];
									break;
								}
							}
						}
						if ( $found_city === false ) {
							$city = ucwords( remove_accents( $city ) );
							if ( array_search( 'Other', array_column( $ali_states['addressList'][ $found_state ]['children'], 'n' ) ) !== false ) {
								array_push( $address_, $city );
								$city = 'Other';
							}
						}
					} else {
						$city = ucwords( remove_accents( $city ) );
					}
				}
				if ( count( $address_ ) ) {
					if ( $address1 ) {
						$address1 = implode( ', ', array_merge( array( $address1 ), $address_ ) );
					}
					if ( $address2 ) {
						$address2 = implode( ', ', array_merge( array( $address2 ), $address_ ) );
					}
				}
			} else {
				$state = isset( $states[ $state_code ] ) ? remove_accents( $states[ $state_code ] ) : ( self::country_support_city_other( $country ) ? 'Other' : $city );
				$city  = ucwords( remove_accents( $city ) );
			}
		} else {
			if ( self::country_support_city_other( $country ) ) {
				$state = 'Other';
			} else {
				$state = $city;
			}
		}

		$result = array(
			'name'         => remove_accents( $name ),
			'fname'        => remove_accents( $order->get_shipping_first_name() ),
			'lname'        => remove_accents( $order->get_shipping_last_name() ),
			'phone'        => VI_WOO_ALIDROPSHIP_DATA::sanitize_phone_number( $phone ),
			'street'       => remove_accents( $address1 ),
			'address2'     => remove_accents( $address2 ),
			'city'         => $city,
			'state_code'   => remove_accents( $state_code ),
			'state'        => $state,
			'country'      => $country,
			'countryName'  => $country_name,
			'postcode'     => $post_code,
			'phoneCountry' => $phone_country,
			'cpf'          => '',
			'rutNo'        => '',
            'passportNo'          => '',
            'fromOrderId'  => $order->get_id()
		);

		if ( $country === 'BR' ) {
			$result['cpf'] = $order->get_shipping_company();
			if ( ! $result['cpf'] ) {
				$result['cpf'] = $order->get_billing_company();
			}
			$cpf_custom_meta_key = self::$settings->get_params( 'cpf_custom_meta_key' );
			if ( $cpf_custom_meta_key ) {
				$cpf_custom_meta = $order->get_meta( $cpf_custom_meta_key );
				if ( $cpf_custom_meta ) {
					$result['cpf'] = $cpf_custom_meta;
				}
			}
		}
		if ( $country === 'CL' ) {
			$rut_meta_key = self::$settings->get_params( 'rut_meta_key' );
			if ( $rut_meta_key ) {
				$rut = $order->get_meta( $rut_meta_key );
				if ( $rut ) {
					$result['rutNo'] = substr( $rut, 0, 12 );
				}
			}
		}
        /*add RFC/CURP for Mexico*/
        if ($country === 'MX') {
            $rfc_curp_meta_key = self::$settings->get_params('rfc_curp_meta_key');
            if ($rfc_curp_meta_key) {
//				$rfc_curp = get_post_meta( $order->get_id(), 'rfc_curp_meta_key', true );
                $rfc_curp = $order->get_meta($rfc_curp_meta_key);
                if ($rfc_curp) {
                    $result['passportNo'] = trim($rfc_curp);
                }
            }
        }
		if ( $address_number ) {
			$result['street'] = "{$result['street']}, {$address_number}";
		}

		if ( $neighborhood ) {
			$neighborhood = remove_accents( $neighborhood );
			if ( $result['address2'] ) {
				$result['street']   = "{$result['street']}, {$result['address2']}";
				$result['address2'] = '';
			}
			$result['street'] = "{$result['street']}, {$neighborhood}";
		}
		if ( $result['cpf'] ) {
			$result['cpf'] = substr( VI_WOO_ALIDROPSHIP_DATA::sanitize_phone_number( $result['cpf'] ), 0, 11 );
		}

		return apply_filters( 'vi_wad_fulfillment_customer_info', $result, $order );
	}

	public static function filter_country( $country ) {
		switch ( $country ) {
			case 'AQ':
			case 'BV':
			case 'IO':
			case 'CU':
			case 'TF':
			case 'HM':
			case 'IR':
			case 'IM':
			case 'SH':
			case 'PN':
			case 'SD':
			case 'SJ':
			case 'SY':
			case 'TK':
			case 'UM':
			case 'EH':
				$country = 'OTHER';
				break;
			case 'AX':
				$country = 'ALA';
				break;
			case 'CN':
				$country = 'HK';
				break;
			case 'CD':
				$country = 'ZR';
				break;
			case 'GG':
				$country = 'GGY';
				break;
			case 'JE':
				$country = 'JEY';
				break;
			case 'ME':
				$country = 'MNE';
				break;
			case 'KP':
				$country = 'KR';
				break;
			case 'BL':
				$country = 'BLM';
				break;
			case 'MF':
				$country = 'MAF';
				break;
			case 'RS':
				$country = 'SRB';
				break;
			case 'GS':
				$country = 'SGS';
				break;
			case 'TL':
				$country = 'TLS';
				break;
			case 'GB':
				$country = 'UK';
				break;
			default:
		}

		return $country;
	}

	private static function country_support_city_other( $country_code ) {
		return in_array( $country_code, array(
			'BR',
			'CL',
			'CZ',
			'FR',
			'IN',
			'ID',
			'IT',
			'KZ',
			'KR',
			'NL',
			'NZ',
			'PL',
			'RU',
			'SA',
			'ES',
			'TR',
			'UA',
			'UK',
			'US',
			'TH',
			'PE',
			'DE',
			'NG',
			'CO',
			'JP',
			'MA',
			'AE',
			'LK',
			'VN',
			'PK',
			'AU',
			'AT',
			'MY',
			'IL',
			'PT',
			'BE',
		) );
	}

	public static function get_phone_country_code( $country = '' ) {
		$map = '{"VU":"+678","EC":"+593","VN":"+84","VI":"","DZ":"+213","VG":"+1 (284)","DM":"+1 (767)","VE":"+58","DO":"+1 (8)","VC":"+1 (784)","VA":"+39 (066)","DE":"+49","UZ":"+998","UY":"+598","DK":"+45","DJ":"+253","US":"+1","UM":"","UG":"+256","UA":"+380","ET":"+251","ES":"+34","ER":"+291","EH":"+212","EG":"+20","TZ":"+255","EE":"+372","TT":"+1 (868)","TV":"+688","GD":"+1 (473)","GE":"+995","GF":"+594","GA":"+241","ASC":"","GB":"+44","FR":"+33","FO":"+298","FK":"+500","FJ":"+679","FM":"+691","FI":"+358","WS":"+685","GY":"+592","GW":"+245","GU":"","GT":"+502","GR":"+30","GQ":"+240","WF":"+681","GP":"+590","GN":"+224","GM":"+220","GL":"+299","GI":"+350","GH":"+233","GG":"+44","RE":"+262","RO":"+40","AT":"+43","AS":"","AR":"+54","AQ":"","AX":"","AW":"+297","QA":"+974","AU":"+61","AZ":"+994","BA":"+387","PT":"+351","AD":"+376","PW":"+680","AG":"+1 (268)","PR":"+1","AE":"+971","PS":"","AF":"","AL":"+355","AI":"","AO":"+244","PY":"+595","AM":"+374","AN":"","TG":"+228","BW":"+267","TF":"","BV":"","BY":"+375","TD":"+235","BS":"+1 (242)","TK":"","TJ":"+992","BR":"+55","TH":"+66","BT":"+975","TO":"+676","TN":"+216","TM":"+993","CA":"+1","TL":"+670","BZ":"+501","TR":"+90","BF":"+226","SV":"+503","BG":"+359","SS":"+211","BH":"+973","ST":"+239","BI":"+257","SY":"+963","BB":"+1 (246)","SZ":"+268","BD":"+880","SX":"+590","BE":"+32","BN":"+673","BO":"+591","BQ":"","BJ":"+229","TC":"+1 (649)","BL":"","BM":"+1 (441)","CZ":"+420","SD":"+249","CY":"+357","SC":"+248","CX":"","CW":"","SE":"+46","CV":"+238","SH":"","CU":"+53","SG":"+65","SJ":"+47","SI":"+386","SL":"+232","SK":"+421","SN":"+221","SM":"+378","SO":"+252","SGS":"","SR":"+597","CI":"+225","RS":"+381","CG":"+242","CH":"+41","RU":"+7","CF":"+236","RW":"+250","CC":"","CD":"+243","CR":"+506","CO":"+57","CM":"+237","CN":"+86","CK":"","SA":"+966","CL":"+56","SB":"+677","LV":"+371","LU":"+352","LT":"+370","LY":"+218","LS":"+266","LR":"+231","MG":"+261","MH":"+692","ME":"+382","MF":"","MK":"+389","ML":"+223","MC":"+377","MD":"+373","MA":"+212","MV":"+960","MU":"+230","MX":"+52","MW":"+265","MZ":"+258","MY":"+60","MN":"+976","MM":"+95","MP":"","MR":"+222","MQ":"+596","MT":"+356","MS":"","NF":"","NG":"+234","NI":"+505","NL":"+31","NA":"+264","NC":"+687","NE":"+227","NZ":"+64","NU":"","NR":"+674","NP":"+977","NO":"+47","OM":"+968","PL":"+48","PM":"+508","PN":"","PH":"+63","PK":"+92","PE":"+51","PF":"+689","PG":"+675","PA":"+507","ZA":"+27","HN":"+504","HM":"","HR":"+385","EAZ":"","HT":"+509","HU":"+36","ZM":"+260","ID":"+62","ZW":"+263","IE":"+353","IL":"+972","IM":"+44","IN":"+91","IO":"","IQ":"+964","IR":"+98","YE":"+967","IS":"+354","IT":"+39","JE":"+44","YT":"+262","JP":"+81","JO":"+962","JM":"+1 (876)","KI":"+686","KH":"","KG":"+996","KE":"+254","GBA":"","KP":"+850","KR":"+82","KM":"+269","KN":"+1 (869)","KW":"+965","KY":"+1 (345)","KZ":"+77","KS":"","LA":"+856","LC":"+1 (758)","LB":"+961","LI":"+423","LK":"+94"}';
		$map = vi_wad_json_decode( $map );
		if ( $country ) {
			return isset( $map[ $country ] ) ? $map[ $country ] : '';
		} else {
			return $map;
		}
	}
}PK     \ X  X    auth.phpnu [        <?php
if (!defined('ABSPATH')) {
    exit;
}

class VI_WOO_ALIDROPSHIP_Admin_Auth {
    protected $settings;

    public function __construct() {
        $this->settings = VI_WOO_ALIDROPSHIP_DATA::get_instance();
        add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
        add_action('admin_menu', array($this, 'admin_menu'), 20);
//        add_filter('woocommerce_locate_template', array($this, 'woocommerce_locate_template'), 10, 3);
        add_filter( 'woocommerce_api_permissions_in_scope', array( $this, 'extension_permissions' ), PHP_INT_MAX, 2 );
    }

    private static function set( $name, $set_name = false ) {
        return VI_WOO_ALIDROPSHIP_DATA::set($name, $set_name);
    }

    public function admin_menu() {
        /*Menu slug must be the same as pro version*/
        add_submenu_page('',
            esc_html__('Auth', 'woo-alidropship'),
            esc_html__('Auth', 'woo-alidropship'),
            'manage_options',
            'vi-woocommerce-alidropship-auth',
            array($this, 'page_callback')
        );
    }

    public function page_callback() {
        $api_credentials = get_option('vi_wad_temp_api_credentials', array());
        ?>
        <div class="wrap">
            <h2><?php esc_html_e('Authorize WooCommerce AliExpress Dropshipping Extension', 'woo-alidropship') ?></h2>
            <?php
            if (!empty($api_credentials['consumer_key']) && !empty($api_credentials['consumer_secret'])) {
                ?>
                <form method="post" class="<?php echo esc_attr(self::set('auth-form')) ?>">
                    <input type="hidden" value="<?php echo esc_attr($api_credentials['consumer_key']) ?>"
                           name="vi_wad_consumer_key">
                    <input type="hidden" value="<?php echo esc_attr($api_credentials['consumer_secret']) ?>"
                           name="vi_wad_consumer_secret">
                </form>
                <?php
            }
            ?>
        </div>
        <?php
        delete_option('vi_wad_temp_api_credentials');
    }
    public function extension_permissions( $permissions, $scope ) {
        if ( ( wc_clean(wp_unslash($_REQUEST['app_name']??'')) === 'WooCommerce AliExpress Dropshipping Extension' ) && $scope === 'read_write' ) {// phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $permissions = [
                    esc_html__( 'Import and sync AliExpress products','woo-alidropship' ),
                    esc_html__( 'Get orders data to fulfill AliExpress orders', 'woo-alidropship' ),
                    esc_html__( 'Sync your WooCommerce orders with AliExpress orders', 'woo-alidropship' ),
            ];
        }

        return $permissions;
    }

    public function enqueue_semantic() {
        wp_dequeue_style('eopa-admin-css');
        /*Stylesheet*/
        wp_enqueue_style('vi-woocommerce-alidropship-form', VI_WOO_ALIDROPSHIP_CSS . 'form.min.css', [], VI_WOO_ALIDROPSHIP_VERSION);
        wp_enqueue_style('vi-woocommerce-alidropship-table', VI_WOO_ALIDROPSHIP_CSS . 'table.min.css', [], VI_WOO_ALIDROPSHIP_VERSION);
        wp_enqueue_style('vi-woocommerce-alidropship-icon', VI_WOO_ALIDROPSHIP_CSS . 'icon.min.css', [], VI_WOO_ALIDROPSHIP_VERSION);
        wp_enqueue_style('vi-woocommerce-alidropship-segment', VI_WOO_ALIDROPSHIP_CSS . 'segment.min.css', [], VI_WOO_ALIDROPSHIP_VERSION);
        wp_enqueue_style('vi-woocommerce-alidropship-button', VI_WOO_ALIDROPSHIP_CSS . 'button.min.css', [], VI_WOO_ALIDROPSHIP_VERSION);
        wp_enqueue_style('select2', VI_WOO_ALIDROPSHIP_CSS . 'select2.min.css', [], VI_WOO_ALIDROPSHIP_VERSION);
        wp_enqueue_script('select2-v4', VI_WOO_ALIDROPSHIP_JS . 'select2.js', array('jquery'), '4.0.3', false);
    }

    public function bump_request_timeout( $val ) {
        return $this->settings->get_params('request_timeout');
    }

    public function admin_enqueue_scripts() {
        global $pagenow;
        $page = isset($_REQUEST['page']) ? wp_unslash(sanitize_text_field($_REQUEST['page'])) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if ($pagenow === 'admin.php' && $page === 'vi-woocommerce-alidropship-auth') {
            wp_enqueue_script('vi-woocommerce-alidropship-auth', VI_WOO_ALIDROPSHIP_JS . 'auth.js', array('jquery'), VI_WOO_ALIDROPSHIP_VERSION, false);
        }
    }

    public function woocommerce_locate_template( $template, $template_name, $template_path ) {
        global $woocommerce;

        $_template = $template;

        if (!$template_path) {
            $template_path = $woocommerce->template_url;
        }

        $plugin_path = VI_WOO_ALIDROPSHIP_DIR . '/templates/woocommerce/';

        // Look within passed path within the theme - this is priority
        $template = locate_template(

            array(
                $template_path . $template_name,
                $template_name
            )
        );

        // Modification: Get the template from this plugin, if it exists
        if (!$template && file_exists($plugin_path . $template_name)) {
            $template = $plugin_path . $template_name;
        }

        // Use default template
        if (!$template) {
            $template = $_template;
        }

        // Return what we found
        return $template;
    }
}

PK     \^  ^    imported.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class VI_WOO_ALIDROPSHIP_Admin_Imported
 */
class VI_WOO_ALIDROPSHIP_Admin_Imported {
	private static $settings;
	private $product_count;

	public function __construct() {
		self::$settings = VI_WOO_ALIDROPSHIP_DATA::get_instance();
		add_action( 'admin_init', array( $this, 'cancel_overriding' ) );
		add_action( 'admin_menu', array( $this, 'admin_menu' ), 11 );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 999999 );
		add_filter( 'set-screen-option', array( $this, 'save_screen_options' ), 10, 3 );
		add_action( 'wp_ajax_vi_wad_override_product', array( $this, 'override_product' ) );
		add_action( 'wp_ajax_vi_wad_trash_product', array( $this, 'trash' ) );
		add_action( 'wp_ajax_vi_wad_restore_product', array( $this, 'restore' ) );
		add_action( 'admin_head', array( $this, 'menu_product_count' ), 999 );
		add_action( 'wp_ajax_vi_wad_delete_product', array( $this, 'delete' ) );
	}

	public function delete() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		vi_wad_set_time_limit();
		$product_id         = isset( $_POST['product_id'] ) ? sanitize_text_field( $_POST['product_id'] ) : '';
		$woo_product_id     = isset( $_POST['woo_product_id'] ) ? sanitize_text_field( $_POST['woo_product_id'] ) : '';
		$delete_woo_product = isset( $_POST['delete_woo_product'] ) ? sanitize_text_field( $_POST['delete_woo_product'] ) : '';
		if ( $delete_woo_product != self::$settings->get_params( 'delete_woo_product' ) ) {
			$args                       = self::$settings->get_params();
			$args['delete_woo_product'] = $delete_woo_product;
			update_option( 'wooaliexpressdropship_params', $args );
		}
		$response = array(
			'status'  => 'success',
			'message' => '',
		);
		if ( $product_id ) {
			if ( Ali_Product_Table::get_post( $product_id ) ) {
				$delete = Ali_Product_Table::wp_delete_post( $product_id, true );
				if ( false === $delete ) {
					$response['status']  = 'error';
					$response['message'] = esc_html__( 'Can not delete product', 'woo-alidropship' );
				}
			}

			if ( $woo_product_id && get_post( $woo_product_id ) ) {
				delete_post_meta( $woo_product_id, '_vi_wad_aliexpress_product_id' );
				delete_post_meta( $woo_product_id, '_vi_wad_aliexpress_variation_attr' );
				delete_post_meta( $woo_product_id, '_vi_wad_aliexpress_variation_ship_from' );
				delete_post_meta( $woo_product_id, '_vi_wad_migrate_from_id' );
				if ( 1 == $delete_woo_product ) {
					$delete = wp_delete_post( $woo_product_id, true );
					if ( false === $delete ) {
						$response['status']  = 'error';
						$response['message'] = esc_html__( 'Can not delete product', 'woo-alidropship' );
					}
				}
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $response );
	}

	public function cancel_overriding() {
		$page = isset( $_REQUEST['page'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['page'] ) ) : '';
		if ( $page === 'woo-alidropship-imported-list' ) {
			$overridden_product = isset( $_REQUEST['overridden_product'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['overridden_product'] ) ) : '';
			$cancel_overriding  = isset( $_REQUEST['cancel_overriding'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['cancel_overriding'] ) ) : '';
			$_wpnonce           = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '';
			if ( $overridden_product && $cancel_overriding && wp_verify_nonce( $_wpnonce, 'cancel_overriding_nonce' ) ) {
				$product = Ali_Product_Table::get_post( $cancel_overriding );
				if ( $product && $product->post_status === 'override' && $product->post_parent == $overridden_product ) {
					Ali_Product_Table::wp_update_post( array(
						'ID'          => $cancel_overriding,
						'post_parent' => '',
						'post_status' => 'draft',
					) );
				}
				wp_safe_redirect( remove_query_arg( array( 'cancel_overriding', '_wpnonce', 'overridden_product' ) ) );
				exit();
			}
		}
	}

	public function admin_enqueue_scripts() {
		$page = isset( $_REQUEST['page'] ) ? sanitize_text_field( $_REQUEST['page'] ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		global $pagenow;
		if ( $pagenow !== 'admin.php' ) {
			return;
		}
		if ( $page === 'woo-alidropship-imported-list' ) {
			VI_WOO_ALIDROPSHIP_Admin_Settings::enqueue_semantic();
			wp_enqueue_style( 'woo-alidropship-admin-imported-style', VI_WOO_ALIDROPSHIP_CSS . 'imported-list.css', '', VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_script( 'woo-alidropship-imported-list', VI_WOO_ALIDROPSHIP_JS . 'imported-list.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
			wp_localize_script( 'woo-alidropship-imported-list', 'vi_wad_imported_list_params', array(
					'url'                => admin_url( 'admin-ajax.php' ),
					'_vi_wad_ajax_nonce' => VI_WOO_ALIDROPSHIP_Admin_Settings::create_ajax_nonce(),
					'check'              => esc_attr__( 'Check', 'woo-alidropship' ),
					'override'           => esc_attr__( 'Override', 'woo-alidropship' ),
				)
			);
			add_action( 'admin_footer', array( $this, 'delete_product_options' ) );
		}
	}

	public function delete_product_options() {
		?>
        <div class="<?php echo esc_attr( self::set( array(
			'delete-product-options-container',
			'hidden'
		) ) ) ?>">
            <div class="<?php echo esc_attr( self::set( 'overlay' ) ) ?>"></div>
            <div class="<?php echo esc_attr( self::set( 'delete-product-options-content' ) ) ?>">
                <div class="<?php echo esc_attr( self::set( 'delete-product-options-content-header' ) ) ?>">
                    <h2 class="<?php echo esc_attr( self::set( array( 'delete-product-options-content-header-delete', 'hidden' ) ) ) ?>">
						<?php esc_html_e( 'Delete: ', 'woo-alidropship' ) ?>
                        <span class="<?php echo esc_attr( self::set( 'delete-product-options-product-title' ) ) ?>"> </span>
                    </h2>
                    <span class="<?php echo esc_attr( self::set( 'delete-product-options-close' ) ) ?>"> </span>
                    <h2 class="<?php echo esc_attr( self::set( array( 'delete-product-options-content-header-override', 'hidden' ) ) ) ?>">
						<?php esc_html_e( 'Override: ', 'woo-alidropship' ) ?>
                        <span class="<?php echo esc_attr( self::set( 'delete-product-options-product-title' ) ) ?>"> </span>
                    </h2>
                </div>
                <div class="<?php echo esc_attr( self::set( 'delete-product-options-content-body' ) ) ?>">
                    <div class="<?php echo esc_attr( self::set( 'delete-product-options-content-body-row' ) ) ?>">
                        <div class="<?php echo esc_attr( self::set( array( 'delete-product-options-delete-woo-product-wrap', 'hidden' ) ) ) ?>">
                            <input type="checkbox" <?php checked( self::$settings->get_params( 'delete_woo_product' ), 1 ) ?>
                                   value="1"
                                   id="<?php echo esc_attr( self::set( 'delete-product-options-delete-woo-product' ) ) ?>"
                                   class="<?php echo esc_attr( self::set( 'delete-product-options-delete-woo-product' ) ) ?>">
                            <label for="<?php echo esc_attr( self::set( 'delete-product-options-delete-woo-product' ) ) ?>"><?php esc_html_e( 'Also delete product from your WooCommerce store.', 'woo-alidropship' ) ?></label>
                        </div>
                        <div class="<?php echo esc_attr( self::set( array( 'delete-product-options-override-product-wrap', 'hidden' ) ) ) ?>">
                            <label for="<?php echo esc_attr( self::set( 'delete-product-options-override-product' ) ) ?>"><?php esc_html_e( 'AliExpress Product ID:', 'woo-alidropship' ) ?></label>
                            <input type="text"
                                   id="<?php echo esc_attr( self::set( 'delete-product-options-override-product' ) ) ?>"
                                   class="<?php echo esc_attr( self::set( 'delete-product-options-override-product' ) ) ?>">
                            <div class="<?php echo esc_attr( self::set( array( 'delete-product-options-override-product-new-wrap', 'hidden' ) ) ) ?>">
                                <span class="<?php echo esc_attr( self::set( 'delete-product-options-override-product-new-close' ) ) ?>"> </span>
                                <div class="<?php echo esc_attr( self::set( 'delete-product-options-override-product-new-image' ) ) ?>">
                                    <img src="<?php echo esc_url( VI_WOO_ALIDROPSHIP_IMAGES . 'loading.gif' ) ?>">
                                </div>
                                <div class="<?php echo esc_attr( self::set( 'delete-product-options-override-product-new-title' ) ) ?>"></div>
                            </div>
                        </div>
                        <div class="<?php echo esc_attr( self::set( 'delete-product-options-override-product-message' ) ) ?>"></div>
                    </div>
                </div>
                <div class="<?php echo esc_attr( self::set( 'delete-product-options-content-footer' ) ) ?>">
                    <span class="vi-ui button positive mini <?php echo esc_attr( self::set( array( 'delete-product-options-button-override', 'hidden' ) ) ) ?>"
                          data-product_id="" data-woo_product_id="">
                            <?php esc_html_e( 'Check', 'woo-alidropship' ) ?>
                        </span>
                    <span class="vi-ui button mini negative <?php echo esc_attr( self::set( array( 'delete-product-options-button-delete', 'hidden' ) ) ) ?>"
                          data-product_id="" data-woo_product_id="">
                            <?php esc_html_e( 'Delete', 'woo-alidropship' ) ?>
                        </span>
                    <span class="vi-ui button mini <?php echo esc_attr( self::set( 'delete-product-options-button-cancel' ) ) ?>">
                            <?php esc_html_e( 'Cancel', 'woo-alidropship' ) ?>
                        </span>
                </div>
            </div>
            <div class="<?php echo esc_attr( self::set( 'saving-overlay' ) ) ?>"></div>
        </div>
		<?php
	}

	/**
	 * Adds the order processing count to the menu.
	 */
	public function menu_product_count() {
		global $submenu;
		if ( isset( $submenu['woo-alidropship-import-list'] ) ) {
			// Add count if user has access.
			if ( apply_filters( 'woo_aliexpress_dropship_product_count_in_menu', true ) && current_user_can( 'manage_options' ) ) {
				$product_count = $this->get_product_count();
				foreach ( $submenu['woo-alidropship-import-list'] as $key => $menu_item ) {
					if ( 0 === strpos( $menu_item[0], _x( 'Imported', 'Admin menu name', 'woo-alidropship' ) ) ) {
						$submenu['woo-alidropship-import-list'][ $key ][0] .= ' <span class="update-plugins count-' . esc_attr( $product_count->publish ) . '"><span class="' . self::set( 'imported-list-count' ) . '">' . number_format_i18n( $product_count->publish ) . '</span></span>'; // WPCS: override ok.
						break;
					}
				}
			}
		}
	}

	public function get_product_count() {
		if ( $this->product_count === null ) {
			$this->product_count = Ali_Product_Table::wp_count_posts( 'vi_wad_draft_product' );
		}

		return $this->product_count;
	}

	public function restore() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		vi_wad_set_time_limit();
		$product_id = isset( $_POST['product_id'] ) ? sanitize_text_field( $_POST['product_id'] ) : '';
		$response   = array(
			'status'  => 'success',
			'message' => '',
		);
		if ( $product_id ) {
			$post = Ali_Product_Table::get_post( $product_id );
			Ali_Product_Table::wp_publish_post( $post );
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $response );
	}

	/**
	 * Delete imported products
	 */
	public function trash() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		vi_wad_set_time_limit();
		$product_id = isset( $_POST['product_id'] ) ? sanitize_text_field( $_POST['product_id'] ) : '';
		$response   = array(
			'status'  => 'success',
			'message' => '',
		);
		if ( $product_id ) {
			$reslut = wp_trash_post( $product_id );
			if ( ! $reslut ) {
				$response['status']  = 'error';
				$response['message'] = esc_html__( 'Can not delete product', 'woo-alidropship' );
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $response );
	}

	public function override_product() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		vi_wad_set_time_limit();
		$override_product_url = isset( $_POST['override_product_url'] ) ? sanitize_text_field( stripslashes( $_POST['override_product_url'] ) ) : '';
		$step                 = isset( $_POST['step'] ) ? sanitize_text_field( stripslashes( $_POST['step'] ) ) : '';
		$product_id           = isset( $_POST['product_id'] ) ? sanitize_text_field( $_POST['product_id'] ) : '';
		$response             = array(
			'status'           => 'error',
			'message'          => '',
			'image'            => '',
			'title'            => '',
			'data'             => '',
			'exist_product_id' => '',
		);
		$product_sku = $override_product_url;
        if (!$product_sku){
	        $response['message'] = esc_html__( 'Please enter AliExpress Product ID( the product must be imported to the import list before checking)', 'woo-alidropship' );
	        wp_send_json( $response );
        }
		if ( $product_sku == Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_sku', true ) ) {
			$response['message'] = esc_html__( 'Can not override itself', 'woo-alidropship' );
			wp_send_json( $response );
		}
		$exist_product_id = VI_WOO_ALIDROPSHIP_DATA::product_get_id_by_aliexpress_id( $product_sku );
        if (!$exist_product_id){
	        $response['message'] = esc_html__( 'Not found. Please make sure the product is added to the import list before checking', 'woo-alidropship' );
	        wp_send_json( $response );
        }
		$exist_product                = Ali_Product_Table::get_post( $exist_product_id );
		if (!$exist_product){
			$response['message'] = esc_html__( 'Not found product data. Please make sure the product is added to the import list before checking', 'woo-alidropship' );
			wp_send_json( $response );
		}
        if ($exist_product->post_status !== 'draft' ){
	        if ( $exist_product->post_status === 'publish' ) {
		        $response['status']  = 'exist';
		        $response['message'] = esc_html__( 'This product has already been imported', 'woo-alidropship' );
	        } else {
		        $response['status']  = 'override';
		        $response['message'] = esc_html__( 'This product is overriding an other product.', 'woo-alidropship' );
	        }
            if ($step !== 'check'){
                $response['status'] ='error';
            }
	        wp_send_json( $response );
        }
		if ( $step === 'check' ) {
			$response['exist_product_id'] = $exist_product_id;
			$response['title']            = $exist_product->post_title;
			$gallery                      = Ali_Product_Table::get_post_meta( $exist_product_id, '_vi_wad_gallery', true );
			$response['image']            = ( is_array( $gallery ) && count( $gallery ) ) ? $gallery[0] : wc_placeholder_img_src();
			$response['status'] = 'success';
		} else {
			$post = Ali_Product_Table::get_post( $product_id );
			if ( $post ) {
				$update_post = Ali_Product_Table::wp_update_post( array(
						'ID'          => $exist_product_id,
						'post_status' => 'override',
						'post_parent' => $product_id,
						'edit_date'   => true,
					)
				);
				if ( ! is_wp_error( $update_post ) ) {
					$title                            = $exist_product->post_title;
					$response['status']               = 'success';
					$response['button_override_html'] = self::button_override_html( $product_id, $exist_product_id );
					$response['data']                 = '<div class="vi-ui message"><span>' . sprintf( __( 'This product is being overridden by: %1$s. Please go to %2$s to complete the process.', 'woo-alidropship' ), '<strong>' . $title . '</strong>', '<a target="_blank" href="' . admin_url( 'admin.php?page=woo-alidropship-import-list&vi_wad_search_id=' . $exist_product_id ) . '">Import list</a>' ) . '</span></div>';//phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
				} else {
					$response['message'] = $update_post->get_error_message();
				}
			} else {
				$response['message'] = esc_html__( 'Not find this product data to override', 'woo-alidropship' );
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification

		wp_send_json( $response );
	}

	private static function set( $name, $set_name = false ) {
		return VI_WOO_ALIDROPSHIP_DATA::set( $name, $set_name );
	}

	/**
	 * @param $status
	 * @param $option
	 * @param $value
	 *
	 * @return mixed
	 */
	public function save_screen_options( $status, $option, $value ) {
		if ( $option === 'vi_wad_imported_per_page' ) {
			return $value;
		}

		return $status;
	}

	public function admin_menu() {
		$imported_list = add_submenu_page(
			'woo-alidropship-import-list',
			esc_html__( 'Imported Products - ALD - Dropshipping and Fulfillment for AliExpress and WooCommerce', 'woo-alidropship' ),
			esc_html__( 'Imported', 'woo-alidropship' ),
			'manage_options',
			'woo-alidropship-imported-list',
			array( $this, 'imported_list_callback' )
		);
		add_action( "load-$imported_list", array( $this, 'screen_options_page_imported' ) );
	}

	public function screen_options_page_imported() {
		add_screen_option( 'per_page', array(
			'label'   => esc_html__( 'Number of items per page', 'wp-admin' ),
			'default' => 5,
			'option'  => 'vi_wad_imported_per_page'
		) );
	}

	public function imported_list_callback() {
		$user     = get_current_user_id();
		$screen   = get_current_screen();
		$option   = $screen->get_option( 'per_page', 'option' );
		$per_page = get_user_meta( $user, $option, true );

		if ( empty ( $per_page ) || $per_page < 1 ) {
			$per_page = $screen->get_option( 'per_page', 'default' );
		}

		$paged  = isset( $_GET['paged'] ) ? sanitize_text_field( $_GET['paged'] ) : 1;// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$status = ! empty( $_GET['post_status'] ) ? sanitize_text_field( $_GET['post_status'] ) : 'publish';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		?>
        <div class="wrap">
            <h2><?php esc_html_e( 'All imported products', 'woo-alidropship' ) ?></h2>
			<?php
			$args             = array(
				'post_type'      => 'vi_wad_draft_product',
				'post_status'    => $status,
				'order'          => 'DESC',
				'orderby'        => 'meta_value_num',
				'fields'         => 'ids',
				'posts_per_page' => $per_page,
				'paged'          => $paged,
				'meta_query'     => array(// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
					'relation' => 'and',
					array(
						'key'     => '_vi_wad_woo_id',
						'compare' => 'exists',
					)
				),
			);
			$keyword          = isset( $_GET['vi_wad_search'] ) ? sanitize_text_field( $_GET['vi_wad_search'] ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$vi_wad_search_id = isset( $_GET['vi_wad_search_woo_id'] ) ? sanitize_text_field( $_GET['vi_wad_search_woo_id'] ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			if ( $vi_wad_search_id ) {
				$args['meta_value']     = $vi_wad_search_id;// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
				$args['posts_per_page'] = 1;
				$keyword                = '';
			} else if ( $keyword ) {
				$args['s'] = $keyword;
			}
			//			$the_query     = new WP_Query( $args );
			$the_query     = VI_WOO_ALIDROPSHIP_DATA::is_ald_table() ? new Ali_Product_Query( $args ) : new WP_Query( $args );
			$count         = $the_query->found_posts;
			$total_page    = $the_query->max_num_pages;
			$paged         = $total_page >= intval( $paged ) ? $paged : 1;
			$product_count = $this->get_product_count();
			if ( $the_query->have_posts() ) {
				ob_start();
				?>
                <form method="get" class="<?php echo esc_attr( self::set( 'imported-products-' . $status ) ) ?>">
                    <input type="hidden" name="page" value="woo-alidropship-imported-list">
                    <input type="hidden" name="post_status" value="<?php echo esc_attr( $status ) ?>">
                    <div class="tablenav top">
                        <div class="subsubsub">
                            <ul>
                                <li class="<?php echo esc_attr( self::set( 'imported-products-count-publish-container' ) ) ?>">
                                    <a href="<?php echo esc_attr( admin_url( 'admin.php?page=woo-alidropship-imported-list' ) ) ?>">
										<?php esc_html_e( 'Publish', 'woo-alidropship' ); ?></a>
                                    (<span class="<?php echo esc_attr( self::set( 'imported-products-count-publish' ) ) ?>"><?php echo esc_html( $product_count->publish ) ?></span>)
                                </li>
                                |
                                <li class="<?php echo esc_attr( self::set( 'imported-products-count-trash-container' ) ) ?>">
                                    <a href="<?php echo esc_attr( admin_url( 'admin.php?page=woo-alidropship-imported-list&post_status=trash' ) ) ?>">
										<?php esc_html_e( 'Trash', 'woo-alidropship' ); ?></a>
                                    (<span class="<?php echo esc_attr( self::set( 'imported-products-count-trash' ) ) ?>"><?php echo esc_html( $product_count->trash ) ?></span>)
                                </li>
                            </ul>
                        </div>
                        <div class="tablenav-pages">
                            <div class="pagination-links">
								<?php
								if ( $paged > 2 ) {
									?>
                                    <a class="prev-page button" href="<?php echo esc_url( add_query_arg(
										array(
											'page'          => 'woo-alidropship-imported-list',
											'paged'         => 1,
											'vi_wad_search' => $keyword,
											'post_status'   => $status,
										), admin_url( 'admin.php' )
									) ) ?>"><span
                                                class="screen-reader-text"><?php esc_html_e( 'First Page', 'woo-alidropship' ) ?></span><span
                                                aria-hidden="true">«</span></a>
									<?php
								} else {
									?>
                                    <span class="tablenav-pages-navspan button disabled" aria-hidden="true">«</span>
									<?php
								}
								/*Previous button*/
								if ( $per_page * $paged > $per_page ) {
									$p_paged = $paged - 1;
								} else {
									$p_paged = 0;
								}
								if ( $p_paged ) {
									$p_url = add_query_arg(
										array(
											'page'          => 'woo-alidropship-imported-list',
											'paged'         => $p_paged,
											'vi_wad_search' => $keyword,
											'post_status'   => $status,
										), admin_url( 'admin.php' )
									);
									?>
                                    <a class="prev-page button" href="<?php echo esc_url( $p_url ) ?>"><span
                                                class="screen-reader-text"><?php esc_html_e( 'Previous Page', 'woo-alidropship' ) ?></span><span
                                                aria-hidden="true">‹</span></a>
									<?php
								} else {
									?>
                                    <span class="tablenav-pages-navspan button disabled" aria-hidden="true">‹</span>
									<?php
								}
								?>
                                <span class="screen-reader-text"><?php esc_html_e( 'Current Page', 'woo-alidropship' ) ?></span>
                                <span id="table-paging" class="paging-input">
                                    <span class="tablenav-paging-text">
                                        <input class="current-page" type="text" name="paged" size="1"
                                               value="<?php echo esc_html( $paged ) ?>"><span
                                                class="tablenav-paging-text"><?php esc_html_e( ' of ', 'woo-alidropship' ) ?>
                                            <span
                                                    class="total-pages"><?php echo esc_html( $total_page ) ?></span>
                                        </span>
                                    </span>
                                </span>
								<?php /*Next button*/
								if ( $per_page * $paged < $count ) {
									$n_paged = $paged + 1;
								} else {
									$n_paged = 0;
								}
								if ( $n_paged ) {
									$n_url = add_query_arg(
										array(
											'page'          => 'woo-alidropship-imported-list',
											'paged'         => $n_paged,
											'vi_wad_search' => $keyword,
											'post_status'   => $status,
										), admin_url( 'admin.php' )
									); ?>
                                    <a class="next-page button" href="<?php echo esc_url( $n_url ) ?>"><span
                                                class="screen-reader-text"><?php esc_html_e( 'Next Page', 'woo-alidropship' ) ?></span><span
                                                aria-hidden="true">›</span></a>
									<?php
								} else {
									?>
                                    <span class="tablenav-pages-navspan button disabled" aria-hidden="true">›</span>
									<?php
								}
								if ( $total_page > $paged + 1 ) {
									?>
                                    <a class="next-page button" href="<?php echo esc_url( add_query_arg(
										array(
											'page'          => 'woo-alidropship-imported-list',
											'paged'         => $total_page,
											'vi_wad_search' => $keyword,
											'post_status'   => $status,
										), admin_url( 'admin.php' )
									) ) ?>"><span
                                                class="screen-reader-text"><?php esc_html_e( 'Last Page', 'woo-alidropship' ) ?></span><span
                                                aria-hidden="true">»</span></a>
									<?php
								} else {
									?>
                                    <span class="tablenav-pages-navspan button disabled" aria-hidden="true">»</span>
									<?php
								}
								?>
                            </div>
                        </div>
                        <p class="search-box">
                            <input type="search" class="text short" name="vi_wad_search"
                                   placeholder="<?php esc_attr_e( 'Search imported product', 'woo-alidropship' ) ?>"
                                   value="<?php echo esc_attr( $keyword ) ?>">
                            <input type="submit" name="submit" class="button"
                                   value="<?php echo esc_attr( 'Search product', 'woo-alidropship' ) ?>">
                        </p>
                    </div>
                </form>
				<?php
				$pagination_html = ob_get_clean();
				echo wp_kses( $pagination_html, VI_WOO_ALIDROPSHIP_DATA::allow_html() );
				$key = 0;
				foreach ( $the_query->posts as $product_id ) {
					$product            = Ali_Product_Table::get_post( $product_id );
					$woo_product_id     = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_woo_id', true );
					$title              = $product->post_title;
					$woo_product        = wc_get_product( $woo_product_id );
					$woo_product_status = '';
					$woo_product_name   = $title;
					$sku                = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_sku', true );
					$woo_sku            = $sku;
					if ( $woo_product ) {
						$woo_sku            = $woo_product->get_sku();
						$woo_product_status = $woo_product->get_status();
						$woo_product_name   = $woo_product->get_name();
					}
					$gallery    = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_gallery', true );
					$store_info = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_store_info', true );
					$image      = wp_get_attachment_thumb_url( Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_product_image', true ) );
					if ( ! $image ) {
						$image = ( is_array( $gallery ) && count( $gallery ) ) ? array_shift( $gallery ) : '';
					}
					$variations         = Ali_Product_Table::get_post_meta( $product_id, '_vi_wad_variations', true );
					$overriding_product = VI_WOO_ALIDROPSHIP_DATA::get_overriding_product( $product_id );
					$accordion_active   = '';
					if ( $overriding_product ) {
						$accordion_active = 'active';
					}
					?>
                    <div class="vi-ui styled fluid accordion  <?php echo esc_attr( self::set( 'accordion' ) ); ?>"
                         id="<?php echo esc_attr( self::set( 'product-item-id-' . $product_id ) ) ?>">
                        <div class="title <?php echo esc_attr( $accordion_active ) ?>">
                            <i class="dropdown icon <?php echo esc_attr( self::set( 'accordion-title-icon' ) ); ?>"> </i>
                            <div class="<?php echo esc_attr( self::set( 'accordion-product-image-title-container' ) ) ?>">
                                <div class="<?php echo esc_attr( self::set( 'accordion-product-image-title' ) ) ?>">
                                    <img src="<?php echo esc_url( $image ? $image : wc_placeholder_img_src() ) ?>"
                                         class="<?php echo esc_attr( self::set( 'accordion-product-image' ) ) ?>">
                                    <div class="<?php echo esc_attr( self::set( 'accordion-product-title-container' ) ) ?>">
                                        <div class="<?php echo esc_attr( self::set( 'accordion-product-title' ) ) ?>"
                                             title="<?php echo esc_attr( $title ) ?>"><?php echo esc_html( $title ) ?></div>
										<?php
										if ( ! empty( $store_info['name'] ) ) {
											$store_name = $store_info['name'];
											if ( ! empty( $store_info['url'] ) ) {
												$store_name = '<a class="' . esc_attr( self::set( 'accordion-store-url' ) ) . '" href="' . esc_url( $store_info['url'] ) . '" target="_blank">' . $store_name . '</a>';
											}
											?>
                                            <div>
												<?php
												esc_html_e( 'Store: ', 'woo-alidropship' );
												echo wp_kses( $store_name, VI_WOO_ALIDROPSHIP_DATA::allow_html() );
												?>
                                            </div>
											<?php
										}
										?>
                                    </div>
                                </div>
                                <div class="<?php echo esc_attr( self::set( 'button-view-and-edit' ) ) ?>">
                                    <a href="<?php echo esc_url( "https://www.aliexpress.com/item/{$sku}.html" ); ?>"
                                       target="_blank" class="button"
                                       rel="nofollow"><?php esc_html_e( 'View on AliExpress', 'woo-alidropship' ) ?></a>
									<?php
									if ( $woo_product ) {
										if ( $woo_product_status !== 'trash' ) {
											echo VI_WOO_ALIDROPSHIP_Admin_Import_List::get_button_view_edit_html( $woo_product_id );// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
										} else {
											if ( $status !== 'trash' ) {
												?>
                                                <span class="vi-ui black button <?php echo esc_attr( self::set( 'button-trash' ) ) ?>"
                                                      title="<?php esc_attr_e( 'This product is trashed from your WooCommerce store.', 'woo-alidropship' ) ?>"
                                                      data-product_title="<?php echo esc_attr( $title ) ?>"
                                                      data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                                      data-woo_product_id=""><?php esc_html_e( 'Trash', 'woo-alidropship' ) ?>
                                                </span>
                                                <span class="vi-ui button negative <?php echo esc_attr( self::set( 'button-delete' ) ) ?>"
                                                      title="<?php esc_attr_e( 'Delete this product permanently', 'woo-alidropship' ) ?>"
                                                      data-product_title="<?php echo esc_attr( $title ) ?>"
                                                      data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                                      data-woo_product_id="<?php echo esc_attr( $woo_product ? $woo_product_id : '' ) ?>"><?php esc_html_e( 'Delete', 'woo-alidropship' ) ?>
                                                </span>
												<?php
											} else {
												?>
                                                <span class="vi-ui button positive <?php echo esc_attr( self::set( 'button-restore' ) ) ?>"
                                                      title="<?php esc_attr_e( 'Restore this product', 'woo-alidropship' ) ?>"
                                                      data-product_title="<?php echo esc_attr( $title ) ?>"
                                                      data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                                      data-woo_product_id="<?php echo esc_attr( $woo_product ? $woo_product_id : '' ) ?>"><?php esc_html_e( 'Restore', 'woo-alidropship' ) ?></span>
                                                <span class="vi-ui button negative <?php echo esc_attr( self::set( 'button-delete' ) ) ?>"
                                                      title="<?php esc_attr_e( 'Delete this product permanently', 'woo-alidropship' ) ?>"
                                                      data-product_title="<?php echo esc_attr( $title ) ?>"
                                                      data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                                      data-woo_product_id="<?php echo esc_attr( $woo_product ? $woo_product_id : '' ) ?>"><?php esc_html_e( 'Delete', 'woo-alidropship' ) ?></span>
												<?php
											}
										}
									} else {
										if ( $status !== 'trash' ) {
											?>
                                            <span class="vi-ui black button <?php echo esc_attr( self::set( 'button-trash' ) ) ?>"
                                                  title="<?php esc_attr_e( 'This product is deleted from your WooCommerce store.', 'woo-alidropship' ) ?>"
                                                  data-product_title="<?php echo esc_attr( $title ) ?>"
                                                  data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                                  data-woo_product_id=""><?php esc_html_e( 'Trash', 'woo-alidropship' ) ?>
                                            </span>
                                            <span class="vi-ui button negative <?php echo esc_attr( self::set( 'button-delete' ) ) ?>"
                                                  title="<?php esc_attr_e( 'Delete this product permanently', 'woo-alidropship' ) ?>"
                                                  data-product_title="<?php echo esc_attr( $title ) ?>"
                                                  data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                                  data-woo_product_id="<?php echo esc_attr( $woo_product ? $woo_product_id : '' ) ?>"><?php esc_html_e( 'Delete', 'woo-alidropship' ) ?>
                                            </span>
											<?php
										} else {
											?>
                                            <span class="vi-ui button negative <?php echo esc_attr( self::set( 'button-delete' ) ) ?>"
                                                  title="<?php esc_attr_e( 'Delete this product permanently', 'woo-alidropship' ) ?>"
                                                  data-product_title="<?php echo esc_attr( $title ) ?>"
                                                  data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                                  data-woo_product_id="<?php echo esc_attr( $woo_product ? $woo_product_id : '' ) ?>"><?php esc_html_e( 'Delete', 'woo-alidropship' ) ?>
                                            </span>
											<?php
										}
									}
									?>
                                    <span class="vi-ui button negative mini loading <?php echo esc_attr( self::set( 'button-deleting' ) ) ?>"><?php esc_html_e( 'Delete', 'woo-alidropship' ) ?></span>
                                </div>
                            </div>
                        </div>
                        <div class="content <?php echo esc_attr( $accordion_active ) ?>">
							<?php
							if ( $overriding_product ) {
								$overriding_product_title = get_the_title( $overriding_product );
								?>
                                <div class="vi-ui message">
                                    <span><?php echo wp_kses_post(sprintf( __( 'This product is being overridden by: %1$s. Please go to %2$s to complete the process.', 'woo-alidropship' ), '<strong>' . $overriding_product_title . '</strong>', '<a target="_blank" href="' . esc_url( admin_url( 'admin.php?page=woo-alidropship-import-list&vi_wad_search=' . urlencode( $overriding_product_title ) ) ) . '">Import list</a>' )) //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment ?></span>
                                </div>
								<?php
							}
							?>
                            <div class="<?php echo esc_attr( self::set( 'message' ) ) ?>"></div>
                            <form class="vi-ui form <?php echo esc_attr( self::set( 'product-container' ) ) ?>"
                                  method="post">
                                <div class="field">
                                    <div class="fields">
                                        <div class="three wide field">
                                            <div class="<?php echo esc_attr( self::set( 'product-image' ) ) ?>">
                                                <img style="width: 100%"
                                                     src="<?php echo esc_url( $image ? $image : wc_placeholder_img_src() ) ?>"
                                                     class="<?php echo esc_attr( self::set( 'import-data-image' ) ) ?>">
                                                <input type="hidden"
                                                       name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][image]' ) ?>"
                                                       value="<?php echo esc_attr( $image ? $image : wc_placeholder_img_src() ) ?>">
                                            </div>
                                        </div>
                                        <div class="thirteen wide field">
                                            <div class="field">
                                                <label><?php esc_html_e( 'WooCommerce product title' ) ?></label>
                                                <input type="text" value="<?php echo esc_attr( $woo_product_name ) ?>"
                                                       readonly
                                                       name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][title]' ) ?>"
                                                       class="<?php echo esc_attr( self::set( 'import-data-title' ) ) ?>">
                                            </div>
                                            <div class="field">
                                                <div class="equal width fields">
                                                    <div class="field">
                                                        <label><?php esc_html_e( 'Sku', 'woo-alidropship' ) ?></label>
                                                        <input type="text" value="<?php echo esc_attr( $woo_sku ) ?>"
                                                               readonly
                                                               name="<?php echo esc_attr( 'vi_wad_product[' . $product_id . '][sku]' ) ?>"
                                                               class="<?php echo esc_attr( self::set( 'import-data-sku' ) ) ?>">
                                                    </div>
                                                    <div class="field">
                                                        <label><?php esc_html_e( 'Cost', 'woo-alidropship' ) ?></label>
                                                        <div class="<?php echo esc_attr( self::set( 'price-field' ) ) ?>">
															<?php
															if ( count( $variations ) == 1 ) {
																$variation_sale_price    = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations[0]['sale_price'] );
																$variation_regular_price = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variations[0]['regular_price'] );
																$price                   = $variation_sale_price ? $variation_sale_price : $variation_regular_price;
																echo wc_price( $price, array( 'currency'     => 'USD', 'price_format' => '%1$s&nbsp;%2$s' ) );// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
															} else {
																$min_price = 0;
																$max_price = 0;
																foreach ( $variations as $variation_k => $variation_v ) {
																	$variation_sale_price    = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variation_v['sale_price'] );
																	$variation_regular_price = VI_WOO_ALIDROPSHIP_DATA::string_to_float( $variation_v['regular_price'] );
																	$price                   = $variation_sale_price ? $variation_sale_price : $variation_regular_price;
																	if ( ! $min_price ) {
																		$min_price = $price;
																	}
																	if ( $price < $min_price ) {
																		$min_price = $price;
																	}
																	if ( $price > $max_price ) {
																		$max_price = $price;
																	}
																}
																if ( $min_price && $min_price != $max_price ) {
																	echo wc_price( $min_price, array(// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
																			'currency'     => 'USD',
																			'price_format' => '%1$s&nbsp;%2$s'
																		) ) . ' - ' . wc_price( $max_price, array(// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
																			'currency'     => 'USD',
																			'price_format' => '%1$s&nbsp;%2$s'
																		) );
																} elseif ( $max_price ) {
																	echo wc_price( $max_price, array(// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
																		'currency'     => 'USD',
																		'price_format' => '%1$s&nbsp;%2$s'
																	) );
																}
															}
															?>
                                                        </div>
                                                    </div>
													<?php
													if ( $woo_product && $woo_product_status !== 'trash' ) {
														?>
                                                        <div class="field">
                                                            <label><?php esc_html_e( 'WooCommerce Price', 'woo-alidropship' ) ?></label>
                                                            <div class="<?php echo esc_attr( self::set( 'price-field' ) ) ?>">
																<?php
																echo wp_kses( $woo_product->get_price_html(), VI_WOO_ALIDROPSHIP_DATA::allow_html() );
																?>
                                                            </div>
                                                        </div>
														<?php
													}
													?>
                                                </div>
                                            </div>

                                            <div class="field">
                                                <div class="equal width fields">
                                                    <div class="field">
                                                        <div class="<?php echo esc_attr( self::set( 'button-override-container' ) ) ?>">
															<?php
															if ( $status !== 'trash' ) {
																if ( $woo_product && $woo_product_status !== 'trash' ) {
																	?>
                                                                    <span class="vi-ui button negative <?php echo esc_attr( self::set( 'button-delete' ) ) ?>"
                                                                          title="<?php esc_attr_e( 'Delete this product permanently', 'woo-alidropship' ) ?>"
                                                                          data-product_title="<?php echo esc_attr( $title ) ?>"
                                                                          data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                                                          data-woo_product_id="<?php echo esc_attr( $woo_product ? $woo_product_id : '' ) ?>"><?php esc_html_e( 'Delete', 'woo-alidropship' ) ?></span>
																	<?php
																	if ( ! $overriding_product ) {
																		?>
                                                                        <span class="vi-ui button positive <?php echo esc_attr( self::set( 'button-override' ) ) ?>"
                                                                              title="<?php esc_attr_e( 'Override this product', 'woo-alidropship' ) ?>"
                                                                              data-product_title="<?php echo esc_attr( $title ) ?>"
                                                                              data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                                                              data-woo_product_id="<?php echo esc_attr( $woo_product_id ) ?>"><?php esc_html_e( 'Override', 'woo-alidropship' ) ?></span>
																		<?php
																	} else {
																		echo self::button_override_html( $product_id, $overriding_product );// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
																	}
																}
															}
															?>
                                                        </div>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
					<?php
					$key ++;
				}
				echo wp_kses( $pagination_html, VI_WOO_ALIDROPSHIP_DATA::allow_html());
			}
			wp_reset_postdata();
			?>
        </div>
		<?php
	}

	public static function button_override_html( $product_id, $overriding_product ) {
		ob_start();
		?>
        <a title="<?php esc_attr_e( 'Go to import list to complete overriding', 'woo-alidropship' ) ?>"
           class="vi-ui button positive <?php echo esc_attr( self::set( 'button-complete-overriding' ) ) ?>"
           target="_blank"
           href="<?php echo esc_url( admin_url( 'admin.php?page=woo-alidropship-import-list&vi_wad_search_id=' . $overriding_product ) ) ?>"><?php esc_html_e( 'Complete overriding', 'woo-alidropship' ) ?></a>
        <a title="<?php esc_attr_e( 'Cancel overriding this product', 'woo-alidropship' ) ?>"
           class="vi-ui button <?php echo esc_attr( self::set( 'button-complete-overriding' ) ) ?>"
           target="_self"
           href="<?php echo esc_url( add_query_arg( array(
			   'page'               => 'woo-alidropship-imported-list',
			   'overridden_product' => $product_id,
			   'cancel_overriding'  => $overriding_product,
			   '_wpnonce'           => wp_create_nonce( 'cancel_overriding_nonce' )
		   ), admin_url( 'admin.php' ) ) ) ?>"><?php esc_html_e( 'Cancel overriding', 'woo-alidropship' ) ?></a>
		<?php
		return ob_get_clean();
	}

	private static function check_ajax_referer() {
		VI_WOO_ALIDROPSHIP_Admin_Settings::check_ajax_referer( 'woo-alidropship-imported-list' );
	}
}PK     \z9$/  $/    product.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class VI_WOO_ALIDROPSHIP_Admin_Product
 */
class VI_WOO_ALIDROPSHIP_Admin_Product {
	private $settings;

	public function __construct() {
		$this->settings = VI_WOO_ALIDROPSHIP_DATA::get_instance();
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
		add_action( 'transition_post_status', array( $this, 'transition_post_status' ), 10, 3 );
		add_action( 'deleted_post', array( $this, 'deleted_post' ) );
		add_filter( 'post_row_actions', array( $this, 'post_row_actions' ), 20, 2 );
		add_action( 'woocommerce_product_after_variable_attributes', array( $this, 'woocommerce_product_after_variable_attributes' ), 10, 3 );
		add_action( 'woocommerce_save_product_variation', array( $this, 'woocommerce_save_product_variation' ), 10, 2 );

		/*Need to check the case when removing attribute, variation is removed from _vi_wad_variations*/
		add_action( 'woocommerce_product_options_pricing', array( $this, 'woocommerce_product_options_pricing' ), 99 );
		add_action( 'woocommerce_process_product_meta_simple', array( $this, 'woocommerce_process_product_meta_simple' ) );
	}

	/**
	 * @param $product_id
	 */
	public function woocommerce_process_product_meta_simple( $product_id ) {
		if ( ! wp_verify_nonce( $_POST['viwad-variation-nonce'] ?? "", 'viwad-variation-settings' ) ) {
			return;
		}
		$skuAttr = isset( $_POST['vi_wad_simple_variation_attr'] ) ? stripslashes( $_POST['vi_wad_simple_variation_attr'] ) : '';
		if ( $skuAttr ) {
			update_post_meta( $product_id, '_vi_wad_aliexpress_variation_attr', $skuAttr );
		}
		$skuID = isset( $_POST['vi_wad_simple_variation_id'] ) ? stripslashes( $_POST['vi_wad_simple_variation_id'] ) : '';
		if ( $skuID ) {
			update_post_meta( $product_id, '_vi_wad_aliexpress_variation_id', $skuID );
		}
	}

	/**
	 *
	 */
	public function woocommerce_product_options_pricing() {
		global $post;
		$product_id = $post->ID;
		if ( get_post_meta( $product_id, '_vi_wad_aliexpress_product_id', true ) ) {
			$from_id = VI_WOO_ALIDROPSHIP_DATA::product_get_id_by_woo_id( $product_id, false, false, array( 'publish', 'override' ) );
			if ( $from_id ) {
				$variations = Ali_Product_Table::get_post_meta( $from_id, '_vi_wad_variations', true );
				$skuAttr    = get_post_meta( $product_id, '_vi_wad_aliexpress_variation_attr', true );
				if ( $skuAttr || count( $variations ) > 1 ) {
					$id = "vi-wad-original-attributes-simple-{$product_id}";
					wp_nonce_field( 'viwad-variation-settings', 'viwad-variation-nonce', false );
					?>
                    <p class="vi-wad-original-attributes vi-wad-original-attributes-simple form-field"><label
                                for="<?php echo esc_attr( $id ) ?>"><?php esc_html_e( 'Original AliExpress variation', 'woo-alidropship' ); ?></label><?php echo wc_help_tip( __( 'If your customers buy this product, this selected AliExpress variation will be used when fulfilling AliExpress orders', 'woo-alidropship' ) ) //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped  ?>
                        <select id="<?php echo esc_attr( $id ) ?>"
                                class="vi-wad-original-attributes-select"
                                name="vi_wad_simple_variation_attr">
                            <option value=""><?php esc_html_e( 'Please select original variation', 'woo-alidropship' ); ?></option>
							<?php
							foreach ( $variations as $key => $value ) {
								$attr_name = $value['skuAttr'];
								if ( isset( $value['attributes_sub'] ) && count( $value['attributes_sub'] ) > count( $value['attributes'] ) ) {
									$attr_name = implode( ', ', $value['attributes_sub'] );
								} elseif ( count( $value['attributes'] ) ) {
									$attr_name = implode( ', ', $value['attributes'] );
								}
								?>
                                <option value="<?php echo esc_attr( $value['skuAttr'] ) ?>"
                                        data-vi_wad_sku_id="<?php echo esc_attr( $value['skuId'] ) ?>" <?php selected( $value['skuAttr'], $skuAttr ) ?>><?php echo esc_html( $attr_name ) ?></option>
								<?php
							}
							?>
                        </select>
                        <input type="hidden" class="vi-wad-original-sku-id" name="vi_wad_simple_variation_id"
                               value="<?php echo esc_attr( get_post_meta( $product_id, '_vi_wad_aliexpress_variation_id', true ) ) ?>">
                    </p>
					<?php
				}
			}
		}
	}

	/**
	 * @param $variation_id
	 * @param $i
	 */
	public function woocommerce_save_product_variation( $variation_id, $i ) {
		if ( ! wp_verify_nonce( $_POST[ 'viwad-variation-' . $i . '-nonce' ] ?? "", 'viwad-variation-' . $i . '-settings' ) ) {
			return;
		}
		$skuAttr = isset( $_POST['vi_wad_variation_attr'], $_POST['vi_wad_variation_attr'][ $i ] ) ? stripslashes( $_POST['vi_wad_variation_attr'][ $i ] ) : '';
		if ( $skuAttr ) {
			update_post_meta( $variation_id, '_vi_wad_aliexpress_variation_attr', $skuAttr );
		}
		$skuID = isset( $_POST['vi_wad_variation_id'], $_POST['vi_wad_variation_id'][ $i ] ) ? stripslashes( $_POST['vi_wad_variation_id'][ $i ] ) : '';
		if ( $skuID ) {
			update_post_meta( $variation_id, '_vi_wad_aliexpress_variation_id', $skuID );
		}
	}

	/**
	 * @param $loop
	 * @param $variation_data
	 * @param $variation WP_Post
	 */
	public function woocommerce_product_after_variable_attributes( $loop, $variation_data, $variation ) {
		global $post;
		$product_id = $post->ID;
		if ( $variation && get_post_meta( $product_id, '_vi_wad_aliexpress_product_id', true ) ) {
			$from_id = VI_WOO_ALIDROPSHIP_DATA::product_get_id_by_woo_id( $product_id, false, false, array(
				'publish',
				'override'
			) );
			if ( $from_id ) {
				$variation_id = $variation->ID;
				$variations   = Ali_Product_Table::get_post_meta( $from_id, '_vi_wad_variations', true );
				$skuAttr      = get_post_meta( $variation_id, '_vi_wad_aliexpress_variation_attr', true );
				$id           = "vi-wad-original-attributes-{$variation_id}";
				wp_nonce_field( 'viwad-variation-' . $loop . '-settings', 'viwad-variation-' . $loop . '-nonce', false );
				?>
                <div class="vi-wad-original-attributes vi-wad-original-attributes-variable"><label
                            for="<?php echo esc_attr( $id ) ?>"><?php esc_html_e( 'Original AliExpress variation', 'woo-alidropship' ); ?></label><?php echo wc_help_tip( __( 'If your customers buy this product, this selected AliExpress variation will be used when fulfilling AliExpress orders', 'woo-alidropship' ) ) //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped  ?>
                    <select id="<?php echo esc_attr( $id ) ?>"
                            class="vi-wad-original-attributes-select"
                            name="vi_wad_variation_attr[<?php echo esc_attr( $loop ) ?>]">
						<?php
						if ( ! $skuAttr ) {
							?>
                            <option value=""><?php esc_html_e( 'Please select original variation', 'woo-alidropship' ); ?></option>
							<?php
						}
						foreach ( $variations as $key => $value ) {
							$attr_name = $value['skuAttr'];
							if ( isset( $value['attributes_sub'] ) && count( $value['attributes_sub'] ) > count( $value['attributes'] ) ) {
								$attr_name = implode( ', ', $value['attributes_sub'] );
							} elseif ( count( $value['attributes'] ) ) {
								$attr_name = implode( ', ', $value['attributes'] );
							}
							?>
                            <option value="<?php echo esc_attr( $value['skuAttr'] ) ?>"
                                    data-vi_wad_sku_id="<?php echo esc_attr( $value['skuId'] ) ?>" <?php selected( $value['skuAttr'], $skuAttr ) ?>><?php echo esc_html( $attr_name ) ?></option>
							<?php
						}
						?>
                    </select>
                    <input class="vi-wad-original-sku-id" type="hidden"
                           name="vi_wad_variation_id[<?php echo esc_attr( $loop ) ?>]"
                           value="<?php echo esc_attr( get_post_meta( $variation_id, '_vi_wad_aliexpress_variation_id', true ) ) ?>">
                </div>
				<?php
			}
		}
	}

	/**
	 * @param $actions
	 * @param $post
	 *
	 * @return mixed
	 */
	public function post_row_actions( $actions, $post ) {
		if ( $post && $post->post_type === 'product' && $post->post_status !== 'trash' ) {
			$ali_sku = get_post_meta( $post->ID, '_vi_wad_aliexpress_product_id', true );
			if ( $ali_sku ) {
				$actions['vi_wad_view_on_aliexpress']    = '<a href="' . VI_WOO_ALIDROPSHIP_DATA::get_aliexpress_product_url( $ali_sku ) . '" title="' . esc_attr__( 'View product on AliExpress', 'woo-alidropship' ) . '" target="_blank">' . esc_html__( 'View on AliExpress', 'woo-alidropship' ) . '</a>';
				$href                                    = admin_url( "admin.php?page=woo-alidropship-imported-list&vi_wad_search_woo_id={$post->ID}" );
				$actions['vi_wad_view_on_imported_page'] = '<a href="' . $href . '" title="' . esc_attr__( 'View product on Imported page', 'woo-alidropship' ) . '" target="_blank">' . esc_html__( 'View on Imported', 'woo-alidropship' ) . '</a>';
			}
		}

		return $actions;
	}


	/**Set a product status
	 *
	 * @param $product_id
	 * @param string $status
	 */
	public static function set_status( $product_id, $status = 'trash' ) {
		$ali_sku = get_post_meta( $product_id, '_vi_wad_aliexpress_product_id', true );
		if ( $ali_sku ) {
			if ( $status === 'publish' ) {
				$id = VI_WOO_ALIDROPSHIP_DATA::product_get_id_by_woo_id( $product_id, false, false, 'trash' );
			} else {
				$id = VI_WOO_ALIDROPSHIP_DATA::product_get_id_by_woo_id( $product_id );
			}
			if ( $id ) {
				Ali_Product_Table::wp_update_post( array( 'ID' => $id, 'post_status' => $status ) );
			}
		}
	}

	/**Set a product status to trash when a WC product is deleted
	 *
	 * @param $product_id
	 */
	public function deleted_post( $product_id ) {
		self::set_status( $product_id, 'trash' );
	}

	/**Set a product status to trash when a WC product is trashed and set to publish when a trashed product is restored
	 *
	 * @param $new_status
	 * @param $old_status
	 * @param $post
	 */
	public function transition_post_status( $new_status, $old_status, $post ) {
		if ( 'product' === $post->post_type ) {
			$product_id = $post->ID;
			if ( 'trash' === $new_status ) {
				self::set_status( $product_id );
			} elseif ( $old_status === 'trash' ) {
				self::set_status( $product_id, 'publish' );
			}
		}
	}

	public function admin_enqueue_scripts( $page ) {
		global $post_type;
		if ( $post_type !== 'product' ) {
			return;
		}
		if ( $page === 'post.php' || $page === 'edit.php' ) {
			wp_enqueue_script( 'woo-alidropship-admin-edit-product', VI_WOO_ALIDROPSHIP_JS . 'admin-product.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
			wp_enqueue_style( 'woo-alidropship-admin-edit-product', VI_WOO_ALIDROPSHIP_CSS . 'admin-product.css', '', VI_WOO_ALIDROPSHIP_VERSION );
			add_action( 'post_submitbox_start', array( $this, 'post_submitbox_start' ) );
			wp_localize_script( 'woo-alidropship-admin-edit-product', 'vi_wad_admin_product_params', array(
				'import_page_url' => admin_url( 'admin.php?page=woo-alidropship-import-list' ),
			) );
		}
	}


	public function post_submitbox_start( $post ) {
		if ( $post ) {
			$product_id     = $post->ID;
			$ali_product_id = get_post_meta( $product_id, '_vi_wad_aliexpress_product_id', true );
			if ( $ali_product_id ) {
				?>
                <p class="vi-wad-view-original-product-button">
                    <a href="<?php echo esc_url( "https://www.aliexpress.com/item/{$ali_product_id}.html" ); ?>"
                       target="_blank"
                       class="button"><?php esc_html_e( 'View product on AliExpress', 'woo-alidropship' ); ?></a>
                </p>
				<?php
			}
		}
	}
}
PK     \II  I  	  admin.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class VI_WOO_ALIDROPSHIP_Admin_Admin {
	protected $settings;
	protected $characters_array;

	function __construct() {
		$this->settings = VI_WOO_ALIDROPSHIP_DATA::get_instance();

		add_filter( 'plugin_action_links_woo-alidropship/woo-alidropship.php', array(
			$this,
			'settings_link'
		) );

		add_action( 'init', array( $this, 'init' ) );
		add_action( 'vi_wad_print_scripts', array( $this, 'dismiss_notice' ) );
	}

	/**
	 * Link to Settings
	 *
	 * @param $links
	 *
	 * @return mixed
	 */
	public function settings_link( $links ) {

		array_unshift( $links, sprintf( "<a href='%s'>%s</a>",
			esc_url( admin_url( 'admin.php?page=woo-alidropship' ) ),
			esc_html__( 'Settings', 'woo-alidropship' ) ) );

		array_unshift( $links, sprintf( "<a href='%s'>%s</a>",
			esc_url( admin_url( 'admin.php?page=woo-alidropship-import-list#aldShowModal' ) ),
			esc_html__( 'Find Ali product', 'woo-alidropship' ) ) );
		$links['deactivate'] = str_replace('deactivate-ald-dropshipping-and-fulfillment-for-aliexpress-and-woocommerce', 'deactivate-woo-alidropship', $links['deactivate']);

		return $links;
	}


	/**
	 * Function init when run plugin+
	 */
	function init() {
		/*Register post type*/
		load_plugin_textdomain( 'woo-alidropship' );
		$this->load_plugin_textdomain();
		if ( class_exists( 'VillaTheme_Support' ) ) {
			new VillaTheme_Support( array(
				'support'    => 'https://wordpress.org/support/plugin/woo-alidropship/',
				'docs'       => 'http://docs.villatheme.com/?item=aliexpress-dropshipping-and-fulfillment-for-woocommerce',
				'review'     => 'https://wordpress.org/support/plugin/woo-alidropship/reviews/?rate=5#rate-response',
				'pro_url'    => 'https://1.envato.market/PeXrM',
				'css'        => VI_WOO_ALIDROPSHIP_CSS,
				'image'      => VI_WOO_ALIDROPSHIP_IMAGES,
				'slug'       => 'woo-alidropship',
				'menu_slug'  => 'woo-alidropship-import-list',
				'version'    => VI_WOO_ALIDROPSHIP_VERSION,
				'survey_url' => 'https://script.google.com/macros/s/AKfycbw9mebKbM9JjEYBeedEWSQ3hdrGgl6O5wwqnyqlovdrADAOLscBbY1W89oEmY7JjToTug/exec',
			) );
		}
	}


	/**
	 * load Language translate
	 */
	public function load_plugin_textdomain() {
		$locale = apply_filters( 'plugin_locale', get_locale(), 'woo-alidropship' );
		// Admin Locale
		if ( is_admin() ) {
			load_textdomain( 'woo-alidropship', VI_WOO_ALIDROPSHIP_LANGUAGES . "woo-alidropship-$locale.mo" );
		}

		// Global + Frontend Locale
		load_textdomain( 'woo-alidropship', VI_WOO_ALIDROPSHIP_LANGUAGES . "woo-alidropship-$locale.mo" );
		load_plugin_textdomain( 'woo-alidropship', false, VI_WOO_ALIDROPSHIP_LANGUAGES );
	}

	public function dismiss_notice() {
		update_user_meta( get_current_user_id(), 'vi_wad_show_notice', VI_WOO_ALIDROPSHIP_VERSION );
	}
}
PK     \}Co  o  '  class-villatheme-admin-show-message.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
if ( ! class_exists( 'VILLATHEME_ADMIN_SHOW_MESSAGE' ) ) {
	class VILLATHEME_ADMIN_SHOW_MESSAGE {
		protected static $instance = null;

		public function __construct() {
			add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 1 );
		}

		public function admin_enqueue_scripts() {
			wp_enqueue_style( 'villatheme-admin-show-message', VI_WOO_ALIDROPSHIP_CSS . 'show-message.css', '', VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_script( 'villatheme-admin-show-message', VI_WOO_ALIDROPSHIP_JS . 'show-message.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
		}

		public static function get_instance() {
			// If the single instance hasn't been set, set it now.
			if ( null == self::$instance ) {
				self::$instance = new self;
			}

			return self::$instance;
		}
	}
}PK     \1?Fxd  xd    find_product.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class VI_WOOCOMMERCE_ALIDROPSHIP_Admin_Find_Product
 */
class VI_WOO_ALIDROPSHIP_Admin_Find_Product {
	protected $api_url = 'https://api-sg.aliexpress.com/sync';
	protected $aff_app_key = 33737600;
	protected $per_page = 50;
	protected $mce_init = [];
	protected $qt_init = [];

	public function __construct() {
		add_action( 'admin_init', array( $this, 'admin_init' ), 11 );
		add_action( 'wp_ajax_vi_wad_add_to_import_list', array( $this, 'ajax_add_to_import_list' ) );
		add_action( 'wp_ajax_ald_search_product', array( $this, 'ajax_search_product' ) );
	}

	public function screen_options_page() {
		add_screen_option( 'per_page', array(
			'label'   => esc_html__( 'Number of items per page', 'wp-admin' ),
			'default' => 5,
			'option'  => 'vi_wad_per_page'
		) );
	}

	public function admin_init() {
		if ( ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'ald_find_product' ) && ! empty( $_GET['_wp_http_referer'] ) ) {
			$referer = $_GET['_wp_http_referer'];
			unset( $_GET['_wpnonce'] );
			unset( $_GET['_wp_http_referer'] );

			$referer = add_query_arg( [ 'paged' => 1 ], $referer );

			$url = add_query_arg( $_GET, $referer );
			wp_safe_redirect( $url );
			exit;
		}
	}

	public function base_params( $args ) {

		$params = wp_parse_args( $args, array(
			'format'      => 'json',
			'sign_method' => 'sha256',
		) );

		return $params;
	}

	public function format_price_currency( $args ) {
		$args['currency'] = 'USD';

		return $args;
	}

	private static function get_categories() {
		$categories      = [];
		$categories_file = VI_WOO_ALIDROPSHIP_PACKAGES . 'categories.json';
		if ( is_file( $categories_file ) ) {
			$categories = vi_wad_json_decode( file_get_contents( $categories_file ) );// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
		}

		return $categories;
	}

	private function search_product( $keyword, $category, $country, $paged, $sort ) {
		if ( ! $keyword ) {
			return [];
		}

		$result = [];
		$args   = [
			'keywords'        => $keyword,
			'ship_to_country' => $country,
			'page_size'       => $this->per_page,
			'category_ids'    => $category,
			'page_no'         => $paged,
			'sort'            => $sort,
			'tracking_id'     => 'ald',
		];

		$sign_params = [
			'site_url' => VI_WOO_ALIDROPSHIP_DATA::get_domain_name(),
			'data'     => wp_json_encode( $args )
		];

		$sign_params['app_key'] = $this->aff_app_key;

		$sign_response = VI_WOO_ALIDROPSHIP_DATA::ali_ds_get_sign( $sign_params, 'search_product' );

		if ( $sign_response['status'] == 'error' ) {
			return $result;
		}

		$public_params              = $this->base_params( [ 'app_key' => $this->aff_app_key, 'method' => 'aliexpress.affiliate.product.query' ] );
		$public_params['timestamp'] = $sign_response['data']['timestamp'];
		$public_params['sign']      = $sign_response['data']['data'];

		$response = $this->ali_request( $public_params, $args );

		if ( ! empty( $response['aliexpress_affiliate_product_query_response']['resp_result']['result'] ) ) {
			$result = $response['aliexpress_affiliate_product_query_response']['resp_result']['result'];
		}

		return $result;
	}

	private function ali_request( $params, $body = [] ) {
		try {
			$url     = add_query_arg( array_map( 'urlencode', $params ), $this->api_url );
			$request = wp_remote_post( $url, array(
				'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
				'headers'    => array(
					'Content-Type' => 'text/plain;charset=UTF-8',
				),
				'body'       => $body,
				'timeout'    => 60,
			) );

			if ( ! is_wp_error( $request ) ) {
				$body = wp_remote_retrieve_body( $request );

				return json_decode( $body, true );
			} else {
				return false;
			}
		} catch ( \Exception $e ) {
			return false;
		}
	}

	private static function define_countries() {
		return [
			"AF"    => "Afghanistan",
			"ALA"   => "Aland Islands",
			"AL"    => "Albania",
			"GBA"   => "Alderney",
			"DZ"    => "Algeria",
			"AS"    => "American Samoa",
			"AD"    => "Andorra",
			"AO"    => "Angola",
			"AI"    => "Anguilla",
			"AG"    => "Antigua and Barbuda",
			"AR"    => "Argentina",
			"AM"    => "Armenia",
			"AW"    => "Aruba",
			"ASC"   => "Ascension Island",
			"AU"    => "Australia",
			"AT"    => "Austria",
			"AZ"    => "Azerbaijan",
			"BS"    => "Bahamas",
			"BH"    => "Bahrain",
			"BD"    => "Bangladesh",
			"BB"    => "Barbados",
			"BY"    => "Belarus",
			"BE"    => "Belgium",
			"BZ"    => "Belize",
			"BJ"    => "Benin",
			"BM"    => "Bermuda",
			"BT"    => "Bhutan",
			"BO"    => "Bolivia",
			"BA"    => "Bosnia and Herzegovina",
			"BW"    => "Botswana",
			"BR"    => "Brazil",
			"VG"    => "Virgin Islands (British)",
			"BN"    => "Brunei",
			"BG"    => "Bulgaria",
			"BF"    => "Burkina Faso",
			"BI"    => "Burundi",
			"KH"    => "Cambodia",
			"CM"    => "Cameroon",
			"CA"    => "Canada",
			"CV"    => "Cape Verde",
			"BQ"    => "Caribbean Netherlands",
			"KY"    => "Cayman Islands",
			"CF"    => "Central African Republic",
			"TD"    => "Chad",
			"CL"    => "Chile",
			"CX"    => "Christmas Island",
			"CC"    => "Cocos (Keeling) Islands",
			"CO"    => "Colombia",
			"KM"    => "Comoros",
			"ZR"    => "Congo, The Democratic Republic Of The",
			"CK"    => "Cook Islands",
			"CR"    => "Costa Rica",
			"CI"    => "Cote D'Ivoire",
			"HR"    => "Croatia (local name: Hrvatska)",
			"CW"    => "Curacao",
			"CY"    => "Cyprus",
			"CZ"    => "Czech Republic",
			"DK"    => "Denmark",
			"DJ"    => "Djibouti",
			"DM"    => "Dominica",
			"DO"    => "Dominican Republic",
			"TLS"   => "Timor-Leste",
			"EC"    => "Ecuador",
			"EG"    => "Egypt",
			"SV"    => "El Salvador",
			"GQ"    => "Equatorial Guinea",
			"ER"    => "Eritrea",
			"EE"    => "Estonia",
			"ET"    => "Ethiopia",
			"FK"    => "Falkland Islands (Malvinas)",
			"FO"    => "Faroe Islands",
			"FJ"    => "Fiji",
			"FI"    => "Finland",
			"FR"    => "France",
			"PF"    => "French Polynesia",
			"GA"    => "Gabon",
			"GM"    => "Gambia",
			"GE"    => "Georgia",
			"DE"    => "Germany",
			"GH"    => "Ghana",
			"GI"    => "Gibraltar",
			"GR"    => "Greece",
			"GL"    => "Greenland",
			"GD"    => "Grenada",
			"GP"    => "Guadeloupe",
			"GU"    => "Guam",
			"GT"    => "Guatemala",
			"GGY"   => "Guernsey",
			"GN"    => "Guinea",
			"GW"    => "Guinea-Bissau",
			"GY"    => "Guyana",
			"GF"    => "French Guiana",
			"HT"    => "Haiti",
			"HN"    => "Honduras",
			"HK"    => "Hong Kong,China",
			"HU"    => "Hungary",
			"IS"    => "Iceland",
//			"IN"    => "India",
			"ID"    => "Indonesia",
			"IQ"    => "Iraq",
			"IE"    => "Ireland",
			"IL"    => "Israel",
			"IT"    => "Italy",
			"JM"    => "Jamaica",
			"JP"    => "Japan",
			"JEY"   => "Jersey",
			"JO"    => "Jordan",
			"KZ"    => "Kazakhstan",
			"KE"    => "Kenya",
			"KI"    => "Kiribati",
			"KR"    => "Korea",
			"KS"    => "Kosovo",
			"KW"    => "Kuwait",
			"KG"    => "Kyrgyzstan",
			"LA"    => "Lao People's Democratic Republic",
			"LV"    => "Latvia",
			"LB"    => "Lebanon",
			"LS"    => "Lesotho",
			"LR"    => "Liberia",
			"LY"    => "Libya",
			"LI"    => "Liechtenstein",
			"LT"    => "Lithuania",
			"LU"    => "Luxembourg",
			"MO"    => "Macau,China",
			"MG"    => "Madagascar",
			"MW"    => "Malawi",
			"MY"    => "Malaysia",
			"MV"    => "Maldives",
			"ML"    => "Mali",
			"MT"    => "Malta",
			"MH"    => "Marshall Islands",
			"MQ"    => "Martinique",
			"MR"    => "Mauritania",
			"MU"    => "Mauritius",
			"YT"    => "Mayotte",
			"MX"    => "Mexico",
			"FM"    => "Micronesia",
			"MC"    => "Monaco",
			"MN"    => "Mongolia",
			"MNE"   => "Montenegro",
			"MS"    => "Montserrat",
			"MA"    => "Morocco",
			"MZ"    => "Mozambique",
			"MM"    => "Myanmar",
			"NA"    => "Namibia",
			"NR"    => "Nauru",
			"NP"    => "Nepal",
			"NL"    => "Netherlands",
			"AN"    => "Netherlands Antilles",
			"NC"    => "New Caledonia",
			"NZ"    => "New Zealand",
			"NI"    => "Nicaragua",
			"NE"    => "Niger",
			"NG"    => "Nigeria",
			"NU"    => "Niue",
			"NF"    => "Norfolk Island",
			"MK"    => "Macedonia",
			"MP"    => "Northern Mariana Islands",
			"NO"    => "Norway",
			"OM"    => "Oman",
			"OTHER" => "Other Country",
			"PK"    => "Pakistan",
			"PW"    => "Palau",
			"PS"    => "Palestine",
			"PA"    => "Panama",
			"PG"    => "Papua New Guinea",
			"PY"    => "Paraguay",
			"PE"    => "Peru",
			"PH"    => "Philippines",
			"PL"    => "Poland",
			"PT"    => "Portugal",
			"PR"    => "Puerto Rico",
			"QA"    => "Qatar",
			"MD"    => "Moldova",
			"RE"    => "Reunion",
			"RO"    => "Romania",
			"RU"    => "Russian Federation",
			"RW"    => "Rwanda",
			"BLM"   => "Saint Barthelemy",
			"KN"    => "Saint Kitts and Nevis",
			"LC"    => "Saint Lucia",
			"MAF"   => "Saint Martin",
			"PM"    => "St. Pierre and Miquelon",
			"VC"    => "Saint Vincent and the Grenadines",
			"WS"    => "Samoa",
			"SM"    => "San Marino",
			"ST"    => "Sao Tome and Principe",
			"SA"    => "Saudi Arabia",
			"SN"    => "Senegal",
			"SRB"   => "Serbia",
			"SC"    => "Seychelles",
			"SL"    => "Sierra Leone",
			"SG"    => "Singapore",
			"SX"    => "Sint Maarten",
			"SK"    => "Slovakia (Slovak Republic)",
			"SI"    => "Slovenia",
			"SB"    => "Solomon Islands",
			"SO"    => "Somalia",
			"ZA"    => "South Africa",
			"SGS"   => "South Georgia and the South Sandwich Islands",
			"SS"    => "South Sudan",
			"ES"    => "Spain",
			"LK"    => "Sri Lanka",
			"SR"    => "Suriname",
			"SZ"    => "Swaziland",
			"SE"    => "Sweden",
			"CH"    => "Switzerland",
			"TW"    => "Taiwan,China",
			"TJ"    => "Tajikistan",
			"TZ"    => "Tanzania",
			"TH"    => "Thailand",
			"CG"    => "Congo, The Republic of Congo",
			"VA"    => "Vatican City State (Holy See)",
			"TG"    => "Togo",
			"TO"    => "Tonga",
			"TT"    => "Trinidad and Tobago",
			"TN"    => "Tunisia",
			"TR"    => "Turkey",
			"TM"    => "Turkmenistan",
			"TC"    => "Turks and Caicos Islands",
			"TV"    => "Tuvalu",
			"VI"    => "Virgin Islands (U.S.)",
			"UG"    => "Uganda",
			"UA"    => "Ukraine",
			"AE"    => "United Arab Emirates",
			"UK"    => "United Kingdom",
			"US"    => "United States",
			"UY"    => "Uruguay",
			"UZ"    => "Uzbekistan",
			"VU"    => "Vanuatu",
			"VE"    => "Venezuela",
			"VN"    => "Vietnam",
			"WF"    => "Wallis And Futuna Islands",
			"YE"    => "Yemen",
			"ZM"    => "Zambia",
			"EAZ"   => "Zanzibar",
			"ZW"    => "Zimbabwe",
		];
	}

	public function ajax_add_to_import_list() {
		$return=['status'=>'error'];
		if (!check_ajax_referer( 'woo_alidropship_admin_ajax', 'nonce' ,false)){
			$return['message'] ='Invalid nonce';
			wp_send_json( $return );
		}
		$product_id = isset($_POST['product_id']) ? wc_clean($_POST['product_id']):'';
		$country = isset($_POST['country']) ? wc_clean($_POST['country']):'';
        if (!$product_id || !$country){
	        $import_error = "Invalid data (product_id: {$product_id}, country: {$country}) to get product";
	        $return['message'] =$import_error;
	        wp_send_json( $return );
        }
        $get_data = VI_WOO_ALIDROPSHIP_DATA::get_data( '', [], 'viwad_init_data_before',false,[
			'product_id' => $product_id,
			'target_currency' => 'USD',
			'ship_to_country' => $country,
			'target_language' => 'en',
			'locale' => 'en_US',
			'domain'=>get_site_url(),
			'action' => 'import',
		] );
		if ( $get_data['status'] !== 'success' ) {
			if ( !empty($get_data['message']) ) {
				$result['message']      = $get_data['message'];
			} else {
				$result['message']      = esc_html__( 'Cannot retrieve data. Please contact us and we will help you detect and handle the problem', 'woo-alidropship' );
			}
			wp_send_json( $result );
		}
		$data = $get_data['data']??[];
		$time = time() ;
		$freight     = !empty($get_data['freight']) ? $get_data['freight'] : '';
		if ($freight){
			$freight = VI_WOO_ALIDROPSHIP_DATA::adjust_ali_freight( $freight,$country ==='RU'? 'api_ru':'api' );
		}
		if (empty($freight)){
			$freight = [];
			$time -= HOUR_IN_SECONDS;
		}
		$shipping_info = array(
			'time'          => $time,
			'country'       => $country,
			'company'       =>'',
			'company_name'  => '',
			'freight'       => $freight,
			'freight_ext'   => '',
			'shipping_cost' => null,
			'delivery_time' => '',
		);
		$import_error = $this->add_to_import_list( $data, $shipping_info );
        if ($import_error){
            $return['message'] =$import_error;
        }else {
	        add_filter( 'tiny_mce_before_init', [ $this, 'get_wp_editor_mceinit' ], 10, 2 );
	        add_filter( 'quicktags_settings', [ $this, 'get_wp_editor_qt' ], 10, 2 );
	        ob_start();
	        VI_WOO_ALIDROPSHIP_Admin_Import_List::import_list_html();
	        $return['import_list'] = ob_get_clean();
	        $return['mce_init']    = $this->mce_init;
	        $return['qt_init']     = $this->qt_init;
            $return['status'] = 'success';
	        $return['message'] = esc_html__( 'Product is added to import list', 'woo-alidropship' );
        }
		wp_send_json( $return );
	}
	public function add_to_import_list( $data, $shipping_info ) {
		$error ='';
		$sku     = $data['sku'] ?? '';
		$post_id = VI_WOO_ALIDROPSHIP_DATA::product_get_id_by_aliexpress_id( $sku );
		if ( ! $post_id ) {
			$post_id = VI_WOO_ALIDROPSHIP_DATA::get_instance()->create_product( $data, $shipping_info );
			if ( is_wp_error( $post_id ) ) {
				$error = $post_id->get_error_message();
			} elseif ( ! $post_id ) {
				$error = esc_html__( 'Cannot create post', 'woo-alidropship' );
			}
		} else {
			$error = esc_html__( 'Product exists', 'woo-alidropship' );
		}
        return $error;
	}
	public function get_wp_editor_mceinit( $mceInit, $editor_id ) {
		$this->mce_init[ $editor_id ] = $this->_parse_init( $mceInit );

		return $mceInit;
	}

	public function get_wp_editor_qt( $qtInit, $editor_id ) {
		$this->qt_init[ $editor_id ] = $this->_parse_init( $qtInit );

		return $qtInit;
	}

	private function _parse_init( $init ) {
		$options = '';

		foreach ( $init as $key => $value ) {
			if ( is_bool( $value ) ) {
				$val     = $value ? 'true' : 'false';
				$options .= $key . ':' . $val . ',';
				continue;
			} elseif ( ! empty( $value ) && is_string( $value ) && (
					( '{' === $value[0] && '}' === $value[ strlen( $value ) - 1 ] ) ||
					( '[' === $value[0] && ']' === $value[ strlen( $value ) - 1 ] ) ||
					preg_match( '/^\(?function ?\(/', $value ) ) ) {

				$options .= $key . ':' . $value . ',';
				continue;
			}
			$options .= $key . ':"' . $value . '",';
		}

		return '{' . trim( $options, ' ,' ) . '}';
	}

	public static function search_form() {
		$ald_categories = self::get_categories();
		$countries      = self::define_countries();
		$shipto         = get_option( 'ald_search_product_country' );

		if ( ! $shipto ) {
			$default_country = get_option( 'woocommerce_default_country' );
			$shipto          = current( explode( ':', $default_country ) );
		}

		$shipto = $shipto == 'GB' ? 'UK' : $shipto;

		?>
        <div id="ald-find-product-modal" class="vi-ui modal large">
            <i class="close icon"> </i>
            <div class="header">
                <div class="ald-header-title">
					<?php esc_html_e( 'Find product to import', 'woo-alidropship' ); ?>
                </div>
                <div class="vi-ui negative message ald-message-notice">
                    <div><strong>Important note:</strong> <?php esc_html_e( 'AliExpress does not currently support shipping to certain countries, like India or mainland China. Before starting dropshipping on this platform, it’s recommended to verify whether your country or your target dropshipping destination is supported. Visit AliExpress and check their shipping policies to avoid any potential issues', 'woo-alidropship' ); ?></div>
                </div>
                <form class="vi-ui form small ald-search-product-form">

                    <div class="two fields">
                        <div class="field">
                            <div class="vi-ui labeled input right action">
                                <div class="vi-ui label basic">
									<?php esc_html_e( 'Ship to', 'woo-alidropship' ); ?>
                                </div>
                                <select class="vi-ui dropdown search selection fluid ald-ship-to-country" name="ald_country">
									<?php
									foreach ( $countries as $country_code => $country_name ) {
										printf( "<option value='%s' %s>%s</option>", esc_attr( $country_code ), selected( $shipto, $country_code, false ), esc_html( $country_name ) );
									}
									?>
                                </select>
                            </div>
                        </div>

                        <div class="field">
                            <div class="vi-ui labeled input right action">
                                <div class="vi-ui label basic">
									<?php esc_html_e( 'Sort', 'woo-alidropship' ); ?>
                                </div>
                                <select class="vi-ui dropdown fluid ald-search-product-sort" name="ald_sort">
									<?php
									$sort_options = [
										'SALE_PRICE_ASC'   => esc_html__( 'Price low to high', 'woo-alidropship' ),
										'SALE_PRICE_DESC'  => esc_html__( 'Price high to low', 'woo-alidropship' ),
										'LAST_VOLUME_ASC'  => esc_html__( 'Last volume low to high', 'woo-alidropship' ),
										'LAST_VOLUME_DESC' => esc_html__( 'Last volume high to low', 'woo-alidropship' ),
									];
									foreach ( $sort_options as $key => $name ) {
										printf( "<option value='%s'>%s</option>", esc_attr( $key ), esc_html( $name ) );
									}
									?>
                                </select>
                            </div>
                        </div>
                    </div>

                    <div class="field">
                        <div class="vi-ui action input">
                            <input type="text" placeholder="Search..." name="ald_keyword" class="ald-keyword">
                            <select class="vi-ui search selection dropdown" name="ald_category">
                                <option value=" "><?php esc_html_e( 'All categories' ); ?></option>
								<?php
								foreach ( $ald_categories as $ald_category ) {
									if ( isset( $ald_category['parent_category_id'] ) ) {
										continue;
									}
									printf( "<option value='%s' >%s</option>", esc_attr( $ald_category['category_id'] ), esc_html( $ald_category['category_name'] ) );
								}
								?>
                            </select>
                            <button type="submit" class="vi-ui button ald-search-button" name="ald_search" value="search">
								<?php esc_html_e( 'Search', 'woo-alidropship' ); ?>
                            </button>
                        </div>
                        <span class="ald-keyword-error">
							<?php esc_html_e( 'Input keyword to search', 'woo-alidropship' ); ?>
                        </span>
                    </div>
                </form>

            </div>
            <div class="content scrolling ald-search-result">
            </div>
            <div class="actions">
                <div class="ald-pagination-wrapper"></div>
            </div>
        </div>

		<?php
	}

	public function ajax_search_product() {
        if (!check_ajax_referer( 'woo_alidropship_admin_ajax', 'nonce' ,false)){
	        wp_send_json_error( esc_html__( 'Invalid nonce', 'woo-alidropship' ) );
        }


		$default_country = get_option( 'woocommerce_default_country' );
		$default_country = current( explode( ':', $default_country ) );

		$keyword = ! empty( $_POST['ald_keyword'] ) ? sanitize_text_field( wp_unslash( $_POST['ald_keyword'] ) ) : '';

		if ( ! $keyword ) {
			wp_send_json_error( esc_html__( 'Keyword is empty', 'woo-alidropship' ) );
		}

		$response = [ 'products' => '', 'pagination' => '' ];
		$category           = ! empty( $_POST['ald_category'] ) ? sanitize_text_field( wp_unslash( $_POST['ald_category'] ) ) : '';
		$country            = ! empty( $_POST['ald_country'] ) ? sanitize_text_field( wp_unslash( $_POST['ald_country'] ) ) : $default_country;
		$paged              = ! empty( $_POST['paged'] ) ? sanitize_text_field( wp_unslash( $_POST['paged'] ) ) : 1;
		$sort               = ! empty( $_POST['ald_sort'] ) ? sanitize_text_field( wp_unslash( $_POST['ald_sort'] ) ) : 'SALE_PRICE_ASC';
		$paged              = $paged > 150 ? 150 : $paged;
		$search_products    = $this->search_product( $keyword, $category, $country, $paged, $sort );
		$products           = $search_products['products']['product'] ?? [];
		$current_page       = $search_products['current_page_no'] ?? 1;
		$total_record_count = $search_products['total_record_count'] ?? 0;

		$total_page = ceil( $total_record_count / $this->per_page );
		$total_page -= $total_page > 2 ? 2 : 0;
		$total_page = $total_page > 150 ? 150 : $total_page;

		update_option( 'ald_search_product_country', $country );

		if ( ! empty( $products ) ) {
			ob_start();
			?>
            <div class="vi-ui four column grid">
				<?php
				foreach ( $products as $product ) {
					$product_id = $product['product_id'];
					$posts      = Ali_Product_Table::get_posts( [
						'post_type'   => 'vi_wad_draft_product',
						'post_status' => 'any',
						'meta_query'  => [// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
							array(
								'key'     => '_vi_wad_sku',
								'value'   => $product_id,
								'compare' => '=',
							),
						],
					] );
					$disabled   = ! empty( $posts ) ? ' disabled' : '';

					?>
                    <div class="column">
                        <div class="vi-ui fluid card">
                            <div class="image">
                                <img src="<?php echo esc_url( $product['product_main_image_url'] ) ?>">
                                <div class="ald-product-title">
									<?php
									printf( "<a href='%s' target='_blank' class=''>%s</a>",
										esc_url( $product['product_detail_url'] ), esc_html( $product['product_title'] ) );
									?>
                                </div>
                            </div>
                            <div class="content">
                                <div class="ald-prices-import-button">
                                    <div class="ald-product-prices">
										<?php
										add_filter( 'wc_price_args', [ $this, 'format_price_currency' ] );
										$original_price = $product['target_original_price'] ?? $product['original_price'] ?? '';
										$sale_price     = $product['target_sale_price'] ?? $product['sale_price'] ?? '';
										echo wc_format_sale_price( $original_price, $sale_price );// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
										remove_filter( 'wc_price_args', [ $this, 'format_price_currency' ] );
										?>
                                    </div>
                                    <a href="<?php echo esc_url( add_query_arg( [ 'aldChangeCountry' => $country ], $product['product_detail_url'] ) ) ?>"
                                       data-product_id="<?php echo esc_attr( $product_id ) ?>"
                                       data-product_title="<?php echo esc_attr( $product['product_title'] ) ?>"
                                       class="vi-ui button icon tiny green ald-add-to-import-list<?php echo esc_attr( $disabled ) ?>"
                                       data-tooltip="<?php echo esc_attr__( 'Import this product', 'woo-alidropship' ) ?>">
                                        <i class="plus icon"> </i>
                                    </a>
                                </div>
                            </div>
                        </div>
                    </div>
					<?php
				}
				?>
            </div>
			<?php
			$response['products'] = ob_get_clean();
		} else {
			$response['products'] = esc_html__( 'No product found', 'woo-alidropship' );
		}

		if ( $total_record_count && $total_page > 1 ) {
			ob_start();
			?>
            <div class="ald-pagination">
                <div class="vi-ui pagination menu">
					<?php
					for ( $i = 1; $i <= $total_page; $i ++ ) {
						if ( in_array( $i, [ 1, $current_page - 1, $current_page, $current_page + 1, $total_page - 1, $total_page ] ) ) {
							printf( '<a class="item %s"  data-paged="%d">%s</a>', esc_attr( $current_page == $i ? 'active' : '' ), esc_attr( $i ), esc_html( $i ) );
						} else if ( $i == $current_page - 2 && $current_page - 2 > 1 || $i == $current_page + 2 && $current_page + 2 < $total_page ) {
							echo '<a class="item disabled">...</a>';
						}
					}
					?>
                </div>
            </div>
			<?php
			$response['pagination'] = ob_get_clean();
		}

		wp_send_json_success( $response );
	}
}
PK     \}v  v  	  order.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class VI_WOO_ALIDROPSHIP_Admin_Order {
	private $settings;
	private $is_orders_tracking_active;

	public function __construct() {
		$this->settings = VI_WOO_ALIDROPSHIP_DATA::get_instance();
		//Add column in Order page
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
		add_action( 'manage_shop_order_posts_custom_column', array( $this, 'column_callback_order' ), 10, 2 );
		add_action( 'manage_woocommerce_page_wc-orders_custom_column', array( $this, 'wc_orders_column_callback_order' ), 10, 2 );
		add_filter( 'woocommerce_order_item_display_meta_key', array( $this, 'woocommerce_order_item_display_meta_key' ), 99, 3 );
		add_filter( 'woocommerce_order_item_display_meta_value', array( $this, 'woocommerce_order_item_display_meta_value' ), 99, 3 );
		add_filter( 'woocommerce_hidden_order_itemmeta', array( $this, 'woocommerce_hidden_order_itemmeta' ) );
		add_action( 'woocommerce_after_order_itemmeta', array( $this, 'woocommerce_after_order_itemmeta' ), 10, 3 );
		add_action( 'wp_ajax_vi_wad_manually_update_ali_order_id', array( $this, 'update_ali_order_id' ) );
		add_action( 'wp_ajax_vi_wad_ali_order_detail', array( $this, 'get_ali_order_detail' ) );
		add_filter( 'posts_where', array( $this, 'filter_where' ), 10, 2 );
		add_action( 'woocommerce_new_order_item', array( $this, 'add_order_item_meta' ), 10, 2 );
		add_filter( 'views_edit-shop_order', array( $this, 'ali_filter' ) );
		add_filter( 'views_woocommerce_page_wc-orders', array( $this, 'wc_orders_ali_filter' ) );
		add_action( 'woocommerce_order_actions_end', array( $this, 'order_ali_button' ) );

//		add_filter( 'woocommerce_shop_order_search_fields', array( $this, 'woocommerce_shop_order_search_ali_order' ) );
		add_filter( 'posts_where', array( $this, 'posts_where' ), 1, 2 );
		add_filter( 'woocommerce_orders_table_query_clauses', [ $this, 'add_items_query' ] );
		add_filter( 'woocommerce_order_list_table_prepare_items_query_args', [ $this, 'add_order_filter_status' ] );
	}


	public function posts_join( $join, $wp_query ) {
		global $wpdb;
		$join .= " LEFT JOIN {$wpdb->prefix}woocommerce_order_items as vi_wad_woocommerce_order_items ON $wpdb->posts.ID=vi_wad_woocommerce_order_items.order_id";
		$join .= " LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as vi_wad_woocommerce_order_itemmeta ON vi_wad_woocommerce_order_items.order_item_id=vi_wad_woocommerce_order_itemmeta.order_item_id";

		return $join;
	}

	public function posts_where( $where, $wp_query ) {
		global $wpdb;
		$post_type = isset( $_GET['post_type'] ) ? sanitize_text_field( $_GET['post_type'] ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$post_status = isset( $_GET['post_status'] ) ? sanitize_text_field( $_GET['post_status'] ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended

		if (  $post_type === 'shop_order'  &&  $post_status === 'ali_filter' ) {
			$order_status_for_fulfill = $this->settings->get_params( 'order_status_for_fulfill' );
			$search    = isset( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$where .= $wpdb->prepare( " OR (vi_wad_woocommerce_order_itemmeta.meta_key='_vi_wad_aliexpress_order_id' AND vi_wad_woocommerce_order_itemmeta.meta_value = %s)", $search );
			if ( $order_status_for_fulfill ) {
				$where .= " AND wp_posts.post_status IN ( '" . implode( "','", $order_status_for_fulfill ) . "' )";
			}
            add_filter( 'posts_join', array( $this, 'posts_join' ), 10, 2 );
			add_filter( 'posts_distinct', array( $this, 'posts_distinct' ), 10, 2 );
		}

		return $where;
	}

	public function posts_distinct( $join, $wp_query ) {
		return 'DISTINCT';
	}

	public function woocommerce_shop_order_search_ali_order( $search_fields ) {
		$search_fields[] = '_ali_order_index';

		return $search_fields;
	}

	/**
	 * Update Ali order ID manually
	 *
	 * @throws Exception
	 */
	public function update_ali_order_id() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		check_ajax_referer( 'woo_alidropship_admin_ajax', '_vi_wad_ajax_nonce' );
		$ali_order_id = isset( $_POST['ali_order_id'] ) ? trim( sanitize_text_field( $_POST['ali_order_id'] ) ) : '';
		$item_id      = isset( $_POST['item_id'] ) ? sanitize_text_field( $_POST['item_id'] ) : '';
		$response     = array(
			'status'          => 'error',
			'message'         => '',
			'text'            => '',
			'delete_tracking' => 'no',
		);
		if ( $item_id ) {
			if ( wc_update_order_item_meta( $item_id, '_vi_wad_aliexpress_order_id', $ali_order_id ) ) {
				if ( $ali_order_id ) {
					wc_update_order_item_meta( $item_id, '_vi_wad_aliexpress_order_item_status', 'processing' );
					$response['text'] = $this->status_switch( 'processing' );
				} else {
					wc_update_order_item_meta( $item_id, '_vi_wad_aliexpress_order_item_status', 'pending' );
					$response['text'] = $this->status_switch( 'pending' );
				}
				$item_tracking_data = wc_get_order_item_meta( $item_id, '_vi_wot_order_item_tracking_data', true );
				if ( $item_tracking_data ) {
					$item_tracking_data    = vi_wad_json_decode( $item_tracking_data );
					$current_tracking_data = array_pop( $item_tracking_data );
					if ( $current_tracking_data['tracking_number'] || ( $current_tracking_data['carrier_slug'] && $current_tracking_data['carrier_url'] && $current_tracking_data['carrier_name'] ) ) {
						$item_tracking_data[] = array(
							'tracking_number' => '',
							'carrier_slug'    => '',
							'carrier_url'     => '',
							'carrier_name'    => '',
							'carrier_type'    => '',
							'time'            => time(),
						);
						if ( wc_update_order_item_meta( $item_id, '_vi_wot_order_item_tracking_data', wp_json_encode( $item_tracking_data ) ) ) {
							$response['delete_tracking'] = 'yes';
						}
					}
				}

				$response['status'] = 'success';
			}
		}
		wp_send_json( $response );
	}

	public function status_switch( $stt ) {
		$pattern = array(
			'pending'    => array( __( 'To Order', 'woo-alidropship' ), 'red' ),
			'processing' => array( __( 'Processing', 'woo-alidropship' ), '#0089F7' ),
			'shipped'    => array( __( 'Shipped', 'woo-alidropship' ), '#00B400' ),
		);

		return isset( $pattern[ $stt ] ) ? $pattern[ $stt ] : $pattern['pending'];
	}

	public function admin_enqueue_scripts( $page ) {
		global $post_type;
		$screen = get_current_screen();
		if ( ( $page === 'post.php' && $screen->id === 'shop_order' ) || ( $page == 'woocommerce_page_wc-orders' && ! empty( $_GET['action'] ) && $_GET['action'] == 'edit' ) ) {// phpcs:ignore WordPress.Security.NonceVerification.Recommended
            wp_enqueue_style( 'woo-alidropship-admin-edit-order', VI_WOO_ALIDROPSHIP_CSS . 'admin-order.css', '', VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_script( 'woo-alidropship-admin-edit-order', VI_WOO_ALIDROPSHIP_JS . 'admin-order.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
			if ( class_exists( 'VIWOT_WOO_ORDERS_TRACKING' ) || class_exists( 'VI_WOOCOMMERCE_ORDERS_TRACKING_DATA' ) ) {
				$this->is_orders_tracking_active = true;
			} else {
				$this->is_orders_tracking_active = false;
			}
			wp_localize_script( 'woo-alidropship-admin-edit-order', 'vi_wad_edit_order', array(
				'url'                => admin_url( 'admin-ajax.php' ),
				'_vi_wad_ajax_nonce' => VI_WOO_ALIDROPSHIP_Admin_Settings::create_ajax_nonce(),
			) );
		} elseif ( ( $page === 'edit.php' && $post_type === 'shop_order' ) || ( $page == 'woocommerce_page_wc-orders' && empty( $_GET['action'] ) ) ) {// phpcs:ignore WordPress.Security.NonceVerification.Recommended
            wp_enqueue_style( 'woo-alidropship-popup', VI_WOO_ALIDROPSHIP_CSS . 'popup.min.css',[], VI_WOO_ALIDROPSHIP_VERSION  );
			wp_enqueue_style( 'woo-alidropship-order-status', VI_WOO_ALIDROPSHIP_CSS . 'order-status.css', '', VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_script( 'woo-alidropship-order-status', VI_WOO_ALIDROPSHIP_JS . 'order-status.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION , false);
			wp_localize_script( 'woo-alidropship-order-status', 'orderStt', array(
				'ajaxUrl'            => admin_url( 'admin-ajax.php' ),
				'_vi_wad_ajax_nonce' => VI_WOO_ALIDROPSHIP_Admin_Settings::create_ajax_nonce(),
			) );
			wp_add_inline_script( 'woo-alidropship-order-status', $this->sync_orders_button() );
		}
	}
	public function sync_orders_button() {
		ob_start();
		?>
        <script type="text/javascript">
            'use strict';
            jQuery(document).ready(function ($) {
                jQuery(".wrap .page-title-action").eq(0).after("<a class='page-title-action' target='_blank' href='<?php echo esc_url( VI_WOO_ALIDROPSHIP_DATA::get_get_tracking_url() ) ?>'><?php esc_html_e( 'AliExpress sync', 'woo-alidropship' ) ?></a>");
            });
        </script>
		<?php
		return  preg_replace( '#<script[^>]*>(.*)</script>#is', '$1', ob_get_clean() ) ;
	}

	public function woocommerce_hidden_order_itemmeta( $hidden_order_itemmeta ) {
		$hidden_order_itemmeta[] = '_vi_wad_match_aliexpress_order_id';
		$hidden_order_itemmeta[] = '_vi_wad_aliexpress_order_id';
		$hidden_order_itemmeta[] = '_vi_order_item_tracking_code';
		$hidden_order_itemmeta[] = '_vi_wad_aliexpress_order_item_status';
		$hidden_order_itemmeta[] = '_vi_wot_order_item_tracking_data';

		return $hidden_order_itemmeta;
	}

	/**
	 * @param $item_id
	 * @param $item
	 * @param $product WC_Product
	 *
	 * @throws Exception
	 */
	public function woocommerce_after_order_itemmeta( $item_id, $item, $product ) {
		global $theorder;

		if ( ! $theorder || ! is_a( $item, 'WC_Order_Item_Product' ) || ! is_object( $product ) ) {
			return;
		}

		$order_id   = $theorder->get_id();
		$product_id = $product->get_id();

		if ( ! get_post_meta( $product_id, '_vi_wad_aliexpress_product_id', true ) && ! get_post_meta( $product_id, '_vi_wad_aliexpress_variation_id', true ) ) {
			return;
		}

		$aliexpress_order_id = wc_get_order_item_meta( $item_id, '_vi_wad_aliexpress_order_id', true );
		$ali_order_detail    = $tracking_url = $tracking_url_btn = '';
		if ( $aliexpress_order_id ) {
			$ali_order_detail = "https://trade.aliexpress.com/order_detail.htm?orderId={$aliexpress_order_id}";
			$tracking_url     = "http://track.aliexpress.com/logisticsdetail.htm?tradeId={$aliexpress_order_id}";
			$tracking_url_btn = VI_WOO_ALIDROPSHIP_DATA::get_get_tracking_url( $aliexpress_order_id );
		}
		$item_tracking_data    = wc_get_order_item_meta( $item_id, '_vi_wot_order_item_tracking_data', true );
		$current_tracking_data = array(
			'tracking_number' => '',
			'carrier_slug'    => '',
			'carrier_url'     => '',
			'carrier_name'    => '',
			'carrier_type'    => '',
			'time'            => time(),
		);
		if ( $item_tracking_data ) {
			$item_tracking_data    = vi_wad_json_decode( $item_tracking_data );
			$current_tracking_data = array_pop( $item_tracking_data );
		}
		$tracking_number = apply_filters( 'vi_woo_orders_tracking_current_tracking_number', $current_tracking_data['tracking_number'], $item_id, $order_id );
		$carrier_url     = apply_filters( 'vi_woo_orders_tracking_current_tracking_url', $current_tracking_data['carrier_url'], $item_id, $order_id );
		$carrier_name    = apply_filters( 'vi_woo_orders_tracking_current_carrier_name', $current_tracking_data['carrier_name'], $item_id, $order_id );
		$carrier_slug    = apply_filters( 'vi_woo_orders_tracking_current_carrier_slug', $current_tracking_data['carrier_slug'], $item_id, $order_id );
		$get_tracking    = array( 'item-actions-get-tracking' );
		if ( ! $aliexpress_order_id ) {
			$get_tracking[] = 'hidden';
		}
		?>
        <div class="<?php echo esc_attr( self::set( 'container' ) ) ?>">
            <div class="<?php echo esc_attr( self::set( array(
				'item-details',
				'item-ali-order-id'
			) ) ) ?>"
                 data-product_item_id="<?php echo esc_attr( $item_id ) ?>">
                <div class="<?php echo esc_attr( self::set( 'item-label' ) ) ?>">
                    <span><?php esc_html_e( 'Ali Order ID', 'woo-alidropship' ) ?></span>
                </div>
                <div class="<?php echo esc_attr( self::set( 'item-value' ) ) ?>">
                    <a class="<?php echo esc_attr( self::set( 'ali-order-id' ) ) ?>"
                       href="<?php echo esc_attr( $ali_order_detail ) ?>"
                       data-old_ali_order_id="<?php echo esc_attr( $aliexpress_order_id ) ?>"
                       target="_blank">
                        <input readonly
                               class="<?php echo esc_attr( self::set( array( 'ali-order-id-input' ) ) ) ?>"
                               value="<?php echo esc_attr( $aliexpress_order_id ) ?>">
                    </a>
                </div>
                <div class="<?php echo esc_attr( self::set( 'item-actions' ) ) ?>">
                    <span class="dashicons dashicons-edit <?php echo esc_attr( self::set( 'item-actions-edit' ) ) ?>"
                          title="<?php esc_attr_e( 'Edit', 'woo-alidropship' ) ?>">
                    </span>
                    <span class="dashicons dashicons-yes <?php echo esc_attr( self::set( array(
						'item-actions-save',
						'hidden'
					) ) ) ?>"
                          title="<?php esc_attr_e( 'Save', 'woo-alidropship' ) ?>">
                    </span>
                    <span class="dashicons dashicons-no-alt <?php echo esc_attr( self::set( array(
						'item-actions-cancel',
						'hidden'
					) ) ) ?>"
                          title="<?php esc_attr_e( 'Cancel', 'woo-alidropship' ) ?>">
                    </span>
					<?php
					if ( $this->is_orders_tracking_active ) {
						?>
                        <a href="<?php echo esc_attr( $tracking_url_btn ) ?>" target="_blank">
                            <span class="dashicons dashicons-arrow-down-alt <?php echo esc_attr( self::set( $get_tracking ) ) ?>"
                                  title="<?php esc_attr_e( 'Get tracking', 'woo-alidropship' ) ?>">
                            </span>
                        </a>
						<?php
					}
					?>
                </div>
                <div class="<?php echo esc_attr( self::set( array(
					'item-value-overlay',
					'hidden'
				) ) ) ?>"></div>
            </div>
			<?php
			if ( ! $this->is_orders_tracking_active ) {
				?>
                <div class="<?php echo esc_attr( self::set( array(
					'item-details',
					'item-tracking-number'
				) ) ) ?>" data-product_item_id="<?php echo esc_attr( $item_id ) ?>">
                    <div class="<?php echo esc_attr( self::set( 'item-label' ) ) ?>">
                        <span><?php esc_html_e( 'Tracking number', 'woo-alidropship' ) ?></span>
                    </div>
                    <div class="<?php echo esc_attr( self::set( 'item-value' ) ) ?>">
                        <a class="<?php echo esc_attr( self::set( 'ali-tracking-number' ) ) ?>"
                           href="<?php echo esc_attr( $tracking_url ) ?>"
                           target="_blank">
                            <input readonly
                                   class="<?php echo esc_attr( self::set( array( 'ali-tracking-number-input' ) ) ) ?>"
                                   value="<?php echo esc_attr( $tracking_number ) ?>">
                        </a>
                    </div>
                    <div class="<?php echo esc_attr( self::set( 'item-actions' ) ) ?>">
                        <a href="<?php echo esc_attr( $tracking_url_btn ) ?>" target="_blank">
                            <span class="dashicons dashicons-arrow-down-alt <?php echo esc_attr( self::set( $get_tracking ) ) ?>"
                                  title="<?php esc_attr_e( 'Get tracking', 'woo-alidropship' ) ?>">
                            </span>
                        </a>
                    </div>
                </div>
				<?php
			}
			?>
        </div>
		<?php
	}

	private static function set( $name, $set_name = false ) {
		return VI_WOO_ALIDROPSHIP_DATA::set( $name, $set_name );
	}

	public function woocommerce_order_item_display_meta_key( $display_key, $meta, $item ) {
		if ( $meta->key === '_vi_wad_match_aliexpress_order_id' ) {
			$display_key = esc_html__( 'AliExpress order ID', 'woo-alidropship' );
		}

		return $display_key;
	}

	public function woocommerce_order_item_display_meta_value( $display_value, $meta, $item ) {
		if ( $meta->key === '_vi_wad_match_aliexpress_order_id' ) {
			$value = $meta->value;
			if ( $value ) {
				$display_value = sprintf( '<a target="_blank" href="https://trade.aliexpress.com/order_detail.htm?orderId=%s">%s</a>', $value, $value );
			}
		}

		return $display_value;
	}

	/**
	 * @param $item_id
	 * @param $values
	 *
	 * @throws Exception
	 */
	public function add_order_item_meta( $item_id, $values ) {
		$pid = $values['product_id'];
		if ( get_post_meta( $pid, '_vi_wad_aliexpress_product_id', true ) ) {
			wc_update_order_item_meta( $item_id, '_vi_wad_aliexpress_order_item_status', 'pending' );
			wc_update_order_item_meta( $item_id, '_vi_wad_aliexpress_order_id', '' );
		}
	}

	/**
	 * @param $col_id
	 * @param $order_id
	 *
	 * @throws Exception
	 */
	public function column_callback_order( $col_id, $order_id ) {
		if ( $col_id === 'order_number' ) {
			$order          = wc_get_order( $order_id );
			$statuses       = $this->settings->get_params( 'order_status_for_fulfill' );
			$order_items    = $order->get_items();
			$fulfill_action = $status = $ali_product_id = $ali_pid = '';
			$total          = $ordered = $shipped = $tracking_number = 0;
			$order_stt      = $color = '';

			if ( count( $order_items ) ) {
				foreach ( $order_items as $item_id => $order_item ) {
					$pid            = $order_item->get_data()['product_id'];
					$ali_product_id = get_post_meta( $pid, '_vi_wad_aliexpress_product_id', true );
					$ali_pid        = $ali_product_id ? $ali_product_id : $ali_pid;
					if ( $ali_product_id ) {
						$item_tracking_data = wc_get_order_item_meta( $item_id, '_vi_wot_order_item_tracking_data', true );
						if ( $item_tracking_data ) {
							$item_tracking_data    = vi_wad_json_decode( $item_tracking_data );
							$current_tracking_data = array_pop( $item_tracking_data );
							if ( $current_tracking_data['tracking_number'] ) {
								$tracking_number ++;
							}
						}
						if ( $order_item->get_meta( '_vi_wad_aliexpress_order_id' ) ) {
							$ordered ++;
						}
						if ( $order_item->get_meta( '_vi_wad_aliexpress_order_item_status' ) == 'shipped' ) {
							$shipped ++;
						}
						$total ++;
					}
				}

				if ( $total && $ali_pid && is_array( $statuses ) && in_array( 'wc-' . $order->get_status(), $statuses ) ) {

					$order_rate    = $ordered / $total;
					$tracking_rate = $tracking_number / $total;
					$shipped_rate  = $shipped / $total;

					$href   = add_query_arg( array(
						'fromDomain'  => urlencode( site_url() ),
						'orderID'     => $order_id,
						'fromProduct' => $ali_pid
					), 'https://www.aliexpress.com' );
					$target = '_blank';

					if ( $shipped_rate == 1 ) {
						$order_stt = __( 'Shipped', 'woo-alidropship' );
						$color     = 'shipped';
					} else {
						if ( $order_rate == 0 && $tracking_rate == 0 ) {
							$order_stt = __( 'To Order', 'woo-alidropship' );
							$color     = 'to-order';
						} elseif ( $order_rate < 1 && $tracking_rate <= 1 ) {
							$order_stt = __( 'Processing', 'woo-alidropship' );
							$color     = 'processing';
						} elseif ( $order_rate == 1 && $tracking_rate < 1 ) {
							$order_stt = __( 'Processing', 'woo-alidropship' );
							$color     = 'full-processing';
							$href      = 'javascript:void(0)';
							$target    = '';
						} elseif ( $order_rate == 1 && $tracking_rate == 1 ) {
							$order_stt = __( 'In transit', 'woo-alidropship' );
							$color     = 'completed';
							$href      = 'javascript:void(0)';
							$target    = '';
						}
					}

					$tooltip        = 'Light green: No order  &#xa;Orange: Not enough order & tracking code &#xa;Gray: Not enough tracking code &#xa;Light blue: Full tracking code';
					$fulfill_action = "<a data-tooltip='{$tooltip}' data-position='bottom center' data-inverted='' class='wad-fulfill-button' target='{$target}' href='" . esc_attr( $href ) . "'>" . $order_stt . "</a>";
					$status         = "<button type='button' class='wad-show-detail {$color}' data-id='{$order_id}'><i class='wad-icon dashicons dashicons-arrow-down wad-spinner'></i></button>"; //<span class='wad-shipped-status {$shipped_color}'>{$shipped_view} </span>
				}
			}

			echo wp_kses_post("<div class='wad-fulfill-group {$color}'>" . $fulfill_action . $status . '</div>');
		}
	}

	public function wc_orders_column_callback_order( $col_id, $order ) {
		$order_id = $order->get_id();
		$this->column_callback_order( $col_id, $order_id );
	}

	/**
	 * @throws Exception
	 */
	public function get_ali_order_detail() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		check_ajax_referer( 'woo_alidropship_admin_ajax', '_vi_wad_ajax_nonce' );
		$order_id = isset( $_POST['id'] ) ? sanitize_text_field( $_POST['id'] ) : '';
		if ( ! $order_id ) {
			wp_die();
		}

		$order       = wc_get_order( $order_id );
		$order_items = $order->get_items();
		$res         = '';

		if ( ! empty( $order_items ) ) {
			foreach ( $order_items as $item ) {
				$item_id           = $item->get_id();
				$item_data         = $item->get_data();
				$vid               = $item_data['variation_id'] ? $item_data['variation_id'] : $item_data['product_id'];
				$pid               = $item_data['product_id'];
				$name              = $item_data['name'];
				$ali_pid           = get_post_meta( $pid, '_vi_wad_aliexpress_product_id', true );
				$variation_product = wc_get_product( $vid );
				if ( ! $variation_product ) {
					continue;
				}
				$link               = $variation_product->get_permalink();
				$sku                = $variation_product->get_sku();
				$ali_order_id       = $item->get_meta( '_vi_wad_aliexpress_order_id' );
				$item_tracking_data = wc_get_order_item_meta( $item_id, '_vi_wot_order_item_tracking_data', true );
				$tracking_number    = '';
				$carrier_name       = '';
				$carrier_url        = '';
				if ( $item_tracking_data ) {
					$item_tracking_data    = vi_wad_json_decode( $item_tracking_data );
					$current_tracking_data = array_pop( $item_tracking_data );
					$current_tracking_data = apply_filters( 'vi_woo_alidropship_order_item_tracking_data', $current_tracking_data, $item_id, $order_id );
					$tracking_number       = $current_tracking_data['tracking_number'];
					$carrier_name          = $current_tracking_data['carrier_name'];
					$carrier_url           = $current_tracking_data['carrier_url'];
				}
				$status = $item->get_meta( '_vi_wad_aliexpress_order_item_status' );
				if ( $ali_pid ) {
					$color = $item_stt = $manual = '';

					if ( $status == 'shipped' ) {
						$item_stt = "<span class='wad-item-stt shipped'>" . esc_html__( 'Shipped', 'woo-alidropship' ) . "</span>";
					} else {
						if ( ! $ali_order_id ) {
							$item_stt = "<span class='wad-item-stt to-order'>" . esc_html__( 'To order', 'woo-alidropship' ) . "</span>";
						} elseif ( $ali_order_id && ! $tracking_number ) {
							$item_stt = "<span class='wad-item-stt processing'>" . esc_html__( 'Processing', 'woo-alidropship' ) . "</span>";
						} elseif ( $ali_order_id && $tracking_number ) {
							$item_stt = "<span class='wad-item-stt completed'>" . esc_html__( 'In transit', 'woo-alidropship' ) . "</span>";
						}
					}

					if ( ! $ali_order_id ) {
						$manual = "<a class='wad-manual-btn' href='https://www.aliexpress.com/item/$ali_pid.html' target='_blank'>" . esc_html__( 'Manual', 'woo-alidropship' ) . "</a>";
					}
					ob_start();
					?>
                    <div class='wad-ali-order-item <?php echo esc_attr( $color ) ?>'>
                        <div>
							<?php echo VI_WOO_ALIDROPSHIP_DATA::wp_kses_post( $item_stt ), VI_WOO_ALIDROPSHIP_DATA::wp_kses_post( $manual ) //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
                            <a class="wad-order-item-name"
                               href="<?php echo esc_url( $link ) ?>"><?php echo esc_html( $name ) ?></a>
                        </div>
                        <div>
                            <table class="wad-list-ali-order-items">
                                <tr>
                                    <td>
										<?php
										esc_html_e( 'SKU: ', 'woo-alidropship' );
										echo esc_html( $sku );
										?>
                                    </td>
                                    <td>
										<?php
										esc_html_e( 'Order ID: ', 'woo-alidropship' );
										?>
                                        <a target="_blank"
                                           href="https://trade.aliexpress.com/order_detail.htm?orderId=<?php echo esc_attr( $ali_order_id ) ?>"
                                           class="wad-ali-product-link"><?php echo esc_html( $ali_order_id ) ?></a>
                                        <input type="text" name="wad_ali_order_ID" class="wad-ali-order-id"
                                               value="<?php echo esc_attr( $ali_order_id ) ?>">
                                        <span data-tooltip="Save" data-inverted=''>
                                            <i class="wad-icon dashicons dashicons-yes"></i>
                                        </span>
                                        <span data-tooltip="Edit" data-inverted=''>
                                            <i class="wad-icon dashicons dashicons-edit"></i>
                                        </span>
                                    </td>
                                    <td class="wad-column">
										<?php
										echo esc_html__( 'Tracking code: ', 'woo-alidropship' );
										if ( $carrier_url ) {
											?>
                                            <a href="<?php echo esc_attr( $carrier_url ) ?>"
                                               target="_blank"><?php echo esc_html( $tracking_number ) ?></a>
											<?php
										} else {
											?>
                                            <span><?php echo esc_html( $tracking_number ) ?></span>
											<?php
										}
										if ( $ali_order_id ) {
											?>
                                            <a href="<?php echo esc_url( VI_WOO_ALIDROPSHIP_DATA::get_get_tracking_url( $ali_order_id ) ) ?>"
                                               target="_blank" class="wad-get-tracking-code-manual">
                                                <i class="dashicons dashicons-arrow-down-alt"></i>
                                            </a>
											<?php
										}

										?>
                                    </td>
                                    <td>
										<?php
										if ( $carrier_name ) {
											esc_html_e( 'Carrier: ', 'woo-alidropship' );
											if ( $carrier_url ) {
												?>
                                                <a href="<?php echo esc_attr( $carrier_url ) ?>"
                                                   target="_blank"><?php echo esc_html( $carrier_name ) ?></a>
												<?php
											} else {
												?>
                                                <span><?php echo esc_html( $carrier_name ) ?></span>
												<?php
											}
										}
										?>
                                    </td>
                                </tr>
                            </table>
                        </div>
                    </div>
					<?php
					$res .= ob_get_clean();
				}
			}
			if ( $res ) {
				wp_send_json_success( $res );
			} else {
				wp_send_json_error();
			}
		}
		wp_die();
	}

	public function filter_order() {
		if ( get_current_screen()->id === 'edit-shop_order' ) {
			$stt = '';
			if ( isset( $_GET['vi_wad_order_stt'] ) ) {// phpcs:ignore WordPress.Security.NonceVerification.Recommended
				$stt = esc_attr( sanitize_text_field( $_GET['vi_wad_order_stt'] ) );// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			}
			$options = array(
				''           => __( 'Filter by AliExpress order status', 'woo-alidropship' ),
				'pending'    => __( 'To Order', 'woo-alidropship' ),
				'processing' => __( 'Processing', 'woo-alidropship' ),
				'shipped'    => __( 'Shipped', 'woo-alidropship' ),
			);
			?>
            <select name="vi_wad_order_stt" class="wad-order-filter">
				<?php
				foreach ( $options as $option => $show ) {
					?>
                    <option value="<?php echo esc_attr( $option ) ?>" <?php selected( $stt, $option ) ?>><?php echo esc_html( $show ) ?></option>
					<?php
				}
				?>
            </select>
			<?php
		}
	}

	public function filter_where( $where, $wp_q ) {
		if ( isset( $_GET['post_status'], $_GET['post_type'] ) && sanitize_text_field( $_GET['post_status'] ) == 'ali_filter' && sanitize_text_field( $_GET['post_type'] ) == 'shop_order' ) {// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			global $wpdb;
			$t_order_items    = $wpdb->prefix . "woocommerce_order_items";
			$t_order_itemmeta = $wpdb->prefix . "woocommerce_order_itemmeta";
			$order_stt        = $this->settings->get_params( 'order_status_for_fulfill' );
			$order_stt        = implode( "','", $order_stt );
			$query            = "SELECT  wp_posts.ID FROM  $wpdb->posts AS wp_posts LEFT JOIN $t_order_items ON wp_posts.ID=$t_order_items.order_id ";
			$query            .= "LEFT JOIN $t_order_itemmeta ON $t_order_items.order_item_id=$t_order_itemmeta.order_item_id ";
			$query            .= " WHERE wp_posts.post_status IN ( '$order_stt' )AND $t_order_itemmeta.meta_key='_vi_wad_aliexpress_order_id' AND $t_order_itemmeta.meta_value=''";
			$where            .= " AND $wpdb->posts.ID IN( $query)";
		}

		//		if ( is_search() ) {
		//			if ( ! empty( $_GET['vi_wad_order_stt'] ) ) {
		//				$stt   = sanitize_text_field( $_GET['vi_wad_order_stt'] );
		//				$where .= " AND $wpdb->posts.ID IN(";
		//				$where .= " SELECT  $wpdb->posts.ID FROM  $wpdb->posts LEFT JOIN $t_order_items ON $wpdb->posts.ID=$t_order_items.order_id LEFT JOIN $t_order_itemmeta ON $t_order_items.order_item_id=$t_order_itemmeta.order_item_id WHERE $t_order_itemmeta.meta_key='_vi_wad_aliexpress_order_item_status' AND $t_order_itemmeta.meta_value='{$stt}')";
		//			}
		//		}

		return $where;
	}


	public function ali_filter( $views ) {
		global $wpdb;
		$t_order_items    = $wpdb->prefix . "woocommerce_order_items";
		$t_order_itemmeta = $wpdb->prefix . "woocommerce_order_itemmeta";
		$count_posts      = 0;
		$ids              = array();
		$order_stt        = $this->settings->get_params( 'order_status_for_fulfill' );
		if ( $order_stt ) {
			$order_stt   = implode( "','", $order_stt );
			$query       = "SELECT COUNT(DISTINCT wp_posts.ID) FROM  $wpdb->posts AS wp_posts LEFT JOIN $t_order_items ON wp_posts.ID=$t_order_items.order_id ";
			$query       .= "LEFT JOIN $t_order_itemmeta ON $t_order_items.order_item_id=$t_order_itemmeta.order_item_id ";
			$query       .= " WHERE wp_posts.post_status IN ( '$order_stt' )AND $t_order_itemmeta.meta_key='_vi_wad_aliexpress_order_id' AND $t_order_itemmeta.meta_value=''";
			$count_posts = $wpdb->get_var( $query );// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		}
		$views['ali_filter'] = "<a href='edit.php?post_status=ali_filter&post_type=shop_order'>" . __( 'To order', 'woo-alidropship' ) . "</a>(" . $count_posts . ")";

		return $views;
	}

	public function wc_orders_ali_filter( $views ) {
		$current = ! empty( $_GET['status'] ) && $_GET['status'] == 'ali_filter' ? 'current' : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended

		$views['ali_filter'] = sprintf( "<a href='%s' class='%s'>%s <span class='count'>(%s)</span></a>",
			esc_url( admin_url( 'admin.php?page=wc-orders&status=ali_filter' ) ),
			esc_attr( $current ),
			esc_html__( 'To order', 'woo-alidropship' ),
			esc_html( VI_WOO_ALIDROPSHIP_DATA::get_ali_orders() )
		);

		return $views;
	}

	public function order_ali_button( $order_id ) {
		$order       = new WC_Order( $order_id );
		$order_items = $order->get_items();
		$ali_pid     = '';

		if ( count( $order_items ) ) {
			foreach ( $order_items as $order_item ) {
				$pid            = $order_item->get_data()['product_id'];
				$ali_product_id = get_post_meta( $pid, '_vi_wad_aliexpress_product_id', true );
				$ali_pid        = $ali_product_id ? $ali_product_id : $ali_pid;
			}
		}
		$statuses = $this->settings->get_params( 'order_status_for_fulfill' );
		if ( is_array( $statuses ) && $ali_pid && in_array( 'wc-' . $order->get_status(), $statuses ) ) {
			$href = add_query_arg( array(
				'fromDomain'  => urlencode( site_url() ),
				'orderID'     => $order_id,
				'fromProduct' => $ali_pid
			), 'https://www.aliexpress.com' );
			?>
            <li class="wide">
                <div class="vi-wad-ali-order-btn">
                    <a href="<?php echo esc_url( $href ); ?>" target="_blank"
                       class="button"><?php esc_html_e( 'To Order AliExpress', 'woo-alidropship' ); ?></a>
                </div>
            </li>
			<?php
		}
	}

	public function add_items_query( $args ) {
		if ( isset( $_GET['status'], $_GET['page'] ) && $_GET['status'] === 'ali_filter' && $_GET['page'] === 'wc-orders' ) {// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			global $wpdb;
			$args['join']  .= " LEFT JOIN {$wpdb->prefix}woocommerce_order_items ON {$wpdb->prefix}wc_orders.id={$wpdb->prefix}woocommerce_order_items.order_id";
			$args['join']  .= " LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta ON {$wpdb->prefix}woocommerce_order_items.order_item_id={$wpdb->prefix}woocommerce_order_itemmeta.order_item_id";
			$args['where'] .= " AND {$wpdb->prefix}woocommerce_order_itemmeta.meta_key='_vi_wad_aliexpress_order_id'";
		}

		return $args;
	}

	public function add_order_filter_status( $order_query_args ) {
		if (! empty( $_GET['page'] ) && sanitize_text_field( wp_unslash( $_GET['page'] ) ) === 'wc-orders'){// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$current = ! empty( $_GET['status'] ) && sanitize_text_field( wp_unslash( $_GET['status'] ) ) === 'ali_filter' ? 'current' : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		}else{
			$current = ! empty( $_GET['post_status'] ) && sanitize_text_field( wp_unslash( $_GET['post_status'] ) ) === 'ali_filter' ? 'current' : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		}
		if (!$current){
			return  $order_query_args;
		}
		$order_status_for_fulfill   = $this->settings->get_params( 'order_status_for_fulfill' );
		$order_query_args['status'] = $order_status_for_fulfill;

		return $order_query_args;
	}
}
PK     \n  n    error_images.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class VI_WOO_ALIDROPSHIP_Admin_Error_Images {
	protected $settings;

	public function __construct() {
		$this->settings = VI_WOO_ALIDROPSHIP_DATA::get_instance();
		add_action( 'admin_init', array( $this, 'create_table' ) );
		add_action( 'admin_init', array( $this, 'empty_list' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
		add_action( 'admin_menu', array( $this, 'admin_menu' ), 17 );
		add_action( 'wp_ajax_vi_wad_download_error_product_images', array( $this, 'download_error_product_images' ) );
		add_action( 'wp_ajax_vi_wad_delete_error_product_images', array( $this, 'delete_error_product_images' ) );
		add_filter( 'set-screen-option', array( $this, 'save_screen_options' ), 10, 3 );
		add_action( 'admin_head', array( $this, 'menu_product_count' ), 999 );
		add_action( 'wp_ajax_wad_search_product_failed_images', array( $this, 'search_product' ) );
	}

	private static function check_ajax_referer() {
		VI_WOO_ALIDROPSHIP_Admin_Settings::check_ajax_referer( 'woo-alidropship-error-images' );
	}

	public function search_product() {
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$keyword = isset( $_GET['keyword'] ) ? sanitize_text_field( $_GET['keyword'] ) : '';
		if ( empty( $keyword ) ) {
			die();
		}
		$found_products = array();
		$product_ids    = VI_WOO_ALIDROPSHIP_Error_Images_Table::get_products_ids( $keyword );
		foreach ( $product_ids as $product_id ) {
			$found_products[] = array(
				'id'   => $product_id,
				'text' => "(#{$product_id}) " . get_the_title( $product_id )
			);
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $found_products );
	}

	public function empty_list() {
		global $wpdb;
		$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
		if ( ! empty( $_GET['vi_wad_empty_error_images'] ) && $page === 'woo-alidropship-error-images' ) {
			$nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
			if ( wp_verify_nonce( $nonce ) ) {
				$wpdb->query( "DELETE from {$wpdb->prefix}vi_wad_error_product_images" );// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				wp_safe_redirect( admin_url( "admin.php?page={$page}" ) );
				exit();
			}
		}
	}

	public function menu_product_count() {
		global $submenu;
		if ( isset( $submenu['woo-alidropship-import-list'] ) ) {
			// Add count if user has access.
			if ( apply_filters( 'woo_aliexpress_dropship_error_images_count_in_menu', true ) && current_user_can( 'manage_options' ) ) {
				$product_count = VI_WOO_ALIDROPSHIP_Error_Images_Table::get_rows( 0, 0, true );
				foreach ( $submenu['woo-alidropship-import-list'] as $key => $menu_item ) {
					if ( 0 === strpos( $menu_item[0], _x( 'Failed Images', 'Admin menu name', 'woo-alidropship' ) ) ) {
						$submenu['woo-alidropship-import-list'][ $key ][0] .= ' <span class="update-plugins count-' . esc_attr( $product_count ) . '"><span class="' . self::set( 'error-images-count' ) . '">' . number_format_i18n( $product_count ) . '</span></span>'; // WPCS: override ok.
						break;
					}
				}
			}
		}
	}

	private static function set( $name, $set_name = false ) {
		return VI_WOO_ALIDROPSHIP_DATA::set( $name, $set_name );
	}

	public function create_table() {
		if ( ! get_option( 'vi_wad_create_table_of_error_product_images' ) ) {
			VI_WOO_ALIDROPSHIP_Error_Images_Table::create_table();
			update_option( 'vi_wad_create_table_of_error_product_images', time() );
		}
	}

	public function download_error_product_images() {
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		vi_wad_set_time_limit();
		$id       = isset( $_POST['item_id'] ) ? sanitize_text_field( wp_slash( $_POST['item_id'] ) ) : '';
		$response = array(
			'status'  => 'error',
			'message' => 'Error',
		);
		if ( $id ) {
			$data = VI_WOO_ALIDROPSHIP_Error_Images_Table::get_row( $id );
			if ( count( $data ) ) {
				$product_id = $data['product_id'];
				$post       = get_post( $product_id );
				if ( $post && $post->post_type === 'product' ) {
					if ( $data['set_gallery'] != 2 || ( ! $this->settings->get_params( 'use_external_image' ) && $this->settings->get_params( 'download_description_images' ) ) ) {
						$thumb_id = VI_WOO_ALIDROPSHIP_DATA::download_image( $image_id, html_entity_decode( $data['image_src'] ), $product_id );


						if ( $thumb_id && ! is_wp_error( $thumb_id ) ) {
							$cancel = apply_filters( 'ald_cancel_set_product_gallery', false, $thumb_id, $data );
							if ( ! $cancel ) {
								if ( $data['set_gallery'] == 2 ) {
									$downloaded_url = wp_get_attachment_url( $thumb_id );
									$description    = html_entity_decode( $post->post_content, ENT_QUOTES | ENT_XML1, 'UTF-8' );
									$description    = preg_replace( '/[^"]{0,}' . preg_quote( $image_id, '/' ) . '[^"]{0,}/U', $downloaded_url, $description );
									$description    = str_replace( $data['image_src'], $downloaded_url, $description );
									wp_update_post( array( 'ID' => $product_id, 'post_content' => $description ) );
								} else {
									if ( $data['product_ids'] ) {
										$product_ids = explode( ',', $data['product_ids'] );
										foreach ( $product_ids as $v_id ) {
											if ( in_array( get_post_type( $v_id ), array( 'product', 'product_variation' ) ) ) {
												update_post_meta( $v_id, '_thumbnail_id', $thumb_id );
											}
										}
									}

									if ( 1 == $data['set_gallery'] ) {
										$gallery = get_post_meta( $product_id, '_product_image_gallery', true );
										if ( $gallery ) {
											$gallery_array = explode( ',', $gallery );
										} else {
											$gallery_array = array();
										}
										$gallery_array[] = $thumb_id;
										update_post_meta( $product_id, '_product_image_gallery', implode( ',', array_unique( $gallery_array ) ) );
									}
								}
							}
							$response['status'] = 'success';
							VI_WOO_ALIDROPSHIP_Error_Images_Table::delete( $id );
						} else {
							$response['message'] = $thumb_id->get_error_message();
						}
					} else {
						$response['message'] = esc_html__( 'Please disable "Use external links for images" and enable "Import description images"', 'woo-alidropship' );
					}
				} else {
					$response['message'] = esc_html__( 'Product does not exist', 'woo-alidropship' );
				}
			} else {
				$response['message'] = esc_html__( 'Not found', 'woo-alidropship' );
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $response );
	}

	public function delete_error_product_images() {
		self::check_ajax_referer();
		// phpcs:disable WordPress.Security.NonceVerification
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		vi_wad_set_time_limit();
		$id       = isset( $_POST['item_id'] ) ? sanitize_text_field( wp_slash( $_POST['item_id'] ) ) : '';
		$response = array(
			'status'  => 'error',
			'message' => 'Error',
		);
		if ( $id ) {
			$delete = VI_WOO_ALIDROPSHIP_Error_Images_Table::delete( $id );
			if ( $delete ) {
				$response['status'] = 'success';
			} else {
				$response['message'] = esc_html__( 'Can not remove image from list', 'woo-alidropship' );
			}
		} else {
			$response['message'] = esc_html__( 'Not found', 'woo-alidropship' );
		}
		// phpcs:enable WordPress.Security.NonceVerification
		wp_send_json( $response );
	}

	public function save_screen_options( $status, $option, $value ) {
		if ( 'vi_wad_error_images_per_page' === $option ) {
			return $value;
		}

		return $status;
	}

	/**
	 * Add Screen Options
	 */
	public function screen_options_page() {
		add_screen_option( 'per_page', array(
			'label'   => esc_html__( 'Number of items per page', 'wp-admin' ),
			'default' => 10,
			'option'  => 'vi_wad_error_images_per_page'
		) );
	}

	public function admin_menu() {
		$import_list = add_submenu_page(
			'woo-alidropship-import-list',
			esc_html__( 'Failed Images', 'woo-alidropship' ),
			esc_html__( 'Failed Images', 'woo-alidropship' ),
			'manage_options',
			'woo-alidropship-error-images',
			array( $this, 'page_callback' )
		);
		add_action( "load-$import_list", array( $this, 'screen_options_page' ) );
	}

	public function page_callback() {
		$user     = get_current_user_id();
		$screen   = get_current_screen();
		$option   = $screen->get_option( 'per_page', 'option' );
		$per_page = get_user_meta( $user, $option, true );
		if ( empty ( $per_page ) || $per_page < 1 ) {
			$per_page = $screen->get_option( 'per_page', 'default' );
		}
		$paged = isset( $_GET['paged'] ) ? sanitize_text_field( $_GET['paged'] ) : 1;// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		?>
        <div class="wrap">
            <h2><?php esc_html_e( 'All failed images', 'woo-alidropship' ) ?></h2>
			<?php
			$vi_wad_search_product_id = isset( $_GET['vi_wad_search_product_id'] ) ? sanitize_text_field( $_GET['vi_wad_search_product_id'] ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$count                    = VI_WOO_ALIDROPSHIP_Error_Images_Table::get_rows( 0, 0, true, $vi_wad_search_product_id );
			$results                  = VI_WOO_ALIDROPSHIP_Error_Images_Table::get_rows( $per_page, ( $paged - 1 ) * $per_page, false, $vi_wad_search_product_id );
			if ( count( $results ) ) {
				if ( $this->settings->get_params( 'use_external_image' ) || ! $this->settings->get_params( 'download_description_images' ) ) {
					?>
                    <div class="vi-ui negative message">
                        <div><?php esc_html_e( 'Please disable "Use external links for images" and enable "Import description images" to make Import button available for Description images', 'woo-alidropship' ); ?></div>
                    </div>
					<?php
				}
				ob_start();
				?>
                <form class="vi-ui form">
                    <table class="vi-ui celled table">
                        <thead>
                        <tr>
                            <th><?php esc_html_e( 'Index', 'woo-alidropship' ) ?></th>
                            <th><?php esc_html_e( 'Product ID', 'woo-alidropship' ) ?></th>
                            <th><?php esc_html_e( 'Product Title', 'woo-alidropship' ) ?></th>
                            <th><?php esc_html_e( 'Product/Variation IDs', 'woo-alidropship' ) ?></th>
                            <th><?php esc_html_e( 'Image url', 'woo-alidropship' ) ?></th>
                            <th><?php esc_html_e( 'Used for', 'woo-alidropship' ) ?></th>
                            <th><?php esc_html_e( 'Actions', 'woo-alidropship' ) ?></th>
                        </tr>
                        </thead>
                        <tbody>
						<?php
						foreach ( $results as $key => $result ) {
							$product = wc_get_product( $result['product_id'] );
							if ( ! $product ) {
								?>
                                <tr>
                                    <td>
                                        <span class="<?php echo esc_attr( self::set( 'index' ) ) ?>"><?php echo esc_html( $key + 1 ) ?></span>
                                    </td>

									<?php
									foreach ( $result as $result_k => $result_v ) {
										if ( $result_k === 'id' ) {
											continue;
										}
										?>
                                        <td>
										<span>
                                            <?php
                                            switch ( $result_k ) {
	                                            case 'image_src':
		                                            ?>
                                                    <img width="48" height="48"
                                                         src="<?php echo esc_attr( $result_v ) ?>">
		                                            <?php
		                                            break;
	                                            case 'product_ids':
		                                            echo wp_kses_post( str_replace( ',', ', ', $result_v ) );
		                                            break;
	                                            case 'set_gallery':
		                                            if ( $result_v == 2 ) {
			                                            esc_attr_e( 'Description', 'woo-alidropship' );
		                                            } elseif ( $result_v == 1 ) {
			                                            esc_attr_e( 'Gallery', 'woo-alidropship' );
		                                            } else {
			                                            esc_attr_e( 'Product/variation image', 'woo-alidropship' );
		                                            }
		                                            break;
	                                            default:
		                                            echo esc_html( $result_v );
                                            }
                                            ?>
                                        </span>
                                        </td>
										<?php
										if ( $result_k === 'product_id' ) {
											?>
                                            <td>-
                                            </td>
											<?php
										}
									}
									?>
                                    <td>
                                        <div class="<?php echo esc_attr( self::set( 'actions-container' ) ) ?>">
                                            <span><?php esc_html_e( 'The product this image belongs to was deleted so this image is now removed from list', 'woo-alidropship' ) ?></span>
                                        </div>
                                    </td>
                                </tr>
								<?php
								VI_WOO_ALIDROPSHIP_Error_Images_Table::delete( $result['id'] );
								continue;
							} else {
								?>
                                <tr>
                                    <td>
                                        <span class="<?php echo esc_attr( self::set( 'index' ) ) ?>"><?php echo esc_html( $key + 1 ) ?></span>
                                    </td>
									<?php
									$hide_import_button = false;
									foreach ( $result as $result_k => $result_v ) {
										if ( $result_k === 'id' ) {
											continue;
										}
										?>
                                        <td>
										<span>
                                            <?php
                                            switch ( $result_k ) {
	                                            case 'image_src':
		                                            ?>
                                                    <img width="48" height="48"
                                                         src="<?php echo esc_attr( $result_v ) ?>">
		                                            <?php
		                                            break;
	                                            case 'product_ids':
		                                            echo wp_kses_post( str_replace( ',', ', ', $result_v ) );
		                                            break;
	                                            case 'set_gallery':
		                                            if ( $result_v == 2 ) {
			                                            esc_attr_e( 'Description', 'woo-alidropship' );
			                                            if ( $this->settings->get_params( 'use_external_image' ) || ! $this->settings->get_params( 'download_description_images' ) ) {
				                                            $hide_import_button = true;
			                                            }
		                                            } elseif ( $result_v == 1 ) {
			                                            esc_attr_e( 'Gallery', 'woo-alidropship' );
		                                            } else {
			                                            esc_attr_e( 'Product/variation image', 'woo-alidropship' );
		                                            }
		                                            break;
	                                            default:
		                                            echo esc_html( $result_v );
                                            }
                                            ?>
                                        </span>
                                        </td>
										<?php
										if ( $result_k === 'product_id' ) {
											?>
                                            <td><a class="<?php echo esc_attr( self::set( 'product-title' ) ) ?>"
                                                   target="_blank"
                                                   href="<?php echo esc_url( admin_url( 'post.php?action=edit&post=' . $result['product_id'] ) ) ?>"><?php echo esc_html( $product->get_title() ) ?></a>
                                            </td>
											<?php
										}
									}
									?>
                                    <td>
                                        <div class="<?php echo esc_attr( self::set( 'actions-container' ) ) ?>">
											<?php
											if ( ! $hide_import_button ) {
												?>
                                                <span class="vi-ui positive button <?php echo esc_attr( self::set( 'action-download' ) ) ?>"
                                                      data-item_id="<?php echo esc_attr( $result['id'] ) ?>"><?php esc_html_e( 'Import', 'woo-alidropship' ) ?></span>
												<?php
											}
											?>
                                            <span class="vi-ui negative button <?php echo esc_attr( self::set( 'action-delete' ) ) ?>"
                                                  data-item_id="<?php echo esc_attr( $result['id'] ) ?>"><?php esc_html_e( 'Delete', 'woo-alidropship' ) ?></span>
                                        </div>
                                    </td>
                                </tr>
								<?php
							}
						}
						?>
                        </tbody>
                    </table>
                </form>
				<?php
				$image_list = ob_get_clean();
				ob_start();
				?>
                <form method="get">
                    <input type="hidden" name="page" value="woo-alidropship-error-images">
                    <div class="tablenav top">
                        <div class="<?php echo esc_attr( self::set( 'button-all-container' ) ) ?>">
                            <span class="vi-ui button positive <?php echo esc_attr( self::set( 'action-download-all' ) ) ?>"><?php esc_html_e( 'Import All', 'woo-alidropship' ) ?></span>
                            <span class="vi-ui button negative <?php echo esc_attr( self::set( 'action-delete-all' ) ) ?>"><?php esc_html_e( 'Delete All', 'woo-alidropship' ) ?></span>
                            <a href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'vi_wad_empty_error_images', 1 ) ) ) ?>"
                               class="vi-ui button negative <?php echo esc_attr( self::set( 'action-empty-error-images' ) ) ?>"
                               title="<?php esc_attr_e( 'Remove all failed images from database', 'woo-alidropship' ) ?>"><?php esc_html_e( 'Empty List', 'woo-alidropship' ) ?></a>
                        </div>
                        <div class="tablenav-pages">
                            <div class="pagination-links">
								<?php
								$total_page = ceil( $count / $per_page );
								/*Previous button*/
								if ( $per_page * $paged > $per_page ) {
									$p_paged = $paged - 1;
								} else {
									$p_paged = 0;
								}
								if ( $p_paged ) {
									$p_url = add_query_arg(
										array(
											'page'                     => 'woo-alidropship-error-images',
											'paged'                    => $p_paged,
											'vi_wad_search_product_id' => $vi_wad_search_product_id,
										), admin_url( 'admin.php' )
									);
									?>
                                    <a class="prev-page button" href="<?php echo esc_url( $p_url ) ?>"><span
                                                class="screen-reader-text"><?php esc_html_e( 'Previous Page', 'woo-alidropship' ) ?></span><span
                                                aria-hidden="true">‹</span></a>
									<?php
								} else {
									?>
                                    <span class="tablenav-pages-navspan button disabled" aria-hidden="true">‹</span>
									<?php
								}
								?>
                                <span class="screen-reader-text"><?php esc_html_e( 'Current Page', 'woo-alidropship' ) ?></span>
                                <span id="table-paging" class="paging-input">
                                    <span class="tablenav-paging-text">
                                        <input class="current-page" type="text" name="paged" size="1"
                                               value="<?php echo esc_html( $paged ) ?>"><span
                                                class="tablenav-paging-text"><?php esc_html_e( ' of ', 'woo-alidropship' ) ?>
                                            <span
                                                    class="total-pages"><?php echo esc_html( $total_page ) ?></span>
                                        </span>
                                    </span>
                                </span>
								<?php /*Next button*/
								if ( $per_page * $paged < $count ) {
									$n_paged = $paged + 1;
								} else {
									$n_paged = 0;
								}
								if ( $n_paged ) {
									$n_url = add_query_arg(
										array(
											'page'                     => 'woo-alidropship-error-images',
											'paged'                    => $n_paged,
											'vi_wad_search_product_id' => $vi_wad_search_product_id,
										), admin_url( 'admin.php' )
									); ?>
                                    <a class="next-page button" href="<?php echo esc_url( $n_url ) ?>"><span
                                                class="screen-reader-text"><?php esc_html_e( 'Next Page', 'woo-alidropship' ) ?></span><span
                                                aria-hidden="true">›</span></a>
									<?php
								} else {
									?>
                                    <span class="tablenav-pages-navspan button disabled" aria-hidden="true">›</span>
									<?php
								}
								?>
                            </div>
                        </div>
						<?php
						$products = VI_WOO_ALIDROPSHIP_Error_Images_Table::get_products_ids();
						if ( count( $products ) < 100 ) {
							if ( count( $products ) > 1 ) {
								ob_start();
								foreach ( $products as $product_id ) {
									$product = wc_get_product( $product_id );
									if ( $product ) {
										?>
                                        <option value="<?php echo esc_attr( $product_id ) ?>" <?php selected( $product_id, $vi_wad_search_product_id ) ?>><?php echo esc_html( "(#{$product_id}){$product->get_title()}" ) ?></option>
										<?php
									}
								}
								$filter_product_html = ob_get_clean();
								if ( $filter_product_html ) {
									?>
                                    <p class="search-box">
                                        <select name="vi_wad_search_product_id" class="vi-wad-search-product-id">
                                            <option value=""><?php esc_html_e( 'Filter by product', 'woo-alidropship' ) ?></option>
											<?php
											echo wp_kses( $filter_product_html, VI_WOO_ALIDROPSHIP_DATA::allow_html() );
											?>
                                        </select>
                                    </p>
									<?php
								}
							}
						} else {
							?>
                            <p class="search-box">
                                <select name="vi_wad_search_product_id" class="vi-wad-search-product-id-ajax">
									<?php
									if ( $vi_wad_search_product_id ) {
										$product = wc_get_product( $vi_wad_search_product_id );
										if ( $product ) {
											?>
                                            <option value="<?php echo esc_attr( $vi_wad_search_product_id ) ?>"
                                                    selected><?php echo esc_html( "(#{$vi_wad_search_product_id}){$product->get_title()}" ) ?></option>
											<?php
										}
									}
									?>
                                </select>
                            </p>
							<?php
						}
						?>
                    </div>
                </form>
				<?php
				$pagination_html = ob_get_clean();
				echo wp_kses( $pagination_html, $this->settings::allow_html() );
				echo wp_kses( $image_list, $this->settings::allow_html() );
				echo wp_kses( $pagination_html, $this->settings::allow_html() );
			} else {
				?>
                <div class="vi-ui segment">
                    <p>
						<?php esc_html_e( 'You don\'t have any failed images.', 'woo-alidropship' ) ?>
                    </p>
                </div>
				<?php
			}
			wp_reset_postdata();
			?>
        </div>
		<?php
	}

	public function enqueue_semantic() {
		wp_dequeue_script( 'select-js' );//Causes select2 error, from ThemeHunk MegaMenu Plus plugin
		wp_dequeue_style( 'eopa-admin-css' );
		/*Stylesheet*/
		wp_enqueue_style( 'vi-woo-alidropship-form', VI_WOO_ALIDROPSHIP_CSS . 'form.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'vi-woo-alidropship-table', VI_WOO_ALIDROPSHIP_CSS . 'table.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'vi-woo-alidropship-icon', VI_WOO_ALIDROPSHIP_CSS . 'icon.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'vi-woo-alidropship-segment', VI_WOO_ALIDROPSHIP_CSS . 'segment.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'vi-woo-alidropship-button', VI_WOO_ALIDROPSHIP_CSS . 'button.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'vi-woo-alidropship-select2', VI_WOO_ALIDROPSHIP_CSS . 'select2.min.css', [], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_script( 'vi-woo-alidropship-select2-v4', VI_WOO_ALIDROPSHIP_JS . 'select2.js', array( 'jquery' ), '4.0.3', false );
	}

	public function bump_request_timeout( $val ) {
		return $this->settings->get_params( 'request_timeout' );
	}

	public function admin_enqueue_scripts() {
		global $pagenow;
		$page = isset( $_REQUEST['page'] ) ? wp_unslash( sanitize_text_field( $_REQUEST['page'] ) ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( $pagenow === 'admin.php' && $page === 'woo-alidropship-error-images' ) {
			$this->enqueue_semantic();
			wp_enqueue_style( 'woo-alidropship-error-images', VI_WOO_ALIDROPSHIP_CSS . 'error-images.css', '', VI_WOO_ALIDROPSHIP_VERSION );
			wp_enqueue_script( 'woo-alidropship-error-images', VI_WOO_ALIDROPSHIP_JS . 'error-images.js', array( 'jquery' ), VI_WOO_ALIDROPSHIP_VERSION, false );
			wp_localize_script( 'woo-alidropship-error-images', 'vi_wad_params_admin_error_images', array(
				'url'                     => admin_url( 'admin-ajax.php' ),
				'_vi_wad_ajax_nonce'      => VI_WOO_ALIDROPSHIP_Admin_Settings::create_ajax_nonce(),
				'i18n_confirm_delete'     => esc_html__( 'Are you sure you want to delete this item?', 'woo-alidropship' ),
				'i18n_confirm_delete_all' => esc_html__( 'Are you sure you want to delete all item(s) on this page?', 'woo-alidropship' ),
			) );
		}
	}
}PK     \UIJ      transfer_settings.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class VI_WOO_ALIDROPSHIP_Admin_Transfer_Settings {
	protected $settings;
	protected $error;

	public function __construct() {
		$this->settings = VI_WOO_ALIDROPSHIP_DATA::get_instance();
		add_action( 'admin_init', array( $this, 'admin_init' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
		add_action( 'admin_menu', array( $this, 'admin_menu' ), 20 );
	}

	private static function set( $name, $set_name = false ) {
		return VI_WOO_ALIDROPSHIP_DATA::set( $name, $set_name );
	}

	public function admin_init() {
		global $wooaliexpressdropship_settings;
		if ( isset( $_POST['vi_wad_import_settings'] ) && isset( $_POST['_wooaliexpressdropship_nonce'] ) && wp_verify_nonce( sanitize_text_field( $_POST['_wooaliexpressdropship_nonce'] ), 'wooaliexpressdropship_save_settings' ) ) {
			$args = vi_wad_json_decode( base64_decode( sanitize_text_field( $_POST['vi_wad_transfer_settings>'] ) ) );
			if ( is_array( $args ) && count( $args ) ) {
				$this->error = false;
				$args        = array_merge( $this->settings->get_params(), $args );
				update_option( 'wooaliexpressdropship_params', $args );
				$wooaliexpressdropship_settings = $args;
				$this->settings                 = VI_WOO_ALIDROPSHIP_DATA::get_instance( true );
			} else {
				$this->error = true;
			}
		}
	}

	public function admin_menu() {
		add_submenu_page(
			'woo-alidropship-import-list',
			esc_html__( 'Transfer Settings', 'woo-alidropship' ),
			esc_html__( 'Transfer Settings', 'woo-alidropship' ),
			'manage_options',
			'woo-alidropship-transfer-settings',
			array( $this, 'page_callback' )
		);
	}

	public function page_callback() {
		?>
        <div class="wrap">
            <h2><?php esc_attr_e( 'Export/Import Settings', 'woo-alidropship' ) ?></h2>
            <div class="vi-ui segment">
				<?php
				if ( $this->error === true ) {
					?>
                    <div class="vi-ui negative message">
                        <div class="header">
							<?php esc_html_e( 'Invalid input' ); ?>
                        </div>
                    </div>
					<?php
				} elseif ( $this->error === false ) {
					?>
                    <div class="vi-ui positive message">
                        <div class="header">
							<?php esc_html_e( 'Import settings successfully' ); ?>
                        </div>
                    </div>
					<?php
				}
				?>
                <form class="vi-ui form" method="post">
					<?php
					wp_nonce_field( 'wooaliexpressdropship_save_settings', '_wooaliexpressdropship_nonce' )
					?>
                    <h4><?php esc_html_e( 'Your current settings:', 'woo-alidropship' ) ?></h4>
                    <textarea style="width: 100%;min-height: 200px; "
                              name="<?php echo esc_attr( self::set( 'transfer-settings', true ) ) ?>>"><?php echo esc_html( trim( base64_encode( wp_json_encode( $this->settings->get_params() ) ) ) ); ?></textarea>
                    <p>
                        <input type="submit" class="vi-ui primary button"
                               name="<?php echo esc_attr( self::set( 'import-settings', true ) ) ?>"
                               value="<?php esc_attr_e( 'Import Settings', 'woo-alidropship' ) ?>">
                    </p>
                </form>
                <div class="vi-ui blue message">
                    <div>
						<?php esc_html_e( 'To move your settings from site A to site B, please copy this field from site A and paste it to the same field on site B then click Import Settings.' ); ?>
                    </div>
                </div>
            </div>
        </div>
		<?php
	}

	public function enqueue_semantic() {
		wp_dequeue_style( 'eopa-admin-css' );
		/*Stylesheet*/
		wp_enqueue_style( 'vi-woo-alidropship-form', VI_WOO_ALIDROPSHIP_CSS . 'form.min.css' ,[], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'vi-woo-alidropship-table', VI_WOO_ALIDROPSHIP_CSS . 'table.min.css',[], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'vi-woo-alidropship-icon', VI_WOO_ALIDROPSHIP_CSS . 'icon.min.css',[], VI_WOO_ALIDROPSHIP_VERSION  );
		wp_enqueue_style( 'vi-woo-alidropship-segment', VI_WOO_ALIDROPSHIP_CSS . 'segment.min.css' ,[], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'vi-woo-alidropship-button', VI_WOO_ALIDROPSHIP_CSS . 'button.min.css' ,[], VI_WOO_ALIDROPSHIP_VERSION );
		wp_enqueue_style( 'vi-woo-alidropship-message', VI_WOO_ALIDROPSHIP_CSS . 'message.min.css' ,[], VI_WOO_ALIDROPSHIP_VERSION );
//		wp_enqueue_style( 'select2', VI_WOO_ALIDROPSHIP_CSS . 'select2.min.css',[], VI_WOO_ALIDROPSHIP_VERSION  );
//		if ( woocommerce_version_check( '3.0.0' ) ) {
//			wp_enqueue_script( 'select2' );
//		} else {
//			wp_enqueue_script( 'select2-v4', VI_WOO_ALIDROPSHIP_JS . 'select2.js', array( 'jquery' ), '4.0.3' , false);
//		}
	}


	public function admin_enqueue_scripts() {
		global $pagenow;
		$page = isset( $_REQUEST['page'] ) ? wp_unslash( sanitize_text_field( $_REQUEST['page'] ) ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( $pagenow === 'admin.php' && $page === 'woo-alidropship-transfer-settings' ) {
			$this->enqueue_semantic();
		}
	}
}PK     \.0dc  c    migrate-new-table.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class VI_WOO_ALIDROPSHIP_Admin_Migrate_New_Table {
	public static $migrate_process;

	public function __construct() {
		add_action( 'init', [ $this, 'background_process' ] );
		add_action( 'wp_ajax_ald_migrate_to_new_table', array( $this, 'migrate_to_new_table' ) );
		add_action( 'wp_ajax_ald_migrate_remove_old_data', array( $this, 'remove_old_data' ) );
	}

	public function migrate_to_new_table() {
		check_ajax_referer( 'woo_alidropship_admin_ajax', '_vi_wad_ajax_nonce' );
		Ali_Product_Table::create_table();
		$migrate_process = new VI_WOO_ALIDROPSHIP_BACKGROUND_MIGRATE_NEW_TABLE();

		if ( $migrate_process->is_queue_empty() && ! $migrate_process->is_process_running() ) {
			$migrate_process->push_to_queue( [ 'step' => 'move' ] );
			$migrate_process->save()->dispatch();
		}

		wp_send_json_success( esc_html__( 'Migration progress has started running in the background.', 'woo-alidropship' ) );
	}

	public function remove_old_data() {
		check_ajax_referer( 'woo_alidropship_admin_ajax', '_vi_wad_ajax_nonce' );
		$migrate_process = new VI_WOO_ALIDROPSHIP_BACKGROUND_MIGRATE_NEW_TABLE();

		if ( $migrate_process->is_queue_empty() && ! $migrate_process->is_process_running() ) {
			$migrate_process->push_to_queue( [ 'step' => 'delete' ] );
			$migrate_process->save()->dispatch();
		}

		wp_send_json_success( esc_html__( 'Deletion progress has started running in the background.', 'woo-alidropship' ) );
	}

	public function background_process() {
		self::$migrate_process = new VI_WOO_ALIDROPSHIP_BACKGROUND_MIGRATE_NEW_TABLE();
		if ( ! self::$migrate_process->is_queue_empty() || self::$migrate_process->is_process_running() ) {
//			error_log( print_r( $migrate_process, true ) );
		}
	}

	public static function migrate_process() {
		return self::$migrate_process;
	}
}

PK     \`/  /    edit-contact-form.phpnu [        <?php

// don't load directly
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

$save_button = sprintf(
	'<input %s />',
	wpcf7_format_atts( array(
		'type' => 'submit',
		'class' => 'button-primary',
		'name' => 'wpcf7-save',
		'value' => __( 'Save', 'contact-form-7' ),
	) )
);

$formatter = new WPCF7_HTMLFormatter( array(
	'allowed_html' => array_merge( wpcf7_kses_allowed_html(), array(
		'form' => array(
			'method' => true,
			'action' => true,
			'id' => true,
			'class' => true,
			'disabled' => true,
		),
	) ),
) );

$formatter->append_start_tag( 'div', array(
	'class' => 'wrap',
	'id' => 'wpcf7-contact-form-editor',
) );

$formatter->append_start_tag( 'h1', array(
	'class' => 'wp-heading-inline',
) );

$formatter->append_preformatted(
	esc_html( $post->initial()
		? __( 'Add Contact Form', 'contact-form-7' )
		: __( 'Edit Contact Form', 'contact-form-7' )
	)
);

$formatter->end_tag( 'h1' );

if ( ! $post->initial() and current_user_can( 'wpcf7_edit_contact_forms' ) ) {
	$formatter->append_whitespace();

	$formatter->append_preformatted(
		wpcf7_link(
			menu_page_url( 'wpcf7-new', false ),
			__( 'Add Contact Form', 'contact-form-7' ),
			array( 'class' => 'page-title-action' )
		)
	);
}

$formatter->append_start_tag( 'hr', array(
	'class' => 'wp-header-end',
) );

$formatter->call_user_func( static function () use ( $post ) {
	do_action( 'wpcf7_admin_warnings',
		$post->initial() ? 'wpcf7-new' : 'wpcf7',
		wpcf7_current_action(),
		$post
	);

	do_action( 'wpcf7_admin_notices',
		$post->initial() ? 'wpcf7-new' : 'wpcf7',
		wpcf7_current_action(),
		$post
	);
} );

if ( $post ) {
	$formatter->append_start_tag( 'form', array(
		'method' => 'post',
		'action' => esc_url( add_query_arg(
			array( 'post' => $post_id ),
			menu_page_url( 'wpcf7', false )
		) ),
		'id' => 'wpcf7-admin-form-element',
		'disabled' => ! current_user_can( 'wpcf7_edit_contact_form', $post_id ),
	) );

	if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
		$formatter->call_user_func( static function () use ( $post_id ) {
			wp_nonce_field( 'wpcf7-save-contact-form_' . $post_id );
		} );
	}

	$formatter->append_start_tag( 'input', array(
		'type' => 'hidden',
		'id' => 'post_ID',
		'name' => 'post_ID',
		'value' => (int) $post_id,
	) );

	$formatter->append_start_tag( 'input', array(
		'type' => 'hidden',
		'id' => 'wpcf7-locale',
		'name' => 'wpcf7-locale',
		'value' => $post->locale(),
	) );

	$formatter->append_start_tag( 'input', array(
		'type' => 'hidden',
		'id' => 'hiddenaction',
		'name' => 'action',
		'value' => 'save',
	) );

	$formatter->append_start_tag( 'input', array(
		'type' => 'hidden',
		'id' => 'active-tab',
		'name' => 'active-tab',
		'value' => wpcf7_superglobal_get( 'active-tab' ),
	) );

	$formatter->append_start_tag( 'div', array(
		'id' => 'poststuff',
	) );

	$formatter->append_start_tag( 'div', array(
		'id' => 'post-body',
		'class' => 'metabox-holder columns-2 wp-clearfix',
	) );

	$formatter->append_start_tag( 'div', array(
		'id' => 'post-body-content',
	) );

	$formatter->append_start_tag( 'div', array(
		'id' => 'titlediv',
	) );

	$formatter->append_start_tag( 'div', array(
		'id' => 'titlewrap',
	) );

	$formatter->append_start_tag( 'input', array(
		'type' => 'text',
		'name' => 'post_title',
		'value' => $post->initial() ? '' : $post->title(),
		'id' => 'title',
		'spellcheck' => 'true',
		'autocomplete' => 'off',
		'disabled' => ! current_user_can( 'wpcf7_edit_contact_form', $post_id ),
		'placeholder' => __( 'Enter title here', 'contact-form-7' ),
		'aria-label' => __( 'Enter title here', 'contact-form-7' ),
	) );

	$formatter->end_tag( 'div' ); // #titlewrap

	$formatter->append_start_tag( 'div', array(
		'class' => 'inside',
	) );

	if ( ! $post->initial() ) {
		if ( $shortcode = $post->shortcode() ) {
			$formatter->append_start_tag( 'p', array(
				'class' => 'description',
			) );

			$formatter->append_start_tag( 'label', array(
				'for' => 'wpcf7-shortcode',
			) );

			$formatter->append_preformatted(
				esc_html( __( 'Copy this shortcode and paste it into your post, page, or text widget content:', 'contact-form-7' ) )
			);

			$formatter->end_tag( 'label' );

			$formatter->append_whitespace();

			$formatter->append_start_tag( 'span', array(
				'class' => 'shortcode wp-ui-highlight',
			) );

			$formatter->append_start_tag( 'input', array(
				'type' => 'text',
				'id' => 'wpcf7-shortcode',
				'readonly' => true,
				'class' => 'large-text code selectable',
				'value' => $shortcode,
			) );

			$formatter->end_tag( 'p' );
		}

		if ( $shortcode = $post->shortcode( array( 'use_old_format' => true ) ) ) {
			$formatter->append_start_tag( 'p', array(
				'class' => 'description',
			) );

			$formatter->append_start_tag( 'label', array(
				'for' => 'wpcf7-shortcode-old',
			) );

			$formatter->append_preformatted(
				esc_html( __( 'You can also use this old-style shortcode:', 'contact-form-7' ) )
			);

			$formatter->end_tag( 'label' );

			$formatter->append_whitespace();

			$formatter->append_start_tag( 'span', array(
				'class' => 'shortcode old',
			) );

			$formatter->append_start_tag( 'input', array(
				'type' => 'text',
				'id' => 'wpcf7-shortcode-old',
				'readonly' => true,
				'class' => 'large-text code selectable',
				'value' => $shortcode,
			) );

			$formatter->end_tag( 'p' );
		}
	}

	$formatter->end_tag( 'div' ); // .inside
	$formatter->end_tag( 'div' ); // #titlediv
	$formatter->end_tag( 'div' ); // #post-body-content

	$formatter->append_start_tag( 'div', array(
		'id' => 'postbox-container-1',
		'class' => 'postbox-container',
	) );

	if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
		$formatter->append_start_tag( 'section', array(
			'id' => 'submitdiv',
			'class' => 'postbox',
		) );

		$formatter->append_start_tag( 'h2' );

		$formatter->append_preformatted(
			esc_html( __( 'Status', 'contact-form-7' ) )
		);

		$formatter->end_tag( 'h2' );

		$formatter->append_start_tag( 'div', array(
			'class' => 'inside',
		) );

		$formatter->append_start_tag( 'div', array(
			'class' => 'submitbox',
			'id' => 'submitpost',
		) );

		$formatter->append_start_tag( 'div', array(
			'id' => 'minor-publishing-actions',
		) );

		$formatter->append_start_tag( 'div', array(
			'class' => 'hidden',
		) );

		$formatter->append_start_tag( 'input', array(
			'type' => 'submit',
			'class' => 'button-primary',
			'name' => 'wpcf7-save',
			'value' => __( 'Save', 'contact-form-7' ),
		) );

		$formatter->end_tag( 'div' ); // .hidden

		if ( ! $post->initial() ) {
			$formatter->append_start_tag( 'input', array(
				'type' => 'submit',
				'name' => 'wpcf7-copy',
				'class' => 'copy button',
				'value' => __( 'Duplicate', 'contact-form-7' ),
			) );
		}

		$formatter->end_tag( 'div' ); // #minor-publishing-actions

		$formatter->append_start_tag( 'div', array(
			'id' => 'misc-publishing-actions',
		) );

		$formatter->call_user_func( static function () use ( $post_id ) {
			do_action( 'wpcf7_admin_misc_pub_section', $post_id );
		} );

		$formatter->end_tag( 'div' ); // #misc-publishing-actions

		$formatter->append_start_tag( 'div', array(
			'id' => 'major-publishing-actions',
		) );

		if ( ! $post->initial() ) {
			$formatter->append_start_tag( 'div', array(
				'id' => 'delete-action',
			) );

			$formatter->append_start_tag( 'input', array(
				'type' => 'submit',
				'name' => 'wpcf7-delete',
				'class' => 'delete submitdelete',
				'value' => __( 'Delete', 'contact-form-7' ),
			) );

			$formatter->end_tag( 'div' ); // #delete-action
		}

		$formatter->append_start_tag( 'div', array(
			'id' => 'publishing-action',
		) );

		$formatter->append_preformatted( '<span class="spinner"></span>' );
		$formatter->append_preformatted( $save_button );

		$formatter->end_tag( 'div' ); // #publishing-action

		$formatter->append_preformatted( '<div class="clear"></div>' );

		$formatter->end_tag( 'div' ); // #major-publishing-actions
		$formatter->end_tag( 'div' ); // #submitpost
		$formatter->end_tag( 'div' ); // .inside
		$formatter->end_tag( 'section' ); // #submitdiv
	}

	$formatter->append_start_tag( 'section', array(
		'id' => 'informationdiv',
		'class' => 'postbox',
	) );

	$formatter->append_start_tag( 'h2' );

	$formatter->append_preformatted(
		esc_html( __( 'Do you need help?', 'contact-form-7' ) )
	);

	$formatter->end_tag( 'h2' );

	$formatter->append_start_tag( 'div', array(
		'class' => 'inside',
	) );

	$formatter->append_start_tag( 'p' );

	$formatter->append_preformatted(
		esc_html( __( 'Here are some available options to help solve your problems.', 'contact-form-7' ) )
	);

	$formatter->end_tag( 'p' );

	$formatter->append_start_tag( 'ol' );

	$formatter->append_start_tag( 'li' );

	$formatter->append_preformatted(
		sprintf(
			/* translators: 1: URL to FAQ, 2: URL to docs */
			'<a href="%1$s">FAQ</a> and <a href="%2$s">docs</a>',
			__( 'https://contactform7.com/faq/', 'contact-form-7' ),
			__( 'https://contactform7.com/docs/', 'contact-form-7' )
		)
	);

	$formatter->append_start_tag( 'li' );

	$formatter->append_preformatted(
		wpcf7_link(
			__( 'https://wordpress.org/support/plugin/contact-form-7/', 'contact-form-7' ),
			__( 'Support forums', 'contact-form-7' )
		)
	);

	$formatter->append_start_tag( 'li' );

	$formatter->append_preformatted(
		wpcf7_link(
			__( 'https://contactform7.com/custom-development/', 'contact-form-7' ),
			__( 'Professional services', 'contact-form-7' )
		)
	);

	$formatter->end_tag( 'ol' );
	$formatter->end_tag( 'div' ); // .inside
	$formatter->end_tag( 'section' ); // #informationdiv
	$formatter->end_tag( 'div' ); // #postbox-container-1

	$formatter->append_start_tag( 'div', array(
		'id' => 'postbox-container-2',
		'class' => 'postbox-container',
	) );

	$formatter->append_start_tag( 'div', array(
		'id' => 'contact-form-editor',
	) );

	$formatter->call_user_func( static function () use ( $post, $post_id ) {
		$editor = new WPCF7_Editor( $post );
		$panels = array();

		if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
			$panels = array(
				'form-panel' => array(
					'title' => __( 'Form', 'contact-form-7' ),
					'callback' => 'wpcf7_editor_panel_form',
				),
				'mail-panel' => array(
					'title' => __( 'Mail', 'contact-form-7' ),
					'callback' => 'wpcf7_editor_panel_mail',
				),
				'messages-panel' => array(
					'title' => __( 'Messages', 'contact-form-7' ),
					'callback' => 'wpcf7_editor_panel_messages',
				),
			);

			$additional_settings = $post->prop( 'additional_settings' );

			if ( ! is_scalar( $additional_settings ) ) {
				$additional_settings = '';
			}

			$additional_settings = trim( $additional_settings );
			$additional_settings = explode( "\n", $additional_settings );
			$additional_settings = array_filter( $additional_settings );
			$additional_settings = count( $additional_settings );

			$panels['additional-settings-panel'] = array(
				'title' => $additional_settings
					? sprintf(
						/* translators: %d: number of additional settings */
						__( 'Additional Settings (%d)', 'contact-form-7' ),
						$additional_settings
					)
					: __( 'Additional Settings', 'contact-form-7' ),
				'callback' => 'wpcf7_editor_panel_additional_settings',
			);
		}

		$panels = apply_filters( 'wpcf7_editor_panels', $panels );

		foreach ( $panels as $id => $panel ) {
			$editor->add_panel( $id, $panel['title'], $panel['callback'] );
		}

		$editor->display();
	} );

	$formatter->end_tag( 'div' ); // #contact-form-editor

	if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
		$formatter->append_start_tag( 'p', array(
			'class' => 'submit',
		) );

		$formatter->append_preformatted( $save_button );

		$formatter->end_tag( 'p' );
	}

	$formatter->end_tag( 'div' ); // #postbox-container-2
	$formatter->end_tag( 'div' ); // #post-body

	$formatter->append_preformatted( '<br class="clear" />' );

	$formatter->end_tag( 'div' ); // #poststuff
	$formatter->end_tag( 'form' );
}

$formatter->end_tag( 'div' ); // .wrap

$formatter->print();

$tag_generator = WPCF7_TagGenerator::get_instance();
$tag_generator->print_panels( $post );

do_action( 'wpcf7_admin_footer', $post );
PK     \y7  7    includes/editor.phpnu [        <?php

class WPCF7_Editor {

	private $contact_form;
	private $panels = array();

	public function __construct( WPCF7_ContactForm $contact_form ) {
		$this->contact_form = $contact_form;
	}

	public function add_panel( $panel_id, $title, $callback ) {
		if ( wpcf7_is_name( $panel_id ) ) {
			$this->panels[$panel_id] = array(
				'title' => $title,
				'callback' => $callback,
			);
		}
	}

	public function display() {
		if ( empty( $this->panels ) ) {
			return;
		}

		$active_panel_id = wpcf7_superglobal_get( 'active-tab' );

		if ( ! array_key_exists( $active_panel_id, $this->panels ) ) {
			$active_panel_id = array_key_first( $this->panels );
		}

		$formatter = new WPCF7_HTMLFormatter();

		$formatter->append_start_tag( 'nav', array(
			'id' => 'contact-form-editor-tabs',
			'role' => 'tablist',
			'aria-label' => __( 'Contact form editor tabs', 'contact-form-7' ),
			'data-active-tab' => absint( array_search(
				$active_panel_id, array_keys( $this->panels ), true
			) ),
		) );

		foreach ( $this->panels as $panel_id => $panel ) {
			$active = $panel_id === $active_panel_id;

			$formatter->append_start_tag( 'button', array(
				'type' => 'button',
				'role' => 'tab',
				'aria-selected' => $active ? 'true' : 'false',
				'aria-controls' => $panel_id,
				'id' => sprintf( '%s-tab', $panel_id ),
				'tabindex' => $active ? '0' : '-1',
			) );

			$formatter->append_preformatted( esc_html( $panel['title'] ) );
		}

		$formatter->end_tag( 'nav' );

		foreach ( $this->panels as $panel_id => $panel ) {
			$active = $panel_id === $active_panel_id;

			$formatter->append_start_tag( 'section', array(
				'role' => 'tabpanel',
				'aria-labelledby' => sprintf( '%s-tab', $panel_id ),
				'id' => $panel_id,
				'class' => 'contact-form-editor-panel',
				'tabindex' => '0',
				'hidden' => ! $active,
			) );

			if ( is_callable( $panel['callback'] ) ) {
				$formatter->call_user_func( $panel['callback'], $this->contact_form );
			}

			$formatter->end_tag( 'section' );
		}

		$formatter->print();
	}
}

function wpcf7_editor_panel_form( $post ) {
	$description = sprintf(
		/* translators: %s: URL to support page about the form template */
		__( 'You can edit the form template here. For details, see <a href="%s">Editing form template</a>.', 'contact-form-7' ),
		__( 'https://contactform7.com/editing-form-template/', 'contact-form-7' )
	);

	$formatter = new WPCF7_HTMLFormatter();

	$formatter->append_start_tag( 'h2' );
	$formatter->append_preformatted( esc_html( __( 'Form', 'contact-form-7' ) ) );
	$formatter->end_tag( 'h2' );

	$formatter->append_start_tag( 'fieldset' );

	$formatter->append_start_tag( 'legend' );
	$formatter->append_preformatted( $description );
	$formatter->end_tag( 'legend' );

	$formatter->call_user_func( static function () {
		$tag_generator = WPCF7_TagGenerator::get_instance();
		$tag_generator->print_buttons();
	} );

	$formatter->append_start_tag( 'textarea', array(
		'id' => 'wpcf7-form',
		'name' => 'wpcf7-form',
		'cols' => 100,
		'rows' => 24,
		'class' => 'large-text code',
		'data-config-field' => 'form.body',
	) );

	$formatter->append_preformatted( esc_textarea( $post->prop( 'form' ) ) );

	$formatter->end_tag( 'textarea' );

	$formatter->print();
}

function wpcf7_editor_panel_mail( $post ) {
	wpcf7_editor_box_mail( $post );

	echo '<br class="clear" />';

	wpcf7_editor_box_mail( $post, array(
		'id' => 'wpcf7-mail-2',
		'name' => 'mail_2',
		'title' => __( 'Mail (2)', 'contact-form-7' ),
		'use' => __( 'Use Mail (2)', 'contact-form-7' ),
	) );
}

function wpcf7_editor_box_mail( $post, $options = '' ) {
	$options = wp_parse_args( $options, array(
		'id' => 'wpcf7-mail',
		'name' => 'mail',
		'title' => __( 'Mail', 'contact-form-7' ),
		'use' => null,
	) );

	$id = esc_attr( $options['id'] );

	$mail = wp_parse_args( $post->prop( $options['name'] ), array(
		'active' => false,
		'recipient' => '',
		'sender' => '',
		'subject' => '',
		'body' => '',
		'additional_headers' => '',
		'attachments' => '',
		'use_html' => false,
		'exclude_blank' => false,
	) );

	$formatter = new WPCF7_HTMLFormatter();

	$formatter->append_start_tag( 'div', array(
		'class' => 'contact-form-editor-box-mail',
		'id' => $id,
	) );

	$formatter->append_start_tag( 'h2' );
	$formatter->append_preformatted( esc_html( $options['title'] ) );
	$formatter->end_tag( 'h2' );

	if ( ! empty( $options['use'] ) ) {
		$formatter->append_start_tag( 'label', array(
			'for' => sprintf( '%s-active', $id ),
		) );

		$formatter->append_start_tag( 'input', array(
			'type' => 'checkbox',
			'id' => sprintf( '%s-active', $id ),
			'name' => sprintf( '%s[active]', $id ),
			'data-config-field' => '',
			'data-toggle' => sprintf( '%s-fieldset', $id ),
			'value' => '1',
			'checked' => $mail['active'],
		) );

		$formatter->append_whitespace();
		$formatter->append_preformatted( esc_html( $options['use'] ) );
		$formatter->end_tag( 'label' );

		$formatter->append_start_tag( 'p', array(
			'class' => 'description',
		) );

		$formatter->append_preformatted(
			esc_html( __( 'Mail (2) is an additional mail template often used as an autoresponder.', 'contact-form-7' ) )
		);

		$formatter->end_tag( 'p' );
	}

	$formatter->append_start_tag( 'fieldset', array(
		'id' => sprintf( '%s-fieldset', $id ),
	) );

	$formatter->append_start_tag( 'legend' );

	$description = sprintf(
		/* translators: %s: URL to support page about the email template */
		__( 'You can edit the email template here. For details, see <a href="%s">Setting up mail</a>.', 'contact-form-7' ),
		__( 'https://contactform7.com/setting-up-mail/', 'contact-form-7' )
	);

	$formatter->append_preformatted( $description );

	$formatter->append_start_tag( 'br' );

	$formatter->append_preformatted(
		esc_html( __( 'In the following fields, you can use these mail-tags:', 'contact-form-7' ) )
	);

	$formatter->append_start_tag( 'br' );

	$formatter->call_user_func( static function () use ( $post, $options ) {
		$post->suggest_mail_tags( $options['name'] );
	} );

	$formatter->end_tag( 'legend' );

	$formatter->append_start_tag( 'table', array(
		'class' => 'form-table',
	) );

	$formatter->append_start_tag( 'tbody' );

	$formatter->append_start_tag( 'tr' );

	$formatter->append_start_tag( 'th', array(
		'scope' => 'row',
	) );

	$formatter->append_start_tag( 'label', array(
		'for' => sprintf( '%s-recipient', $id ),
	) );

	$formatter->append_preformatted(
		esc_html( __( 'To', 'contact-form-7' ) )
	);

	$formatter->append_start_tag( 'td' );

	$formatter->append_start_tag( 'input', array(
		'type' => 'text',
		'id' => sprintf( '%s-recipient', $id ),
		'name' => sprintf( '%s[recipient]', $id ),
		'class' => 'large-text code',
		'size' => 70,
		'value' => $mail['recipient'],
		'data-config-field' => sprintf( '%s.recipient', $options['name'] ),
	) );

	$formatter->end_tag( 'tr' );

	$formatter->append_start_tag( 'tr' );

	$formatter->append_start_tag( 'th', array(
		'scope' => 'row',
	) );

	$formatter->append_start_tag( 'label', array(
		'for' => sprintf( '%s-sender', $id ),
	) );

	$formatter->append_preformatted(
		esc_html( __( 'From', 'contact-form-7' ) )
	);

	$formatter->append_start_tag( 'td' );

	$formatter->append_start_tag( 'input', array(
		'type' => 'text',
		'id' => sprintf( '%s-sender', $id ),
		'name' => sprintf( '%s[sender]', $id ),
		'class' => 'large-text code',
		'size' => 70,
		'value' => $mail['sender'],
		'data-config-field' => sprintf( '%s.sender', $options['name'] ),
	) );

	$formatter->end_tag( 'tr' );

	$formatter->append_start_tag( 'tr' );

	$formatter->append_start_tag( 'th', array(
		'scope' => 'row',
	) );

	$formatter->append_start_tag( 'label', array(
		'for' => sprintf( '%s-subject', $id ),
	) );

	$formatter->append_preformatted(
		esc_html( __( 'Subject', 'contact-form-7' ) )
	);

	$formatter->append_start_tag( 'td' );

	$formatter->append_start_tag( 'input', array(
		'type' => 'text',
		'id' => sprintf( '%s-subject', $id ),
		'name' => sprintf( '%s[subject]', $id ),
		'class' => 'large-text code',
		'size' => 70,
		'value' => $mail['subject'],
		'data-config-field' => sprintf( '%s.subject', $options['name'] ),
	) );

	$formatter->end_tag( 'tr' );

	$formatter->append_start_tag( 'tr' );

	$formatter->append_start_tag( 'th', array(
		'scope' => 'row',
	) );

	$formatter->append_start_tag( 'label', array(
		'for' => sprintf( '%s-additional-headers', $id ),
	) );

	$formatter->append_preformatted(
		esc_html( __( 'Additional headers', 'contact-form-7' ) )
	);

	$formatter->append_start_tag( 'td' );

	$formatter->append_start_tag( 'textarea', array(
		'id' => sprintf( '%s-additional-headers', $id ),
		'name' => sprintf( '%s[additional_headers]', $id ),
		'cols' => 100,
		'rows' => 4,
		'class' => 'large-text code',
		'data-config-field' => sprintf( '%s.additional_headers', $options['name'] ),
	) );

	$formatter->append_preformatted(
		esc_textarea( $mail['additional_headers'] )
	);

	$formatter->end_tag( 'tr' );

	$formatter->append_start_tag( 'tr' );

	$formatter->append_start_tag( 'th', array(
		'scope' => 'row',
	) );

	$formatter->append_start_tag( 'label', array(
		'for' => sprintf( '%s-body', $id ),
	) );

	$formatter->append_preformatted(
		esc_html( __( 'Message body', 'contact-form-7' ) )
	);

	$formatter->append_start_tag( 'td' );

	$formatter->append_start_tag( 'textarea', array(
		'id' => sprintf( '%s-body', $id ),
		'name' => sprintf( '%s[body]', $id ),
		'cols' => 100,
		'rows' => 18,
		'class' => 'large-text code',
		'data-config-field' => sprintf( '%s.body', $options['name'] ),
	) );

	$formatter->append_preformatted(
		esc_textarea( $mail['body'] )
	);

	$formatter->end_tag( 'textarea' );

	$formatter->append_start_tag( 'p' );

	$formatter->append_start_tag( 'label', array(
		'for' => sprintf( '%s-exclude-blank', $id ),
	) );

	$formatter->append_start_tag( 'input', array(
		'type' => 'checkbox',
		'id' => sprintf( '%s-exclude-blank', $id ),
		'name' => sprintf( '%s[exclude_blank]', $id ),
		'value' => '1',
		'checked' => $mail['exclude_blank'],
	) );

	$formatter->append_whitespace();

	$formatter->append_preformatted(
		esc_html( __( 'Exclude a line from output if all of its mail-tags are blank', 'contact-form-7' ) )
	);

	$formatter->append_start_tag( 'p' );

	$formatter->append_start_tag( 'label', array(
		'for' => sprintf( '%s-use-html', $id ),
	) );

	$formatter->append_start_tag( 'input', array(
		'type' => 'checkbox',
		'id' => sprintf( '%s-use-html', $id ),
		'name' => sprintf( '%s[use_html]', $id ),
		'value' => '1',
		'checked' => $mail['use_html'],
	) );

	$formatter->append_whitespace();

	$formatter->append_preformatted(
		esc_html( __( 'Use HTML content type', 'contact-form-7' ) )
	);

	$formatter->end_tag( 'tr' );

	$formatter->append_start_tag( 'tr' );

	$formatter->append_start_tag( 'th', array(
		'scope' => 'row',
	) );

	$formatter->append_start_tag( 'label', array(
		'for' => sprintf( '%s-attachments', $id ),
	) );

	$formatter->append_preformatted(
		esc_html( __( 'File attachments', 'contact-form-7' ) )
	);

	$formatter->append_start_tag( 'td' );

	$formatter->append_start_tag( 'textarea', array(
		'id' => sprintf( '%s-attachments', $id ),
		'name' => sprintf( '%s[attachments]', $id ),
		'cols' => 100,
		'rows' => 4,
		'class' => 'large-text code',
		'data-config-field' => sprintf( '%s.attachments', $options['name'] ),
	) );

	$formatter->append_preformatted(
		esc_textarea( $mail['attachments'] )
	);

	$formatter->end_tag( 'textarea' );
	$formatter->end_tag( 'tr' );

	$formatter->print();
}

function wpcf7_editor_panel_messages( $post ) {
	$description = sprintf(
		/* translators: %s: URL to support page about the messages editor */
		__( 'You can edit messages used in various situations here. For details, see <a href="%s">Editing messages</a>.', 'contact-form-7' ),
		__( 'https://contactform7.com/editing-messages/', 'contact-form-7' )
	);

	$messages = wpcf7_messages();

	if (
		isset( $messages['captcha_not_match'] ) and
		! wpcf7_use_really_simple_captcha()
	) {
		unset( $messages['captcha_not_match'] );
	}

	$formatter = new WPCF7_HTMLFormatter();

	$formatter->append_start_tag( 'h2' );

	$formatter->append_preformatted(
		esc_html( __( 'Messages', 'contact-form-7' ) )
	);

	$formatter->end_tag( 'h2' );

	$formatter->append_start_tag( 'fieldset' );

	$formatter->append_start_tag( 'legend' );
	$formatter->append_preformatted( $description );
	$formatter->end_tag( 'legend' );

	foreach ( $messages as $key => $arr ) {
		$field_id = sprintf( 'wpcf7-message-%s', strtr( $key, '_', '-' ) );
		$field_name = sprintf( 'wpcf7-messages[%s]', $key );

		$formatter->append_start_tag( 'p', array(
			'class' => 'description',
		) );

		$formatter->append_start_tag( 'label', array(
			'for' => $field_id,
		) );

		$formatter->append_preformatted( esc_html( $arr['description'] ) );
		$formatter->append_start_tag( 'br' );

		$formatter->append_start_tag( 'input', array(
			'type' => 'text',
			'id' => $field_id,
			'name' => $field_name,
			'class' => 'large-text',
			'size' => 70,
			'value' => $post->message( $key, false ),
			'data-config-field' => sprintf( 'messages.%s', $key ),
		) );
	}

	$formatter->print();
}

function wpcf7_editor_panel_additional_settings( $post ) {
	$description = sprintf(
		/* translators: %s: URL to support page about the additional settings editor */
		__( 'You can add customization code snippets here. For details, see <a href="%s">Additional settings</a>.', 'contact-form-7' ),
		__( 'https://contactform7.com/additional-settings/', 'contact-form-7' )
	);

	$formatter = new WPCF7_HTMLFormatter();

	$formatter->append_start_tag( 'h2' );

	$formatter->append_preformatted(
		esc_html( __( 'Additional Settings', 'contact-form-7' ) )
	);

	$formatter->end_tag( 'h2' );

	$formatter->append_start_tag( 'fieldset' );

	$formatter->append_start_tag( 'legend' );
	$formatter->append_preformatted( $description );
	$formatter->end_tag( 'legend' );

	$formatter->append_start_tag( 'textarea', array(
		'id' => 'wpcf7-additional-settings',
		'name' => 'wpcf7-additional-settings',
		'cols' => 100,
		'rows' => 24,
		'class' => 'large-text',
		'data-config-field' => 'additional_settings.body',
	) );

	$formatter->append_preformatted(
		esc_textarea( $post->prop( 'additional_settings' ) )
	);

	$formatter->end_tag( 'textarea' );

	$formatter->print();
}
PK     \\  \    includes/help-tabs.phpnu [        <?php

class WPCF7_Help_Tabs {

	private $screen;

	public function __construct( WP_Screen $screen ) {
		$this->screen = $screen;
	}

	public function set_help_tabs( $screen_type ) {
		switch ( $screen_type ) {
			case 'list':
				$this->screen->add_help_tab( array(
					'id' => 'list_overview',
					'title' => __( 'Overview', 'contact-form-7' ),
					'content' => $this->content( 'list_overview' ),
				) );

				$this->screen->add_help_tab( array(
					'id' => 'list_available_actions',
					'title' => __( 'Available Actions', 'contact-form-7' ),
					'content' => $this->content( 'list_available_actions' ),
				) );

				$this->sidebar();

				return;
			case 'edit':
				$this->screen->add_help_tab( array(
					'id' => 'edit_overview',
					'title' => __( 'Overview', 'contact-form-7' ),
					'content' => $this->content( 'edit_overview' ),
				) );

				$this->screen->add_help_tab( array(
					'id' => 'edit_form_tags',
					'title' => __( 'Form-tags', 'contact-form-7' ),
					'content' => $this->content( 'edit_form_tags' ),
				) );

				$this->screen->add_help_tab( array(
					'id' => 'edit_mail_tags',
					'title' => __( 'Mail-tags', 'contact-form-7' ),
					'content' => $this->content( 'edit_mail_tags' ),
				) );

				$this->sidebar();

				return;
			case 'integration':
				$this->screen->add_help_tab( array(
					'id' => 'integration_overview',
					'title' => __( 'Overview', 'contact-form-7' ),
					'content' => $this->content( 'integration_overview' ),
				) );

				$this->sidebar();

				return;
		}
	}

	private function content( $name ) {
		$content = array();

		$content['list_overview'] = '<p>' . __( 'On this screen, you can manage contact forms provided by Contact Form 7. You can manage an unlimited number of contact forms. Each contact form has a unique ID and Contact Form 7 shortcode ([contact-form-7 ...]). To insert a contact form into a post or a text widget, insert the shortcode into the target.', 'contact-form-7' ) . '</p>';

		$content['list_available_actions'] = '<p>' . __( 'Hovering over a row in the contact forms list will display action links that allow you to manage your contact form. You can perform the following actions:', 'contact-form-7' ) . '</p>';
		$content['list_available_actions'] .= '<p>' . __( '<strong>Edit</strong> - Navigates to the editing screen for that contact form. You can also reach that screen by clicking on the contact form title.', 'contact-form-7' ) . '</p>';
		$content['list_available_actions'] .= '<p>' . __( '<strong>Duplicate</strong> - Clones that contact form. A cloned contact form inherits all content from the original, but has a different ID.', 'contact-form-7' ) . '</p>';

		$content['edit_overview'] = '<p>' . __( 'On this screen, you can edit a contact form. A contact form is comprised of the following components:', 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( '<strong>Title</strong> is the title of a contact form. This title is only used for labeling a contact form, and can be edited.', 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( '<strong>Form</strong> is a content of HTML form. You can use arbitrary HTML, which is allowed inside a form element. You can also use Contact Form 7&#8217;s form-tags here.', 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( '<strong>Mail</strong> manages a mail template (headers and message body) that this contact form will send when users submit it. You can use Contact Form 7&#8217;s mail-tags here.', 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( '<strong>Mail (2)</strong> is an additional mail template that works similar to Mail. Mail (2) is different in that it is sent only when Mail has been sent successfully.', 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( 'In <strong>Messages</strong>, you can edit various types of messages used for this contact form. These messages are relatively short messages, like a validation error message you see when you leave a required field blank.', 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( '<strong>Additional Settings</strong> provides a place where you can customize the behavior of this contact form by adding code snippets.', 'contact-form-7' ) . '</p>';

		$content['edit_form_tags'] = '<p>' . __( 'A form-tag is a short code enclosed in square brackets used in a form content. A form-tag generally represents an input field, and its components can be separated into four parts: type, name, options, and values. Contact Form 7 supports several types of form-tags including text fields, number fields, date fields, checkboxes, radio buttons, menus, file-uploading fields, CAPTCHAs, and quiz fields.', 'contact-form-7' ) . '</p>';
		$content['edit_form_tags'] .= '<p>' . __( 'While form-tags have a comparatively complex syntax, you do not need to know the syntax to add form-tags because you can use the straightforward tag generator (<strong>Generate Tag</strong> button on this screen).', 'contact-form-7' ) . '</p>';

		$content['edit_mail_tags'] = '<p>' . __( 'A mail-tag is also a short code enclosed in square brackets that you can use in every Mail and Mail (2) field. A mail-tag represents a user input value through an input field of a corresponding form-tag.', 'contact-form-7' ) . '</p>';
		$content['edit_mail_tags'] .= '<p>' . __( 'There are also special mail-tags that have specific names, but do not have corresponding form-tags. They are used to represent meta information of form submissions like the submitter&#8217;s IP address or the URL of the page.', 'contact-form-7' ) . '</p>';

		$content['integration_overview'] = '<p>' . __( 'On this screen, you can manage services that are available through Contact Form 7. Using API will allow you to collaborate with any services that are available.', 'contact-form-7' ) . '</p>';
		$content['integration_overview'] .= '<p>' . __( 'You may need to first sign up for an account with the service that you plan to use. When you do so, you would need to authorize Contact Form 7 to access the service with your account.', 'contact-form-7' ) . '</p>';
		$content['integration_overview'] .= '<p>' . __( 'Any information you provide will not be shared with service providers without your authorization.', 'contact-form-7' ) . '</p>';

		if ( ! empty( $content[$name] ) ) {
			return $content[$name];
		}
	}

	public function sidebar() {
		$content = '<p><strong>' . __( 'For more information:', 'contact-form-7' ) . '</strong></p>';
		$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/docs/', 'contact-form-7' ), __( 'Docs', 'contact-form-7' ) ) . '</p>';
		$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/faq/', 'contact-form-7' ), __( 'FAQ', 'contact-form-7' ) ) . '</p>';
		$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/support/', 'contact-form-7' ), __( 'Support', 'contact-form-7' ) ) . '</p>';

		$this->screen->set_help_sidebar( $content );
	}
}
PK     \ZRP    +  includes/class-contact-forms-list-table.phpnu [        <?php

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

class WPCF7_Contact_Form_List_Table extends WP_List_Table {

	public static function define_columns() {
		$columns = array(
			'cb' => '<input type="checkbox" />',
			'title' => __( 'Title', 'contact-form-7' ),
			'shortcode' => __( 'Shortcode', 'contact-form-7' ),
			'author' => __( 'Author', 'contact-form-7' ),
			'date' => __( 'Date', 'contact-form-7' ),
		);

		return $columns;
	}

	public function __construct() {
		parent::__construct( array(
			'singular' => 'post',
			'plural' => 'posts',
			'ajax' => false,
		) );
	}

	public function prepare_items() {
		$current_screen = get_current_screen();
		$per_page = $this->get_items_per_page( 'wpcf7_contact_forms_per_page' );

		$args = array(
			'posts_per_page' => $per_page,
			'orderby' => 'title',
			'order' => 'ASC',
			'offset' => ( $this->get_pagenum() - 1 ) * $per_page,
		);

		if ( $search_keyword = wpcf7_superglobal_request( 's' ) ) {
			$args['s'] = $search_keyword;
		}

		if ( $order_by = wpcf7_superglobal_request( 'orderby' ) ) {
			$args['orderby'] = $order_by;
		}

		if (
			$order = wpcf7_superglobal_request( 'order' ) and
			'desc' === strtolower( $order )
		) {
			$args['order'] = 'DESC';
		}

		$this->items = WPCF7_ContactForm::find( $args );

		$total_items = WPCF7_ContactForm::count();
		$total_pages = ceil( $total_items / $per_page );

		$this->set_pagination_args( array(
			'total_items' => $total_items,
			'total_pages' => $total_pages,
			'per_page' => $per_page,
		) );
	}

	public function get_columns() {
		return get_column_headers( get_current_screen() );
	}

	protected function get_sortable_columns() {
		$columns = array(
			'title' => array( 'title', true ),
			'author' => array( 'author', false ),
			'date' => array( 'date', false ),
		);

		return $columns;
	}

	protected function get_bulk_actions() {
		$actions = array(
			'delete' => __( 'Delete', 'contact-form-7' ),
		);

		return $actions;
	}

	protected function column_default( $item, $column_name ) {
		return '';
	}

	public function column_cb( $item ) {
		return sprintf(
			'<input type="checkbox" name="%1$s[]" value="%2$s" />',
			$this->_args['singular'],
			$item->id()
		);
	}

	public function column_title( $item ) {
		$edit_link = add_query_arg(
			array(
				'post' => absint( $item->id() ),
				'action' => 'edit',
			),
			menu_page_url( 'wpcf7', false )
		);

		$output = sprintf(
			'<a class="row-title" href="%1$s" aria-label="%2$s">%3$s</a>',
			esc_url( $edit_link ),
			esc_attr( sprintf(
				/* translators: %s: title of contact form */
				__( 'Edit &#8220;%s&#8221;', 'contact-form-7' ),
				$item->title()
			) ),
			esc_html( $item->title() )
		);

		$output = sprintf( '<strong>%s</strong>', $output );

		if ( wpcf7_validate_configuration()
		and current_user_can( 'wpcf7_edit_contact_form', $item->id() ) ) {
			$config_validator = new WPCF7_ConfigValidator( $item );
			$config_validator->restore();

			if ( $count_errors = $config_validator->count_errors() ) {
				$error_notice = sprintf(
					/* translators: %s: number of errors detected */
					_n(
						'%s configuration error detected',
						'%s configuration errors detected',
						$count_errors, 'contact-form-7' ),
					number_format_i18n( $count_errors )
				);

				$output .= sprintf(
					'<div class="config-error"><span class="icon-in-circle" aria-hidden="true">!</span> %s</div>',
					$error_notice
				);
			}
		}

		return $output;
	}

	protected function handle_row_actions( $item, $column_name, $primary ) {
		if ( $column_name !== $primary ) {
			return '';
		}

		$edit_link = add_query_arg(
			array(
				'post' => absint( $item->id() ),
				'action' => 'edit',
			),
			menu_page_url( 'wpcf7', false )
		);

		$actions = array(
			'edit' => wpcf7_link( $edit_link, __( 'Edit', 'contact-form-7' ) ),
		);

		if ( current_user_can( 'wpcf7_edit_contact_form', $item->id() ) ) {
			$copy_link = add_query_arg(
				array(
					'post' => absint( $item->id() ),
					'action' => 'copy',
				),
				menu_page_url( 'wpcf7', false )
			);

			$copy_link = wp_nonce_url(
				$copy_link,
				'wpcf7-copy-contact-form_' . absint( $item->id() )
			);

			$actions = array_merge( $actions, array(
				'copy' => wpcf7_link( $copy_link, __( 'Duplicate', 'contact-form-7' ) ),
			) );
		}

		return $this->row_actions( $actions );
	}

	public function column_author( $item ) {
		$post = get_post( $item->id() );

		if ( ! $post ) {
			return;
		}

		$author = get_userdata( $post->post_author );

		if ( false === $author ) {
			return;
		}

		return esc_html( $author->display_name );
	}

	public function column_shortcode( $item ) {
		$shortcodes = array( $item->shortcode() );

		$output = '';

		foreach ( $shortcodes as $shortcode ) {
			$output .= "\n" . sprintf(
				'<span class="shortcode"><input %s /></span>',
				wpcf7_format_atts( array(
					'type' => 'text',
					'readonly' => true,
					'value' => $shortcode,
					'class' => 'large-text code selectable',
				) )
			);
		}

		return trim( $output );
	}

	public function column_date( $item ) {
		$datetime = get_post_datetime( $item->id() );

		if ( false === $datetime ) {
			return '';
		}

		$t_time = sprintf(
			/* translators: 1: date, 2: time */
			__( '%1$s at %2$s', 'contact-form-7' ),
			/* translators: date format, see https://www.php.net/date */
			$datetime->format( __( 'Y/m/d', 'contact-form-7' ) ),
			/* translators: time format, see https://www.php.net/date */
			$datetime->format( __( 'g:i a', 'contact-form-7' ) )
		);

		return $t_time;
	}
}
PK     \m      includes/config-validator.phpnu [        <?php

add_action( 'wpcf7_admin_menu', 'wpcf7_admin_init_bulk_cv', 10, 0 );

function wpcf7_admin_init_bulk_cv() {
	if (
		! wpcf7_validate_configuration() or
		! current_user_can( 'wpcf7_edit_contact_forms' )
	) {
		return;
	}

	$result = WPCF7::get_option( 'bulk_validate' );
	$last_important_update = WPCF7_ConfigValidator::last_important_update;

	if (
		! empty( $result['version'] ) and
		version_compare( $last_important_update, $result['version'], '<=' )
	) {
		return;
	}

	add_filter( 'wpcf7_admin_menu_change_notice',
		'wpcf7_admin_menu_change_notice_bulk_cv',
		10, 1
	);

	add_action( 'wpcf7_admin_warnings',
		'wpcf7_admin_warnings_bulk_cv',
		5, 3
	);
}

function wpcf7_admin_menu_change_notice_bulk_cv( $counts ) {
	$counts['wpcf7'] += 1;
	return $counts;
}

function wpcf7_admin_warnings_bulk_cv( $page, $action, $object ) {
	if ( 'wpcf7' === $page and 'validate' === $action ) {
		return;
	}

	wp_admin_notice(
		sprintf(
			'%1$s &raquo; %2$s',
			__( 'Misconfiguration leads to mail delivery failure or other troubles. Validate your contact forms now.', 'contact-form-7' ),
			wpcf7_link(
				add_query_arg(
					array( 'action' => 'validate' ),
					menu_page_url( 'wpcf7', false )
				),
				__( 'Validate Contact Form 7 Configuration', 'contact-form-7' )
			)
		),
		array( 'type' => 'warning' )
	);
}

add_action( 'wpcf7_admin_load', 'wpcf7_load_bulk_validate_page', 10, 2 );

function wpcf7_load_bulk_validate_page( $page, $action ) {
	if (
		'wpcf7' !== $page or
		'validate' !== $action or
		! wpcf7_validate_configuration() or
		'POST' !== wpcf7_superglobal_server( 'REQUEST_METHOD' )
	) {
		return;
	}

	check_admin_referer( 'wpcf7-bulk-validate' );

	if ( ! current_user_can( 'wpcf7_edit_contact_forms' ) ) {
		wp_die( wp_kses_data( __( 'You are not allowed to validate configuration.', 'contact-form-7' ) ) );
	}

	$contact_forms = WPCF7_ContactForm::find();

	$result = array(
		'timestamp' => time(),
		'version' => WPCF7_VERSION,
		'count_valid' => 0,
		'count_invalid' => 0,
	);

	foreach ( $contact_forms as $contact_form ) {
		$config_validator = new WPCF7_ConfigValidator( $contact_form );
		$config_validator->validate();
		$config_validator->save();

		if ( $config_validator->is_valid() ) {
			$result['count_valid'] += 1;
		} else {
			$result['count_invalid'] += 1;
		}
	}

	WPCF7::update_option( 'bulk_validate', $result );

	$redirect_to = add_query_arg(
		array(
			'message' => 'validated',
		),
		menu_page_url( 'wpcf7', false )
	);

	wp_safe_redirect( $redirect_to );
	exit();
}

function wpcf7_admin_bulk_validate_page() {
	$contact_forms = WPCF7_ContactForm::find();
	$count = WPCF7_ContactForm::count();

	$submit_text = sprintf(
		/* translators: %s: number of contact forms */
		_n(
			'Validate %s contact form now',
			'Validate %s contact forms now',
			$count, 'contact-form-7'
		),
		number_format_i18n( $count )
	);

	$formatter = new WPCF7_HTMLFormatter( array(
		'allowed_html' => array_merge( wpcf7_kses_allowed_html(), array(
			'form' => array(
				'action' => true,
				'method' => true,
			),
		) ),
	) );

	$formatter->append_start_tag( 'div', array(
		'class' => 'wrap',
	) );

	$formatter->append_start_tag( 'h1' );

	$formatter->append_preformatted(
		esc_html( __( 'Validate Configuration', 'contact-form-7' ) )
	);

	$formatter->end_tag( 'h1' );

	$formatter->append_start_tag( 'form', array(
		'method' => 'post',
		'action' => '',
	) );

	$formatter->append_start_tag( 'p' );

	$formatter->call_user_func( static function () {
		wp_nonce_field( 'wpcf7-bulk-validate' );
	} );

	$formatter->append_start_tag( 'input', array(
		'type' => 'hidden',
		'name' => 'action',
		'value' => 'validate',
	) );

	$formatter->append_start_tag( 'input', array(
		'type' => 'submit',
		'class' => 'button',
		'value' => $submit_text,
	) );

	$formatter->end_tag( 'form' );

	$formatter->append_preformatted(
		wpcf7_link(
			__( 'https://contactform7.com/configuration-validator-faq/', 'contact-form-7' ),
			__( 'FAQ about Configuration Validator', 'contact-form-7' )
		)
	);

	$formatter->print();
}
PK     \N^`8!  8!    includes/welcome-panel.phpnu [        <?php

abstract class WPCF7_WelcomePanelColumn {

	abstract protected function icon();
	abstract protected function title();
	abstract protected function content();

	public function print_content() {
		$content = $this->content();

		if ( is_array( $content ) ) {
			$content = implode( "\n\n", $content );
		}

		$content = wp_kses_post( $content );
		$content = wptexturize( $content );
		$content = convert_chars( $content );
		$content = wpautop( $content );

		$formatter = new WPCF7_HTMLFormatter();

		$formatter->append_start_tag( 'div', array(
			'class' => 'welcome-panel-column',
		) );

		$formatter->append_start_tag( 'h3' );

		$formatter->append_start_tag( 'span', array(
			'class' => sprintf( 'dashicons dashicons-%s', $this->icon() ),
			'aria-hidden' => 'true',
		) );

		$formatter->end_tag( 'span' );

		$formatter->append_whitespace();

		$formatter->append_preformatted( $this->title() );

		$formatter->end_tag( 'h3' );

		$formatter->append_preformatted( $content );

		$formatter->print();
	}
}


class WPCF7_WelcomePanelColumn_AntiSpam extends WPCF7_WelcomePanelColumn {

	protected function icon() {
		return 'shield';
	}

	protected function title() {
		return __( 'Getting spammed? You have protection.', 'contact-form-7' );
	}

	protected function content() {
		return array(
			__( 'Spammers target everything; your contact forms are not an exception. Before you get spammed, protect your contact forms with the powerful anti-spam features Contact Form 7 provides.', 'contact-form-7' ),
			sprintf(
				/* translators: 1: URL to support page about Akismet, 2: Cloudflare Turnstile, 3: Disallowed list */
				__( 'Contact Form 7 supports spam-filtering with <a href="%1$s">Akismet</a>. <a href="%2$s">Cloudflare Turnstile</a> blocks annoying spambots. Plus, using <a href="%3$s">disallowed list</a>, you can block messages containing specified keywords or those sent from specified IP addresses.', 'contact-form-7' ),
				__( 'https://contactform7.com/spam-filtering-with-akismet/', 'contact-form-7' ),
				__( 'https://contactform7.com/turnstile-integration/', 'contact-form-7' ),
				__( 'https://contactform7.com/comment-blacklist/', 'contact-form-7' )
			),
		);
	}
}


class WPCF7_WelcomePanelColumn_Donation extends WPCF7_WelcomePanelColumn {

	protected function icon() {
		return 'megaphone';
	}

	protected function title() {
		return __( 'Contact Form 7 needs your support.', 'contact-form-7' );
	}

	protected function content() {
		return array(
			__( 'It is hard to continue to maintain this plugin without support from users like you.', 'contact-form-7' ),
			sprintf(
				/* translators: %s: URL to support page about ways to contribute */
				__( 'There are several ways for you to <a href="%s">contribute to the project</a>: testing, coding, translating it into your local languages, helping other users, financial donations, etc, etc. We equally welcome you regardless of the way you contribute.', 'contact-form-7' ),
				__( 'https://contactform7.com/contributing/', 'contact-form-7' )
			),
		);
	}
}


class WPCF7_WelcomePanelColumn_Flamingo extends WPCF7_WelcomePanelColumn {

	protected function icon() {
		return 'editor-help';
	}

	protected function title() {
		return __( 'Before you cry over spilt mail&#8230;', 'contact-form-7' );
	}

	protected function content() {
		return array(
			__( 'Contact Form 7 does not store submitted messages anywhere. Therefore, you may lose important messages forever if your mail server has issues or you make a mistake in mail configuration.', 'contact-form-7' ),
			sprintf(
				/* translators: %s: URL to support page about the Flamingo plugin */
				__( 'Install a message storage plugin before this happens to you. <a href="%s">Flamingo</a> saves all messages through contact forms into the database. Flamingo is a free WordPress plugin created by the same author as Contact Form 7.', 'contact-form-7' ),
				__( 'https://contactform7.com/save-submitted-messages-with-flamingo/', 'contact-form-7' )
			),
		);
	}
}


class WPCF7_WelcomePanelColumn_Integration extends WPCF7_WelcomePanelColumn {

	protected function icon() {
		return 'superhero-alt';
	}

	protected function title() {
		return __( 'You have strong allies to back you up.', 'contact-form-7' );
	}

	protected function content() {
		return array(
			sprintf(
				/* translators: %s: URL to support page about the Brevo integration */
				__( 'Your contact forms will become more powerful and versatile by integrating them with external APIs. With CRM and email marketing services, you can build your own contact lists (<a href="%s">Brevo</a>).', 'contact-form-7' ),
				__( 'https://contactform7.com/sendinblue-integration/', 'contact-form-7' )
			),
			sprintf(
				/* translators: 1: URL to support page about Cloudflare Turnstile, 2: Stripe */
				__( 'With help from cloud-based machine learning, anti-spam services will protect your forms (<a href="%1$s">Cloudflare Turnstile</a>). Even payment services are natively supported (<a href="%2$s">Stripe</a>).', 'contact-form-7' ),
				__( 'https://contactform7.com/turnstile-integration/', 'contact-form-7' ),
				__( 'https://contactform7.com/stripe-integration/', 'contact-form-7' )
			),
		);
	}
}


function wpcf7_welcome_panel() {
	$columns = array();

	$flamingo_is_active = defined( 'FLAMINGO_VERSION' );

	$sendinblue_is_active = false;

	if (
		class_exists( 'WPCF7_Sendinblue' ) and
		$sendinblue = WPCF7_Sendinblue::get_instance()
	) {
		$sendinblue_is_active = $sendinblue->is_active();
	}

	if ( $flamingo_is_active and $sendinblue_is_active ) {
		$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
		$columns[] = new WPCF7_WelcomePanelColumn_Donation();
	} elseif ( $flamingo_is_active ) {
		$columns[] = new WPCF7_WelcomePanelColumn_Integration();
		$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
	} elseif ( $sendinblue_is_active ) {
		$columns[] = new WPCF7_WelcomePanelColumn_Flamingo();
		$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
	} else {
		$columns[] = new WPCF7_WelcomePanelColumn_Flamingo();
		$columns[] = new WPCF7_WelcomePanelColumn_Integration();
	}

	$classes = 'wpcf7-welcome-panel';

	$vers = (array) get_user_meta( get_current_user_id(),
		'wpcf7_hide_welcome_panel_on', true
	);

	if ( wpcf7_version_grep( wpcf7_version( 'only_major=1' ), $vers ) ) {
		$classes .= ' hidden';
	}

?>
<div id="wpcf7-welcome-panel" class="<?php echo esc_attr( $classes ); ?>">
	<?php wp_nonce_field( 'wpcf7-welcome-panel-nonce', 'welcomepanelnonce', false ); ?>
	<a class="welcome-panel-close" href="<?php echo esc_url( menu_page_url( 'wpcf7', false ) ); ?>"><?php echo esc_html( __( 'Dismiss', 'contact-form-7' ) ); ?></a>

	<div class="welcome-panel-content">
		<div class="welcome-panel-column-container">
<?php

	foreach ( $columns as $column ) {
		$column->print_content();
	}

?>
		</div>
	</div>
</div>
<?php
}


add_action(
	'wp_ajax_wpcf7-update-welcome-panel',
	'wpcf7_admin_ajax_welcome_panel',
	10, 0
);

function wpcf7_admin_ajax_welcome_panel() {
	check_ajax_referer( 'wpcf7-welcome-panel-nonce', 'welcomepanelnonce' );

	$vers = get_user_meta( get_current_user_id(),
		'wpcf7_hide_welcome_panel_on', true
	);

	if ( empty( $vers ) or ! is_array( $vers ) ) {
		$vers = array();
	}

	if ( empty( $_POST['visible'] ) ) {
		$vers[] = wpcf7_version( 'only_major=1' );
	} else {
		$vers = array_diff( $vers, array( wpcf7_version( 'only_major=1' ) ) );
	}

	$vers = array_unique( $vers );

	update_user_meta( get_current_user_id(),
		'wpcf7_hide_welcome_panel_on', $vers
	);

	wp_die( 1 );
}


add_filter(
	'screen_settings',
	'wpcf7_welcome_panel_screen_settings',
	10, 2
);

function wpcf7_welcome_panel_screen_settings( $screen_settings, $screen ) {

	if ( 'toplevel_page_wpcf7' !== $screen->id ) {
		return $screen_settings;
	}

	$vers = (array) get_user_meta( get_current_user_id(),
		'wpcf7_hide_welcome_panel_on', true
	);

	$checkbox_id = 'wpcf7-welcome-panel-show';
	$checked = ! in_array( wpcf7_version( 'only_major=1' ), $vers, true );

	$checkbox = sprintf(
		'<input %s />',
		wpcf7_format_atts( array(
			'id' => $checkbox_id,
			'type' => 'checkbox',
			'checked' => $checked,
		) )
	);

	$screen_settings .= sprintf( '
<fieldset class="wpcf7-welcome-panel-options">
<legend>%1$s</legend>
<label for="%2$s">%3$s %4$s</label>
</fieldset>',
		esc_html( __( 'Welcome panel', 'contact-form-7' ) ),
		esc_attr( $checkbox_id ),
		$checkbox,
		esc_html( __( 'Show welcome panel', 'contact-form-7' ) )
	);

	return $screen_settings;
}
PK     \I#1  1    includes/js/index.jsnu [        (()=>{"use strict";var e={n:t=>{var a=t&&t.__esModule?()=>t.default:()=>t;return e.d(a,{a}),a},d:(t,a)=>{for(var r in a)e.o(a,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:a[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.wp.i18n,a=document.querySelector("#contact-form-editor"),r=window.wp.apiFetch;var c=e.n(r);const o=e=>{const t=document.createElement("span");return t.classList.add("icon-in-circle"),t.setAttribute("aria-hidden","true"),t.append(e),t},n=e=>e.replace(/[^0-9a-z]+/gi,"-"),l=e=>{const t=document.querySelector(`#${e.dataset?.toggle}`);t&&(e.checked?t.classList.remove("hidden"):t.classList.add("hidden"))},i=()=>{document.querySelectorAll("#contact-form-editor .config-error, #misc-publishing-actions .config-error").forEach((e=>{e.remove()})),document.querySelectorAll("#contact-form-editor [data-config-field]").forEach((e=>{const t=e.dataset.configField;d(t).length?(e.setAttribute("aria-invalid","true"),e.setAttribute("aria-describedby",n(`wpcf7-config-error-for-${t}`)),e.after(u(t))):e.removeAttribute("aria-invalid")})),document.querySelectorAll("#contact-form-editor-tabs [data-panel]").forEach((e=>{e.querySelectorAll(".icon-in-circle").forEach((e=>{e.remove()})),s(e.dataset.panel)&&e.querySelector("a")?.append(o("!"))}));let e=0;if(document.querySelectorAll("#contact-form-editor .contact-form-editor-panel").forEach((a=>{const r=s(a.id);if(r){e+=r;const c=document.createElement("div");c.classList.add("config-error"),c.append(o("!"),(0,t.sprintf)((0,t._n)("%d configuration error detected in this tab panel.","%d configuration errors detected in this tab panel.",r,"contact-form-7"),r)),a.prepend(c)}})),e){const a=document.createElement("div");a.classList.add("misc-pub-section","config-error");const r=document.createElement("a");r.setAttribute("href",wpcf7.configValidator.docUrl),r.append((0,t.__)("How to resolve?","contact-form-7")),a.append(o("!"),(0,t.sprintf)((0,t._n)("%d configuration error detected.","%d configuration errors detected.",e,"contact-form-7"),e),document.createElement("br"),r),document.querySelector("#misc-publishing-actions")?.append(a)}},s=e=>document.querySelectorAll(`#${e} ul.config-error li`)?.length,d=e=>{const t=[];for(const a in wpcf7.configValidator.errors)a===e&&t.push(...wpcf7.configValidator.errors[a]);return t},u=e=>{if(!e)return"";const t=document.createElement("ul");return t.setAttribute("id",n(`wpcf7-config-error-for-${e}`)),t.classList.add("config-error"),d(e).forEach((e=>{if(!e.message)return;const a=document.createElement("li");if(a.append(o("!")),e.link){const t=document.createElement("a");t.setAttribute("href",e.link),t.append(e.message),a.append(" ",t)}else a.append(" ",e.message);t.append(a)})),t},m=document.querySelector("#wpcf7-welcome-panel"),p=e=>{const t=m.querySelector("#welcomepanelnonce")?.value;if(!t)return;const a=new FormData;a.append("action","wpcf7-update-welcome-panel"),a.append("visible",e),a.append("welcomepanelnonce",t),fetch(new Request(ajaxurl,{method:"POST",body:a})),e?m.classList.remove("hidden"):m.classList.add("hidden")},f=e=>{var t;const a=e.dataset.id,r=e.querySelector('[name="name"]');let c=null!==(t=r?.value.trim())&&void 0!==t?t:"";r&&(c||(c=`${a}-${Math.floor(1e3*Math.random())}`),r.value=c),e.querySelectorAll(".tag").forEach((t=>{const a=e.querySelector('[name="tagtype"]')?.value||t.name;a&&(t.value=v(a,e))})),e.querySelectorAll("span.mail-tag").forEach((e=>{e.innerText=`[${c}]`})),e.querySelectorAll("input.mail-tag").forEach((e=>{e.value=`[${c}]`}))},v=(e,t)=>{var a,r,c;const o=null!==(a=t.querySelector(`.scope.${e}`))&&void 0!==a?a:t,n=e+(t.querySelector('[name="required"]:checked')?"*":""),l=null!==(r=t.querySelector('[name="name"]')?.value)&&void 0!==r?r:"",i=[];o.querySelectorAll(".option").forEach((e=>{"checkbox"===e.type?e.checked&&i.push(e.name):"radio"===e.type?e.checked&&!e.classList.contains("default")&&i.push(`${e.name}:${e.value}`):""!==e.value&&(e.classList.contains("filetype")?i.push(`${e.name}:${e.value.split(/[,|\s]+/).join("|")}`):e.classList.contains("color")?i.push(`${e.name}:#${e.value}`):"class"===e.name?e.value.split(" ").forEach((e=>{i.push(`class:${e}`)})):i.push(`${e.name}:${e.value}`))})),"radio"===e&&i.push("default:1");const s=null!==(c=o.querySelector('[name="values"]')?.value.split("\n").map((e=>e.trim())).filter((e=>""!==e)).map((e=>`"${e.replace(/["]/g,"&quot;")}"`)))&&void 0!==c?c:[],d=[n,l,i.join(" "),s.join(" ")].map((e=>e.trim())).filter((e=>""!==e)),u=o.querySelector('[name="content"]')?.value.trim();return u?`[${d.join(" ")}] ${u} [/${n}]`:`[${d.join(" ")}]`},g=e=>{const t=h(e);t?(e.querySelectorAll('[data-tag-part="tag"]').forEach((e=>{e.value=t})),e.querySelectorAll('[data-taggen="insert-tag"]').forEach((e=>{e.disabled=!1})),e.querySelectorAll('[data-tag-part="mail-tag"]').forEach((t=>{const a=e.querySelector('[data-tag-part="name"]');a&&(t.innerText=`[${a.value.trim()}]`)}))):(e.querySelectorAll('[data-tag-part="tag"]').forEach((e=>{e.value=""})),e.querySelectorAll('[data-taggen="insert-tag"]').forEach((e=>{e.disabled=!0})))},h=e=>{var t,a;const r=e.querySelector('[data-tag-part="basetype"]')?.value.trim();if(!r)return;if(e.querySelector(":invalid"))return;let c=r;const o=e.querySelector('[data-tag-part="type-suffix"]');o&&(["checkbox","radio"].includes(o?.type)?c+=o.checked?o.value.trim():"":c+=o.value.trim());const n=e.querySelector('[data-tag-part="name"]');let l=null!==(t=n?.value.trim())&&void 0!==t?t:"";n&&(l||(l=`${r}-${Math.floor(1e3*Math.random())}`),n.value=l);const i=[];e.querySelectorAll('[data-tag-part="option"]').forEach((e=>{const t=e.dataset.tagOption?.trim();t&&(["checkbox","radio"].includes(e?.type)&&!e.checked||t.split(" ").forEach((t=>{t.endsWith(":")?e.value?.split(" ").forEach((e=>{(e=e.trim())&&i.push(t+e)})):i.push(t)})))}));const s=null!==(a=e.querySelector('[data-tag-part="value"]')?.value.split("\n").map((e=>e.trim())).filter((e=>""!==e)).map((e=>`"${e.replace(/["]/g,"&quot;")}"`)))&&void 0!==a?a:[],d=[c,l,i.join(" "),s.join(" ")].map((e=>e.trim())).filter((e=>""!==e)),u=e.querySelector('[data-tag-part="content"]')?.value.trim();return u?`[${d.join(" ")}] ${u} [/${c}]`:`[${d.join(" ")}]`},y=e=>{const t=document.querySelector("#wpcf7-admin-form-element");if(!t)return;let a=!1;t.querySelectorAll("input, textarea, select").forEach((e=>{if(!a)switch(e.type){case"button":case"hidden":case"image":case"reset":case"search":case"submit":break;case"checkbox":case"radio":a=e.defaultChecked!==e.checked;break;case"select-multiple":case"select-one":e.querySelectorAll("option").forEach((e=>{a||e.defaultSelected===e.selected||(a=!0)}));break;default:a=e.defaultValue!==e.value}})),a&&e.preventDefault()};document.addEventListener("DOMContentLoaded",(e=>{a&&a.querySelectorAll(':scope > [role="tablist"]').forEach((e=>{const t=e.querySelectorAll(':scope > [role="tab"]');let r=parseInt(e.dataset.activeTab);e.addEventListener("keydown",(a=>{["ArrowLeft","ArrowRight"].includes(a.key)&&(t[r].setAttribute("tabindex","-1"),"ArrowLeft"===a.key&&(r-=1,r<0&&(r=t.length-1)),"ArrowRight"===a.key&&(r+=1,t.length<=r&&(r=0)),t[r].setAttribute("tabindex","0"),t[r].focus(),e.dataset.activeTab=r)})),t.forEach((t=>{t.addEventListener("click",(r=>{const c=t.getAttribute("aria-controls");if(!c)return;const o=c.split(" ").reduceRight(((e,t)=>{const r=a.querySelector(`#${t}`);return r&&(e=r),e}),null);o&&(e.querySelectorAll(':scope > [aria-selected="true"]').forEach((e=>{e.setAttribute("aria-selected","false")})),t.setAttribute("aria-selected","true"),a.querySelectorAll(':scope > [role="tabpanel"]').forEach((e=>{e.setAttribute("hidden","hidden")})),o.removeAttribute("hidden"),document.querySelectorAll('input[name="active-tab"]').forEach((e=>{e.value=o.id})))}))}))})),document.querySelectorAll("#contact-form-editor [data-config-field]").forEach((e=>{e.addEventListener("change",(e=>{const t=document.querySelector('[name="post_ID"]')?.value;t&&0<t&&(e=>{const{namespace:t}=wpcf7.apiSettings,a=`/${t}/contact-forms/${e}`,r=new FormData;document.querySelectorAll("#contact-form-editor [data-config-field]").forEach((e=>{const t=e.name?.replace(/^wpcf7-/,"").replace(/-/g,"_");if(!t)return;let a;["checkbox","radio"].includes(e.type)?e.checked&&(a=e.value):a=e.value,void 0!==a&&(t.endsWith("[]")?r.append(t,a):r.set(t,a))})),r.set("context","dry-run"),c()({path:a,method:"POST",body:r}).then((e=>{wpcf7.configValidator.errors=e.config_errors,i()}))})(t)}))})),i(),(()=>{if(!m)return;const e=document.querySelector("#wpcf7-welcome-panel-show");m.querySelectorAll(".welcome-panel-close").forEach((t=>{t.addEventListener("click",(t=>{p(0),e?.removeAttribute("checked"),t.preventDefault()}))})),e?.addEventListener("click",(t=>{p(e?.checked?1:0)}))})(),document.querySelectorAll('[data-taggen="open-dialog"]').forEach((e=>{e.addEventListener("click",(t=>{const a=document.querySelector(`#${e.dataset.target}`);if(a){const e=a.querySelector("form.tag-generator-panel");e&&("1"===e.dataset.version?(e=>{f(e),e.querySelectorAll(".control-box").forEach((t=>{t.addEventListener("change",(t=>{var a;"name"===(a=t.target).name&&(a.value=a.value.replace(/[^0-9a-zA-Z:._-]/g,"").replace(/^[^a-zA-Z]+/,"")),a.classList.contains("numeric")&&(a.value=a.value.replace(/[^0-9.-]/g,"")),a.classList.contains("idvalue")&&(a.value=a.value.replace(/[^-0-9a-zA-Z_]/g,"")),a.classList.contains("classvalue")&&(a.value=a.value.split(" ").map((e=>e.replace(/[^-0-9a-zA-Z_]/g,""))).join(" ").replace(/\s+/g," ").trim()),a.classList.contains("color")&&(a.value=a.value.replace(/[^0-9a-fA-F]/g,"")),a.classList.contains("filesize")&&(a.value=a.value.replace(/[^0-9kKmMbB]/g,"")),a.classList.contains("filetype")&&(a.value=a.value.replace(/[^0-9a-zA-Z.,|\s]/g,"")),a.classList.contains("date")&&(a.value.match(/^\d{4}-\d{2}-\d{2}$/)||(a.value="")),"values"===a.name&&(a.value=a.value.trim()),f(e)}))}))})(e):"2"===e.dataset.version&&(e=>{var t;null!==(t=e.reset())&&void 0!==t||g(e),e.querySelectorAll(".control-box").forEach((t=>{t.addEventListener("change",(t=>{g(e)})),t.addEventListener("keyup",(t=>{var a;"text"!==(null!==(a=t.target.type)&&void 0!==a?a:"")&&"textarea"!==t.target.tagName?.toLowerCase()||g(e)}))}))})(e)),a.showModal()}}))})),document.querySelectorAll("dialog.tag-generator-dialog").forEach((e=>{e.querySelectorAll('[data-taggen="close-dialog"]').forEach((t=>{t.addEventListener("click",(t=>e.close("")))})),e.querySelectorAll('[data-taggen="insert-tag"], .insert-tag').forEach((t=>{t.addEventListener("click",(t=>{const a=e.querySelector('[data-tag-part="tag"], .tag');e.close(a?.value)}))})),e.addEventListener("close",(t=>{var a;const r=document.querySelector("textarea#wpcf7-form");if(null===r)return;if(""===e.returnValue)return;const c=null!==(a=r.selectionEnd)&&void 0!==a?a:0;0===c&&(e.returnValue+="\n\n"),r.value=r.value.substring(0,c)+e.returnValue+r.value.substring(c),r.selectionStart=c,r.selectionEnd=c+e.returnValue.length,r.focus()}))})),(()=>{const e=document.querySelector("#wpcf7-admin-form-element");e&&(window.addEventListener("beforeunload",y),e.addEventListener("submit",(e=>{e.submitter?.name&&"wpcf7-copy"===e.submitter.name||window.removeEventListener("beforeunload",y)})))})();const r=document.querySelector("input#title");r&&""===r.value&&r.focus(),document.querySelector("#wpcf7-admin-form-element")?.addEventListener("submit",(e=>{const a=document.querySelector('#wpcf7-admin-form-element [name="action"]'),r=document.querySelector('#wpcf7-admin-form-element [name="_wpnonce"]');"wpcf7-save"===e.submitter?.name&&(a&&(a.value="save"),r&&(r.value=wpcf7.nonce.save),document.querySelectorAll("#wpcf7-admin-form-element #publishing-action .spinner").forEach((e=>{e.classList.add("is-active")}))),"wpcf7-copy"===e.submitter?.name&&(a&&(a.value="copy"),r&&(r.value=wpcf7.nonce.copy)),"wpcf7-delete"===e.submitter?.name&&(window.confirm((0,t.__)("You are about to delete this contact form.\n  'Cancel' to stop, 'OK' to delete.","contact-form-7"))?(a&&(a.value="delete"),r&&(r.value=wpcf7.nonce.delete)):e.preventDefault())})),document.querySelectorAll('.contact-form-editor-box-mail span.mailtag, [data-tag-part="mail-tag"]').forEach((e=>{e.addEventListener("click",(t=>{const a=document.createRange();a.selectNodeContents(e),window.getSelection().addRange(a)}))})),document.querySelectorAll("input.selectable").forEach((e=>{e.addEventListener("click",(t=>{e.focus(),e.select()}))})),document.querySelectorAll("[data-toggle]").forEach((e=>{l(e),e.addEventListener("change",(t=>{l(e)}))})),document.querySelectorAll("#wpcf7-sendinblue-enable-contact-list, #wpcf7-sendinblue-enable-transactional-email").forEach((e=>{e.addEventListener("change",(t=>{e.checked?e.closest("tr").classList.remove("inactive"):e.closest("tr").classList.add("inactive")}))}))}))})();PK     \Ϸr   r     includes/js/index.asset.phpnu [        <?php

return array(
	'dependencies' => array(
		'wp-api-fetch',
		'wp-i18n',
	),
	'version' => WPCF7_VERSION,
);
PK     \E;  ;    includes/tag-generator.phpnu [        <?php

/**
 * The base class for form-tag generators management.
 */
class WPCF7_TagGenerator {

	private static $instance;

	private $panels = array();

	private function __construct() {}


	/**
	 * Returns the singleton instance of this class.
	 */
	public static function get_instance() {
		if ( empty( self::$instance ) ) {
			self::$instance = new self();
		}

		return self::$instance;
	}


	/**
	 * Adds a form-tag generator instance.
	 */
	public function add( $id, $title, $callback, $options = '' ) {
		$id = trim( $id );

		if (
			'' === $id or
			! wpcf7_is_name( $id ) or
			! is_callable( $callback )
		) {
			return false;
		}

		$options = wp_parse_args( $options, array(
			'version' => '1',
		) );

		$this->panels[$id] = array(
			'title' => $title,
			'content' => 'tag-generator-panel-' . $id,
			'options' => $options,
			'callback' => $callback,
		);

		if ( version_compare( $options['version'], '2', '<' ) ) {
			$message = sprintf(
				/* translators: 1: version, 2: tag generator title */
				__( 'Use of tag generator instances older than version 2 is deprecated. Version %1$s instance (%2$s) detected.', 'contact-form-7' ),
				$options['version'],
				$title
			);

			wp_trigger_error( __METHOD__, $message, E_USER_DEPRECATED );
		}

		return true;
	}


	/**
	 * Renders form-tag generator calling buttons.
	 */
	public function print_buttons() {
		$formatter = new WPCF7_HTMLFormatter();

		$formatter->append_start_tag( 'span', array(
			'id' => 'tag-generator-list',
			'class' => 'hide-if-no-js',
		) );

		foreach ( (array) $this->panels as $panel ) {
			$formatter->append_start_tag( 'button', array(
				'type' => 'button',
				'data-taggen' => 'open-dialog',
				'data-target' => $panel['content'],
				'title' => sprintf(
					/* translators: %s: title of form-tag */
					__( 'Form-tag Generator: %s', 'contact-form-7' ),
					$panel['title']
				),
			) );

			$formatter->append_preformatted( esc_html( $panel['title'] ) );
		}

		$formatter->print();
	}


	/**
	 * Renders form-tag generator dialog panels (hidden until called).
	 */
	public function print_panels( WPCF7_ContactForm $contact_form ) {
		$formatter = new WPCF7_HTMLFormatter( array(
			'allowed_html' => array_merge( wpcf7_kses_allowed_html(), array(
				'dialog' => array(
					'id' => true,
					'class' => true,
				),
				'form' => array(
					'method' => true,
					'class' => true,
					'data-*' => true,
				),
			) ),
		) );

		foreach ( (array) $this->panels as $id => $panel ) {
			$callback = $panel['callback'];

			$options = array_merge( $panel['options'], array(
				'id' => $id,
				'title' => $panel['title'],
				'content' => $panel['content'],
			) );

			if ( is_callable( $callback ) ) {
				$formatter->append_start_tag( 'dialog', array(
					'id' => $options['content'],
					'class' => 'tag-generator-dialog',
				) );

				$formatter->append_start_tag( 'button', array(
					'class' => 'close-button',
					'title' => __( 'Close this dialog box', 'contact-form-7' ),
					'data-taggen' => 'close-dialog',
				) );

				$formatter->append_preformatted(
					esc_html( __( 'Close', 'contact-form-7' ) )
				);

				$formatter->end_tag( 'button' );

				$formatter->append_start_tag( 'form', array(
					'method' => 'dialog',
					'class' => 'tag-generator-panel',
					'data-id' => $options['id'],
					'data-version' => $options['version'],
				) );

				$formatter->call_user_func( $callback, $contact_form, $options );

				$formatter->close_all_tags();
			}
		}

		$formatter->print();
	}

}


/**
 * Class helps to implement a form-tag generator content.
 */
class WPCF7_TagGeneratorGenerator {

	private $key = '';


	/**
	 * The constructor.
	 */
	public function __construct( $key ) {
		$this->key = $key;
	}


	/**
	 * Returns a unique reference ID.
	 */
	public function ref( $suffix = '' ) {
		$ref = sprintf( '%s-%s', $this->key, $suffix );
		$ref = strtolower( $ref );
		$ref = preg_replace( '/[^0-9a-z-]/', '', $ref );
		$ref = preg_replace( '/[-]+/', '-', $ref );
		$ref = trim( $ref, '-' );
		return $ref;
	}


	/**
	 * Calls one of the template methods.
	 */
	public function print( $part, $options = '' ) {
		if ( is_callable( array( $this, $part ) ) ) {
			call_user_func( array( $this, $part ), $options );
		}
	}


	/**
	 * Template method for field type field.
	 */
	private function field_type( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'with_required' => false,
			'with_optional' => false,
			'select_options' => array(),
		) );

		$formatter = new WPCF7_HTMLFormatter();

		$formatter->append_start_tag( 'fieldset' );

		$formatter->append_start_tag( 'legend', array(
			'id' => $this->ref( 'type-legend' ),
		) );

		$formatter->append_preformatted(
			esc_html( __( 'Field type', 'contact-form-7' ) )
		);

		$formatter->end_tag( 'legend' );

		$formatter->append_start_tag( 'select', array(
			'data-tag-part' => 'basetype',
			'aria-labelledby' => $this->ref( 'type-legend' ),
		) );

		foreach ( (array) $options['select_options'] as $basetype => $title ) {
			$formatter->append_start_tag( 'option', array(
				'value' => $basetype,
			) );

			$formatter->append_preformatted( esc_html( $title ) );
		}

		$formatter->end_tag( 'select' );

		if ( $options['with_required'] ) {
			$formatter->append_start_tag( 'br' );
			$formatter->append_start_tag( 'label' );

			$formatter->append_start_tag( 'input', array(
				'type' => 'checkbox',
				'data-tag-part' => 'type-suffix',
				'value' => '*',
			) );

			$formatter->append_whitespace();

			$formatter->append_preformatted(
				esc_html( __( 'This is a required field.', 'contact-form-7' ) )
			);
		}

		if ( $options['with_optional'] ) {
			$formatter->append_start_tag( 'br' );
			$formatter->append_start_tag( 'label' );

			$formatter->append_start_tag( 'input', array(
				'type' => 'checkbox',
				'data-tag-part' => 'option',
				'data-tag-option' => 'optional',
				'checked' => true,
			) );

			$formatter->append_whitespace();

			$formatter->append_preformatted(
				esc_html( __( 'This checkbox is optional.', 'contact-form-7' ) )
			);
		}

		$formatter->print();
	}


	/**
	 * Template method for field name field.
	 */
	private function field_name( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'ask_if' => '',
		) );

?>
<fieldset>
	<legend id="<?php echo esc_attr( $this->ref( 'name-legend' ) ); ?>"><?php
		echo esc_html( __( 'Field name', 'contact-form-7' ) );
	?></legend>
	<input type="text" data-tag-part="name" pattern="[A-Za-z][A-Za-z0-9_\-]*" aria-labelledby="<?php echo esc_attr( $this->ref( 'name-legend' ) ); ?>" />

<?php
		$tag_option = $label = '';

		if ( 'author_name' === $options['ask_if'] ) {
			$tag_option = 'autocomplete:name';

			if ( wpcf7_akismet_is_available() ) {
				$tag_option .= ' akismet:author';
			}

			$label = __( "This field expects the submitter name.", 'contact-form-7' );
		} elseif ( 'author_email' === $options['ask_if'] ) {
			$tag_option = 'autocomplete:email';

			if ( wpcf7_akismet_is_available() ) {
				$tag_option .= ' akismet:author_email';
			}

			$label = __( "This field expects the submitter email.", 'contact-form-7' );
		} elseif ( 'author_url' === $options['ask_if'] ) {
			$tag_option = 'autocomplete:url';

			if ( wpcf7_akismet_is_available() ) {
				$tag_option .= ' akismet:author_url';
			}

			$label = __( "This field expects the submitter URL.", 'contact-form-7' );
		} elseif ( 'author_tel' === $options['ask_if'] ) {
			$tag_option = 'autocomplete:tel';
			$label = __( "This field expects the submitter telephone number.", 'contact-form-7' );
		}

		if ( $tag_option ) {
?>
	<br />
	<label>
		<input type="checkbox" data-tag-part="option" data-tag-option="<?php echo esc_attr( $tag_option ); ?>" />
		<?php echo esc_html( $label ); ?>
	</label>
<?php
		}
?>
</fieldset>
<?php
	}


	/**
	 * Template method for ID attribute option field.
	 */
	private function id_attr( $options = '' ) {
?>
<fieldset>
	<legend id="<?php echo esc_attr( $this->ref( 'id-legend' ) ); ?>"><?php
		echo esc_html( __( 'ID attribute', 'contact-form-7' ) );
	?></legend>
	<input type="text" data-tag-part="option" data-tag-option="id:" pattern="[A-Za-z][A-Za-z0-9_\-]*" aria-labelledby="<?php echo esc_attr( $this->ref( 'id-legend' ) ); ?>" />
</fieldset>
<?php
	}


	/**
	 * Template method for class attribute option field.
	 */
	private function class_attr( $options = '' ) {
?>
<fieldset>
	<legend id="<?php echo esc_attr( $this->ref( 'class-legend' ) ); ?>"><?php
		echo esc_html( __( 'Class attribute', 'contact-form-7' ) );
	?></legend>
	<input type="text" data-tag-part="option" data-tag-option="class:" pattern="[A-Za-z0-9_\-\s]*" aria-labelledby="<?php echo esc_attr( $this->ref( 'class-legend' ) ); ?>" />
</fieldset>
<?php
	}


	/**
	 * Template method for min/max options.
	 */
	private function min_max( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'type' => 'number',
			'title' => __( 'Length', 'contact-form-7' ),
			'min_option' => 'minlength:',
			'max_option' => 'maxlength:',
			'accept_minus' => false,
		) );

		$formatter = new WPCF7_HTMLFormatter();

		$formatter->append_start_tag( 'fieldset' );

		$formatter->append_start_tag( 'legend' );
		$formatter->append_preformatted( esc_html( $options['title'] ) );
		$formatter->end_tag( 'legend' );

		$formatter->append_start_tag( 'label' );

		$formatter->append_preformatted(
			esc_html( __( 'Min', 'contact-form-7' ) )
		);

		$formatter->append_whitespace();

		$formatter->append_start_tag( 'input', array(
			'type' => $options['type'],
			'data-tag-part' => 'option',
			'data-tag-option' => $options['min_option'],
			'min' => $options['accept_minus'] ? null : 0,
		) );

		$formatter->end_tag( 'label' );

		$formatter->append_preformatted( ' &#8660; ' );

		$formatter->append_start_tag( 'label' );

		$formatter->append_preformatted(
			esc_html( __( 'Max', 'contact-form-7' ) )
		);

		$formatter->append_whitespace();

		$formatter->append_start_tag( 'input', array(
			'type' => $options['type'],
			'data-tag-part' => 'option',
			'data-tag-option' => $options['max_option'],
			'min' => $options['accept_minus'] ? null : 0,
		) );

		$formatter->end_tag( 'label' );

		$formatter->print();
	}


	/**
	 * Template method for default value field.
	 */
	private function default_value( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'type' => 'text',
			'title' => __( 'Default value', 'contact-form-7' ),
			'with_placeholder' => false,
			'use_content' => false,
		) );

		$formatter = new WPCF7_HTMLFormatter();

		$formatter->append_start_tag( 'fieldset' );

		$formatter->append_start_tag( 'legend', array(
			'id' => $this->ref( 'value-legend' ),
		) );

		$formatter->append_preformatted( esc_html( $options['title'] ) );

		$formatter->end_tag( 'legend' );

		$formatter->append_start_tag( 'input', array(
			'type' => $options['type'],
			'data-tag-part' => $options['use_content'] ? 'content' : 'value',
			'aria-labelledby' => $this->ref( 'value-legend' ),
		) );

		if ( $options['with_placeholder'] ) {
			$formatter->append_start_tag( 'br' );
			$formatter->append_start_tag( 'label' );

			$formatter->append_start_tag( 'input', array(
				'type' => 'checkbox',
				'data-tag-part' => 'option',
				'data-tag-option' => 'placeholder',
			) );

			$formatter->append_whitespace();

			$formatter->append_preformatted(
				esc_html( __( 'Use this text as the placeholder.', 'contact-form-7' ) )
			);
		}

		$formatter->print();
	}


	/**
	 * Template method for selectable values useful for checkboxes or a menu.
	 */
	private function selectable_values( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'first_as_label' => false,
			'use_label_element' => false,
		) );

		$formatter = new WPCF7_HTMLFormatter();

		$formatter->append_start_tag( 'fieldset' );

		$formatter->append_start_tag( 'legend', array(
			'id' => $this->ref( 'selectable-values-legend' ),
		) );

		$formatter->append_preformatted(
			esc_html( __( 'Selectable values', 'contact-form-7' ) )
		);

		$formatter->end_tag( 'legend' );

		$formatter->append_start_tag( 'span', array(
			'id' => $this->ref( 'selectable-values-description' ),
		) );

		$formatter->append_preformatted(
			esc_html( __( 'One item per line.', 'contact-form-7' ) )
		);

		$formatter->end_tag( 'span' );

		$formatter->append_start_tag( 'br' );

		$formatter->append_start_tag( 'textarea', array(
			'required' => true,
			'data-tag-part' => 'value',
			'aria-labelledby' => $this->ref( 'selectable-values-legend' ),
			'aria-describedby' => $this->ref( 'selectable-values-description' ),
		) );

		$formatter->append_preformatted(
			esc_html( __( "Option 1\nOption 2\nOption 3", 'contact-form-7' ) )
		);

		$formatter->end_tag( 'textarea' );

		if ( $options['first_as_label'] ) {
			$formatter->append_start_tag( 'br' );
			$formatter->append_start_tag( 'label' );

			$formatter->append_start_tag( 'input', array(
				'type' => 'checkbox',
				'checked' => 'checked' === $options['first_as_label'],
				'data-tag-part' => 'option',
				'data-tag-option' => 'first_as_label',
			) );

			$formatter->append_whitespace();

			$formatter->append_preformatted(
				esc_html( __( 'Use the first item as a label.', 'contact-form-7' ) )
			);

			$formatter->end_tag( 'label' );
		}

		if ( $options['use_label_element'] ) {
			$formatter->append_start_tag( 'br' );
			$formatter->append_start_tag( 'label' );

			$formatter->append_start_tag( 'input', array(
				'type' => 'checkbox',
				'checked' => 'checked' === $options['use_label_element'],
				'data-tag-part' => 'option',
				'data-tag-option' => 'use_label_element',
			) );

			$formatter->append_whitespace();

			$formatter->append_preformatted(
				esc_html( __( 'Wrap each item with a label element.', 'contact-form-7' ) )
			);

			$formatter->end_tag( 'label' );
		}

		$formatter->print();
	}


	/**
	 * Template method for insert-box content including the result form-tag.
	 */
	private function insert_box_content( $options = '' ) {
		$formatter = new WPCF7_HTMLFormatter();

		$formatter->append_start_tag( 'div', array(
			'class' => 'flex-container',
		) );

		$formatter->append_start_tag( 'input', array(
			'type' => 'text',
			'class' => 'code selectable',
			'readonly' => true,
			'data-tag-part' => 'tag',
			'aria-label' => __( 'The form-tag to be inserted into the form template', 'contact-form-7' ),
		) );

		$formatter->append_whitespace();

		$formatter->append_start_tag( 'button', array(
			'type' => 'button',
			'class' => 'button button-primary',
			'data-taggen' => 'insert-tag',
		) );

		$formatter->append_preformatted(
			esc_html( __( 'Insert Tag', 'contact-form-7' ) )
		);

		$formatter->end_tag( 'button' );

		$formatter->print();
	}


	/**
	 * Template method for a tip message about mail-tag.
	 */
	private function mail_tag_tip( $options = '' ) {
		$formatter = new WPCF7_HTMLFormatter();

		$formatter->append_start_tag( 'p', array(
			'class' => 'mail-tag-tip',
		) );

		$formatter->append_preformatted( sprintf(
			/* translators: %s: mail-tag corresponding to the form-tag */
			esc_html( __( 'To use the user input in the email, insert the corresponding mail-tag %s into the email template.', 'contact-form-7' ) ),
			'<strong data-tag-part="mail-tag"></strong>'
		) );

		$formatter->print();
	}

}
PK     \>'  '    includes/admin-functions.phpnu [        <?php

function wpcf7_current_action() {
	foreach ( array( 'action', 'action2' ) as $var ) {
		$action = wpcf7_superglobal_request( $var, null );

		if ( isset( $action ) and -1 !== $action ) {
			return $action;
		}
	}

	return false;
}

function wpcf7_admin_has_edit_cap() {
	return current_user_can( 'wpcf7_edit_contact_forms' );
}

function wpcf7_add_tag_generator( $name, $title, $elm_id, $callback, $options = array() ) {
	$tag_generator = WPCF7_TagGenerator::get_instance();
	return $tag_generator->add( $name, $title, $callback, $options );
}
PK     \ɣw3  3    includes/css/styles-rtl.cssnu [        /*
 * Form Tab
 */
.tag-generator-panel {
	text-align: right;
}

.tag-generator-dialog > .close-button {
	right: auto;
	left: 8px;
}

form.tag-generator-panel[data-version="1"] {
	.control-box > fieldset > legend {
		border: 1px solid #dfdfdf;
		border-right: 4px solid #00a0d2;
	}

	.insert-box input.tag {
		float: right;
	}

	.insert-box .submitbox input[type="button"] {
		float: left;
	}
}

/*
 * Mail Tab
 */
.contact-form-editor-box-mail span.mailtag {
	margin: 0 4px 0 0;
}

/*
 * Welcome Panel
 */
.wpcf7-welcome-panel .welcome-panel-close {
	left: 10px;
	right: auto;
	padding: 10px 21px 10px 15px;
}

.wpcf7-welcome-panel .welcome-panel-close::before {
	right: 0;
	left: auto;
}

.wpcf7-welcome-panel .welcome-panel-content {
	margin-right: 13px;
}

.wpcf7-welcome-panel .welcome-panel-column {
	float: right;
 	padding: 0 0 0 2%;
}

/*
 * Integration
 */
.card {
	border-left: 1px solid #e5e5e5;
	border-right: 4px solid #e5e5e5;
}

.card img.icon {
	float: right;
	margin: 8px -8px 8px 8px;
}

.card h2.title {
	float: right;
}

.card .infobox {
	float: left;
}
PK     \:p'  '    includes/css/styles.cssnu [        #titlediv .inside p.description {
	margin: 8px 2px 0;
}

#titlediv .inside p.description label {
	cursor: pointer;
}

span.shortcode {
	display: block;
	margin: 2px 0;
}

span.shortcode.old {
	background: #777;
	color: #fff;
}

span.shortcode input {
	font-size: 12px;
	border: none;
	box-shadow: none;
	padding: 4px 8px;
	margin: 0;
}

#wpcf7-contact-form-list-table span.shortcode input,
#wpcf7-contact-form-editor span.shortcode input {
	background: transparent;
}

#wpcf7-contact-form-list-table span.shortcode input {
	color: #444;
}

#wpcf7-contact-form-editor span.shortcode input {
	color: #fff;
	width: 100%;
}

#submitpost input.copy {
	margin-bottom: 10px;
}

#submitpost input.delete {
	padding: 0;
	margin: 0;
	border: none;
	cursor: pointer;
	background: inherit;
	color: #a00;
}

#submitpost input.delete:hover {
	color: #dc3232; /* Red */
}

#submitpost input.delete:focus {
	outline: thin dotted;
}

.postbox-container .postbox h3 {
	border-bottom: 1px solid transparent;
}

div.config-error, span.config-error, ul.config-error {
	color: #444;
	font-style: normal;
	font-size: 13px;
}

ul.config-error {
	margin: 2px 0;
}

ul.config-error li {
	list-style: none;
	padding: 2px 2px;
	margin: 0;
}

#misc-publishing-actions .config-error {
	line-height: 2;
}

[data-config-field][aria-invalid="true"] {
	border-color: #dc3232;
}

#contact-form-editor-tabs .icon-in-circle,
#contact-form-editor .config-error .icon-in-circle,
.wp-list-table .config-error .icon-in-circle,
.icon-in-circle {
	display: inline-block;
	vertical-align: baseline;
	margin: 1px 6px 0;
	padding: 0 5px;
	min-width: 7px;
	height: 17px;
	border-radius: 11px;
	background-color: #ca4a1f;
	color: #fff;
	font-size: 12px;
	font-weight: bold;
	line-height: 17px;
	text-align: center;
	z-index: 26;
}

/*
 * Tabs
 */
#contact-form-editor-tabs {
	border-bottom: 1px solid #aaa;
	padding: 9px 10px 0;
	margin: 0;
}

#contact-form-editor-tabs button {
	display: inline-block;
	border: 1px solid #ccc;
	border-bottom: 1px solid #aaa;
	padding: 6px 10px;
	margin: 0 4px -1px;
	color: #333;
	background-color: #e4e4e4;
	font-size: 14px;
	font-weight: normal;
	line-height: 20px;
}

#contact-form-editor-tabs button[aria-selected="true"] {
	border-top: 1px solid #aaa;
	border-right: 1px solid #aaa;
	border-left: 1px solid #aaa;
	border-bottom: 1px solid #f5f5f5;
	color: #000;
	background-color: #f5f5f5;
	font-weight: bold;
}

#contact-form-editor-tabs button:hover {
	color: #000;
}

#contact-form-editor .contact-form-editor-panel > div.config-error {
	margin-bottom: 1.4em;
}

#contact-form-editor-tabs button[aria-selected="true"] .icon-in-circle {
	display: none;
}

#contact-form-editor .contact-form-editor-panel h2 {
	font-size: 18px;
	font-weight: 400;
	line-height: 24px;
	margin: 8px 0;
	padding: 0;
}

#contact-form-editor .contact-form-editor-panel {
	background-color: #f5f5f5;
	border: 1px solid #aaa;
	border-top: none;
	padding: 16px;
}

#contact-form-editor .form-table th {
	width: 100px;
}

#contact-form-editor .contact-form-editor-panel fieldset legend {
	line-height: 1.5;
	margin: .6em 0 .4em;
}

/*
 * Form Tab
 */
#tag-generator-list button {
	font-size: 12px;
	height: 26px;
	line-height: 24px;
	margin: 2px;
	padding: 0 8px 1px;
}

.tag-generator-dialog {
	padding: 12px;
	border: 1px solid #c3c4c7;
	box-shadow: 0 1px 1px rgba( 0, 0, 0, 0.04 );
	height: 720px;
	width: 720px;
	overflow: auto;
}

.tag-generator-dialog::backdrop {
	background: rgb( 0 0 0 / 50% );
}

.tag-generator-dialog > .close-button {
	position: absolute;
	top: 8px;
	right: 8px;
}

form.tag-generator-panel {
	display: flex;
	flex-direction: column;
	height: 720px;
	width: 720px;
	max-height: 100%;
	max-width: 100%;
	margin-block-end: 0;
}

form.tag-generator-panel[data-version="2"] {
	&:invalid .mail-tag-tip {
		display: none;
	}

	.description-box {
		box-sizing: border-box;
		flex: none;
		margin-inline: -12px;
		padding-inline: 12px;
		border-bottom: 1px solid #dfdfdf;
	}

	.control-box {
		box-sizing: border-box;
		flex: auto;
		display: flex;
		flex-direction: column;
		gap: 12px 0;
		min-height: 120px;
		overflow: auto;
	}

	.control-box > fieldset {
		margin-block: 8px;
		margin-inline-start: 10em;
		line-height: 2.25;
	}

	.control-box > fieldset > legend {
		font-weight: bolder;
		margin-block: 8px;
		margin-inline-start: -10em;
		line-height: 1.25;
	}

	.control-box input[type="text"] {
		width: 20rem;
		max-width: 88%;
	}

	.control-box input[type="number"] {
		width: 8rem;
		max-width: 44%;
	}

	.control-box textarea {
		height: 12ex;
		width: 20rem;
		max-width: 88%;
	}

	.control-box select {
		width: 20rem;
		max-width: 88%;
	}

	.control-box input:invalid,
	.control-box textarea:invalid {
		background-color: #ffe9de;
	}

	.insert-box {
		box-sizing: border-box;
		flex: none;
		margin-block-end: -12px;
		margin-inline: -12px;
		padding-block: 24px 12px;
		padding-inline: 12px;
		background-color: #fcfcfc;
		border-top: 1px solid #dfdfdf;
	}

	.insert-box .flex-container {
		display: flex;
	}

	.insert-box .flex-container > [data-tag-part="tag"] {
		flex: auto;
		margin-inline-end: 8px;
	}

	.insert-box .mail-tag-tip::before {
		font: 1.2rem dashicons;
		content: "\f348" / '';
		color: #646970;
		padding-inline-end: 4px;
		vertical-align: top;
	}
}

form.tag-generator-panel[data-version="1"] {
	.control-box {
		padding: 0;
		margin: 0;
		overflow: auto;
		flex-grow: 1;
	}

	.control-box > fieldset > legend {
		border: 1px solid #dfdfdf;
		border-left: 4px solid #00a0d2;
		background: #f7fcfe;
		padding: 4px 12px;
		margin: 4px 0;
		line-height: 1.4em;
		width: 100%;
		box-sizing: border-box;
	}

	table {
		width: 100%;
	}

	table.form-table th {
		width: 120px;
		padding: 4px 10px 4px 0;
		font-size: 13px;
	}

	table.form-table td {
		padding: 4px 10px;
		font-size: 13px;
	}

	.control-box input.oneline {
		width: 200px;
	}

	.control-box input.large-text {
		width: 400px;
	}

	.control-box textarea.values {
		width: 200px;
		height: 6em;
	}

	.control-box input[type="number"],
	.control-box input[type="date"] {
		width: 88px;
	}

	.control-box table caption {
		text-align: left;
		font-size: 110%;
		font-weight: bold;
		color: #777;
		margin: 10px 0 5px;
	}

	.control-box table.form-table td label {
		line-height: 1.1em;
	}

	.control-box table.form-table td label .description {
		line-height: 1.4em;
	}

	.insert-box {
		margin: 0 -15px -15px;
		padding: 8px 16px;
		background-color: #fcfcfc;
		border-top: 1px solid #dfdfdf;
		overflow: auto;
	}

	.insert-box input.tag {
		width: 510px;
		float: left;
		background-color: transparent;
		box-shadow: none;
	}

	.insert-box .submitbox {
		padding: 0;
	}

	.insert-box .submitbox input[type="button"] {
		float: right;
	}

	.insert-box .description label {
		cursor: text;
	}
}

/*
 * Mail Tab
 */
.contact-form-editor-box-mail span.mailtag {
	display: inline-block;
	margin: 0 0 0 4px;
	padding: 1px 2px;
	cursor: pointer;
	color: #000;
}

.contact-form-editor-box-mail span.mailtag.used {
	color: #666;
}

.contact-form-editor-box-mail span.mailtag.unused {
	font-weight: bold;
}

/*
 * Messages Tab
 */
#messages-panel p.description {
	margin: 5px 0 10px;
}

/*
 * Tabs for integration modules
 */
#sendinblue-panel table tr.inactive ~ tr {
	display: none;
}

#sendinblue-panel .dashicons {
 	text-decoration: none;
}

#sendinblue-panel td p {
 	margin-top: 12px;
}

/*
 * List Table
 */
.fixed .column-title {
	width: 38%;
}

.fixed .column-shortcode {
	width: 38%;
}

/*
 * Welcome Panel
 */
.wpcf7-welcome-panel {
	position: relative;
	overflow: auto;
	margin: 16px 0;
	padding: 23px 10px 0;
	border: 1px solid #c3c4c7;
	box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
	background: #fff;
	font-size: 13px;
	line-height: 1.7;
}

.wpcf7-welcome-panel h3 {
	font-size: 16px;
	font-weight: 600;
	line-height: 2.1em;
	margin: 1em 0 1.2em;
}

.wpcf7-welcome-panel h3 .dashicons {
	position: relative;
	top: -2px;
	display: inline-block;
	width: 60px;
	color: #575757;
	font-size: 40px;
}

.wpcf7-welcome-panel p {
	color: #646970;
}

.wpcf7-welcome-panel p a {
	font-weight: bold;
}

.wpcf7-welcome-panel .welcome-panel-close {
	position: absolute;
	z-index: 2;
	top: 10px;
	right: 10px;
	padding: 10px 15px 10px 21px;
	font-size: 13px;
	line-height: 1.23076923; /* Chrome rounding, needs to be 16px equivalent */
	text-decoration: none;
}

.wpcf7-welcome-panel .welcome-panel-close::before {
	background: 0 0;
	color: #787c82;
	content: "\f153" / '';
	display: block;
	font: normal 16px/20px dashicons;
	speak: never;
	height: 20px;
	text-align: center;
	width: 20px;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	position: absolute;
	top: 8px;
	left: 0;
	transition: all .1s ease-in-out;
}

.wpcf7-welcome-panel .welcome-panel-content {
	display: block;
	margin-left: 13px;
	max-width: 1500px;
	min-height: auto;
}

.wpcf7-welcome-panel .welcome-panel-column-container {
	clear: both;
	position: relative;
}

.wpcf7-welcome-panel .welcome-panel-column {
	display: block;
	width: 48%;
	min-width: 200px;
	float: left;
	padding: 0 2% 0 0;
	margin: 0 0 1em 0;
}

@media screen and (max-width: 870px) {
	.wpcf7-welcome-panel .welcome-panel-column {
		display: block;
		float: none;
		width: 100%;
	}
}

.wpcf7-welcome-panel .welcome-panel-column p {
	margin-top: 7px;
	color: #3c434a;
}

/*
 * Integration
 */
.card {
	background: #fff none repeat scroll 0 0;
	border: 1px solid #e5e5e5;
	border-left: 4px solid #e5e5e5;
	box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
	margin-top: 20px;
	max-width: 520px;
	min-width: 255px;
	padding: 0.7em 2em 1em;
	position: relative;
}

.card.active {
	border-color: #00a0d2;
}

#constant_contact.card.active {
	border-color: #dc3232;
}

.card img.icon {
	float: left;
	margin: 8px 8px 8px -8px;
}

.card h2.title {
	float: left;
	max-width: 240px;
	font-size: 1.3em;
	font-weight: 600;
}

.card .infobox {
	float: right;
	font-size: 13px;
	color: #666;
	margin: 1em;
	line-height: 1.5;
	max-width: 240px;
}

.card .inside .form-table th {
	padding: 15px 10px 15px 0;
	width: 160px;
}

.card .inside .form-table td {
	padding: 10px 10px;
}

.card .checkboxes li {
	margin: 0;
}
PK     \Rqz      plugin-install.phpnu [        <?php
/**
 * Register required, recommended plugins for theme
 *
 * @package Glozin
 */

namespace Glozin\Admin;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Register required plugins
 *
 * @since  1.0
 */
class Plugin_Install {
	/**
	 * Instance
	 *
	 * @var $instance
	 */
	protected static $instance = null;

	/**
	 * Initiator
	 *
	 * @since 1.0.0
	 * @return object
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Instantiate the object.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function __construct() {
		add_action( 'tgmpa_register', array( $this, 'register_required_plugins' ) );
	}


	/**
	 * Register required plugins
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function register_required_plugins() {
		$plugins = array(
			array(
				'name'               => esc_html__( 'WooCommerce', 'glozin' ),
				'slug'               => 'woocommerce',
				'required'           => true,
				'force_activation'   => false,
				'force_deactivation' => false,
			),
			array(
				'name'               => esc_html__( 'Elementor Page Builder', 'glozin' ),
				'slug'               => 'elementor',
				'required'           => true,
				'force_activation'   => false,
				'force_deactivation' => false,
			),
			array(
				'name'               => esc_html__( 'Glozin Addons', 'glozin' ),
				'slug'               => 'glozin-addons',
				'source'             => esc_url( 'https://github.com/uixthemeswp/glozin/raw/refs/heads/main/plugins/glozin-addons.zip' ),
				'required'           => true,
				'force_activation'   => false,
				'force_deactivation' => false,
				'version'            => '1.7.0',
			),
			array(
				'name'               => esc_html__( 'Contact Form 7', 'glozin' ),
				'slug'               => 'contact-form-7',
				'required'           => false,
				'force_activation'   => false,
				'force_deactivation' => false,
			),
			array(
				'name'               => esc_html__( 'MailChimp for WordPress', 'glozin' ),
				'slug'               => 'mailchimp-for-wp',
				'required'           => false,
				'force_activation'   => false,
				'force_deactivation' => false,
			),
			array(
				'name'               => esc_html__( 'WCBoost - Variation Swatches', 'glozin' ),
				'slug'               => 'wcboost-variation-swatches',
				'required'           => false,
				'force_activation'   => false,
				'force_deactivation' => false,
			),
			array(
				'name'               => esc_html__( 'WCBoost - Wishlist', 'glozin' ),
				'slug'               => 'wcboost-wishlist',
				'required'           => false,
				'force_activation'   => false,
				'force_deactivation' => false,
			),
			array(
				'name'               => esc_html__( 'WCBoost - Products Compare', 'glozin' ),
				'slug'               => 'wcboost-products-compare',
				'required'           => false,
				'force_activation'   => false,
				'force_deactivation' => false,
			),
			array(
				'name'               => esc_html__( 'Glozin Demo Importer', 'glozin' ),
				'slug'               => 'glozin-demo-importer',
				'source'             => esc_url( 'https://github.com/uixthemeswp/glozin/raw/refs/heads/main/plugins/glozin-demo-importer.zip' ),
				'required'           => false,
				'force_activation'   => false,
				'force_deactivation' => false,
				'version'            => '1.0.0',
			),
		);
		$config  = array(
			'domain'       => 'glozin',
			'default_path' => '',
			'menu'         => 'install-required-plugins',
			'has_notices'  => true,
			'is_automatic' => false,
			'message'      => '',
			'strings'      => array(
				'page_title'                      => esc_html__( 'Install Required Plugins', 'glozin' ),
				'menu_title'                      => esc_html__( 'Install Plugins', 'glozin' ),
				'installing'                      => esc_html__( 'Installing Plugin: %s', 'glozin' ),
				'oops'                            => esc_html__( 'Something went wrong with the plugin API.', 'glozin' ),
				'notice_can_install_required'     => _n_noop( 'This theme requires the following plugin: %1$s.', 'This theme requires the following plugins: %1$s.', 'glozin' ),
				'notice_can_install_recommended'  => _n_noop( 'This theme recommends the following plugin: %1$s.', 'This theme recommends the following plugins: %1$s.', 'glozin' ),
				'notice_cannot_install'           => _n_noop( 'Sorry, but you do not have the correct permissions to install the %s plugin. Contact the administrator of this site for help on getting the plugin installed.', 'Sorry, but you do not have the correct permissions to install the %s plugins. Contact the administrator of this site for help on getting the plugins installed.', 'glozin' ),
				'notice_can_activate_required'    => _n_noop( 'The following required plugin is currently inactive: %1$s.', 'The following required plugins are currently inactive: %1$s.', 'glozin' ),
				'notice_can_activate_recommended' => _n_noop( 'The following recommended plugin is currently inactive: %1$s.', 'The following recommended plugins are currently inactive: %1$s.', 'glozin' ),
				'notice_cannot_activate'          => _n_noop( 'Sorry, but you do not have the correct permissions to activate the %s plugin. Contact the administrator of this site for help on getting the plugin activated.', 'Sorry, but you do not have the correct permissions to activate the %s plugins. Contact the administrator of this site for help on getting the plugins activated.', 'glozin' ),
				'notice_ask_to_update'            => _n_noop( 'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.', 'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.', 'glozin' ),
				'notice_cannot_update'            => _n_noop( 'Sorry, but you do not have the correct permissions to update the %s plugin. Contact the administrator of this site for help on getting the plugin updated.', 'Sorry, but you do not have the correct permissions to update the %s plugins. Contact the administrator of this site for help on getting the plugins updated.', 'glozin' ),
				'install_link'                    => _n_noop( 'Begin installing plugin', 'Begin installing plugins', 'glozin' ),
				'activate_link'                   => _n_noop( 'Activate installed plugin', 'Activate installed plugins', 'glozin' ),
				'return'                          => esc_html__( 'Return to Required Plugins Installer', 'glozin' ),
				'plugin_activated'                => esc_html__( 'Plugin activated successfully.', 'glozin' ),
				'complete'                        => esc_html__( 'All plugins installed and activated successfully. %s', 'glozin' ),
				'nag_type'                        => 'updated',
			),
		);
		tgmpa( $plugins, $config );
	}
}
PK     \<A      block-editor.phpnu [        <?php
/**
 * Block Editor functions
 *
 * @package Glozin
 */

namespace Glozin\Admin;

use Glozin\Helper;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Block Editor
 *
 */
class Block_Editor {
	/**
	 * Instance
	 *
	 * @var $instance
	 */
	protected static $instance = null;

	/**
	 * Initiator
	 *
	 * @since 1.0.0
	 * @return object
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Instantiate the object.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function __construct() {
		add_action( 'enqueue_block_editor_assets', array( $this, 'block_editor_styles' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'load_admin_style' ) );
	}

	/**
	 * Enqueue editor styles for Gutenberg
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 *
	 */
	public function block_editor_styles() {
		wp_enqueue_style( 'glozin-block-editor-style', get_template_directory_uri() . '/assets/css/editor-blocks.css' );
	}

	/**
	 * Load admin style
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 *
	 */
	public function load_admin_style() {
		wp_enqueue_style( 'glozin-admin-style', get_template_directory_uri() . '/assets/css/glozin-admin.css' );
	}
}
PK     L\Ț    
  report.phpnu [        <?php

/*
Class Name: VI_WNOTIFICATION_F_Admin_Report
Author: Andy Ha (support@villatheme.com)
Author URI: http://villatheme.com
Copyright 2015-2018 villatheme.com. All rights reserved.
*/
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class VI_WNOTIFICATION_F_Admin_Report {

	public function __construct() {
		add_action( 'admin_menu', array( $this, 'menu_page' ) );
	}

	/**
	 * HTML Reporting
	 */
	public function page_callback() { ?>
		<h2><?php esc_html_e( 'Notification for WooCommerce Reporting', 'woo-notification' ) ?></h2>
		<a class="vi-ui button" target="_blank" href="https://1.envato.market/djEZj"><?php esc_html_e( 'Update This Feature', 'woo-notification' ) ?></a>
	<?php }

	/**
	 * Register a custom menu page.
	 */
	public function menu_page() {
		add_submenu_page(
			'woo-notification',
			esc_html__( 'Report', 'woo-notification' ),
			esc_html__( 'Report', 'woo-notification' ),
			'manage_options',
			'woo-notification-report',
			array( $this, 'page_callback' )
		);

	}
}

?>PK     tS\О✿      class-wc-admin-pointers.phpnu [        <?php
/**
 * Adds and controls pointers for contextual help/tutorials
 *
 * @package WooCommerce\Admin\Pointers
 * @version 2.4.0
 */

use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;
use Automattic\WooCommerce\Admin\Features\Features;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Admin_Pointers Class.
 */
class WC_Admin_Pointers {

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'admin_enqueue_scripts', array( $this, 'setup_pointers_for_screen' ) );
	}

	/**
	 * Setup pointers for screen.
	 */
	public function setup_pointers_for_screen() {
		$screen = get_current_screen();

		if ( ! $screen ) {
			return;
		}

		switch ( $screen->id ) {
			case 'product':
				$this->create_product_tutorial();
				$this->create_variable_product_tutorial();
				break;
			case 'woocommerce_page_wc-addons':
				$this->create_wc_addons_tutorial();
				break;
		}
	}

	/**
	 * Pointers for creating a product.
	 */
	public function create_product_tutorial() {
		if ( ! isset( $_GET['tutorial'] ) || ! current_user_can( 'manage_options' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}

		global $wp_post_types;

		if ( ! isset( $wp_post_types ) ) {
			return;
		}

		$labels          = $wp_post_types['product']->labels;
		$labels->add_new = __( 'Enable guided mode', 'woocommerce' );
		WCAdminAssets::register_script( 'wp-admin-scripts', 'product-tour', true );
	}

	/**
	 * Pointers for creating a variable product.
	 */
	public function create_variable_product_tutorial() {
		if ( ! current_user_can( 'manage_options' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}

		WCAdminAssets::register_script( 'wp-admin-scripts', 'variable-product-tour', true );
	}

	/**
	 * Pointers for accessing In-App Marketplace.
	 */
	public function create_wc_addons_tutorial() {
		if ( ! isset( $_GET['tutorial'] ) || ! current_user_can( 'manage_options' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}

		if ( wp_is_mobile() ) {
			return; // Permit In-App Marketplace Tour on desktops only.
		}

		WCAdminAssets::register_script( 'wp-admin-scripts', 'wc-addons-tour', true );
	}
}

new WC_Admin_Pointers();
PK     tS\߷[ [   class-wc-admin-setup-wizard.phpnu [        <?php
/**
 * Setup Wizard Class
 *
 * Takes new users through some basic steps to setup their store.
 *
 * @package     WooCommerce\Admin
 * @version     2.6.0
 * @deprecated  4.6.0
 */

use Automattic\Jetpack\Constants;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Admin_Setup_Wizard class.
 */
class WC_Admin_Setup_Wizard {

	/**
	 * Current step
	 *
	 * @var string
	 */
	private $step = '';

	/**
	 * Steps for the setup wizard
	 *
	 * @var array
	 */
	private $steps = array();

	/**
	 * Actions to be executed after the HTTP response has completed
	 *
	 * @var array
	 */
	private $deferred_actions = array();

	/**
	 * Tweets user can optionally send after install
	 *
	 * @var array
	 */
	private $tweets = array(
		'Someone give me woo-t, I just set up a new store with #WordPress and @WooCommerce!',
		'Someone give me high five, I just set up a new store with #WordPress and @WooCommerce!',
	);

	/**
	 * The version of WordPress required to run the WooCommerce Admin plugin
	 *
	 * @var string
	 */
	private $wc_admin_plugin_minimum_wordpress_version = '5.3';

	/**
	 * Hook in tabs.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function __construct() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
	}

	/**
	 * Add admin menus/screens.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function admin_menus() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		add_dashboard_page( '', '', 'manage_options', 'wc-setup', '' );
	}

	/**
	 * The theme "extra" should only be shown if the current user can modify themes
	 * and the store doesn't already have a WooCommerce theme.
	 *
	 * @deprecated 4.6.0
	 * @return boolean
	 */
	protected function should_show_theme() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$support_woocommerce = current_theme_supports( 'woocommerce' ) && ! wc_is_wp_default_theme_active();

		return (
			current_user_can( 'install_themes' ) &&
			current_user_can( 'switch_themes' ) &&
			! is_multisite() &&
			! $support_woocommerce
		);
	}

	/**
	 * The "automated tax" extra should only be shown if the current user can
	 * install plugins and the store is in a supported country.
	 *
	 * @deprecated 4.6.0
	 * @return bool
	 */
	protected function should_show_automated_tax() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		if ( ! current_user_can( 'install_plugins' ) ) {
			return false;
		}

		$country_code = WC()->countries->get_base_country();
		// https://developers.taxjar.com/api/reference/#countries .
		$tax_supported_countries = array_merge(
			array( 'US', 'CA', 'AU', 'GB' ),
			WC()->countries->get_european_union_countries()
		);

		return in_array( $country_code, $tax_supported_countries, true );
	}

	/**
	 * Should we show the MailChimp install option?
	 * True only if the user can install plugins.
	 *
	 * @deprecated 4.6.0
	 * @return boolean
	 */
	protected function should_show_mailchimp() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		return current_user_can( 'install_plugins' );
	}

	/**
	 * Should we show the Facebook install option?
	 * True only if the user can install plugins,
	 * and up until the end date of the recommendation.
	 *
	 * @deprecated 4.6.0
	 * @return boolean
	 */
	protected function should_show_facebook() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		return current_user_can( 'install_plugins' );
	}

	/**
	 * Is the WooCommerce Admin actively included in the WooCommerce core?
	 * Based on presence of a basic WC Admin function.
	 *
	 * @deprecated 4.6.0
	 * @return boolean
	 */
	protected function is_wc_admin_active() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		return function_exists( 'wc_admin_url' );
	}

	/**
	 * Should we show the WooCommerce Admin install option?
	 * True only if the user can install plugins,
	 * and is running the correct version of WordPress.
	 *
	 * @see WC_Admin_Setup_Wizard::$wc_admin_plugin_minimum_wordpress_version
	 *
	 * @deprecated 4.6.0
	 * @return boolean
	 */
	protected function should_show_wc_admin() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$wordpress_minimum_met = version_compare( get_bloginfo( 'version' ), $this->wc_admin_plugin_minimum_wordpress_version, '>=' );
		return current_user_can( 'install_plugins' ) && $wordpress_minimum_met && ! $this->is_wc_admin_active();
	}

	/**
	 * Should we show the new WooCommerce Admin onboarding experience?
	 *
	 * @deprecated 4.6.0
	 * @return boolean
	 */
	protected function should_show_wc_admin_onboarding() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		// As of WooCommerce 4.1, all new sites should use the latest OBW from wc-admin package.
		// This filter will allow for forcing the old wizard while we migrate e2e tests.
		return ! apply_filters( 'woocommerce_setup_wizard_force_legacy', false );
	}

	/**
	 * Should we display the 'Recommended' step?
	 * True if at least one of the recommendations will be displayed.
	 *
	 * @deprecated 4.6.0
	 * @return boolean
	 */
	protected function should_show_recommended_step() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		return $this->should_show_theme()
			|| $this->should_show_automated_tax()
			|| $this->should_show_mailchimp()
			|| $this->should_show_facebook()
			|| $this->should_show_wc_admin();
	}

	/**
	 * Register/enqueue scripts and styles for the Setup Wizard.
	 *
	 * Hooked onto 'admin_enqueue_scripts'.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function enqueue_scripts() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
	}

	/**
	 * Show the setup wizard.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function setup_wizard() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		if ( empty( $_GET['page'] ) || 'wc-setup' !== $_GET['page'] ) { // WPCS: CSRF ok, input var ok.
			return;
		}
		$default_steps = array(
			'new_onboarding' => array(
				'name'    => '',
				'view'    => array( $this, 'wc_setup_new_onboarding' ),
				'handler' => array( $this, 'wc_setup_new_onboarding_save' ),
			),
			'store_setup'    => array(
				'name'    => __( 'Store setup', 'woocommerce' ),
				'view'    => array( $this, 'wc_setup_store_setup' ),
				'handler' => array( $this, 'wc_setup_store_setup_save' ),
			),
			'payment'        => array(
				'name'    => __( 'Payment', 'woocommerce' ),
				'view'    => array( $this, 'wc_setup_payment' ),
				'handler' => array( $this, 'wc_setup_payment_save' ),
			),
			'shipping'       => array(
				'name'    => __( 'Shipping', 'woocommerce' ),
				'view'    => array( $this, 'wc_setup_shipping' ),
				'handler' => array( $this, 'wc_setup_shipping_save' ),
			),
			'recommended'    => array(
				'name'    => __( 'Recommended', 'woocommerce' ),
				'view'    => array( $this, 'wc_setup_recommended' ),
				'handler' => array( $this, 'wc_setup_recommended_save' ),
			),
			'activate'       => array(
				'name'    => __( 'Activate', 'woocommerce' ),
				'view'    => array( $this, 'wc_setup_activate' ),
				'handler' => array( $this, 'wc_setup_activate_save' ),
			),
			'next_steps'     => array(
				'name'    => __( 'Ready!', 'woocommerce' ),
				'view'    => array( $this, 'wc_setup_ready' ),
				'handler' => '',
			),
		);

		// Hide the new/improved onboarding experience screen if the user is not part of the a/b test.
		if ( ! $this->should_show_wc_admin_onboarding() ) {
			unset( $default_steps['new_onboarding'] );
		}

		// Hide recommended step if nothing is going to be shown there.
		if ( ! $this->should_show_recommended_step() ) {
			unset( $default_steps['recommended'] );
		}

		// Hide shipping step if the store is selling digital products only.
		if ( 'virtual' === get_option( 'woocommerce_product_type' ) ) {
			unset( $default_steps['shipping'] );
		}

		// Hide activate section when the user does not have capabilities to install plugins, think multiside admins not being a super admin.
		if ( ! current_user_can( 'install_plugins' ) ) {
			unset( $default_steps['activate'] );
		}

		$this->steps = apply_filters( 'woocommerce_setup_wizard_steps', $default_steps );
		$this->step  = isset( $_GET['step'] ) ? sanitize_key( $_GET['step'] ) : current( array_keys( $this->steps ) ); // WPCS: CSRF ok, input var ok.

		// @codingStandardsIgnoreStart
		if ( ! empty( $_POST['save_step'] ) && isset( $this->steps[ $this->step ]['handler'] ) ) {
			call_user_func( $this->steps[ $this->step ]['handler'], $this );
		}
		// @codingStandardsIgnoreEnd

		ob_start();
		$this->setup_wizard_header();
		$this->setup_wizard_steps();
		$this->setup_wizard_content();
		$this->setup_wizard_footer();
		exit;
	}

	/**
	 * Get the URL for the next step's screen.
	 *
	 * @param string $step  slug (default: current step).
	 * @return string       URL for next step if a next step exists.
	 *                      Admin URL if it's the last step.
	 *                      Empty string on failure.
	 *
	 * @deprecated 4.6.0
	 * @since 3.0.0
	 */
	public function get_next_step_link( $step = '' ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		if ( ! $step ) {
			$step = $this->step;
		}

		$keys = array_keys( $this->steps );
		if ( end( $keys ) === $step ) {
			return admin_url();
		}

		$step_index = array_search( $step, $keys, true );
		if ( false === $step_index ) {
			return '';
		}

		return add_query_arg( 'step', $keys[ $step_index + 1 ], remove_query_arg( 'activate_error' ) );
	}

	/**
	 * Setup Wizard Header.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function setup_wizard_header() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		// same as default WP from wp-admin/admin-header.php.
		$wp_version_class = 'branch-' . str_replace( array( '.', ',' ), '-', floatval( get_bloginfo( 'version' ) ) );

		set_current_screen();
		?>
		<!DOCTYPE html>
		<html <?php language_attributes(); ?>>
		<head>
			<meta name="viewport" content="width=device-width" />
			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
			<title><?php esc_html_e( 'WooCommerce &rsaquo; Setup Wizard', 'woocommerce' ); ?></title>
			<?php do_action( 'admin_enqueue_scripts' ); ?>
			<?php wp_print_scripts( 'wc-setup' ); ?>
			<?php do_action( 'admin_print_styles' ); ?>
			<?php do_action( 'admin_head' ); ?>
		</head>
		<body class="wc-setup wp-core-ui <?php echo esc_attr( 'wc-setup-step__' . $this->step ); ?> <?php echo esc_attr( $wp_version_class ); ?>">
		<h1 class="wc-logo"><a href="https://woocommerce.com/"><img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/woocommerce_logo.png" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" /></a></h1>
		<?php
	}

	/**
	 * Setup Wizard Footer.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function setup_wizard_footer() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$current_step = $this->step;
		?>
			<?php if ( 'new_onboarding' === $current_step || 'store-setup' === $current_step ) : ?>
				<a class="wc-setup-footer-links" href="<?php echo esc_url( admin_url() ); ?>"><?php esc_html_e( 'Not right now', 'woocommerce' ); ?></a>
			<?php elseif ( 'recommended' === $current_step || 'activate' === $current_step ) : ?>
				<a class="wc-setup-footer-links" href="<?php echo esc_url( $this->get_next_step_link() ); ?>"><?php esc_html_e( 'Skip this step', 'woocommerce' ); ?></a>
			<?php endif; ?>
			<?php do_action( 'woocommerce_setup_footer' ); ?>
			</body>
		</html>
		<?php
	}

	/**
	 * Output the steps.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function setup_wizard_steps() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$output_steps      = $this->steps;
		$selected_features = array_filter( $this->wc_setup_activate_get_feature_list() );

		// Hide the activate step if Jetpack is already active, unless WooCommerce Services
		// features are selected, or unless the Activate step was already taken.
		if ( class_exists( 'Jetpack' ) && Jetpack::is_active() && empty( $selected_features ) && 'yes' !== get_transient( 'wc_setup_activated' ) ) {
			unset( $output_steps['activate'] );
		}

		unset( $output_steps['new_onboarding'] );

		?>
		<ol class="wc-setup-steps">
			<?php
			foreach ( $output_steps as $step_key => $step ) {
				$is_completed = array_search( $this->step, array_keys( $this->steps ), true ) > array_search( $step_key, array_keys( $this->steps ), true );

				if ( $step_key === $this->step ) {
					?>
					<li class="active"><?php echo esc_html( $step['name'] ); ?></li>
					<?php
				} elseif ( $is_completed ) {
					?>
					<li class="done">
						<a href="<?php echo esc_url( add_query_arg( 'step', $step_key, remove_query_arg( 'activate_error' ) ) ); ?>"><?php echo esc_html( $step['name'] ); ?></a>
					</li>
					<?php
				} else {
					?>
					<li><?php echo esc_html( $step['name'] ); ?></li>
					<?php
				}
			}
			?>
		</ol>
		<?php
	}

	/**
	 * Output the content for the current step.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function setup_wizard_content() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		echo '<div class="wc-setup-content">';
		if ( ! empty( $this->steps[ $this->step ]['view'] ) ) {
			call_user_func( $this->steps[ $this->step ]['view'], $this );
		}
		echo '</div>';
	}

	/**
	 * Display's a prompt for users to try out the new improved WooCommerce onboarding experience in WooCommerce Admin.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_new_onboarding() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		?>
			<div class="wc-setup-step__new_onboarding-wrapper">
				<p class="wc-setup-step__new_onboarding-welcome"><?php esc_html_e( 'Welcome to', 'woocommerce' ); ?></p>
				<h1 class="wc-logo"><a href="https://woocommerce.com/"><img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/woocommerce_logo.png" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" /></a></h1>
				<p><?php esc_html_e( 'Get your store up and running more quickly with our new and improved setup experience', 'woocommerce' ); ?></p>

				<form method="post" class="activate-new-onboarding">
					<?php wp_nonce_field( 'wc-setup' ); ?>
					<input type="hidden" name="save_step" value="new_onboarding" />
					<p class="wc-setup-actions step">
						<button class="button-primary button button-large" value="<?php esc_attr_e( 'Yes please', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Yes please', 'woocommerce' ); ?></button>
					</p>
				</form>
				<?php if ( ! $this->is_wc_admin_active() ) : ?>
					<p class="wc-setup-step__new_onboarding-plugin-info"><?php esc_html_e( 'The "WooCommerce Admin" plugin will be installed and activated', 'woocommerce' ); ?></p>
				<?php endif; ?>
			</div>
		<?php
	}

	/**
	 * Installs WooCommerce admin and redirects to the new onboarding experience.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_new_onboarding_save() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
	}

	/**
	 * Initial "store setup" step.
	 * Location, product type, page setup, and tracking opt-in.
	 *
	 * @return void
	 */
	public function wc_setup_store_setup() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$address        = WC()->countries->get_base_address();
		$address_2      = WC()->countries->get_base_address_2();
		$city           = WC()->countries->get_base_city();
		$state          = WC()->countries->get_base_state();
		$country        = WC()->countries->get_base_country();
		$postcode       = WC()->countries->get_base_postcode();
		$currency       = get_option( 'woocommerce_currency', 'USD' );
		$product_type   = get_option( 'woocommerce_product_type', 'both' );
		$sell_in_person = get_option( 'woocommerce_sell_in_person', 'none_selected' );

		if ( empty( $country ) ) {
			$user_location = WC_Geolocation::geolocate_ip();
			$country       = $user_location['country'];
			$state         = $user_location['state'];
		}

		$locale_info         = include WC()->plugin_path() . '/i18n/locale-info.php';
		$currency_by_country = wp_list_pluck( $locale_info, 'currency_code' );
		?>
		<form method="post" class="address-step">
			<input type="hidden" name="save_step" value="store_setup" />
			<?php wp_nonce_field( 'wc-setup' ); ?>
			<p class="store-setup"><?php esc_html_e( 'The following wizard will help you configure your store and get you started quickly.', 'woocommerce' ); ?></p>

			<div class="store-address-container">

				<label for="store_country" class="location-prompt"><?php esc_html_e( 'Where is your store based?', 'woocommerce' ); ?></label>
				<select id="store_country" name="store_country" required data-placeholder="<?php esc_attr_e( 'Choose a country / region&hellip;', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'Country / Region', 'woocommerce' ); ?>" class="location-input wc-enhanced-select dropdown">
					<?php foreach ( WC()->countries->get_countries() as $code => $label ) : ?>
						<option <?php selected( $code, $country ); ?> value="<?php echo esc_attr( $code ); ?>"><?php echo esc_html( $label ); ?></option>
					<?php endforeach; ?>
				</select>

				<label class="location-prompt" for="store_address"><?php esc_html_e( 'Address', 'woocommerce' ); ?></label>
				<input type="text" id="store_address" class="location-input" name="store_address" required value="<?php echo esc_attr( $address ); ?>" />

				<label class="location-prompt" for="store_address_2"><?php esc_html_e( 'Address line 2', 'woocommerce' ); ?></label>
				<input type="text" id="store_address_2" class="location-input" name="store_address_2" value="<?php echo esc_attr( $address_2 ); ?>" />

				<div class="city-and-postcode">
					<div>
						<label class="location-prompt" for="store_city"><?php esc_html_e( 'City', 'woocommerce' ); ?></label>
						<input type="text" id="store_city" class="location-input" name="store_city" required value="<?php echo esc_attr( $city ); ?>" />
					</div>
					<div class="store-state-container hidden">
						<label for="store_state" class="location-prompt">
							<?php esc_html_e( 'State', 'woocommerce' ); ?>
						</label>
						<select id="store_state" name="store_state" data-placeholder="<?php esc_attr_e( 'Choose a state&hellip;', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'State', 'woocommerce' ); ?>" class="location-input wc-enhanced-select dropdown"></select>
					</div>
					<div>
						<label class="location-prompt" for="store_postcode"><?php esc_html_e( 'Postcode / ZIP', 'woocommerce' ); ?></label>
						<input type="text" id="store_postcode" class="location-input" name="store_postcode" required value="<?php echo esc_attr( $postcode ); ?>" />
					</div>
				</div>
			</div>

			<div class="store-currency-container">
			<label class="location-prompt" for="currency_code">
				<?php esc_html_e( 'What currency do you accept payments in?', 'woocommerce' ); ?>
			</label>
			<select
				id="currency_code"
				name="currency_code"
				required
				data-placeholder="<?php esc_attr_e( 'Choose a currency&hellip;', 'woocommerce' ); ?>"
				class="location-input wc-enhanced-select dropdown"
			>
				<option value=""><?php esc_html_e( 'Choose a currency&hellip;', 'woocommerce' ); ?></option>
				<?php foreach ( get_woocommerce_currencies() as $code => $name ) : ?>
					<option value="<?php echo esc_attr( $code ); ?>" <?php selected( $currency, $code ); ?>>
						<?php
						$symbol = get_woocommerce_currency_symbol( $code );

						if ( $symbol === $code ) {
							/* translators: 1: currency name 2: currency code */
							echo esc_html( sprintf( __( '%1$s (%2$s)', 'woocommerce' ), $name, $code ) );
						} else {
							/* translators: 1: currency name 2: currency symbol, 3: currency code */
							echo esc_html( sprintf( __( '%1$s (%2$s %3$s)', 'woocommerce' ), $name, get_woocommerce_currency_symbol( $code ), $code ) );
						}
						?>
					</option>
				<?php endforeach; ?>
			</select>
			<script type="text/javascript">
				var wc_setup_currencies = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( $currency_by_country ) ); ?>' ) );
				var wc_base_state       = "<?php echo esc_js( $state ); ?>";
			</script>
			</div>

			<div class="product-type-container">
			<label class="location-prompt" for="product_type">
				<?php esc_html_e( 'What type of products do you plan to sell?', 'woocommerce' ); ?>
			</label>
			<select id="product_type" name="product_type" required class="location-input wc-enhanced-select dropdown">
				<option value="both" <?php selected( $product_type, 'both' ); ?>><?php esc_html_e( 'I plan to sell both physical and digital products', 'woocommerce' ); ?></option>
				<option value="physical" <?php selected( $product_type, 'physical' ); ?>><?php esc_html_e( 'I plan to sell physical products', 'woocommerce' ); ?></option>
				<option value="virtual" <?php selected( $product_type, 'virtual' ); ?>><?php esc_html_e( 'I plan to sell digital products', 'woocommerce' ); ?></option>
			</select>
			</div>

			<div class="sell-in-person-container">
			<input
				type="checkbox"
				id="woocommerce_sell_in_person"
				name="sell_in_person"
				value="yes"
				<?php checked( $sell_in_person, true ); ?>
			/>
			<label class="location-prompt" for="woocommerce_sell_in_person">
				<?php esc_html_e( 'I will also be selling products or services in person.', 'woocommerce' ); ?>
			</label>
			</div>

			<input type="checkbox" id="wc_tracker_checkbox" name="wc_tracker_checkbox" value="yes" <?php checked( 'yes', get_option( 'woocommerce_allow_tracking', 'no' ) ); ?> />

			<?php $this->tracking_modal(); ?>

			<p class="wc-setup-actions step">
				<button class="button-primary button button-large" value="<?php esc_attr_e( "Let's go!", 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( "Let's go!", 'woocommerce' ); ?></button>
			</p>
		</form>
		<?php
	}

	/**
	 * Template for the usage tracking modal.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function tracking_modal() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		?>
		<script type="text/template" id="tmpl-wc-modal-tracking-setup">
			<div class="wc-backbone-modal woocommerce-tracker">
				<div class="wc-backbone-modal-content">
					<section class="wc-backbone-modal-main" role="main">
						<header class="wc-backbone-modal-header">
							<h1><?php esc_html_e( 'Help improve WooCommerce with usage tracking', 'woocommerce' ); ?></h1>
						</header>
						<article>
							<p>
							<?php
								printf(
									wp_kses(
										/* translators: %1$s: usage tracking help link */
										__( 'Learn more about how usage tracking works, and how you\'ll be helping in our <a href="%1$s" target="_blank">usage tracking documentation</a>.', 'woocommerce' ),
										array(
											'a' => array(
												'href'   => array(),
												'target' => array(),
											),
										)
									),
									'https://woocommerce.com/usage-tracking/'
								);
							?>
							</p>
							<p class="woocommerce-tracker-checkbox">
								<input type="checkbox" id="wc_tracker_checkbox_dialog" name="wc_tracker_checkbox_dialog" value="yes" <?php checked( 'yes', get_option( 'woocommerce_allow_tracking', 'no' ) ); ?> />
								<label for="wc_tracker_checkbox_dialog"><?php esc_html_e( 'Enable usage tracking and help improve WooCommerce', 'woocommerce' ); ?></label>
							</p>
						</article>
						<footer>
							<div class="inner">
								<button class="button button-primary button-large" id="wc_tracker_submit" aria-label="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>"><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
							</div>
						</footer>
					</section>
				</div>
			</div>
			<div class="wc-backbone-modal-backdrop modal-close"></div>
		</script>
		<?php
	}

	/**
	 * Save initial store settings.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_store_setup_save() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
	}

	/**
	 * Finishes replying to the client, but keeps the process running for further (async) code execution.
	 *
	 * @see https://core.trac.wordpress.org/ticket/41358 .
	 * @return void
	 */
	protected function close_http_connection() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		// Only 1 PHP process can access a session object at a time, close this so the next request isn't kept waiting.
		// @codingStandardsIgnoreStart
		if ( session_id() ) {
			session_write_close();
		}
		// @codingStandardsIgnoreEnd

		wc_set_time_limit( 0 );

		// fastcgi_finish_request is the cleanest way to send the response and keep the script running, but not every server has it.
		if ( is_callable( 'fastcgi_finish_request' ) ) {
			fastcgi_finish_request();
		} else {
			// Fallback: send headers and flush buffers.
			if ( ! headers_sent() ) {
				header( 'Connection: close' );
			}
			@ob_end_flush(); // @codingStandardsIgnoreLine.
			flush();
		}
	}

	/**
	 * Function called after the HTTP request is finished, so it's executed without the client having to wait for it.
	 *
	 * @see WC_Admin_Setup_Wizard::install_plugin
	 * @see WC_Admin_Setup_Wizard::install_theme
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function run_deferred_actions() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$this->close_http_connection();
		foreach ( $this->deferred_actions as $action ) {
			$action['func']( ...$action['args'] );

			// Clear the background installation flag if this is a plugin.
			if (
				isset( $action['func'][1] ) &&
				'background_installer' === $action['func'][1] &&
				isset( $action['args'][0] )
			) {
				delete_option( 'woocommerce_setup_background_installing_' . $action['args'][0] );
			}
		}
	}

	/**
	 * Helper method to queue the background install of a plugin.
	 *
	 * @param string $plugin_id  Plugin id used for background install.
	 * @param array  $plugin_info Plugin info array containing name and repo-slug, and optionally file if different from [repo-slug].php.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	protected function install_plugin( $plugin_id, $plugin_info ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		// Make sure we don't trigger multiple simultaneous installs.
		if ( get_option( 'woocommerce_setup_background_installing_' . $plugin_id ) ) {
			return;
		}

		$plugin_file = isset( $plugin_info['file'] ) ? $plugin_info['file'] : $plugin_info['repo-slug'] . '.php';
		if ( is_plugin_active( $plugin_info['repo-slug'] . '/' . $plugin_file ) ) {
			return;
		}

		if ( empty( $this->deferred_actions ) ) {
			add_action( 'shutdown', array( $this, 'run_deferred_actions' ) );
		}

		array_push(
			$this->deferred_actions,
			array(
				'func' => array( 'WC_Install', 'background_installer' ),
				'args' => array( $plugin_id, $plugin_info ),
			)
		);

		// Set the background installation flag for this plugin.
		update_option( 'woocommerce_setup_background_installing_' . $plugin_id, true );
	}


	/**
	 * Helper method to queue the background install of a theme.
	 *
	 * @param string $theme_id  Theme id used for background install.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	protected function install_theme( $theme_id ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		if ( empty( $this->deferred_actions ) ) {
			add_action( 'shutdown', array( $this, 'run_deferred_actions' ) );
		}
		array_push(
			$this->deferred_actions,
			array(
				'func' => array( 'WC_Install', 'theme_background_installer' ),
				'args' => array( $theme_id ),
			)
		);
	}

	/**
	 * Helper method to install Jetpack.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	protected function install_jetpack() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$this->install_plugin(
			'jetpack',
			array(
				'name'      => __( 'Jetpack', 'woocommerce' ),
				'repo-slug' => 'jetpack',
			)
		);
	}

	/**
	 * Helper method to install WooCommerce Services and its Jetpack dependency.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	protected function install_woocommerce_services() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$this->install_jetpack();
		$this->install_plugin(
			'woocommerce-services',
			array(
				'name'      => __( 'WooCommerce Services', 'woocommerce' ),
				'repo-slug' => 'woocommerce-services',
			)
		);
	}

	/**
	 * Retrieve info for missing WooCommerce Services and/or Jetpack plugin.
	 *
	 * @deprecated 4.6.0
	 * @return array
	 */
	protected function get_wcs_requisite_plugins() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$plugins = array();
		if ( ! is_plugin_active( 'woocommerce-services/woocommerce-services.php' ) && ! get_option( 'woocommerce_setup_background_installing_woocommerce-services' ) ) {
			$plugins[] = array(
				'name' => __( 'WooCommerce Services', 'woocommerce' ),
				'slug' => 'woocommerce-services',
			);
		}
		if ( ! is_plugin_active( 'jetpack/jetpack.php' ) && ! get_option( 'woocommerce_setup_background_installing_jetpack' ) ) {
			$plugins[] = array(
				'name' => __( 'Jetpack', 'woocommerce' ),
				'slug' => 'jetpack',
			);
		}
		return $plugins;
	}

	/**
	 * Plugin install info message markup with heading.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function plugin_install_info() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		?>
		<span class="plugin-install-info">
			<span class="plugin-install-info-label"><?php esc_html_e( 'The following plugins will be installed and activated for you:', 'woocommerce' ); ?></span>
			<span class="plugin-install-info-list"></span>
		</span>
		<?php
	}

	/**
	 * Get shipping methods based on country code.
	 *
	 * @param string $country_code Country code.
	 * @param string $currency_code Currency code.
	 *
	 * @deprecated 4.6.0
	 * @return array
	 */
	protected function get_wizard_shipping_methods( $country_code, $currency_code ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$shipping_methods = array(
			'flat_rate'     => array(
				'name'        => __( 'Flat Rate', 'woocommerce' ),
				'description' => __( 'Set a fixed price to cover shipping costs.', 'woocommerce' ),
				'settings'    => array(
					'cost' => array(
						'type'          => 'text',
						'default_value' => __( 'Cost', 'woocommerce' ),
						'description'   => __( 'What would you like to charge for flat rate shipping?', 'woocommerce' ),
						'required'      => true,
					),
				),
			),
			'free_shipping' => array(
				'name'        => __( 'Free Shipping', 'woocommerce' ),
				'description' => __( "Don't charge for shipping.", 'woocommerce' ),
			),
		);

		return $shipping_methods;
	}

	/**
	 * Render the available shipping methods for a given country code.
	 *
	 * @param string $country_code Country code.
	 * @param string $currency_code Currency code.
	 * @param string $input_prefix Input prefix.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	protected function shipping_method_selection_form( $country_code, $currency_code, $input_prefix ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$selected         = 'flat_rate';
		$shipping_methods = $this->get_wizard_shipping_methods( $country_code, $currency_code );
		?>
		<div class="wc-wizard-shipping-method-select">
			<div class="wc-wizard-shipping-method-dropdown">
				<select
					id="<?php echo esc_attr( "{$input_prefix}[method]" ); ?>"
					name="<?php echo esc_attr( "{$input_prefix}[method]" ); ?>"
					class="method wc-enhanced-select"
					data-plugins="<?php echo wc_esc_json( wp_json_encode( $this->get_wcs_requisite_plugins() ) ); ?>"
				>
				<?php foreach ( $shipping_methods as $method_id => $method ) : ?>
					<option value="<?php echo esc_attr( $method_id ); ?>" <?php selected( $selected, $method_id ); ?>><?php echo esc_html( $method['name'] ); ?></option>
				<?php endforeach; ?>
				</select>
			</div>
			<div class="shipping-method-descriptions">
				<?php foreach ( $shipping_methods as $method_id => $method ) : ?>
					<p class="shipping-method-description <?php echo esc_attr( $method_id ); ?> <?php echo $method_id !== $selected ? 'hide' : ''; ?>">
						<?php echo esc_html( $method['description'] ); ?>
					</p>
				<?php endforeach; ?>
			</div>
		</div>

		<div class="shipping-method-settings">
		<?php foreach ( $shipping_methods as $method_id => $method ) : ?>
			<?php
			if ( empty( $method['settings'] ) ) {
				continue;
			}
			?>
			<div class="shipping-method-setting <?php echo esc_attr( $method_id ); ?> <?php echo $method_id !== $selected ? 'hide' : ''; ?>">
			<?php foreach ( $method['settings'] as $setting_id => $setting ) : ?>
				<?php $method_setting_id = "{$input_prefix}[{$method_id}][{$setting_id}]"; ?>
				<input
					type="<?php echo esc_attr( $setting['type'] ); ?>"
					placeholder="<?php echo esc_attr( $setting['default_value'] ); ?>"
					id="<?php echo esc_attr( $method_setting_id ); ?>"
					name="<?php echo esc_attr( $method_setting_id ); ?>"
					class="<?php echo esc_attr( $setting['required'] ? 'shipping-method-required-field' : '' ); ?>"
					<?php echo ( $method_id === $selected && $setting['required'] ) ? 'required' : ''; ?>
				/>
				<p class="description">
					<?php echo esc_html( $setting['description'] ); ?>
				</p>
			<?php endforeach; ?>
			</div>
		<?php endforeach; ?>
		</div>
		<?php
	}

	/**
	 * Render a product weight unit dropdown.
	 *
	 * @deprecated 4.6.0
	 * @return string|false
	 */
	protected function get_product_weight_selection() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$weight_unit = get_option( 'woocommerce_weight_unit' );
		ob_start();
		?>
		<span class="wc-setup-shipping-unit">
			<select id="weight_unit" name="weight_unit" class="wc-enhanced-select">
				<option value="kg" <?php selected( $weight_unit, 'kg' ); ?>><?php esc_html_e( 'Kilograms', 'woocommerce' ); ?></option>
				<option value="g" <?php selected( $weight_unit, 'g' ); ?>><?php esc_html_e( 'Grams', 'woocommerce' ); ?></option>
				<option value="lbs" <?php selected( $weight_unit, 'lbs' ); ?>><?php esc_html_e( 'Pounds', 'woocommerce' ); ?></option>
				<option value="oz" <?php selected( $weight_unit, 'oz' ); ?>><?php esc_html_e( 'Ounces', 'woocommerce' ); ?></option>
			</select>
		</span>
		<?php

		return ob_get_clean();
	}

	/**
	 * Render a product dimension unit dropdown.
	 *
	 * @deprecated 4.6.0
	 * @return string|false
	 */
	protected function get_product_dimension_selection() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$dimension_unit = get_option( 'woocommerce_dimension_unit' );
		ob_start();
		?>
		<span class="wc-setup-shipping-unit">
			<select id="dimension_unit" name="dimension_unit" class="wc-enhanced-select">
				<option value="m" <?php selected( $dimension_unit, 'm' ); ?>><?php esc_html_e( 'Meters', 'woocommerce' ); ?></option>
				<option value="cm" <?php selected( $dimension_unit, 'cm' ); ?>><?php esc_html_e( 'Centimeters', 'woocommerce' ); ?></option>
				<option value="mm" <?php selected( $dimension_unit, 'mm' ); ?>><?php esc_html_e( 'Millimeters', 'woocommerce' ); ?></option>
				<option value="in" <?php selected( $dimension_unit, 'in' ); ?>><?php esc_html_e( 'Inches', 'woocommerce' ); ?></option>
				<option value="yd" <?php selected( $dimension_unit, 'yd' ); ?>><?php esc_html_e( 'Yards', 'woocommerce' ); ?></option>
			</select>
		</span>
		<?php

		return ob_get_clean();
	}

	/**
	 * Shipping.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_shipping() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$country_code          = WC()->countries->get_base_country();
		$country_name          = WC()->countries->countries[ $country_code ];
		$prefixed_country_name = WC()->countries->estimated_for_prefix( $country_code ) . $country_name;
		$currency_code         = get_woocommerce_currency();
		$existing_zones        = WC_Shipping_Zones::get_zones();
		$intro_text            = '';

		if ( empty( $existing_zones ) ) {
			$intro_text = sprintf(
				/* translators: %s: country name including the 'the' prefix if needed */
				__( "We've created two Shipping Zones - for %s and for the rest of the world. Below you can set Flat Rate shipping costs for these Zones or offer Free Shipping.", 'woocommerce' ),
				$prefixed_country_name
			);
		}

		$is_wcs_labels_supported  = $this->is_wcs_shipping_labels_supported_country( $country_code );
		$is_shipstation_supported = $this->is_shipstation_supported_country( $country_code );

		?>
		<h1><?php esc_html_e( 'Shipping', 'woocommerce' ); ?></h1>
		<?php if ( $intro_text ) : ?>
			<p><?php echo wp_kses_post( $intro_text ); ?></p>
		<?php endif; ?>
		<form method="post">
			<?php if ( $is_wcs_labels_supported || $is_shipstation_supported ) : ?>
				<ul class="wc-setup-shipping-recommended">
				<?php
				if ( $is_wcs_labels_supported ) :
					$this->display_recommended_item(
						array(
							'type'        => 'woocommerce_services',
							'title'       => __( 'Did you know you can print shipping labels at home?', 'woocommerce' ),
							'description' => __( 'Use WooCommerce Shipping (powered by WooCommerce Services & Jetpack) to save time at the post office by printing your shipping labels at home.', 'woocommerce' ),
							'img_url'     => WC()->plugin_url() . '/assets/images/obw-woocommerce-services-icon.png',
							'img_alt'     => __( 'WooCommerce Services icon', 'woocommerce' ),
							'plugins'     => $this->get_wcs_requisite_plugins(),
						)
					);
				elseif ( $is_shipstation_supported ) :
					$this->display_recommended_item(
						array(
							'type'        => 'shipstation',
							'title'       => __( 'Did you know you can print shipping labels at home?', 'woocommerce' ),
							'description' => __( 'We recommend using ShipStation to save time at the post office by printing your shipping labels at home. Try ShipStation free for 30 days.', 'woocommerce' ),
							'img_url'     => WC()->plugin_url() . '/assets/images/obw-shipstation-icon.png',
							'img_alt'     => __( 'ShipStation icon', 'woocommerce' ),
							'plugins'     => array(
								array(
									'name' => __( 'ShipStation', 'woocommerce' ),
									'slug' => 'woocommerce-shipstation-integration',
								),
							),
						)
					);
				endif;
				?>
				</ul>
			<?php endif; ?>

			<?php if ( empty( $existing_zones ) ) : ?>
				<ul class="wc-wizard-services shipping">
					<li class="wc-wizard-service-item">
						<div class="wc-wizard-service-name">
							<p><?php esc_html_e( 'Shipping Zone', 'woocommerce' ); ?></p>
						</div>
						<div class="wc-wizard-service-description">
							<p><?php esc_html_e( 'Shipping Method', 'woocommerce' ); ?></p>
						</div>
					</li>
					<li class="wc-wizard-service-item">
						<div class="wc-wizard-service-name">
							<p><?php echo esc_html( $country_name ); ?></p>
						</div>
						<div class="wc-wizard-service-description">
							<?php $this->shipping_method_selection_form( $country_code, $currency_code, 'shipping_zones[domestic]' ); ?>
						</div>
						<div class="wc-wizard-service-enable">
							<span class="wc-wizard-service-toggle">
								<input id="shipping_zones[domestic][enabled]" type="checkbox" name="shipping_zones[domestic][enabled]" value="yes" checked="checked" class="wc-wizard-shipping-method-enable" data-plugins="true" />
								<label for="shipping_zones[domestic][enabled]">
							</span>
						</div>
					</li>
					<li class="wc-wizard-service-item">
						<div class="wc-wizard-service-name">
							<p><?php esc_html_e( 'Locations not covered by your other zones', 'woocommerce' ); ?></p>
						</div>
						<div class="wc-wizard-service-description">
							<?php $this->shipping_method_selection_form( $country_code, $currency_code, 'shipping_zones[intl]' ); ?>
						</div>
						<div class="wc-wizard-service-enable">
							<span class="wc-wizard-service-toggle">
								<input id="shipping_zones[intl][enabled]" type="checkbox" name="shipping_zones[intl][enabled]" value="yes" checked="checked" class="wc-wizard-shipping-method-enable" data-plugins="true" />
								<label for="shipping_zones[intl][enabled]">
							</span>
						</div>
					</li>
					<li class="wc-wizard-service-info">
						<p>
						<?php
						printf(
							wp_kses(
								/* translators: %1$s: live rates tooltip text, %2$s: shipping extensions URL */
								__( 'If you\'d like to offer <span class="help_tip" data-tip="%1$s">live rates</span> from a specific carrier (e.g. UPS) you can find a variety of extensions available for WooCommerce <a href="%2$s" target="_blank">here</a>.', 'woocommerce' ),
								array(
									'span' => array(
										'class'    => array(),
										'data-tip' => array(),
									),
									'a'    => array(
										'href'   => array(),
										'target' => array(),
									),
								)
							),
							esc_attr__( 'A live rate is the exact cost to ship an order, quoted directly from the shipping carrier.', 'woocommerce' ),
							'https://woocommerce.com/product-category/woocommerce-extensions/shipping-methods/shipping-carriers/'
						);
						?>
						</p>
					</li>
				</ul>
			<?php endif; ?>

			<div class="wc-setup-shipping-units">
				<p>
					<?php
						echo wp_kses(
							sprintf(
								/* translators: %1$s: weight unit dropdown, %2$s: dimension unit dropdown */
								esc_html__( 'We\'ll use %1$s for product weight and %2$s for product dimensions.', 'woocommerce' ),
								$this->get_product_weight_selection(),
								$this->get_product_dimension_selection()
							),
							array(
								'span'   => array(
									'class' => array(),
								),
								'select' => array(
									'id'    => array(),
									'name'  => array(),
									'class' => array(),
								),
								'option' => array(
									'value'    => array(),
									'selected' => array(),
								),
							)
						);
					?>
				</p>
			</div>

			<p class="wc-setup-actions step">
				<?php $this->plugin_install_info(); ?>
				<button class="button-primary button button-large button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
				<?php wp_nonce_field( 'wc-setup' ); ?>
			</p>
		</form>
		<?php
	}

	/**
	 * Save shipping options.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_shipping_save() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
	}

	/**
	 * Is Stripe country supported
	 * https://stripe.com/global .
	 *
	 * @param string $country_code Country code.
	 *
	 * @deprecated 4.6.0
	 * @return bool
	 */
	protected function is_stripe_supported_country( $country_code ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$stripe_supported_countries = array(
			'AU',
			'AT',
			'BE',
			'CA',
			'DK',
			'FI',
			'FR',
			'DE',
			'HK',
			'IE',
			'JP',
			'LU',
			'NL',
			'NZ',
			'NO',
			'SG',
			'ES',
			'SE',
			'CH',
			'GB',
			'US',
		);

		return in_array( $country_code, $stripe_supported_countries, true );
	}

	/**
	 * Is PayPal currency supported.
	 *
	 * @param string $currency Currency code.
	 * @return boolean
	 *
	 * @deprecated 4.6.0
	 */
	protected function is_paypal_supported_currency( $currency ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$supported_currencies = array(
			'AUD',
			'BRL',
			'CAD',
			'MXN',
			'NZD',
			'HKD',
			'SGD',
			'USD',
			'EUR',
			'JPY',
			'TRY',
			'NOK',
			'CZK',
			'DKK',
			'HUF',
			'ILS',
			'MYR',
			'PHP',
			'PLN',
			'SEK',
			'CHF',
			'TWD',
			'THB',
			'GBP',
			'RMB',
			'RUB',
			'INR',
		);
		return in_array( $currency, $supported_currencies, true );
	}

	/**
	 * Is Klarna Checkout country supported.
	 *
	 * @param string $country_code Country code.
	 *
	 * @deprecated 4.6.0
	 * @return bool
	 */
	protected function is_klarna_checkout_supported_country( $country_code ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$supported_countries = array(
			'SE', // Sweden.
			'FI', // Finland.
			'NO', // Norway.
			'NL', // Netherlands.
		);
		return in_array( $country_code, $supported_countries, true );
	}

	/**
	 * Is Klarna Payments country supported.
	 *
	 * @param string $country_code Country code.
	 *
	 * @deprecated 4.6.0
	 * @return bool
	 */
	protected function is_klarna_payments_supported_country( $country_code ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$supported_countries = array(
			'DK', // Denmark.
			'DE', // Germany.
			'AT', // Austria.
		);
		return in_array( $country_code, $supported_countries, true );
	}

	/**
	 * Is Square country supported
	 *
	 * @param string $country_code Country code.
	 *
	 * @deprecated 4.6.0
	 * @return bool
	 */
	protected function is_square_supported_country( $country_code ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$square_supported_countries = array(
			'US',
			'CA',
			'JP',
			'GB',
			'AU',
		);
		return in_array( $country_code, $square_supported_countries, true );
	}

	/**
	 * Is eWAY Payments country supported
	 *
	 * @param string $country_code Country code.
	 *
	 * @deprecated 4.6.0
	 * @return bool
	 */
	protected function is_eway_payments_supported_country( $country_code ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$supported_countries = array(
			'AU', // Australia.
			'NZ', // New Zealand.
		);
		return in_array( $country_code, $supported_countries, true );
	}

	/**
	 * Is ShipStation country supported
	 *
	 * @param string $country_code Country code.
	 *
	 * @deprecated 4.6.0
	 * @return bool
	 */
	protected function is_shipstation_supported_country( $country_code ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$supported_countries = array(
			'AU', // Australia.
			'CA', // Canada.
			'GB', // United Kingdom.
		);
		return in_array( $country_code, $supported_countries, true );
	}

	/**
	 * Is WooCommerce Services shipping label country supported
	 *
	 * @param string $country_code Country code.
	 *
	 * @deprecated 4.6.0
	 * @return bool
	 */
	protected function is_wcs_shipping_labels_supported_country( $country_code ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$supported_countries = array(
			'US', // United States.
		);
		return in_array( $country_code, $supported_countries, true );
	}

	/**
	 * Helper method to retrieve the current user's email address.
	 *
	 * @deprecated 4.6.0
	 * @return string Email address
	 */
	protected function get_current_user_email() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$current_user = wp_get_current_user();
		$user_email   = $current_user->user_email;

		return $user_email;
	}

	/**
	 * Array of all possible "in cart" gateways that can be offered.
	 *
	 * @deprecated 4.6.0
	 * @return array
	 */
	protected function get_wizard_available_in_cart_payment_gateways() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$user_email = $this->get_current_user_email();

		$stripe_description = '<p>' . sprintf(
			/* translators: %s: URL */
			__( 'Accept debit and credit cards in 135+ currencies, methods such as Alipay, and one-touch checkout with Apple Pay. <a href="%s" target="_blank">Learn more</a>.', 'woocommerce' ),
			'https://woocommerce.com/products/stripe/'
		) . '</p>';
		$paypal_checkout_description = '<p>' . sprintf(
			/* translators: %s: URL */
			__( 'Safe and secure payments using credit cards or your customer\'s PayPal account. <a href="%s" target="_blank">Learn more</a>.', 'woocommerce' ),
			'https://woocommerce.com/products/woocommerce-gateway-paypal-checkout/'
		) . '</p>';
		$klarna_checkout_description = '<p>' . sprintf(
			/* translators: %s: URL */
			__( 'Full checkout experience with pay now, pay later and slice it. No credit card numbers, no passwords, no worries. <a href="%s" target="_blank">Learn more about Klarna</a>.', 'woocommerce' ),
			'https://woocommerce.com/products/klarna-checkout/'
		) . '</p>';
		$klarna_payments_description = '<p>' . sprintf(
			/* translators: %s: URL */
			__( 'Choose the payment that you want, pay now, pay later or slice it. No credit card numbers, no passwords, no worries. <a href="%s" target="_blank">Learn more about Klarna</a>.', 'woocommerce' ),
			'https://woocommerce.com/products/klarna-payments/ '
		) . '</p>';
		$square_description = '<p>' . sprintf(
			/* translators: %s: URL */
			__( 'Securely accept credit and debit cards with one low rate, no surprise fees (custom rates available). Sell online and in store and track sales and inventory in one place. <a href="%s" target="_blank">Learn more about Square</a>.', 'woocommerce' ),
			'https://woocommerce.com/products/square/'
		) . '</p>';

		return array(
			'stripe'              => array(
				'name'        => __( 'WooCommerce Stripe Gateway', 'woocommerce' ),
				'image'       => WC()->plugin_url() . '/assets/images/stripe.png',
				'description' => $stripe_description,
				'class'       => 'checked stripe-logo',
				'repo-slug'   => 'woocommerce-gateway-stripe',
				'settings'    => array(
					'create_account' => array(
						'label'       => __( 'Set up Stripe for me using this email:', 'woocommerce' ),
						'type'        => 'checkbox',
						'value'       => 'yes',
						'default'     => 'yes',
						'placeholder' => '',
						'required'    => false,
						'plugins'     => $this->get_wcs_requisite_plugins(),
					),
					'email'          => array(
						'label'       => __( 'Stripe email address:', 'woocommerce' ),
						'type'        => 'email',
						'value'       => $user_email,
						'placeholder' => __( 'Stripe email address', 'woocommerce' ),
						'required'    => true,
					),
				),
			),
			'ppec_paypal'         => array(
				'name'        => __( 'WooCommerce PayPal Checkout Gateway', 'woocommerce' ),
				'image'       => WC()->plugin_url() . '/assets/images/paypal.png',
				'description' => $paypal_checkout_description,
				'enabled'     => false,
				'class'       => 'checked paypal-logo',
				'repo-slug'   => 'woocommerce-gateway-paypal-express-checkout',
				'settings'    => array(
					'reroute_requests' => array(
						'label'       => __( 'Set up PayPal for me using this email:', 'woocommerce' ),
						'type'        => 'checkbox',
						'value'       => 'yes',
						'default'     => 'yes',
						'placeholder' => '',
						'required'    => false,
						'plugins'     => $this->get_wcs_requisite_plugins(),
					),
					'email'            => array(
						'label'       => __( 'Direct payments to email address:', 'woocommerce' ),
						'type'        => 'email',
						'value'       => $user_email,
						'placeholder' => __( 'Email address to receive payments', 'woocommerce' ),
						'required'    => true,
					),
				),
			),
			WC_Gateway_Paypal::ID => array(
				'name'        => __( 'PayPal Standard', 'woocommerce' ),
				'description' => __( 'Accept payments via PayPal using account balance or credit card.', 'woocommerce' ),
				'image'       => '',
				'settings'    => array(
					'email' => array(
						'label'       => __( 'PayPal email address:', 'woocommerce' ),
						'type'        => 'email',
						'value'       => $user_email,
						'placeholder' => __( 'PayPal email address', 'woocommerce' ),
						'required'    => true,
					),
				),
			),
			'klarna_checkout'     => array(
				'name'        => __( 'Klarna Checkout for WooCommerce', 'woocommerce' ),
				'description' => $klarna_checkout_description,
				'image'       => WC()->plugin_url() . '/assets/images/klarna-black.png',
				'enabled'     => true,
				'class'       => 'klarna-logo',
				'repo-slug'   => 'klarna-checkout-for-woocommerce',
			),
			'klarna_payments'     => array(
				'name'        => __( 'Klarna Payments for WooCommerce', 'woocommerce' ),
				'description' => $klarna_payments_description,
				'image'       => WC()->plugin_url() . '/assets/images/klarna-black.png',
				'enabled'     => true,
				'class'       => 'klarna-logo',
				'repo-slug'   => 'klarna-payments-for-woocommerce',
			),
			'square'              => array(
				'name'        => __( 'WooCommerce Square', 'woocommerce' ),
				'description' => $square_description,
				'image'       => WC()->plugin_url() . '/assets/images/square-black.png',
				'class'       => 'square-logo',
				'enabled'     => false,
				'repo-slug'   => 'woocommerce-square',
			),
			'eway'                => array(
				'name'        => __( 'WooCommerce eWAY Gateway', 'woocommerce' ),
				'description' => __( 'The eWAY extension for WooCommerce allows you to take credit card payments directly on your store without redirecting your customers to a third party site to make payment.', 'woocommerce' ),
				'image'       => WC()->plugin_url() . '/assets/images/eway-logo.jpg',
				'enabled'     => false,
				'class'       => 'eway-logo',
				'repo-slug'   => 'woocommerce-gateway-eway',
			),
			'payfast'             => array(
				'name'        => __( 'WooCommerce PayFast Gateway', 'woocommerce' ),
				'description' => __( 'The PayFast extension for WooCommerce enables you to accept payments by Credit Card and EFT via one of South Africa’s most popular payment gateways. No setup fees or monthly subscription costs.', 'woocommerce' ),
				'image'       => WC()->plugin_url() . '/assets/images/payfast.png',
				'class'       => 'payfast-logo',
				'enabled'     => false,
				'repo-slug'   => 'woocommerce-payfast-gateway',
				'file'        => 'gateway-payfast.php',
			),
		);
	}

	/**
	 * Simple array of "in cart" gateways to show in wizard.
	 *
	 * @deprecated 4.6.0
	 * @return array
	 */
	public function get_wizard_in_cart_payment_gateways() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$gateways = $this->get_wizard_available_in_cart_payment_gateways();
		$country  = WC()->countries->get_base_country();
		$currency = get_woocommerce_currency();

		$can_stripe  = $this->is_stripe_supported_country( $country );
		$can_eway    = $this->is_eway_payments_supported_country( $country );
		$can_payfast = ( 'ZA' === $country ); // South Africa.
		$can_paypal  = $this->is_paypal_supported_currency( $currency );

		if ( ! current_user_can( 'install_plugins' ) ) {
			return $can_paypal ? array( WC_Gateway_Paypal::ID => $gateways[ WC_Gateway_Paypal::ID ] ) : array();
		}

		$klarna_or_square = false;

		if ( $this->is_klarna_checkout_supported_country( $country ) ) {
			$klarna_or_square = 'klarna_checkout';
		} elseif ( $this->is_klarna_payments_supported_country( $country ) ) {
			$klarna_or_square = 'klarna_payments';
		} elseif ( $this->is_square_supported_country( $country ) && get_option( 'woocommerce_sell_in_person' ) ) {
			$klarna_or_square = 'square';
		}

		$offered_gateways = array();

		if ( $can_stripe ) {
			$gateways['stripe']['enabled']  = true;
			$gateways['stripe']['featured'] = true;
			$offered_gateways              += array( 'stripe' => $gateways['stripe'] );
		} elseif ( $can_paypal ) {
			$gateways['ppec_paypal']['enabled'] = true;
		}

		if ( $klarna_or_square ) {
			if ( in_array( $klarna_or_square, array( 'klarna_checkout', 'klarna_payments' ), true ) ) {
				$gateways[ $klarna_or_square ]['enabled']  = true;
				$gateways[ $klarna_or_square ]['featured'] = false;
				$offered_gateways                         += array(
					$klarna_or_square => $gateways[ $klarna_or_square ],
				);
			} else {
				$offered_gateways += array(
					$klarna_or_square => $gateways[ $klarna_or_square ],
				);
			}
		}

		if ( $can_paypal ) {
			$offered_gateways += array( 'ppec_paypal' => $gateways['ppec_paypal'] );
		}

		if ( $can_eway ) {
			$offered_gateways += array( 'eway' => $gateways['eway'] );
		}

		if ( $can_payfast ) {
			$offered_gateways += array( 'payfast' => $gateways['payfast'] );
		}

		return $offered_gateways;
	}

	/**
	 * Simple array of "manual" gateways to show in wizard.
	 *
	 * @deprecated 4.6.0
	 * @return array
	 */
	public function get_wizard_manual_payment_gateways() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$gateways = array(
			WC_Gateway_Cheque::ID => array(
				'name'        => _x( 'Check payments', 'Check payment method', 'woocommerce' ),
				'description' => __( 'A simple offline gateway that lets you accept a check as method of payment.', 'woocommerce' ),
				'image'       => '',
				'class'       => '',
			),
			WC_Gateway_BACS::ID   => array(
				'name'        => __( 'Bank transfer (BACS) payments', 'woocommerce' ),
				'description' => __( 'A simple offline gateway that lets you accept BACS payment.', 'woocommerce' ),
				'image'       => '',
				'class'       => '',
			),
			WC_Gateway_COD::ID    => array(
				'name'        => __( 'Cash on delivery', 'woocommerce' ),
				'description' => __( 'A simple offline gateway that lets you accept cash on delivery.', 'woocommerce' ),
				'image'       => '',
				'class'       => '',
			),
		);

		return $gateways;
	}

	/**
	 * Display service item in list.
	 *
	 * @param int   $item_id Item ID.
	 * @param array $item_info Item info array.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function display_service_item( $item_id, $item_info ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$item_class = 'wc-wizard-service-item';
		if ( isset( $item_info['class'] ) ) {
			$item_class .= ' ' . $item_info['class'];
		}

		$previously_saved_settings = get_option( 'woocommerce_' . $item_id . '_settings' );

		// Show the user-saved state if it was previously saved.
		// Otherwise, rely on the item info.
		if ( is_array( $previously_saved_settings ) ) {
			$should_enable_toggle = ( isset( $previously_saved_settings['enabled'] ) && 'yes' === $previously_saved_settings['enabled'] ) ? true : ( isset( $item_info['enabled'] ) && $item_info['enabled'] );
		} else {
			$should_enable_toggle = isset( $item_info['enabled'] ) && $item_info['enabled'];
		}

		$plugins = null;
		if ( isset( $item_info['repo-slug'] ) ) {
			$plugin  = array(
				'slug' => $item_info['repo-slug'],
				'name' => $item_info['name'],
			);
			$plugins = array( $plugin );
		}

		?>
		<li class="<?php echo esc_attr( $item_class ); ?>">
			<div class="wc-wizard-service-name">
				<?php if ( ! empty( $item_info['image'] ) ) : ?>
					<img src="<?php echo esc_attr( $item_info['image'] ); ?>" alt="<?php echo esc_attr( $item_info['name'] ); ?>" />
				<?php else : ?>
					<p><?php echo esc_html( $item_info['name'] ); ?></p>
				<?php endif; ?>
			</div>
			<div class="wc-wizard-service-enable">
				<span class="wc-wizard-service-toggle <?php echo esc_attr( $should_enable_toggle ? '' : 'disabled' ); ?>" tabindex="0">
					<input
						id="wc-wizard-service-<?php echo esc_attr( $item_id ); ?>"
						type="checkbox"
						name="wc-wizard-service-<?php echo esc_attr( $item_id ); ?>-enabled"
						value="yes" <?php checked( $should_enable_toggle ); ?>
						data-plugins="<?php echo wc_esc_json( wp_json_encode( $plugins ) ); ?>"
					/>
					<label for="wc-wizard-service-<?php echo esc_attr( $item_id ); ?>">
				</span>
			</div>
			<div class="wc-wizard-service-description">
				<?php echo wp_kses_post( wpautop( $item_info['description'] ) ); ?>
				<?php if ( ! empty( $item_info['settings'] ) ) : ?>
					<div class="wc-wizard-service-settings <?php echo $should_enable_toggle ? '' : 'hide'; ?>">
						<?php foreach ( $item_info['settings'] as $setting_id => $setting ) : ?>
							<?php
							$is_checkbox = 'checkbox' === $setting['type'];

							if ( $is_checkbox ) {
								$checked = false;
								if ( isset( $previously_saved_settings[ $setting_id ] ) ) {
									$checked = 'yes' === $previously_saved_settings[ $setting_id ];
								} elseif ( false === $previously_saved_settings && isset( $setting['default'] ) ) {
									$checked = 'yes' === $setting['default'];
								}
							}
							if ( 'email' === $setting['type'] ) {
								$value = empty( $previously_saved_settings[ $setting_id ] )
									? $setting['value']
									: $previously_saved_settings[ $setting_id ];
							}
							?>
							<?php $input_id = $item_id . '_' . $setting_id; ?>
							<div class="<?php echo esc_attr( 'wc-wizard-service-setting-' . $input_id ); ?>">
								<label
									for="<?php echo esc_attr( $input_id ); ?>"
									class="<?php echo esc_attr( $input_id ); ?>"
								>
									<?php echo esc_html( $setting['label'] ); ?>
								</label>
								<input
									type="<?php echo esc_attr( $setting['type'] ); ?>"
									id="<?php echo esc_attr( $input_id ); ?>"
									class="<?php echo esc_attr( 'payment-' . $setting['type'] . '-input' ); ?>"
									name="<?php echo esc_attr( $input_id ); ?>"
									value="<?php echo esc_attr( isset( $value ) ? $value : $setting['value'] ); ?>"
									placeholder="<?php echo esc_attr( $setting['placeholder'] ); ?>"
									<?php echo ( $setting['required'] ) ? 'required' : ''; ?>
									<?php echo $is_checkbox ? checked( isset( $checked ) && $checked, true, false ) : ''; ?>
									data-plugins="<?php echo wc_esc_json( wp_json_encode( isset( $setting['plugins'] ) ? $setting['plugins'] : null ) ); ?>"
								/>
								<?php if ( ! empty( $setting['description'] ) ) : ?>
									<span class="wc-wizard-service-settings-description"><?php echo esc_html( $setting['description'] ); ?></span>
								<?php endif; ?>
							</div>
						<?php endforeach; ?>
					</div>
				<?php endif; ?>
			</div>
		</li>
		<?php
	}

	/**
	 * Is it a featured service?
	 *
	 * @param array $service Service info array.
	 *
	 * @deprecated 4.6.0
	 * @return boolean
	 */
	public function is_featured_service( $service ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		return ! empty( $service['featured'] );
	}

	/**
	 * Is this a non featured service?
	 *
	 * @param array $service Service info array.
	 *
	 * @deprecated 4.6.0
	 * @return boolean
	 */
	public function is_not_featured_service( $service ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		return ! $this->is_featured_service( $service );
	}

	/**
	 * Payment Step.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_payment() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$featured_gateways = array_filter( $this->get_wizard_in_cart_payment_gateways(), array( $this, 'is_featured_service' ) );
		$in_cart_gateways  = array_filter( $this->get_wizard_in_cart_payment_gateways(), array( $this, 'is_not_featured_service' ) );
		$manual_gateways   = $this->get_wizard_manual_payment_gateways();
		?>
		<h1><?php esc_html_e( 'Payment', 'woocommerce' ); ?></h1>
		<form method="post" class="wc-wizard-payment-gateway-form">
			<p>
				<?php
				printf(
					wp_kses(
						/* translators: %s: Link */
						__( 'WooCommerce can accept both online and offline payments. <a href="%s" target="_blank">Additional payment methods</a> can be installed later.', 'woocommerce' ),
						array(
							'a' => array(
								'href'   => array(),
								'target' => array(),
							),
						)
					),
					esc_url( admin_url( 'admin.php?page=wc-addons&section=payment-gateways' ) )
				);
				?>
			</p>
			<?php if ( $featured_gateways ) : ?>
			<ul class="wc-wizard-services featured">
				<?php
				foreach ( $featured_gateways as $gateway_id => $gateway ) {
					$this->display_service_item( $gateway_id, $gateway );
				}
				?>
			</ul>
			<?php endif; ?>
			<?php if ( $in_cart_gateways ) : ?>
			<ul class="wc-wizard-services in-cart">
				<?php
				foreach ( $in_cart_gateways as $gateway_id => $gateway ) {
					$this->display_service_item( $gateway_id, $gateway );
				}
				?>
			</ul>
			<?php endif; ?>
			<ul class="wc-wizard-services manual">
				<li class="wc-wizard-services-list-toggle closed">
					<div class="wc-wizard-service-name">
						<?php esc_html_e( 'Offline Payments', 'woocommerce' ); ?>
					</div>
					<div class="wc-wizard-service-description">
						<?php esc_html_e( 'Collect payments from customers offline.', 'woocommerce' ); ?>
					</div>
					<div class="wc-wizard-service-enable" tabindex="0">
						<input class="wc-wizard-service-list-toggle" id="wc-wizard-service-list-toggle" type="checkbox">
						<label for="wc-wizard-service-list-toggle"></label>
					</div>
				</li>
				<?php
				foreach ( $manual_gateways as $gateway_id => $gateway ) {
					$this->display_service_item( $gateway_id, $gateway );
				}
				?>
			</ul>
			<p class="wc-setup-actions step">
				<?php $this->plugin_install_info(); ?>
				<button type="submit" class="button-primary button button-large button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
				<?php wp_nonce_field( 'wc-setup' ); ?>
			</p>
		</form>
		<?php
	}

	/**
	 * Payment Step save.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_payment_save() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
	}

	/**
	 * Display recommended item.
	 *
	 * @param array $item_info Item info array.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	protected function display_recommended_item( $item_info ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$type        = $item_info['type'];
		$title       = $item_info['title'];
		$description = $item_info['description'];
		$img_url     = $item_info['img_url'];
		$img_alt     = $item_info['img_alt'];
		?>
		<li class="recommended-item checkbox">
			<input
				id="<?php echo esc_attr( 'wc_recommended_' . $type ); ?>"
				type="checkbox"
				name="<?php echo esc_attr( 'setup_' . $type ); ?>"
				value="yes"
				checked
				data-plugins="<?php echo wc_esc_json( wp_json_encode( isset( $item_info['plugins'] ) ? $item_info['plugins'] : null ) ); ?>"
			/>
			<label for="<?php echo esc_attr( 'wc_recommended_' . $type ); ?>">
				<img
					src="<?php echo esc_url( $img_url ); ?>"
					class="<?php echo esc_attr( 'recommended-item-icon-' . $type ); ?> recommended-item-icon"
					alt="<?php echo esc_attr( $img_alt ); ?>" />
				<div class="recommended-item-description-container">
					<h3><?php echo esc_html( $title ); ?></h3>
					<p><?php echo wp_kses( $description, array(
						'a' => array(
							'href'   => array(),
							'target' => array(),
							'rel'    => array(),
						),
						'em' => array(),
					) ); ?></p>
				</div>
			</label>
		</li>
		<?php
	}

	/**
	 * Recommended step
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_recommended() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		?>
		<h1><?php esc_html_e( 'Recommended for All WooCommerce Stores', 'woocommerce' ); ?></h1>
		<p>
			<?php esc_html_e( 'Enhance your store with these recommended free features.', 'woocommerce' ); ?>
		</p>
		<form method="post">
			<ul class="recommended-step">
				<?php
				if ( $this->should_show_theme() ) :
					$theme      = wp_get_theme();
					$theme_name = $theme['Name'];
					$this->display_recommended_item( array(
						'type'        => 'storefront_theme',
						'title'       => __( 'Storefront Theme', 'woocommerce' ),
						'description' => sprintf(
							/* translators: %s: theme name. */
							__(
								'Design your store with deep WooCommerce integration. If toggled on, we’ll install <a href="https://woocommerce.com/storefront/" target="_blank" rel="noopener noreferrer">Storefront</a>, and your current theme <em>%s</em> will be deactivated.',
								'woocommerce'
							),
							$theme_name
						),
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-storefront-icon.svg',
						'img_alt'     => __( 'Storefront icon', 'woocommerce' ),
					) );
				endif;

				if ( $this->should_show_automated_tax() ) :
					$this->display_recommended_item( array(
						'type'        => 'automated_taxes',
						'title'       => __( 'Automated Taxes', 'woocommerce' ),
						'description' => __( 'Save time and errors with automated tax calculation and collection at checkout. Powered by WooCommerce Services and Jetpack.', 'woocommerce' ),
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-taxes-icon.svg',
						'img_alt'     => __( 'automated taxes icon', 'woocommerce' ),
						'plugins'     => $this->get_wcs_requisite_plugins(),
					) );
				endif;

				if ( $this->should_show_wc_admin() ) :
					$this->display_recommended_item( array(
						'type'        => 'wc_admin',
						'title'       => __( 'WooCommerce Admin', 'woocommerce' ),
						'description' => __( 'Manage your store\'s reports and monitor key metrics with a new and improved interface and dashboard.', 'woocommerce' ),
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-woocommerce-admin-icon.svg',
						'img_alt'     => __( 'WooCommerce Admin icon', 'woocommerce' ),
						'plugins'     => array( array( 'name' => __( 'WooCommerce Admin', 'woocommerce' ), 'slug' => 'woocommerce-admin' ) ),
					) );
				endif;

				if ( $this->should_show_mailchimp() ) :
					$this->display_recommended_item( array(
						'type'        => 'mailchimp',
						'title'       => __( 'Mailchimp', 'woocommerce' ),
						'description' => __( 'Join the 16 million customers who use Mailchimp. Sync list and store data to send automated emails, and targeted campaigns.', 'woocommerce' ),
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-mailchimp-icon.svg',
						'img_alt'     => __( 'Mailchimp icon', 'woocommerce' ),
						'plugins'     => array( array( 'name' => __( 'Mailchimp for WooCommerce', 'woocommerce' ), 'slug' => 'mailchimp-for-woocommerce' ) ),
					) );
				endif;

				if ( $this->should_show_facebook() ) :
					$this->display_recommended_item( array(
						'type'        => 'facebook',
						'title'       => __( 'Facebook', 'woocommerce' ),
						'description' => __( 'Enjoy all Facebook products combined in one extension: pixel tracking, catalog sync, messenger chat, shop functionality and Instagram shopping (coming soon)!', 'woocommerce' ),
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-facebook-icon.svg',
						'img_alt'     => __( 'Facebook icon', 'woocommerce' ),
						'plugins'     => array( array( 'name' => __( 'Facebook for WooCommerce', 'woocommerce' ), 'slug' => 'facebook-for-woocommerce' ) ),
					) );
				endif;
			?>
		</ul>
			<p class="wc-setup-actions step">
				<?php $this->plugin_install_info(); ?>
				<button type="submit" class="button-primary button button-large button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
				<?php wp_nonce_field( 'wc-setup' ); ?>
			</p>
		</form>
		<?php
	}

	/**
	 * Recommended step save.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_recommended_save() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
	}

	/**
	 * Go to the next step if Jetpack was connected.
	 *
	 * @return void
	 */
	protected function wc_setup_activate_actions() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		if (
			isset( $_GET['from'] ) &&
			'wpcom' === $_GET['from'] &&
			class_exists( 'Jetpack' ) &&
			Jetpack::is_active()
		) {
			wp_redirect( esc_url_raw( remove_query_arg( 'from', $this->get_next_step_link() ) ) );
			exit;
		}
	}

	/**
	 * Get feature list for activation.
	 *
	 * @deprecated 4.6.0
	 * @return array
	 */
	protected function wc_setup_activate_get_feature_list() {
		$features = array();

		$stripe_settings = get_option( 'woocommerce_stripe_settings', false );
		$stripe_enabled  = is_array( $stripe_settings )
			&& isset( $stripe_settings['create_account'] ) && 'yes' === $stripe_settings['create_account']
			&& isset( $stripe_settings['enabled'] ) && 'yes' === $stripe_settings['enabled'];
		$ppec_settings   = get_option( 'woocommerce_ppec_paypal_settings', false );
		$ppec_enabled    = is_array( $ppec_settings )
			&& isset( $ppec_settings['reroute_requests'] ) && 'yes' === $ppec_settings['reroute_requests']
			&& isset( $ppec_settings['enabled'] ) && 'yes' === $ppec_settings['enabled'];

		$features['payment'] = $stripe_enabled || $ppec_enabled;
		$features['taxes']   = (bool) get_option( 'woocommerce_setup_automated_taxes', false );
		$features['labels']  = (bool) get_option( 'woocommerce_setup_shipping_labels', false );

		return $features;
	}

	/**
	 * Get feature list string for activation.
	 *
	 * @deprecated 4.6.0
	 * @return string|false
	 */
	protected function wc_setup_activate_get_feature_list_str() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$features = $this->wc_setup_activate_get_feature_list();
		if ( $features['payment'] && $features['taxes'] && $features['labels'] ) {
			return __( 'payment setup, automated taxes and discounted shipping labels', 'woocommerce' );
		} else if ( $features['payment'] && $features['taxes'] ) {
			return __( 'payment setup and automated taxes', 'woocommerce' );
		} else if ( $features['payment'] && $features['labels'] ) {
			return __( 'payment setup and discounted shipping labels', 'woocommerce' );
		} else if ( $features['payment'] ) {
			return __( 'payment setup', 'woocommerce' );
		} else if ( $features['taxes'] && $features['labels'] ) {
			return __( 'automated taxes and discounted shipping labels', 'woocommerce' );
		} else if ( $features['taxes'] ) {
			return __( 'automated taxes', 'woocommerce' );
		} else if ( $features['labels'] ) {
			return __( 'discounted shipping labels', 'woocommerce' );
		}
		return false;
	}

	/**
	 * Activate step.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_activate() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$this->wc_setup_activate_actions();

		$jetpack_connected = class_exists( 'Jetpack' ) && Jetpack::is_active();

		$has_jetpack_error = false;
		if ( isset( $_GET['activate_error'] ) ) {
			$has_jetpack_error = true;

			$title = __( "Sorry, we couldn't connect your store to Jetpack", 'woocommerce' );

			$error_message = $this->get_activate_error_message( sanitize_text_field( wp_unslash( $_GET['activate_error'] ) ) );
			$description = $error_message;
		} else {
			$feature_list = $this->wc_setup_activate_get_feature_list_str();

			$description = false;

			if ( $feature_list ) {
				if ( ! $jetpack_connected ) {
					/* translators: %s: list of features, potentially comma separated */
					$description_base = __( 'Your store is almost ready! To activate services like %s, just connect with Jetpack.', 'woocommerce' );
				} else {
					$description_base = __( 'Thanks for using Jetpack! Your store is almost ready: to activate services like %s, just connect your store.', 'woocommerce' );
				}
				$description = sprintf( $description_base, $feature_list );
			}

			if ( ! $jetpack_connected ) {
				$title = $feature_list ?
					__( 'Connect your store to Jetpack', 'woocommerce' ) :
					__( 'Connect your store to Jetpack to enable extra features', 'woocommerce' );
				$button_text = __( 'Continue with Jetpack', 'woocommerce' );
			} elseif ( $feature_list ) {
				$title = __( 'Connect your store to activate WooCommerce Services', 'woocommerce' );
				$button_text = __( 'Continue with WooCommerce Services', 'woocommerce' );
			} else {
				wp_redirect( esc_url_raw( $this->get_next_step_link() ) );
				exit;
			}
		}
		?>
		<h1><?php echo esc_html( $title ); ?></h1>
		<p><?php echo esc_html( (string) $description ); ?></p>

		<?php if ( $jetpack_connected ) : ?>
			<div class="activate-splash">
				<img
					class="jetpack-logo"
					src="<?php echo esc_url( WC()->plugin_url() . '/assets/images/jetpack_horizontal_logo.png' ); ?>"
					alt="<?php esc_attr_e( 'Jetpack logo', 'woocommerce' ); ?>"
				/>
				<img
					class="wcs-notice"
					src="<?php echo esc_url( WC()->plugin_url() . '/assets/images/wcs-notice.png' ); ?>"
				/>
			</div>
		<?php else : ?>
			<img
				class="jetpack-logo"
				src="<?php echo esc_url( WC()->plugin_url() . '/assets/images/jetpack_vertical_logo.png' ); ?>"
				alt="<?php esc_attr_e( 'Jetpack logo', 'woocommerce' ); ?>"
			/>
		<?php endif; ?>

		<?php if ( $has_jetpack_error ) : ?>
			<p class="wc-setup-actions step">
				<a
					href="<?php echo esc_url( $this->get_next_step_link() ); ?>"
					class="button-primary button button-large"
				>
					<?php esc_html_e( 'Finish setting up your store', 'woocommerce' ); ?>
				</a>
			</p>
		<?php else : ?>
			<p class="jetpack-terms">
				<?php
					printf(
						wp_kses_post( __( 'By connecting your site you agree to our fascinating <a href="%1$s" target="_blank">Terms of Service</a> and to <a href="%2$s" target="_blank">share details</a> with WordPress.com', 'woocommerce' ) ),
						'https://wordpress.com/tos',
						'https://jetpack.com/support/what-data-does-jetpack-sync'
					);
				?>
			</p>
			<form method="post" class="activate-jetpack">
				<p class="wc-setup-actions step">
					<button type="submit" class="button-primary button button-large" value="<?php echo esc_attr( $button_text ); ?>"><?php echo esc_html( $button_text ); ?></button>
				</p>
				<input type="hidden" name="save_step" value="activate" />
				<?php wp_nonce_field( 'wc-setup' ); ?>
			</form>
			<?php if ( ! $jetpack_connected ) : ?>
				<h3 class="jetpack-reasons">
					<?php
						echo esc_html( $description ?
							__( "Bonus reasons you'll love Jetpack", 'woocommerce' ) :
							__( "Reasons you'll love Jetpack", 'woocommerce' )
						);
					?>
				</h3>
				<ul class="wc-wizard-features">
					<li class="wc-wizard-feature-item">
						<p class="wc-wizard-feature-name">
							<strong><?php esc_html_e( 'Better security', 'woocommerce' ); ?></strong>
						</p>
						<p class="wc-wizard-feature-description">
							<?php esc_html_e( 'Protect your store from unauthorized access.', 'woocommerce' ); ?>
						</p>
					</li>
					<li class="wc-wizard-feature-item">
						<p class="wc-wizard-feature-name">
							<strong><?php esc_html_e( 'Store stats', 'woocommerce' ); ?></strong>
						</p>
						<p class="wc-wizard-feature-description">
							<?php esc_html_e( 'Get insights on how your store is doing, including total sales, top products, and more.', 'woocommerce' ); ?>
						</p>
					</li>
					<li class="wc-wizard-feature-item">
						<p class="wc-wizard-feature-name">
							<strong><?php esc_html_e( 'Store monitoring', 'woocommerce' ); ?></strong>
						</p>
						<p class="wc-wizard-feature-description">
							<?php esc_html_e( 'Get an alert if your store is down for even a few minutes.', 'woocommerce' ); ?>
						</p>
					</li>
					<li class="wc-wizard-feature-item">
						<p class="wc-wizard-feature-name">
							<strong><?php esc_html_e( 'Product promotion', 'woocommerce' ); ?></strong>
						</p>
						<p class="wc-wizard-feature-description">
							<?php esc_html_e( "Share new items on social media the moment they're live in your store.", 'woocommerce' ); ?>
						</p>
					</li>
				</ul>
			<?php endif; ?>
		<?php endif; ?>
	<?php
	}

	/**
	 * Get all activate errors.
	 *
	 * @deprecated 4.6.0
	 * @return array
	 */
	protected function get_all_activate_errors() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		return array(
			'default' => __( "Sorry! We tried, but we couldn't connect Jetpack just now 😭. Please go to the Plugins tab to connect Jetpack, so that you can finish setting up your store.", 'woocommerce' ),
			'jetpack_cant_be_installed' => __( "Sorry! We tried, but we couldn't install Jetpack for you 😭. Please go to the Plugins tab to install it, and finish setting up your store.", 'woocommerce' ),
			'register_http_request_failed' => __( "Sorry! We couldn't contact Jetpack just now 😭. Please make sure that your site is visible over the internet, and that it accepts incoming and outgoing requests via curl. You can also try to connect to Jetpack again, and if you run into any more issues, please contact support.", 'woocommerce' ),
			'siteurl_private_ip_dev' => __( "Your site might be on a private network. Jetpack can only connect to public sites. Please make sure your site is visible over the internet, and then try connecting again 🙏." , 'woocommerce' ),
		);
	}

	/**
	 * Get activate error message.
	 *
	 * @param string $code Error code.
	 *
	 * @deprecated 4.6.0
	 * @return string
	 */
	protected function get_activate_error_message( $code = '' ) {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		$errors = $this->get_all_activate_errors();
		return array_key_exists( $code, $errors ) ? $errors[ $code ] : $errors['default'];
	}

	/**
	 * Activate step save.
	 *
	 * Install, activate, and launch connection flow for Jetpack.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_activate_save() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
	}

	/**
	 * Final step.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public function wc_setup_ready() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', 'Onboarding is maintained in WooCommerce Admin.' );
		// We've made it! Don't prompt the user to run the wizard again.
		WC_Admin_Notices::remove_notice( 'install', true );

		$user_email = $this->get_current_user_email();
		$docs_url   = 'https://woocommerce.com/documentation/plugins/woocommerce/getting-started/?utm_source=setupwizard&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin';
		$help_text  = sprintf(
			/* translators: %1$s: link to docs */
			__( 'Visit WooCommerce.com to learn more about <a href="%1$s" target="_blank">getting started</a>.', 'woocommerce' ),
			$docs_url
		);
		?>
		<h1><?php esc_html_e( "You're ready to start selling!", 'woocommerce' ); ?></h1>

		<div class="woocommerce-message woocommerce-newsletter">
			<p><?php esc_html_e( "We're here for you — get tips, product updates, and inspiration straight to your mailbox.", 'woocommerce' ); ?></p>
			<form action="//woocommerce.us8.list-manage.com/subscribe/post?u=2c1434dc56f9506bf3c3ecd21&amp;id=13860df971&amp;SIGNUPPAGE=plugin" method="post" target="_blank" novalidate>
				<div class="newsletter-form-container">
					<input
						class="newsletter-form-email"
						type="email"
						value="<?php echo esc_attr( $user_email ); ?>"
						name="EMAIL"
						placeholder="<?php esc_attr_e( 'Email address', 'woocommerce' ); ?>"
						required
					>
					<p class="wc-setup-actions step newsletter-form-button-container">
						<button
							type="submit"
							value="<?php esc_attr_e( 'Yes please!', 'woocommerce' ); ?>"
							name="subscribe"
							id="mc-embedded-subscribe"
							class="button-primary button newsletter-form-button"
						><?php esc_html_e( 'Yes please!', 'woocommerce' ); ?></button>
					</p>
				</div>
			</form>
		</div>

		<ul class="wc-wizard-next-steps">
			<li class="wc-wizard-next-step-item">
				<div class="wc-wizard-next-step-description">
					<p class="next-step-heading"><?php esc_html_e( 'Next step', 'woocommerce' ); ?></p>
					<h3 class="next-step-description"><?php esc_html_e( 'Create some products', 'woocommerce' ); ?></h3>
					<p class="next-step-extra-info"><?php esc_html_e( "You're ready to add products to your store.", 'woocommerce' ); ?></p>
				</div>
				<div class="wc-wizard-next-step-action">
					<p class="wc-setup-actions step">
						<a class="button button-primary button-large" href="<?php echo esc_url( admin_url( 'post-new.php?post_type=product&tutorial=true' ) ); ?>">
							<?php esc_html_e( 'Create a product', 'woocommerce' ); ?>
						</a>
					</p>
				</div>
			</li>
			<li class="wc-wizard-next-step-item">
				<div class="wc-wizard-next-step-description">
					<p class="next-step-heading"><?php esc_html_e( 'Have an existing store?', 'woocommerce' ); ?></p>
					<h3 class="next-step-description"><?php esc_html_e( 'Import products', 'woocommerce' ); ?></h3>
					<p class="next-step-extra-info"><?php esc_html_e( 'Transfer existing products to your new store — just import a CSV file.', 'woocommerce' ); ?></p>
				</div>
				<div class="wc-wizard-next-step-action">
					<p class="wc-setup-actions step">
						<a class="button button-large" href="<?php echo esc_url( admin_url( 'edit.php?post_type=product&page=product_importer' ) ); ?>">
							<?php esc_html_e( 'Import products', 'woocommerce' ); ?>
						</a>
					</p>
				</div>
			</li>
			<li class="wc-wizard-additional-steps">
				<div class="wc-wizard-next-step-description">
					<p class="next-step-heading"><?php esc_html_e( 'You can also:', 'woocommerce' ); ?></p>
				</div>
				<div class="wc-wizard-next-step-action">
					<p class="wc-setup-actions step">
						<a class="button button-large" href="<?php echo esc_url( admin_url() ); ?>">
							<?php esc_html_e( 'Visit Dashboard', 'woocommerce' ); ?>
						</a>
						<a class="button button-large" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings' ) ); ?>">
							<?php esc_html_e( 'Review Settings', 'woocommerce' ); ?>
						</a>
						<a class="button button-large" href="<?php echo esc_url( add_query_arg( array( 'autofocus' => array( 'panel' => 'woocommerce' ), 'url' => wc_get_page_permalink( 'shop' ) ), admin_url( 'customize.php' ) ) ); ?>">
							<?php esc_html_e( 'View &amp; Customize', 'woocommerce' ); ?>
						</a>
					</p>
				</div>
			</li>
		</ul>
		<p class="next-steps-help-text"><?php echo wp_kses_post( $help_text ); ?></p>
		<?php
	}
}

PK     tS\(f
  
    class-wc-admin-customize.phpnu [        <?php
/**
 * Setup customize items.
 *
 * @package WooCommerce\Admin\Customize
 * @version 3.1.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'WC_Admin_Customize', false ) ) :

	/**
	 * WC_Admin_Customize Class.
	 */
	class WC_Admin_Customize {

		/**
		 * Initialize customize actions.
		 */
		public function __construct() {
			// Include custom items to customizer nav menu settings.
			add_filter( 'customize_nav_menu_available_item_types', array( $this, 'register_customize_nav_menu_item_types' ) );
			add_filter( 'customize_nav_menu_available_items', array( $this, 'register_customize_nav_menu_items' ), 10, 4 );
		}

		/**
		 * Register customize new nav menu item types.
		 * This will register WooCommerce account endpoints as a nav menu item type.
		 *
		 * @since  3.1.0
		 * @param  array $item_types Menu item types.
		 * @return array
		 */
		public function register_customize_nav_menu_item_types( $item_types ) {
			$item_types[] = array(
				'title'      => __( 'WooCommerce Endpoints', 'woocommerce' ),
				'type_label' => __( 'WooCommerce Endpoint', 'woocommerce' ),
				'type'       => 'woocommerce_nav',
				'object'     => 'woocommerce_endpoint',
			);

			return $item_types;
		}

		/**
		 * Register account endpoints to customize nav menu items.
		 *
		 * @since  3.1.0
		 * @param  array   $items  List of nav menu items.
		 * @param  string  $type   Nav menu type.
		 * @param  string  $object Nav menu object.
		 * @param  integer $page   Page number.
		 * @return array
		 */
		public function register_customize_nav_menu_items( $items = array(), $type = '', $object = '', $page = 0 ) {
			if ( 'woocommerce_endpoint' !== $object ) {
				return $items;
			}

			// Don't allow pagination since all items are loaded at once.
			if ( 0 < $page ) {
				return $items;
			}

			// Get items from account menu.
			$endpoints = wc_get_account_menu_items();

			// Remove dashboard item.
			if ( isset( $endpoints['dashboard'] ) ) {
				unset( $endpoints['dashboard'] );
			}

			// Include missing lost password.
			$endpoints['lost-password'] = __( 'Lost password', 'woocommerce' );

			$endpoints = apply_filters( 'woocommerce_custom_nav_menu_items', $endpoints );

			foreach ( $endpoints as $endpoint => $title ) {
				$items[] = array(
					'id'         => $endpoint,
					'title'      => $title,
					'type_label' => __( 'Custom Link', 'woocommerce' ),
					'url'        => esc_url_raw( wc_get_account_endpoint_url( $endpoint ) ),
				);
			}

			return $items;
		}
	}

endif;

return new WC_Admin_Customize();
PK     tS\Q8  8  2  plugin-updates/class-wc-updates-screen-updates.phpnu [        <?php
/**
 * Manages WooCommerce plugin updating on the Updates screen.
 *
 * @package     WooCommerce\Admin
 * @version     3.2.0
 */

use Automattic\Jetpack\Constants;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'WC_Plugin_Updates' ) ) {
	include_once dirname( __FILE__ ) . '/class-wc-plugin-updates.php';
}

/**
 * Class WC_Updates_Screen_Updates
 */
class WC_Updates_Screen_Updates extends WC_Plugin_Updates {

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'admin_print_footer_scripts', array( $this, 'update_screen_modal' ) );
	}

	/**
	 * Show a warning message on the upgrades screen if the user tries to upgrade and has untested plugins.
	 */
	public function update_screen_modal() {
		$updateable_plugins = get_plugin_updates();
		if ( empty( $updateable_plugins['woocommerce/woocommerce.php'] )
			|| empty( $updateable_plugins['woocommerce/woocommerce.php']->update )
			|| empty( $updateable_plugins['woocommerce/woocommerce.php']->update->new_version ) ) {
			return;
		}

		$version_type = Constants::get_constant( 'WC_SSR_PLUGIN_UPDATE_RELEASE_VERSION_TYPE' );
		if ( ! is_string( $version_type ) ) {
			$version_type = 'none';
		}

		$this->new_version            = wc_clean( $updateable_plugins['woocommerce/woocommerce.php']->update->new_version );
		$this->major_untested_plugins = $this->get_untested_plugins( $this->new_version, $version_type );

		if ( ! empty( $this->major_untested_plugins ) ) {
			echo $this->get_extensions_modal_warning(); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
			$this->update_screen_modal_js();
		}
	}

	/**
	 * JS for the modal window on the updates screen.
	 */
	protected function update_screen_modal_js() {
		?>
		<script>
			( function( $ ) {
				var modal_dismissed = false;

				// Show the modal if the WC upgrade checkbox is checked.
				var show_modal_if_checked = function() {
					if ( modal_dismissed ) {
						return;
					}
					var $checkbox = $( 'input[value="woocommerce/woocommerce.php"]' );
					if ( $checkbox.prop( 'checked' ) ) {
						$( '#wc-upgrade-warning' ).trigger( 'click' );
					}
				}

				$( '#plugins-select-all, input[value="woocommerce/woocommerce.php"]' ).on( 'change', function() {
					show_modal_if_checked();
				} );

				// Add a hidden thickbox link to use for bringing up the modal.
				$('body').append( '<a href="#TB_inline?height=600&width=550&inlineId=wc_untested_extensions_modal" class="wc-thickbox" id="wc-upgrade-warning" style="display:none"></a>' );

				// Don't show the modal again once it's been accepted.
				$( '#wc_untested_extensions_modal .accept' ).on( 'click', function( evt ) {
					evt.preventDefault();
					modal_dismissed = true;
					tb_remove();
				});

				// Uncheck the WC update checkbox if the modal is canceled.
				$( '#wc_untested_extensions_modal .cancel' ).on( 'click', function( evt ) {
					evt.preventDefault();
					$( 'input[value="woocommerce/woocommerce.php"]' ).prop( 'checked', false );
					tb_remove();
				});
			})( jQuery );
		</script>
		<?php
		$this->generic_modal_js();
	}
}
new WC_Updates_Screen_Updates();
PK     tS\ȸ}u  u  >  plugin-updates/views/html-notice-untested-extensions-modal.phpnu [        <?php
/**
 * Admin View: Notice - Untested extensions.
 *
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$untested_plugins_msg = sprintf(
	/* translators: %s: version number */
	__( 'The following active plugin(s) have not declared compatibility with WooCommerce %s yet and should be updated and examined further before you proceed:', 'woocommerce' ),
	$new_version
);

?>
<div id="wc_untested_extensions_modal">
	<div class="wc_untested_extensions_modal--content">
		<h1><?php esc_html_e( "Are you sure you're ready?", 'woocommerce' ); ?></h1>
		<div class="wc_plugin_upgrade_notice extensions_warning">
			<p><?php echo esc_html( $untested_plugins_msg ); ?></p>

			<div class="plugin-details-table-container">
				<table class="plugin-details-table" cellspacing="0">
					<thead>
						<tr>
							<th><?php esc_html_e( 'Plugin', 'woocommerce' ); ?></th>
							<th><?php esc_html_e( 'Tested up to WooCommerce version', 'woocommerce' ); ?></th>
						</tr>
					</thead>
					<tbody>
						<?php foreach ( $plugins as $plugin ) : ?>
							<tr>
								<td><?php echo esc_html( $plugin['Name'] ); ?></td>
								<td><?php echo esc_html( $plugin['WC tested up to'] ); ?></td>
							</tr>
						<?php endforeach ?>
					</tbody>
				</table>
			</div>

			<p><?php esc_html_e( 'We strongly recommend creating a backup of your site before updating.', 'woocommerce' ); ?> <a href="https://woocommerce.com/2017/05/create-use-backups-woocommerce/" target="_blank"><?php esc_html_e( 'Learn more', 'woocommerce' ); ?></a></p>

			<?php if ( current_user_can( 'update_plugins' ) ) : ?>
				<div class="actions">
					<a href="#" class="button button-secondary cancel"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></a>
					<a class="button button-primary accept" href="#"><?php esc_html_e( 'Update now', 'woocommerce' ); ?></a>
				</div>
			<?php endif ?>
		</div>
	</div>
</div>
PK     tS\uޔ    ?  plugin-updates/views/html-notice-untested-extensions-inline.phpnu [        <?php
/**
 * Admin View: Notice - Untested extensions.
 *
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div class="wc_plugin_upgrade_notice extensions_warning <?php echo esc_attr( $upgrade_type ); ?>">
	<p><?php echo wp_kses_post( $message ); ?></p>

	<table class="plugin-details-table" cellspacing="0">
		<thead>
			<tr>
				<th><?php esc_html_e( 'Plugin', 'woocommerce' ); ?></th>
				<th><?php esc_html_e( 'Tested up to WooCommerce version', 'woocommerce' ); ?></th>
			</tr>
		</thead>
		<tbody>
			<?php foreach ( $plugins as $plugin ) : ?>
				<tr>
					<td><?php echo esc_html( $plugin['Name'] ); ?></td>
					<td><?php echo esc_html( $plugin['WC tested up to'] ); ?></td>
				</tr>
			<?php endforeach ?>
		</tbody>
	</table>
</div>
PK     tS\ql&  &  2  plugin-updates/class-wc-plugins-screen-updates.phpnu [        <?php
/**
 * Manages WooCommerce plugin updating on the Plugins screen.
 *
 * @package     WooCommerce\Admin
 * @version     3.2.0
 */

use Automattic\Jetpack\Constants;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'WC_Plugin_Updates' ) ) {
	include_once dirname( __FILE__ ) . '/class-wc-plugin-updates.php';
}

/**
 * Class WC_Plugins_Screen_Updates
 */
class WC_Plugins_Screen_Updates extends WC_Plugin_Updates {

	/**
	 * The upgrade notice shown inline.
	 *
	 * @var string
	 */
	protected $upgrade_notice = '';

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'in_plugin_update_message-woocommerce/woocommerce.php', array( $this, 'in_plugin_update_message' ), 10, 2 );
	}

	/**
	 * Show plugin changes on the plugins screen. Code adapted from W3 Total Cache.
	 *
	 * @param array    $args Unused parameter.
	 * @param stdClass $response Plugin update response.
	 */
	public function in_plugin_update_message( $args, $response ) {
		$version_type = Constants::get_constant( 'WC_SSR_PLUGIN_UPDATE_RELEASE_VERSION_TYPE' );
		if ( ! is_string( $version_type ) ) {
			$version_type = 'none';
		}

		$this->new_version            = $response->new_version;
		$this->upgrade_notice         = $this->get_upgrade_notice( $response->new_version );
		$this->major_untested_plugins = $this->get_untested_plugins( $response->new_version, $version_type );

		$current_version_parts = explode( '.', Constants::get_constant( 'WC_VERSION' ) );
		$new_version_parts     = explode( '.', $this->new_version );

		// If user has already moved to the minor version, we don't need to flag up anything.
		if ( version_compare( $current_version_parts[0] . '.' . $current_version_parts[1], $new_version_parts[0] . '.' . $new_version_parts[1], '=' ) ) {
			return;
		}

		if ( ! empty( $this->major_untested_plugins ) ) {
			$this->upgrade_notice .= $this->get_extensions_inline_warning_major();
		}

		if ( ! empty( $this->major_untested_plugins ) ) {
			$this->upgrade_notice .= $this->get_extensions_modal_warning();
			add_action( 'admin_print_footer_scripts', array( $this, 'plugin_screen_modal_js' ) );
		}

		echo apply_filters( 'woocommerce_in_plugin_update_message', $this->upgrade_notice ? '</p>' . wp_kses_post( $this->upgrade_notice ) . '<p class="dummy">' : '' ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
	}

	/**
	 * Get the upgrade notice from WordPress.org.
	 *
	 * @param  string $version WooCommerce new version.
	 * @return string
	 */
	protected function get_upgrade_notice( $version ) {
		$transient_name = 'wc_upgrade_notice_' . $version;
		$upgrade_notice = get_transient( $transient_name );

		if ( false === $upgrade_notice ) {
			$response = wp_safe_remote_get( 'https://plugins.svn.wordpress.org/woocommerce/trunk/readme.txt' );

			if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) {
				$upgrade_notice = $this->parse_update_notice( $response['body'], $version );
				set_transient( $transient_name, $upgrade_notice, DAY_IN_SECONDS );
			}
		}
		return $upgrade_notice;
	}

	/**
	 * Parse update notice from readme file.
	 *
	 * @param  string $content WooCommerce readme file content.
	 * @param  string $new_version WooCommerce new version.
	 * @return string
	 */
	private function parse_update_notice( $content, $new_version ) {
		$version_parts     = explode( '.', $new_version );
		$check_for_notices = array(
			$version_parts[0] . '.0', // Major.
			$version_parts[0] . '.0.0', // Major.
			$version_parts[0] . '.' . $version_parts[1], // Minor.
			$version_parts[0] . '.' . $version_parts[1] . '.' . $version_parts[2], // Patch.
		);
		$notice_regexp     = '~==\s*Upgrade Notice\s*==\s*=\s*(.*)\s*=(.*)(=\s*' . preg_quote( $new_version ) . '\s*=|$)~Uis';
		$upgrade_notice    = '';

		foreach ( $check_for_notices as $check_version ) {
			if ( version_compare( Constants::get_constant( 'WC_VERSION' ), $check_version, '>' ) ) {
				continue;
			}

			$matches = null;
			if ( preg_match( $notice_regexp, $content, $matches ) ) {
				$notices = (array) preg_split( '~[\r\n]+~', trim( $matches[2] ) );

				if ( version_compare( trim( $matches[1] ), $check_version, '=' ) ) {
					$upgrade_notice .= '<p class="wc_plugin_upgrade_notice">';

					foreach ( $notices as $index => $line ) {
						$upgrade_notice .= preg_replace( '~\[([^\]]*)\]\(([^\)]*)\)~', '<a href="${2}">${1}</a>', $line );
					}

					$upgrade_notice .= '</p>';
				}
				break;
			}
		}
		return wp_kses_post( $upgrade_notice );
	}

	/**
	 * JS for the modal window on the plugins screen.
	 */
	public function plugin_screen_modal_js() {
		?>
		<script>
			( function( $ ) {
				var $update_box = $( '#woocommerce-update' );
				var $update_link = $update_box.find('a.update-link').first();
				var update_url = $update_link.attr( 'href' );

				// Set up thickbox.
				$update_link.removeClass( 'update-link' );
				$update_link.addClass( 'wc-thickbox' );
				$update_link.attr( 'href', '#TB_inline?height=600&width=550&inlineId=wc_untested_extensions_modal' );

				// Trigger the update if the user accepts the modal's warning.
				$( '#wc_untested_extensions_modal .accept' ).on( 'click', function( evt ) {
					evt.preventDefault();
					tb_remove();
					$update_link.removeClass( 'wc-thickbox open-plugin-details-modal' );
					$update_link.addClass( 'update-link' );
					$update_link.attr( 'href', update_url );
					$update_link.trigger( 'click' );
				});

				$( '#wc_untested_extensions_modal .cancel' ).on( 'click', function( evt ) {
					evt.preventDefault();
					tb_remove();
				});
			})( jQuery );
		</script>
		<?php
		$this->generic_modal_js();
	}
}
new WC_Plugins_Screen_Updates();
PK     tS\ECJ    *  plugin-updates/class-wc-plugin-updates.phpnu [        <?php
/**
 * Class for displaying plugin warning notifications and determining 3rd party plugin compatibility.
 *
 * @package     WooCommerce\Admin
 * @version     3.2.0
 */

use Automattic\Jetpack\Constants;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Admin_Plugin_Updates Class.
 */
class WC_Plugin_Updates {

	/**
	 * This is the header used by extensions to show requirements.
	 *
	 * @var string
	 */
	const VERSION_REQUIRED_HEADER = 'WC requires at least';

	/**
	 * This is the header used by extensions to show testing.
	 *
	 * @var string
	 */
	const VERSION_TESTED_HEADER = 'WC tested up to';

	/**
	 * The version for the update to WooCommerce.
	 *
	 * @var string
	 */
	protected $new_version = '';

	/**
	 * Array of plugins lacking testing with the major version.
	 *
	 * @var array
	 */
	protected $major_untested_plugins = array();

	/**
	 * Common JS for initializing and managing thickbox-based modals.
	 */
	protected function generic_modal_js() {
		?>
		<script>
			( function( $ ) {
				// Initialize thickbox.
				tb_init( '.wc-thickbox' );

				var old_tb_position = false;

				// Make the WC thickboxes look good when opened.
				$( '.wc-thickbox' ).on( 'click', function( evt ) {
					var $overlay = $( '#TB_overlay' );
					if ( ! $overlay.length ) {
						$( 'body' ).append( '<div id="TB_overlay"></div><div id="TB_window" class="wc_untested_extensions_modal_container"></div>' );
					} else {
						$( '#TB_window' ).removeClass( 'thickbox-loading' ).addClass( 'wc_untested_extensions_modal_container' );
					}

					// WP overrides the tb_position function. We need to use a different tb_position function than that one.
					// This is based on the original tb_position.
					if ( ! old_tb_position ) {
						old_tb_position = tb_position;
					}
					tb_position = function() {
						$( '#TB_window' ).css( { marginLeft: '-' + parseInt( ( TB_WIDTH / 2 ), 10 ) + 'px', width: TB_WIDTH + 'px' } );
						$( '#TB_window' ).css( { marginTop: '-' + parseInt( ( TB_HEIGHT / 2 ), 10 ) + 'px' } );
					};
				});

				// Reset tb_position to WP default when modal is closed.
				$( 'body' ).on( 'thickbox:removed', function() {
					if ( old_tb_position ) {
						tb_position = old_tb_position;
					}
				});
			})( jQuery );
		</script>
		<?php
	}

	/*
	|--------------------------------------------------------------------------
	| Message Helpers
	|--------------------------------------------------------------------------
	|
	| Methods for getting messages.
	*/

	/**
	 * Get the inline warning notice for major version updates.
	 *
	 * @return string
	 */
	protected function get_extensions_inline_warning_major() {
		$upgrade_type  = 'major';
		$plugins       = $this->major_untested_plugins;
		$version_parts = explode( '.', $this->new_version );
		$new_version   = $version_parts[0] . '.0';

		if ( empty( $plugins ) ) {
			return;
		}

		/* translators: %s: version number */
		$message = sprintf( __( "<strong>Heads up!</strong> The versions of the following plugins you're running haven't been tested with WooCommerce %s. Please update them or confirm compatibility before updating WooCommerce, or you may experience issues:", 'woocommerce' ), $new_version );

		ob_start();
		include __DIR__ . '/views/html-notice-untested-extensions-inline.php';
		return ob_get_clean();
	}

	/**
	 * Get the warning notice for the modal window.
	 *
	 * @return string
	 */
	protected function get_extensions_modal_warning() {
		$version_parts = explode( '.', $this->new_version );
		$new_version   = $version_parts[0] . '.0';
		$plugins       = $this->major_untested_plugins;

		ob_start();
		include __DIR__ . '/views/html-notice-untested-extensions-modal.php';
		return ob_get_clean();
	}

	/*
	|--------------------------------------------------------------------------
	| Data Helpers
	|--------------------------------------------------------------------------
	|
	| Methods for getting & manipulating data.
	*/

	/**
	 * Get installed plugins that have a tested version lower than the input version.
	 *
	 * In case of testing major version compatibility and if current WC version is >= major version part
	 * of the $new_version, no plugins are returned, even if they don't explicitly declare compatibility
	 * with the $new_version.
	 *
	 * @param string $new_version WooCommerce version to test against.
	 * @param string $release 'major', 'minor', or 'none'.
	 * @return array of plugin info arrays
	 */
	public function get_untested_plugins( $new_version, $release ) {
		// Since 5.0 all versions are backwards compatible.
		if ( 'none' === $release ) {
			return array();
		}

		$extensions        = array_merge( $this->get_plugins_with_header( self::VERSION_TESTED_HEADER ), $this->get_plugins_for_woocommerce() );
		$untested          = array();
		$new_version_parts = explode( '.', $new_version );
		$version           = $new_version_parts[0];

		if ( 'minor' === $release ) {
			$version .= '.' . $new_version_parts[1];
		}

		foreach ( $extensions as $file => $plugin ) {
			if ( ! empty( $plugin[ self::VERSION_TESTED_HEADER ] ) ) {
				$plugin_version_parts = explode( '.', $plugin[ self::VERSION_TESTED_HEADER ] );

				if ( ! is_numeric( $plugin_version_parts[0] )
					|| ( 'minor' === $release && ! isset( $plugin_version_parts[1] ) )
					|| ( 'minor' === $release && ! is_numeric( $plugin_version_parts[1] ) )
					) {
					continue;
				}

				$plugin_version = $plugin_version_parts[0];

				if ( 'minor' === $release ) {
					$plugin_version .= '.' . $plugin_version_parts[1];
				}

				if ( version_compare( $plugin_version, $version, '<' ) ) {
					$untested[ $file ] = $plugin;
				}
			} else {
				$plugin[ self::VERSION_TESTED_HEADER ] = __( 'unknown', 'woocommerce' );
				$untested[ $file ]                     = $plugin;
			}
		}

		return $untested;
	}

	/**
	 * Get plugins that have a valid value for a specific header.
	 *
	 * @param string $header Plugin header to search for.
	 * @return array Array of plugins that contain the searched header.
	 */
	protected function get_plugins_with_header( $header ) {
		$plugins = get_plugins();
		$matches = array();

		foreach ( $plugins as $file => $plugin ) {
			if ( ! empty( $plugin[ $header ] ) ) {
				$matches[ $file ] = $plugin;
			}
		}

		return apply_filters( 'woocommerce_get_plugins_with_header', $matches, $header, $plugins );
	}

	/**
	 * Get plugins which "maybe" are for WooCommerce.
	 *
	 * @return array of plugin info arrays
	 */
	protected function get_plugins_for_woocommerce() {
		$plugins = get_plugins();
		$matches = array();

		foreach ( $plugins as $file => $plugin ) {
			if ( 'WooCommerce' !== $plugin['Name'] && ( stristr( $plugin['Name'], 'woocommerce' ) || stristr( $plugin['Description'], 'woocommerce' ) ) ) {
				$matches[ $file ] = $plugin;
			}
		}

		return apply_filters( 'woocommerce_get_plugins_for_woocommerce', $matches, $plugins );
	}
}
PK     tS\`e**  **  (  helper/class-wc-product-usage-notice.phpnu [        <?php
/**
 * WooCommerce Product Usage Notice.
 *
 * @package WooCommerce\Admin\Helper
 */

declare( strict_types = 1 );

use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Product usage notice class.
 */
class WC_Product_Usage_Notice {
	/**
	 * User meta key prefix to store dismiss counts per product. Product ID is
	 * the suffix part.
	 *
	 * @var string
	 */
	const DISMISSED_COUNT_META_PREFIX = '_woocommerce_product_usage_notice_dismissed_count_';

	/**
	 * User meta key prefix to store timestamp of last dismissed product usage notice.
	 * Product ID is the suffix part.
	 *
	 * @var string
	 */
	const DISMISSED_TIMESTAMP_META_PREFIX = '_woocommerce_product_usage_notice_dismissed_timestamp_';

	/**
	 * User meta key prefix to store timestamp of last clicked remind later from
	 * product usage notice. Product ID is the suffix part.
	 *
	 * @var string
	 */
	const REMIND_LATER_TIMESTAMP_META_PREFIX = '_woocommerce_product_usage_notice_remind_later_timestamp_';

	/**
	 * User meta key to store timestamp of last dismissed of any product usage
	 * notices. There's no product ID in the meta key.
	 *
	 * @var string
	 */
	const LAST_DISMISSED_TIMESTAMP_META = '_woocommerce_product_usage_notice_last_dismissed_timestamp';

	/**
	 * Array of product usage notice rules from helper API.
	 *
	 * @var array
	 */
	private static $product_usage_notice_rules = array();

	/**
	 * Current product usage notice rule applied to the current admin screen.
	 *
	 * @var array
	 */
	private static $current_notice_rule = array();

	/**
	 * Loads the class, runs on init.
	 *
	 * @return void
	 */
	public static function load() {
		add_action( 'current_screen', array( __CLASS__, 'maybe_show_product_usage_notice' ) );

		add_action( 'wp_ajax_woocommerce_dismiss_product_usage_notice', array( __CLASS__, 'ajax_dismiss' ) );
		add_action( 'wp_ajax_woocommerce_remind_later_product_usage_notice', array( __CLASS__, 'ajax_remind_later' ) );
	}

	/**
	 * Maybe show product usage notice in a given screen object.
	 *
	 * @param \WP_Screen $screen Current \WP_Screen object.
	 */
	public static function maybe_show_product_usage_notice( $screen ) {
		$user_id = get_current_user_id();
		if ( ! $user_id ) {
			return;
		}

		if ( ! WC_Helper::is_site_connected() ) {
			return;
		}

		try {
			self::$product_usage_notice_rules = WC_Helper::get_product_usage_notice_rules();
		} catch ( Exception $e ) {
			return;
		}

		if ( empty( self::$product_usage_notice_rules ) ) {
			return;
		}

		self::$current_notice_rule = self::get_current_notice_rule( $screen );
		if ( empty( self::$current_notice_rule ) ) {
			return;
		}

		$product_id = self::$current_notice_rule['id'];

		if ( self::is_notice_throttled( $user_id, $product_id ) ) {
			return;
		}

		add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_product_usage_notice_scripts' ) );
	}

	/**
	 * Check whether the user clicked "remind later" recently.
	 *
	 * @param int $user_id    User ID.
	 * @param int $product_id Product ID.
	 *
	 * @return bool
	 */
	private static function is_remind_later_clicked_recently( int $user_id, int $product_id ): bool {
		$last_remind_later_ts = absint(
			get_user_meta(
				$user_id,
				self::REMIND_LATER_TIMESTAMP_META_PREFIX . $product_id,
				true
			)
		);
		if ( 0 === $last_remind_later_ts ) {
			return false;
		}

		$seconds_since_clicked_remind_later = time() - $last_remind_later_ts;

		$wait_after_remind_later = self::$current_notice_rule['wait_in_seconds_after_remind_later'];

		return $seconds_since_clicked_remind_later < $wait_after_remind_later;
	}

	/**
	 * Check whether the user has reached max dismissals of product usage notice.
	 *
	 * @param int $user_id    User ID.
	 * @param int $product_id Product ID.
	 *
	 * @return bool
	 */
	private static function has_reached_max_dismissals( int $user_id, int $product_id ): bool {
		$dismiss_count = absint(
			get_user_meta(
				$user_id,
				self::DISMISSED_COUNT_META_PREFIX . $product_id,
				true
			)
		);

		$max_dismissals = self::$current_notice_rule['max_dismissals'];

		return $dismiss_count >= $max_dismissals;
	}

	/**
	 * Check whether the user dismissed any product usage notices recently.
	 *
	 * @param int $user_id User ID.
	 *
	 * @return bool
	 */
	private static function is_any_notices_dismissed_recently( int $user_id ): bool {
		$global_last_dismissed_ts = absint(
			get_user_meta(
				$user_id,
				self::LAST_DISMISSED_TIMESTAMP_META,
				true
			)
		);
		if ( 0 === $global_last_dismissed_ts ) {
			return false;
		}

		$seconds_since_dismissed = time() - $global_last_dismissed_ts;

		$wait_after_any_dismisses = self::$product_usage_notice_rules['wait_in_seconds_after_any_dismisses'];

		return $seconds_since_dismissed < $wait_after_any_dismisses;
	}

	/**
	 * Check whether the user dismissed given product usage notice recently.
	 *
	 * @param int $user_id    User ID.
	 * @param int $product_id Product ID.
	 *
	 * @return bool
	 */
	private static function is_product_notice_dismissed_recently( int $user_id, int $product_id ): bool {
		$last_dismissed_ts = absint(
			get_user_meta(
				$user_id,
				self::DISMISSED_TIMESTAMP_META_PREFIX . $product_id,
				true
			)
		);
		if ( 0 === $last_dismissed_ts ) {
			return false;
		}

		$seconds_since_dismissed = time() - $last_dismissed_ts;

		$wait_after_dismiss = self::$current_notice_rule['wait_in_seconds_after_dismiss'];

		return $seconds_since_dismissed < $wait_after_dismiss;
	}

	/**
	 * Check whether current notice is throttled for the user and product.
	 *
	 * @param int $user_id    User ID.
	 * @param int $product_id Product ID.
	 *
	 * @return bool
	 */
	private static function is_notice_throttled( int $user_id, int $product_id ): bool {
		return self::is_remind_later_clicked_recently( $user_id, $product_id ) ||
			self::has_reached_max_dismissals( $user_id, $product_id ) ||
			self::is_any_notices_dismissed_recently( $user_id ) ||
			self::is_product_notice_dismissed_recently( $user_id, $product_id );
	}

	/**
	 * Enqueue scripts needed to display product usage notice (or modal).
	 */
	public static function enqueue_product_usage_notice_scripts() {
		WCAdminAssets::register_style( 'woo-product-usage-notice', 'style', array( 'wp-components' ) );
		WCAdminAssets::register_script( 'wp-admin-scripts', 'woo-product-usage-notice', true );

		$subscribe_url = add_query_arg(
			array(
				'add-to-cart'  => self::$current_notice_rule['id'],
				'utm_source'   => 'pu',
				'utm_medium'   => 'product',
				'utm_campaign' => 'pu_modal_subscribe',
			),
			'https://woocommerce.com/cart/'
		);

		$renew_url = add_query_arg(
			array(
				'renew_product' => self::$current_notice_rule['id'],
				'product_key'   => self::$current_notice_rule['state']['key'],
				'order_id'      => self::$current_notice_rule['state']['order_id'],
				'utm_source'    => 'pu',
				'utm_medium'    => 'product',
				'utm_campaign'  => 'pu_modal_renew',
			),
			'https://woocommerce.com/cart/'
		);

		wp_localize_script(
			'wc-admin-woo-product-usage-notice',
			'wooProductUsageNotice',
			array(
				'subscribeUrl'        => $subscribe_url,
				'renewUrl'            => $renew_url,
				'dismissAction'       => 'woocommerce_dismiss_product_usage_notice',
				'remindLaterAction'   => 'woocommerce_remind_later_product_usage_notice',
				'productId'           => self::$current_notice_rule['id'],
				'productName'         => self::$current_notice_rule['name'],
				'productRegularPrice' => self::$current_notice_rule['regular_price'],
				'dismissNonce'        => wp_create_nonce( 'dismiss_product_usage_notice' ),
				'remindLaterNonce'    => wp_create_nonce( 'remind_later_product_usage_notice' ),
				'showAs'              => self::$current_notice_rule['show_as'],
				'colorScheme'         => self::$current_notice_rule['color_scheme'],
				'subscriptionState'   => self::$current_notice_rule['state'],
				'screenId'            => get_current_screen()->id,
			)
		);
	}

	/**
	 * Get product usage notice rule from a given WP_Screen object.
	 *
	 * @param \WP_Screen $screen Current \WP_Screen object.
	 *
	 * @return array
	 */
	private static function get_current_notice_rule( $screen ) {
		foreach ( self::$product_usage_notice_rules['products'] as $product_id => $rule ) {
			if ( ! isset( $rule['screens'][ $screen->id ] ) ) {
				continue;
			}

			// Check query strings.
			if ( ! self::query_string_matches( $screen, $rule ) ) {
				continue;
			}

			$product_id = absint( $product_id );
			$state      = WC_Helper::get_product_subscription_state( $product_id );
			if ( $state['expired'] || $state['unregistered'] ) {
				$rule['id']    = $product_id;
				$rule['state'] = $state;
				return $rule;
			}
		}

		return array();
	}

	/**
	 * Check whether the screen and GET parameter matches a given rule.
	 *
	 * @param \WP_Screen $screen Current \WP_Screen object.
	 * @param array      $rule   Product usage notice rule.
	 *
	 * @return bool
	 */
	private static function query_string_matches( $screen, $rule ) {
		if ( empty( $rule['screens'][ $screen->id ]['qs'] ) ) {
			return true;
		}

		$qs = $rule['screens'][ $screen->id ]['qs'];
		foreach ( $qs as $key => $val ) {
			// phpcs:disable WordPress.Security.NonceVerification.Recommended
			if ( empty( $_GET[ $key ] ) || $_GET[ $key ] !== $val ) {
				return false;
			}
			// phpcs:enable WordPress.Security.NonceVerification.Recommended
		}
		return true;
	}

	/**
	 * AJAX handler for dismiss action of product usage notice.
	 */
	public static function ajax_dismiss() {
		if ( ! check_ajax_referer( 'dismiss_product_usage_notice' ) ) {
			wp_die( -1 );
		}

		$user_id = get_current_user_id();
		if ( ! $user_id ) {
			wp_die( -1 );
		}

		$product_id = absint( $_GET['product_id'] ?? 0 );
		if ( ! $product_id ) {
			wp_die( -1 );
		}

		$dismiss_count = absint( get_user_meta( $user_id, self::DISMISSED_COUNT_META_PREFIX . $product_id, true ) );
		update_user_meta( $user_id, self::DISMISSED_COUNT_META_PREFIX . $product_id, $dismiss_count + 1 );

		update_user_meta( $user_id, self::DISMISSED_TIMESTAMP_META_PREFIX . $product_id, time() );
		update_user_meta( $user_id, self::LAST_DISMISSED_TIMESTAMP_META, time() );

		wp_die( 1 );
	}

	/**
	 * AJAX handler for "remind later" action of product usage notice.
	 */
	public static function ajax_remind_later() {
		if ( ! check_ajax_referer( 'remind_later_product_usage_notice' ) ) {
			wp_die( -1 );
		}

		$user_id = get_current_user_id();
		if ( ! $user_id ) {
			wp_die( -1 );
		}

		$product_id = absint( $_GET['product_id'] ?? 0 );
		if ( ! $product_id ) {
			wp_die( -1 );
		}

		update_user_meta( $user_id, self::REMIND_LATER_TIMESTAMP_META_PREFIX . $product_id, time() );

		wp_die( 1 );
	}
}

WC_Product_Usage_Notice::load();
PK     tS\y
  
  %  helper/class-wc-helper-orders-api.phpnu [        <?php
/**
 * WooCommerce Admin Helper - React admin interface
 *
 * @package WooCommerce\Admin\Helper
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper_Orders_API
 *
 * Pings WooCommerce.com to create an order and pull in the necessary data to start the installation process.
 */
class WC_Helper_Orders_API {
	/**
	 * Loads the class, runs on init
	 *
	 * @return void
	 */
	public static function load() {
		add_filter( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );
	}

	/**
	 * Registers the REST routes for the Marketplace Orders API.
	 * These endpoints are used by the Marketplace Subscriptions React UI.
	 */
	public static function register_rest_routes() {
		register_rest_route(
			'wc/v3',
			'/marketplace/create-order',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'create_order' ),
				'permission_callback' => array( __CLASS__, 'get_permission' ),
				'args'                => array(
					'product_id' => array(
						'required'          => true,
						'validate_callback' => function( $argument ) {
							return is_int( $argument );
						},
					),
				),
			)
		);
	}

	/**
	 * The Extensions page can only be accessed by users with the manage_woocommerce
	 * capability. So the API mimics that behavior.
	 *
	 * @return bool
	 */
	public static function get_permission() {
		return WC_Helper_Subscriptions_API::get_permission();
	}

	/**
	 * Core function to create an order on WooCommerce.com. Pings the API and catches the exceptions if any.
	 *
	 * @param WP_REST_Request $request Request object.
	 *
	 * @return WP_REST_Response
	 */
	public static function create_order( $request ) {
		if ( ! current_user_can( 'install_plugins' ) ) {
			return new \WP_REST_Response(
				array(
					'message' => __( 'You do not have permission to install plugins.', 'woocommerce' ),
				),
				403
			);
		}

		try {
			$response = WC_Helper_API::post(
				'create-order',
				array(
					'authenticated' => true,
					'body'          => http_build_query(
						array(
							'product_id' => $request['product_id'],
						),
					),
				)
			);

			return new \WP_REST_Response(
				json_decode( wp_remote_retrieve_body( $response ), true ),
				wp_remote_retrieve_response_code( $response )
			);
		} catch ( Exception $e ) {
			return new \WP_REST_Response(
				array(
					'message' => __( 'Could not start the installation process. Reason: ', 'woocommerce' ) . $e->getMessage(),
					'code'    => 'could-not-install',
				),
				500
			);
		}
	}
}

WC_Helper_Orders_API::load();
PK     tS\,p      helper/class-wc-helper-api.phpnu [        <?php
/**
 * WooCommerce Admin Helper API
 *
 * @package WooCommerce\Admin\Helper
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper_API Class
 *
 * Provides a communication interface with the WooCommerce.com Helper API.
 */
class WC_Helper_API {
	/**
	 * Base path for API routes.
	 *
	 * @var $api_base
	 */
	public static $api_base;

	/**
	 * Load
	 *
	 * Allow devs to point the API base to a local API development or staging server.
	 * Note that sslverify will be turned off for the woocommerce.dev + WP_DEBUG combination.
	 * The URL can be changed on plugins_loaded before priority 10.
	 */
	public static function load() {
		self::$api_base = apply_filters( 'woocommerce_helper_api_base', 'https://woocommerce.com/wp-json/helper/1.0' );
	}

	/**
	 * Perform an HTTP request to the Helper API.
	 *
	 * @param string $endpoint The endpoint to request.
	 * @param array  $args Additional data for the request. Set authenticated to a truthy value to enable auth.
	 *
	 * @return array|WP_Error The response from wp_safe_remote_request()
	 */
	public static function request( $endpoint, $args = array() ) {
		if ( ! isset( $args['query_string'] ) ) {
			$args['query_string'] = '';
		}
		$url = self::url( $endpoint, $args['query_string'] );

		if ( ! empty( $args['authenticated'] ) ) {
			if ( ! self::_authenticate( $url, $args ) ) {
				return new WP_Error( 'authentication', __( 'Authentication failed. Please try again after a few minutes. If the issue persists, disconnect your store from WooCommerce.com and reconnect.', 'woocommerce' ), 401 );
			}
		}

		if ( ! isset( $args['user-agent'] ) ) {
			$args['user-agent'] = 'WooCommerce/' . WC()->version . '; ' . get_bloginfo( 'url' );
		}

		/**
		 * Allow developers to filter the request args passed to wp_safe_remote_request().
		 * Useful to remove sslverify when working on a local api dev environment.
		 */
		$args = apply_filters( 'woocommerce_helper_api_request_args', $args, $endpoint );

		// TODO: Check response signatures on certain endpoints.
		return wp_safe_remote_request( $url, $args );
	}

	/**
	 * Create signature for a request.
	 *
	 * @param string $access_token_secret The access token secret.
	 * @param string $url The URL to add the access token and signature to.
	 * @param string $method The request method.
	 * @param array  $body The body of the request.
	 * @return string The signature.
	 */
	private static function create_request_signature( string $access_token_secret, string $url, string $method, $body = null ): string {

		$request_uri  = wp_parse_url( $url, PHP_URL_PATH );
		$query_string = wp_parse_url( $url, PHP_URL_QUERY );

		if ( is_string( $query_string ) ) {
			$request_uri .= '?' . $query_string;
		}

		$data = array(
			'host'        => wp_parse_url( $url, PHP_URL_HOST ),
			'request_uri' => $request_uri,
			'method'      => $method,
		);

		if ( ! empty( $body ) ) {
			$data['body'] = $body;
		}

		return hash_hmac( 'sha256', wp_json_encode( $data ), $access_token_secret );
	}

	/**
	 * Add the access token and signature to the provided URL.
	 *
	 * @param string $url The URL to add the access token and signature to.
	 * @return string
	 */
	public static function add_auth_parameters( string $url ): string {
		$auth = WC_Helper_Options::get( 'auth' );

		if ( empty( $auth['access_token'] ) || empty( $auth['access_token_secret'] ) ) {
			return false;
		}

		$signature = self::create_request_signature( (string) $auth['access_token_secret'], $url, 'GET' );

		return add_query_arg(
			array(
				'token'     => $auth['access_token'],
				'signature' => $signature,
			),
			$url
		);
	}

	/**
	 * Adds authentication headers to an HTTP request.
	 *
	 * @param string $url The request URI.
	 * @param array  $args By-ref, the args that will be passed to wp_remote_request().
	 * @return bool Were the headers added?
	 */
	private static function _authenticate( &$url, &$args ) {
		$auth = WC_Helper_Options::get( 'auth' );

		if ( empty( $auth['access_token'] ) || empty( $auth['access_token_secret'] ) ) {
			return false;
		}

		$signature = self::create_request_signature(
			(string) $auth['access_token_secret'],
			$url,
			! empty( $args['method'] ) ? $args['method'] : 'GET',
			$args['body'] ?? null
		);

		if ( empty( $args['headers'] ) ) {
			$args['headers'] = array();
		}

		$headers         = array(
			'Authorization'   => 'Bearer ' . $auth['access_token'],
			'X-Woo-Signature' => $signature,
		);
		$args['headers'] = wp_parse_args( $headers, $args['headers'] );

		$url = add_query_arg(
			array(
				'token'     => $auth['access_token'],
				'signature' => $signature,
			),
			$url
		);

		return true;
	}

	/**
	 * Wrapper for self::request().
	 *
	 * @param string $endpoint The helper API endpoint to request.
	 * @param array  $args Arguments passed to wp_remote_request().
	 *
	 * @return array The response object from wp_safe_remote_request().
	 */
	public static function get( $endpoint, $args = array() ) {
		$args['method'] = 'GET';
		return self::request( $endpoint, $args );
	}

	/**
	 * Wrapper for self::request().
	 *
	 * @param string $endpoint The helper API endpoint to request.
	 * @param array  $args Arguments passed to wp_remote_request().
	 *
	 * @return array The response object from wp_safe_remote_request().
	 */
	public static function post( $endpoint, $args = array() ) {
		$args['method'] = 'POST';
		return self::request( $endpoint, $args );
	}

	/**
	 * Wrapper for self::request().
	 *
	 * @param string $endpoint The helper API endpoint to request.
	 * @param array  $args Arguments passed to wp_remote_request().
	 *
	 * @return array The response object from wp_safe_remote_request().
	 */
	public static function put( $endpoint, $args = array() ) {
		$args['method'] = 'PUT';
		return self::request( $endpoint, $args );
	}

	/**
	 * Using the API base, form a request URL from a given endpoint.
	 *
	 * @param string $endpoint The endpoint to request.
	 * @param string $query_string Optional query string to append to the URL.
	 *
	 * @return string The absolute endpoint URL.
	 */
	public static function url( $endpoint, $query_string = '' ) {
		$endpoint = ltrim( $endpoint, '/' );
		$endpoint = sprintf( '%s/%s/%s', self::$api_base, $endpoint, $query_string );
		$endpoint = esc_url_raw( $endpoint );
		$endpoint = rtrim( $endpoint, '/' );
		return $endpoint;
	}
}

WC_Helper_API::load();
PK     tS\E0    '  helper/class-wc-helper-sanitization.phpnu [        <?php
/**
 * WooCommerce Admin Sanitization Helper
 *
 * @package WooCommerce\Admin\Helper
 */

declare(strict_types=1);

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper_Sanitization Class
 *
 * Provides sanitization functions for admin content.
 */
class WC_Helper_Sanitization {

	/**
	 * Sanitize CSS markup from API responses for safe rendering in admin pages.
	 *
	 * @param string $css The raw CSS to sanitize.
	 *
	 * @return string Sanitized CSS safe for inclusion in style blocks.
	 */
	public static function sanitize_css( $css ) {
		// Handle non-string inputs (return empty string).
		if ( ! is_string( $css ) ) {
			return '';
		}

		// Remove potentially harmful constructs.
		$css = preg_replace( '/@import\s+[^;]+;?/', '', $css );

		// Block all data URIs.
		$css = preg_replace( '/url\s*\(\s*([\'"]?)data:/i', 'url($1invalid:', $css );

		// Only allow URLs from specific trusted domains and their subdomains.
		$css = preg_replace_callback(
			'/url\s*\(\s*([\'"]?)(https?:\/\/[^)]+)\1\s*\)/i',
			function ( $matches ) {
				$url   = $matches[2];
				$quote = $matches[1];

				// Check if URL belongs to allowed domains.
				if ( preg_match(
					'/^https?:\/\/(([\w-]+\.)*woocommerce\.com|' .
					'([\w-]+\.)*woocommerce\.test|' .
					'([\w-]+\.)*WordPress\.com|' .
					'([\w-]+\.)*wp\.com)/ix',
					$url
				) ) {
					// URL is from a trusted domain, keep it.
					return "url({$quote}{$url}{$quote})";
				} else {
					// URL is not from a trusted domain, make it ineffective.
					return "url({$quote}#blocked-url{$quote})";
				}
			},
			$css
		);

		// Preserve all asterisks by temporarily replacing them.
		$css = str_replace( '*', '__PRESERVED_ASTERISK__', $css );

		// Remove HTML tags and PHP.
		$css = wp_strip_all_tags( $css );

		// Remove any JavaScript events.
		$css = preg_replace( '/\s*expression\s*\(.*?\)/', '', $css );
		$css = preg_replace( '/\s*javascript\s*:/', '', $css );

		// Block other potentially dangerous protocols.
		$css = preg_replace( '/(behavior|eval|calc|mocha)(\s*:|\s*\()/i', 'blocked', $css );

		// Restore all asterisks.
		$css = str_replace( '__PRESERVED_ASTERISK__', '*', $css );

		// We assume relative and root-relative URLs are safe because they point to resources on the same domain.

		// Limit size of CSS to prevent DoS.
		$css = substr( $css, 0, 100000 );

		return $css;
	}

	/**
	 * Sanitize HTML content allowing a subset of SVG elements.
	 *
	 * @param string $html The HTML to sanitize.
	 *
	 * @return string Sanitized HTML with SVG support.
	 */
	public static function sanitize_html( $html ) {
		$allowed_html = wp_kses_allowed_html( 'post' );

		// Selected SVG tags and attributes.
		$svg_tags     = self::wc_kses_safe_svg_tags();
		$allowed_html = array_merge( $allowed_html, $svg_tags );

		return wp_kses( self::wc_pre_sanitize_svg( $html ), $allowed_html );
	}

	/**
	 * Sanitize SVG content before processing with wp_kses.
	 *
	 * @param string $content The SVG content to sanitize.
	 * @return string Sanitized SVG content.
	 */
	public static function wc_pre_sanitize_svg( $content ) {
		// Remove any xlink:href attributes containing javascript.
		$content = preg_replace( '/xlink:href\s*=\s*(["\'])\s*javascript:.*?\1/i', '', $content );

		// Remove foreignObject elements (can contain arbitrary HTML).
		$content = preg_replace( '/<foreignObject\b[^>]*>.*?<\/foreignObject>/is', '', $content );

		return $content;
	}

	/**
	 * Add limited SVG support to wp_kses_post with XSS protection.
	 *
	 * @return array Array of allowed SVG tags and their attributes.
	 */
	public static function wc_kses_safe_svg_tags() {
		// SVG elements and attributes - security focused.
		return array(
			'svg'            => array(
				'class'               => true,
				'aria-hidden'         => true,
				'aria-labelledby'     => true,
				'role'                => true,
				'xmlns'               => true,
				'width'               => true,
				'height'              => true,
				'viewbox'             => true,
				'viewBox'             => true,
				'preserveAspectRatio' => true,
				'fill'                => true,
				'stroke'              => true,
				'stroke-width'        => true,
				'stroke-linecap'      => true,
				'stroke-linejoin'     => true,
				// Explicitly exclude dangerous attributes.
				'onload'              => false,
				'onclick'             => false,
			),
			'g'              => array(
				'fill'      => true,
				'transform' => true,
				'stroke'    => true,
			),
			'title'          => array(
				'title' => true,
			),
			'path'           => array(
				'd'               => true,
				'fill'            => true,
				'transform'       => true,
				'stroke'          => true,
				'stroke-width'    => true,
				'stroke-linecap'  => true,
				'stroke-linejoin' => true,
			),
			'polyline'       => array(
				'points'       => true,
				'fill'         => true,
				'stroke'       => true,
				'stroke-width' => true,
			),
			'polygon'        => array(
				'points'       => true,
				'fill'         => true,
				'stroke'       => true,
				'stroke-width' => true,
			),
			'circle'         => array(
				'cx'           => true,
				'cy'           => true,
				'r'            => true,
				'fill'         => true,
				'stroke'       => true,
				'stroke-width' => true,
			),
			'rect'           => array(
				'x'            => true,
				'y'            => true,
				'width'        => true,
				'height'       => true,
				'fill'         => true,
				'stroke'       => true,
				'stroke-width' => true,
				'rx'           => true,
				'ry'           => true,
			),
			'line'           => array(
				'x1'           => true,
				'y1'           => true,
				'x2'           => true,
				'y2'           => true,
				'stroke'       => true,
				'stroke-width' => true,
			),
			'defs'           => array(),
			'linearGradient' => array(
				'id'            => true,
				'x1'            => true,
				'y1'            => true,
				'x2'            => true,
				'y2'            => true,
				'gradientUnits' => true,
			),
			'radialGradient' => array(
				'id'            => true,
				'cx'            => true,
				'cy'            => true,
				'r'             => true,
				'gradientUnits' => true,
			),
			'stop'           => array(
				'offset'       => true,
				'stop-color'   => true,
				'stop-opacity' => true,
				// Remove style which can contain JavaScript.
				'style'        => false,
			),
			// Removed potentially risky elements.
			// 'use' - can reference external content.
			// 'mask' - not commonly needed and adds complexity.
		);
	}
}
PK     tS\{    %  helper/views/html-section-account.phpnu [        <?php defined( 'ABSPATH' ) or exit(); ?>

<a class="button button-update" href="<?php echo esc_url( $refresh_url ); ?>"><span class="dashicons dashicons-image-rotate"></span> <?php esc_html_e( 'Update', 'woocommerce' ); ?></a>
<div class="user-info">
	<header>
		<p><?php esc_html_e( 'Connected to WooCommerce.com', 'woocommerce' ); ?> <span class="chevron dashicons dashicons-arrow-down-alt2"></span></p>
	</header>
	<section>
		<p><?php echo get_avatar( $auth_user_data['email'], 48 ); ?> <?php echo esc_html( $auth_user_data['email'] ); ?></p>
		<div class="actions">
			<a class="" href="https://woocommerce.com/my-account/my-subscriptions/" target="_blank"><span class="dashicons dashicons-admin-generic"></span> <?php esc_html_e( 'My Subscriptions', 'woocommerce' ); ?></a>
			<a class="" href="<?php echo esc_url( $disconnect_url ); ?>"><span class="dashicons dashicons-no"></span> <?php esc_html_e( 'Disconnect', 'woocommerce' ); ?></a>
		</div>
	</section>
</div>
PK     tS\rxR'  '  !  helper/views/html-section-nav.phpnu [        <?php
/**
 * Helper admin navigation.
 *
 * @package WooCommerce\Helper
 *
 * @deprecated 5.7.0
 */

$addons_url = admin_url( 'admin.php?page=wc-admin&path=/extensions&tab=extensions' );

defined( 'ABSPATH' ) || exit(); ?>

<nav class="nav-tab-wrapper woo-nav-tab-wrapper">
	<a href="<?php echo esc_url( $addons_url ); ?>" class="nav-tab"><?php esc_html_e( 'Browse Extensions', 'woocommerce' ); ?></a>

	<?php
		$count_html = WC_Helper_Updater::get_updates_count_html();
		/* translators: %s: WooCommerce.com Subscriptions tab count HTML. */
		$menu_title = sprintf( __( 'My Subscriptions %s', 'woocommerce' ), $count_html );
	?>
	<a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-addons&section=helper' ) ); ?>" class="nav-tab nav-tab-active"><?php echo wp_kses_post( $menu_title ); ?></a>
</nav>
PK     tS\$J    #  helper/views/html-helper-compat.phpnu [        <?php defined( 'ABSPATH' ) or exit(); ?>

<div class="wrap">
	<h1><?php _e( 'Looking for the WooCommerce Helper?', 'woocommerce' ); ?></h1>
	<p><?php printf( __( 'We\'ve made things simpler and easier to manage moving forward. From now on you can manage all your WooCommerce purchases directly from the Extensions menu within the WooCommerce plugin itself. <a href="%s">View and manage</a> your extensions now.', 'woocommerce' ), esc_url( $helper_url ) ); ?></p>
</div>
PK     tS\A      %  helper/views/html-section-notices.phpnu [        <?php defined( 'ABSPATH' ) or exit(); ?>

<?php foreach ( $notices as $notice ) : ?>
	<div class="notice <?php echo sanitize_html_class( $notice['type'] ); ?>">
		<?php echo wpautop( $notice['message'] ); ?>
	</div>
<?php endforeach; ?>
PK     tS\<c    !  helper/views/html-oauth-start.phpnu [        <?php
/**
 * Admin -> WooCommerce -> Extensions -> WooCommerce.com Subscriptions main page.
 *
 * @package WooCommerce\Views
 */

defined( 'ABSPATH' ) || exit();

?>

<div class="wrap woocommerce wc-addons-wrap wc-helper">
	<?php require WC_Helper::get_view_filename( 'html-section-nav.php' ); ?>
	<h1 class="screen-reader-text"><?php esc_html_e( 'WooCommerce Extensions', 'woocommerce' ); ?></h1>
	<?php require WC_Helper::get_view_filename( 'html-section-notices.php' ); ?>

		<div class="start-container">
			<div class="text">
			<img src="<?php echo esc_url( WC()->plugin_url() . '/assets/images/woo-logo.svg' ); ?>" alt="
								<?php
								esc_attr_e(
									'WooCommerce',
									'woocommerce'
								);
								?>
				" style="width:180px;">

			<?php
			// phpcs:disable WordPress.Security.NonceVerification.Recommended
			if ( ! empty( $_GET['wc-helper-status'] ) && 'helper-disconnected' === $_GET['wc-helper-status'] ) :
				// phpcs:enable WordPress.Security.NonceVerification.Recommended
				?>
					<p><strong><?php esc_html_e( 'Sorry to see you go.', 'woocommerce' ); ?></strong> <?php esc_html_e( 'Feel free to reconnect again using the button below.', 'woocommerce' ); ?></p>
				<?php endif; ?>

				<h2><?php esc_html_e( 'Manage your subscriptions, get important product notifications, and updates, all from the convenience of your WooCommerce dashboard', 'woocommerce' ); ?></h2>
				<p><?php esc_html_e( 'Once connected, your WooCommerce.com purchases will be listed here.', 'woocommerce' ); ?></p>
				<p><a class="button button-primary button-helper-connect" href="<?php echo esc_url( $connect_url ); ?>"><?php esc_html_e( 'Connect', 'woocommerce' ); ?></a></p>
			</div>
		</div>
</div>
PK     tS\<
-  -    helper/views/html-main.phpnu [        <?php
/**
 * Helper main view
 *
 * @package WooCommerce\Helper
 */

?>
<?php defined( 'ABSPATH' ) || exit(); ?>

<div class="wrap woocommerce wc-subscriptions-wrap wc-helper">
	<?php require WC_Helper::get_view_filename( 'html-section-nav.php' ); ?>
	<h1 class="screen-reader-text"><?php esc_html_e( 'WooCommerce Extensions', 'woocommerce' ); ?></h1>

	<?php require WC_Helper::get_view_filename( 'html-section-notices.php' ); ?>

	<div class="subscriptions-header">
		<h2><?php esc_html_e( 'Subscriptions', 'woocommerce' ); ?></h2>
		<?php require WC_Helper::get_view_filename( 'html-section-account.php' ); ?>
		<p>
			<?php
			printf(
				wp_kses(
					/* translators: Introduction to list of WooCommerce.com extensions the merchant has subscriptions for. */
					__(
						'Below is a list of extensions available on your WooCommerce.com account. To receive extension updates please make sure the extension is installed, and its subscription activated and connected to your WooCommerce.com account. Extensions can be activated from the <a href="%s">Plugins</a> screen.',
						'woocommerce'
					),
					array(
						'a' => array(
							'href' => array(),
						),
					)
				),
				esc_url(
					admin_url( 'plugins.php' )
				)
			);
			?>
		</p>
	</div>

	<ul class="subscription-filter">
		<label><?php esc_html_e( 'Sort by:', 'woocommerce' ); ?> <span class="chevron dashicons dashicons-arrow-up-alt2"></span></label>
		<?php
			$filters        = array_keys( WC_Helper::get_filters() );
			$last_filter    = array_pop( $filters );
			$current_filter = WC_Helper::get_current_filter();
			$counts         = WC_Helper::get_filters_counts();
		?>

		<?php
		foreach ( WC_Helper::get_filters() as $key => $label ) :
			// Don't show empty filters.
			if ( empty( $counts[ $key ] ) ) {
				continue;
			}

			$url        = admin_url( 'admin.php?page=wc-addons&section=helper&filter=' . $key );
			$class_html = $current_filter === $key ? 'class="current"' : '';
			?>
			<li>
				<?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				<a <?php echo $class_html; ?> href="<?php echo esc_url( $url ); ?>">
					<?php echo esc_html( $label ); ?>
					<span class="count">(<?php echo absint( $counts[ $key ] ); ?>)</span>
				</a>
			</li>
		<?php endforeach; ?>
	</ul>

	<table class="wp-list-table widefat fixed striped">
		<?php if ( ! empty( $subscriptions ) ) : ?>
			<?php foreach ( $subscriptions as $subscription ) : ?>
				<tbody>
				<tr class="wp-list-table__row is-ext-header">
					<td class="wp-list-table__ext-details">
						<div class="wp-list-table__ext-title">
							<a href="<?php echo esc_url( WC_Helper::add_utm_params_to_url_for_subscription_link( $subscription['product_url'], 'product-name' ) ); ?>" target="_blank">
								<?php echo esc_html( $subscription['product_name'] ); ?>
							</a>
						</div>

						<div class="wp-list-table__ext-description">
							<?php if ( $subscription['lifetime'] ) : ?>
								<span class="renews">
									<?php esc_html_e( 'Lifetime Subscription', 'woocommerce' ); ?>
								</span>
							<?php elseif ( $subscription['expired'] ) : ?>
								<span class="renews">
									<strong><?php esc_html_e( 'Expired :(', 'woocommerce' ); ?></strong>
									<?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?>
								</span>
							<?php elseif ( $subscription['autorenew'] ) : ?>
								<span class="renews">
									<?php esc_html_e( 'Auto renews on:', 'woocommerce' ); ?>
									<?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?>
								</span>
							<?php elseif ( $subscription['expiring'] ) : ?>
								<span class="renews">
									<strong><?php esc_html_e( 'Expiring soon!', 'woocommerce' ); ?></strong>
									<?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?>
								</span>
							<?php else : ?>
								<span class="renews">
									<?php esc_html_e( 'Expires on:', 'woocommerce' ); ?>
									<?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?>
								</span>
							<?php endif; ?>

							<br/>
							<span class="subscription">
								<?php
								if ( ! $subscription['active'] && $subscription['maxed'] ) {
									/* translators: %1$d: sites active, %2$d max sites active */
									printf( esc_html__( 'Subscription: Not available - %1$d of %2$d already in use', 'woocommerce' ), absint( $subscription['sites_active'] ), absint( $subscription['sites_max'] ) );
								} elseif ( $subscription['sites_max'] > 0 ) {
									/* translators: %1$d: sites active, %2$d max sites active */
									printf( esc_html__( 'Subscription: Using %1$d of %2$d sites available', 'woocommerce' ), absint( $subscription['sites_active'] ), absint( $subscription['sites_max'] ) );
								} else {
									esc_html_e( 'Subscription: Unlimited', 'woocommerce' );
								}

								// Check shared.
								if ( ! empty( $subscription['is_shared'] ) && ! empty( $subscription['owner_email'] ) ) {
									/* translators: Email address of person who shared the subscription. */
									printf( '</br>' . esc_html__( 'Shared by %s', 'woocommerce' ), esc_html( $subscription['owner_email'] ) );
								} elseif ( isset( $subscription['master_user_email'] ) ) {
									/* translators: Email address of person who shared the subscription. */
									printf( '</br>' . esc_html__( 'Shared by %s', 'woocommerce' ), esc_html( $subscription['master_user_email'] ) );
								}
								?>
							</span>
						</div>
					</td>
					<td class="wp-list-table__ext-actions">
						<?php if ( ! $subscription['active'] && $subscription['maxed'] ) : ?>
							<a class="button" href="https://woocommerce.com/my-account/my-subscriptions/" target="_blank"><?php esc_html_e( 'Upgrade', 'woocommerce' ); ?></a>
						<?php elseif ( ! $subscription['local']['installed'] && ! $subscription['expired'] ) : ?>
							<a class="button <?php echo empty( $subscription['download_primary'] ) ? 'button-secondary' : ''; ?>" href="<?php echo esc_url( $subscription['download_url'] ); ?>" target="_blank"><?php esc_html_e( 'Download', 'woocommerce' ); ?></a>
						<?php elseif ( $subscription['active'] ) : ?>
							<span class="form-toggle__wrapper">
								<a href="<?php echo esc_url( $subscription['deactivate_url'] ); ?>" class="form-toggle active is-compact" role="link" aria-checked="true"><?php esc_html_e( 'Active', 'woocommerce' ); ?></a>
								<label class="form-toggle__label" for="activate-extension">
									<span class="form-toggle__label-content">
										<label for="activate-extension"><?php esc_html_e( 'Active', 'woocommerce' ); ?></label>
									</span>
									<span class="form-toggle__switch"></span>
								</label>
							</span>
						<?php elseif ( ! $subscription['expired'] ) : ?>
							<span class="form-toggle__wrapper">
								<a href="<?php echo esc_url( $subscription['activate_url'] ); ?>" class="form-toggle is-compact" role="link" aria-checked="false"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></a>
								<label class="form-toggle__label" for="activate-extension">
									<span class="form-toggle__label-content">
										<label for="activate-extension"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></label>
									</span>
									<span class="form-toggle__switch"></span>
								</label>
							</span>
						<?php else : ?>
							<span class="form-toggle__wrapper">
								<span class="form-toggle disabled is-compact"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></span>
								<label class="form-toggle__label" for="activate-extension">
									<span class="form-toggle__label-content">
										<label for="activate-extension"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></label>
									</span>
								</label>
							</span>
						<?php endif; ?>
					</td>
				</tr>

				<?php foreach ( $subscription['actions'] as $subscription_action ) : ?>
				<tr class="wp-list-table__row wp-list-table__ext-updates">
					<td class="wp-list-table__ext-status <?php echo sanitize_html_class( $subscription_action['status'] ); ?>">
						<p><span class="dashicons <?php echo sanitize_html_class( $subscription_action['icon'] ); ?>"></span>
							<?php echo wp_kses_post( $subscription_action['message'] ); ?>
						</p>
					</td>
					<td class="wp-list-table__ext-actions">
						<?php if ( ! empty( $subscription_action['button_label'] ) && ! empty( $subscription_action['button_url'] ) ) : ?>
						<a class="button <?php echo empty( $subscription_action['primary'] ) ? 'button-secondary' : ''; ?>" href="<?php echo esc_url( $subscription_action['button_url'] ); ?>"><?php echo esc_html( $subscription_action['button_label'] ); ?></a>
						<?php endif; ?>
					</td>
				</tr>
				<?php endforeach; ?>

				</tbody>
			<?php endforeach; ?>
		<?php else : ?>
			<tr>
				<td colspan="3"><em><?php esc_html_e( 'Could not find any subscriptions on your WooCommerce.com account', 'woocommerce' ); ?></td>
			</tr>
		<?php endif; ?>
		</tbody>
	</table>

	<?php if ( ! empty( $no_subscriptions ) ) : ?>
		<h2><?php esc_html_e( 'Installed Extensions without a Subscription', 'woocommerce' ); ?></h2>
		<p>Below is a list of WooCommerce.com products available on your site - but are either out-dated or do not have a valid subscription.</p>

		<table class="wp-list-table widefat fixed striped">
			<?php /* Extensions without a subscription. */ ?>
			<?php foreach ( $no_subscriptions as $filename => $data ) : ?>
				<tbody>
					<tr class="wp-list-table__row is-ext-header">
						<td class="wp-list-table__ext-details color-bar autorenews">
							<div class="wp-list-table__ext-title">
								<a href="<?php echo esc_url( WC_Helper::add_utm_params_to_url_for_subscription_link( $data['_product_url'], 'product-name' ) ); ?>" target="_blank">
									<?php echo esc_html( $data['Name'] ); ?>
								</a>
							</div>
							<div class="wp-list-table__ext-description">
							</div>
						</td>
						<td class="wp-list-table__ext-actions">
							<span class="form-toggle__wrapper">
								<span class="form-toggle disabled is-compact" ><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></span>
								<label class="form-toggle__label" for="activate-extension">
									<span class="form-toggle__label-content">
										<label for="activate-extension"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></label>
									</span>
								</label>
							</span>
						</td>
					</tr>

					<?php foreach ( $data['_actions'] as $subscription_action ) : ?>
					<tr class="wp-list-table__row wp-list-table__ext-updates">
						<td class="wp-list-table__ext-status <?php echo sanitize_html_class( $subscription_action['status'] ); ?>">
							<p><span class="dashicons <?php echo sanitize_html_class( $subscription_action['icon'] ); ?>"></span>
								<?php
									echo wp_kses(
										$subscription_action['message'],
										array(
											'a'      => array(
												'href'  => array(),
												'title' => array(),
											),
											'br'     => array(),
											'em'     => array(),
											'strong' => array(),
										)
									);
								?>
							</p>
						</td>
						<td class="wp-list-table__ext-actions">
							<a class="button" href="<?php echo esc_url( $subscription_action['button_url'] ); ?>" target="_blank"><?php echo esc_html( $subscription_action['button_label'] ); ?></a>
						</td>
					</tr>
					<?php endforeach; ?>

				</tbody>

			<?php endforeach; ?>
		</table>
	<?php endif; ?>
</div>
PK     tS\E>  >  6  helper/views/html-notice-woo-updater-not-installed.phpnu [        <?php
/**
 * Helper Admin Notice - Woo Updater Plugin is not Installed.
 *
 * @package WooCommerce\Views
 */

defined( 'ABSPATH' ) || exit;
?>
<div id="message" class="error woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'woo_updater_not_installed' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>
	<p>
	<?php
		echo wp_kses_post(
			sprintf(
				/* translators: 1: Woo Update Manager plugin install URL 2: Woo Update Manager plugin download URL */
				__(
					'Please <a href="%1$s">Install the WooCommerce.com Update Manager</a> to continue receiving the updates and streamlined support included in your WooCommerce.com subscriptions. Alternatively, you can <a href="%2$s">download</a> and install it manually.',
					'woocommerce'
				),
				esc_url( WC_Woo_Update_Manager_Plugin::generate_install_url() ),
				esc_url( WC_Woo_Update_Manager_Plugin::WOO_UPDATE_MANAGER_DOWNLOAD_URL )
			)
		);
		?>
	</p>
</div>
PK     tS\,fU  U  6  helper/views/html-notice-woo-updater-not-activated.phpnu [        <?php
/**
 * Helper Admin Notice - Woo Updater Plugin is not activated.
 *
 * @package WooCommerce\Views
 */

defined( 'ABSPATH' ) || exit;
?>
<div id="message" class="error woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'woo_updater_not_activated' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>
	<p>
		<?php
		echo wp_kses_post(
			sprintf(
			/* translators: 1: WP plugin management URL */
				__(
					'Please <a href="%1$s">activate the WooCommerce.com Update Manager</a> to continue receiving the updates and streamlined support included in your WooCommerce.com subscriptions.',
					'woocommerce'
				),
				esc_url( admin_url( 'plugins.php' ) ),
			)
		);
		?>
	</p>
</div>
PK     tS\#f f   helper/class-wc-helper.phpnu [        <?php
/**
 * WooCommerce Admin Helper
 *
 * @package WooCommerce\Admin\Helper
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\PluginsHelper;
use Automattic\WooCommerce\Admin\Notes\Note;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper Class
 *
 * The main entry-point for all things related to the Helper.
 */
class WC_Helper {
	const NOTE_NAME = 'wccom-api-failed';

	/**
	 * A log object returned by wc_get_logger().
	 *
	 * @var $log
	 */
	public static $log;

	private const CACHE_KEY_CONNECTION_DATA = '_woocommerce_helper_connection_data';

	/**
	 * Get an absolute path to the requested helper view.
	 *
	 * @param string $view The requested view file.
	 *
	 * @return string The absolute path to the view file.
	 */
	public static function get_view_filename( $view ) {
		return __DIR__ . "/views/$view";
	}

	/**
	 * Loads the helper class, runs on init.
	 *
	 * @return void
	 */
	public static function load() {
		self::includes();

		add_action( 'current_screen', array( __CLASS__, 'current_screen' ) );
		add_action( 'woocommerce_helper_output', array( __CLASS__, 'render_helper_output' ) );
		add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts' ) );
		add_action( 'admin_notices', array( __CLASS__, 'admin_notices' ) );

		do_action( 'woocommerce_helper_loaded' );
	}

	/**
	 * Remove all notes signaling an error with the WCCOM API, when the request was successful.
	 *
	 * @return void
	 */
	protected static function remove_api_error_notice() {
		try {
			$data_store = \WC_Data_Store::load( 'admin-note' );
		} catch ( Exception $e ) {
			return;
		}

		$note_ids = $data_store->get_notes_with_name( self::NOTE_NAME );

		if ( ! empty( $note_ids ) ) {
			foreach ( $note_ids as $note_id ) {
				$note = new Note( $note_id );
				if ( $note->get_id() ) {
					$data_store->delete( $note );
				}
			}
		}
	}

	/**
	 * Adds at most one note signaling that there was an error with the WCCOM API.
	 *
	 * @return void
	 */
	protected static function add_api_error_notice() {
		try {
			$data_store = \WC_Data_Store::load( 'admin-note' );
		} catch ( Exception $e ) {
			return;
		}

		$note_ids = $data_store->get_notes_with_name( self::NOTE_NAME );

		if ( ! empty( $note_ids ) ) {
			$current_notice_id = array_shift( $note_ids );

			foreach ( $note_ids as $note_id ) {
				$note = new Note( $note_id );
				if ( $note->get_id() ) {
					$data_store->delete( $note );
				}
			}

			$note = new Note( $current_notice_id );
		} else {
			$note = new Note();
		}

		$note->set_props(
			array(
				'title'        => __( 'We’re having trouble connecting to WooCommerce.com', 'woocommerce' ),
				'content'      => __( 'Some subscription data may be temporarily unavailable. Please refresh the page in a few minutes to try again.', 'woocommerce' ),
				'type'         => Note::E_WC_ADMIN_NOTE_UPDATE,
				'name'         => self::NOTE_NAME,
				'content_data' => (object) array(),
				'source'       => 'woocommerce-admin',
				'status'       => Note::E_WC_ADMIN_NOTE_UNACTIONED,
				'is_deleted'   => false,
			)
		);

		$note->save();
	}

	/**
	 * Get the source page for the connect URL (wc-admin or wc-addons/extensions)
	 *
	 * @return string
	 */
	private static function get_source_page() {
		$page = wc_clean( wp_unslash( $_GET['page'] ?? 'wc-admin' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		return in_array( $page, array( 'wc-admin', 'wc-addons' ), true ) ? $page : 'wc-admin';
	}

	/**
	 * Include supporting helper classes.
	 *
	 * @return void
	 */
	protected static function includes() {
		include_once __DIR__ . '/class-wc-helper-options.php';
		include_once __DIR__ . '/class-wc-helper-api.php';
		include_once __DIR__ . '/class-wc-woo-update-manager-plugin.php';
		include_once __DIR__ . '/class-wc-woo-helper-connection.php';
		include_once __DIR__ . '/class-wc-helper-updater.php';
		include_once __DIR__ . '/class-wc-plugin-api-updater.php';
		include_once __DIR__ . '/class-wc-helper-compat.php';
		include_once __DIR__ . '/class-wc-helper-sanitization.php';
		include_once __DIR__ . '/class-wc-helper-admin.php';
		include_once __DIR__ . '/class-wc-helper-subscriptions-api.php';
		include_once __DIR__ . '/class-wc-helper-orders-api.php';
		include_once __DIR__ . '/class-wc-product-usage-notice.php';
	}

	/**
	 * Render the helper section content based on context.
	 *
	 * @return void
	 */
	public static function render_helper_output() {
		$auth           = WC_Helper_Options::get( 'auth' );
		$auth_user_data = WC_Helper_Options::get( 'auth_user_data' );

		// Return success/error notices.
		$notices = self::_get_return_notices();

		// No active connection.
		if ( ! self::is_site_connected() ) {
			$connect_url = add_query_arg(
				array(
					'page'              => self::get_source_page(),
					'section'           => 'helper',
					'wc-helper-connect' => 1,
					'wc-helper-nonce'   => wp_create_nonce( 'connect' ),
				),
				admin_url( 'admin.php' )
			);

			include self::get_view_filename( 'html-oauth-start.php' );
			return;
		}
		$disconnect_url = add_query_arg(
			array(
				'page'                 => self::get_source_page(),
				'section'              => 'helper',
				'wc-helper-disconnect' => 1,
				'wc-helper-nonce'      => wp_create_nonce( 'disconnect' ),
			),
			admin_url( 'admin.php' )
		);

		$current_filter = self::get_current_filter();
		$refresh_url    = add_query_arg(
			array(
				'page'              => self::get_source_page(),
				'section'           => 'helper',
				'filter'            => $current_filter,
				'wc-helper-refresh' => 1,
				'wc-helper-nonce'   => wp_create_nonce( 'refresh' ),
			),
			admin_url( 'admin.php' )
		);

		// Installed plugins and themes, with or without an active subscription.
		$woo_plugins = self::get_local_woo_plugins();
		$woo_themes  = self::get_local_woo_themes();

		$subscriptions_list_data   = self::get_subscription_list_data();
		$subscriptions             = array_filter(
			$subscriptions_list_data,
			function ( $subscription ) {
				return ! empty( $subscription['product_key'] );
			}
		);
		$updates                   = WC_Helper_Updater::get_update_data();
		$subscriptions_product_ids = wp_list_pluck( $subscriptions, 'product_id' );

		foreach ( $subscriptions as &$subscription ) {
			$subscription['activate_url'] = add_query_arg(
				array(
					'page'                  => self::get_source_page(),
					'section'               => 'helper',
					'filter'                => $current_filter,
					'wc-helper-activate'    => 1,
					'wc-helper-product-key' => $subscription['product_key'],
					'wc-helper-product-id'  => $subscription['product_id'],
					'wc-helper-nonce'       => wp_create_nonce( 'activate:' . $subscription['product_key'] ),
				),
				admin_url( 'admin.php' )
			);

			$subscription['deactivate_url'] = add_query_arg(
				array(
					'page'                  => self::get_source_page(),
					'section'               => 'helper',
					'filter'                => $current_filter,
					'wc-helper-deactivate'  => 1,
					'wc-helper-product-key' => $subscription['product_key'],
					'wc-helper-product-id'  => $subscription['product_id'],
					'wc-helper-nonce'       => wp_create_nonce( 'deactivate:' . $subscription['product_key'] ),
				),
				admin_url( 'admin.php' )
			);

			$subscription['update_url'] = admin_url( 'update-core.php' );

			$local = wp_list_filter( array_merge( $woo_plugins, $woo_themes ), array( '_product_id' => $subscription['product_id'] ) );

			if ( ! empty( $local ) ) {
				$local = array_shift( $local );
				if ( 'plugin' === $local['_type'] ) {
					// A magic update_url.
					$subscription['update_url'] = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $local['_filename'], 'upgrade-plugin_' . $local['_filename'] );

				} elseif ( 'theme' === $local['_type'] ) {
					// Another magic update_url.
					$subscription['update_url'] = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-theme&theme=' . $local['_stylesheet'] ), 'upgrade-theme_' . $local['_stylesheet'] );
				}
			}

			$subscription['download_primary'] = true;
			$subscription['download_url']     = 'https://woocommerce.com/my-account/downloads/';
			if ( ! $subscription['local']['installed'] && ! empty( $updates[ $subscription['product_id'] ] ) ) {
				$subscription['download_url'] = $updates[ $subscription['product_id'] ]['package'];
			}

			$subscription['actions'] = array();

			if ( $subscription['has_update'] && ! $subscription['expired'] ) {
				$action = array(
					/* translators: %s: version number */
					'message'      => sprintf( __( 'Version %s is <strong>available</strong>.', 'woocommerce' ), esc_html( $updates[ $subscription['product_id'] ]['version'] ) ),
					'button_label' => __( 'Update', 'woocommerce' ),
					'button_url'   => $subscription['update_url'],
					'status'       => 'update-available',
					'icon'         => 'dashicons-update',
				);

				// Subscription is not active on this site.
				if ( ! $subscription['active'] ) {
					$action['message']     .= ' ' . __( 'To enable this update you need to <strong>activate</strong> this subscription.', 'woocommerce' );
					$action['button_label'] = null;
					$action['button_url']   = null;
				}

				$subscription['actions'][] = $action;
			}

			if ( $subscription['has_update'] && $subscription['expired'] ) {
				$action = array(
					/* translators: %s: version number */
					'message' => sprintf( __( 'Version %s is <strong>available</strong>.', 'woocommerce' ), esc_html( $updates[ $subscription['product_id'] ]['version'] ) ),
					'status'  => 'expired',
					'icon'    => 'dashicons-info',
				);

				$action['message']     .= ' ' . __( 'To enable this update you need to <strong>purchase</strong> a new subscription.', 'woocommerce' );
				$action['button_label'] = __( 'Purchase', 'woocommerce' );
				$action['button_url']   = self::add_utm_params_to_url_for_subscription_link(
					$subscription['product_url'],
					'purchase'
				);

				$subscription['actions'][] = $action;
			} elseif ( $subscription['expired'] && ! empty( $subscription['master_user_email'] ) ) {
				$action = array(
					'message' => sprintf( __( 'This subscription has expired. Contact the owner to <strong>renew</strong> the subscription to receive updates and support.', 'woocommerce' ) ),
					'status'  => 'expired',
					'icon'    => 'dashicons-info',
				);

				$subscription['actions'][] = $action;
			} elseif ( $subscription['expired'] ) {
				$action = array(
					'message'      => sprintf( __( 'This subscription has expired. Please <strong>renew</strong> to receive updates and support.', 'woocommerce' ) ),
					'button_label' => __( 'Renew', 'woocommerce' ),
					'button_url'   => self::add_utm_params_to_url_for_subscription_link(
						'https://woocommerce.com/my-account/my-subscriptions/',
						'renew'
					),
					'status'       => 'expired',
					'icon'         => 'dashicons-info',
				);

				$subscription['actions'][] = $action;
			}

			if ( $subscription['expiring'] && ! $subscription['autorenew'] ) {
				$action = array(
					'message'      => __( 'Subscription is <strong>expiring</strong> soon.', 'woocommerce' ),
					'button_label' => __( 'Enable auto-renew', 'woocommerce' ),
					'button_url'   => self::add_utm_params_to_url_for_subscription_link(
						'https://woocommerce.com/my-account/my-subscriptions/',
						'auto-renew'
					),
					'status'       => 'expired',
					'icon'         => 'dashicons-info',
				);

				$subscription['download_primary'] = false;
				$subscription['actions'][]        = $action;
			} elseif ( $subscription['expiring'] ) {
				$action = array(
					'message'      => sprintf( __( 'This subscription is expiring soon. Please <strong>renew</strong> to continue receiving updates and support.', 'woocommerce' ) ),
					'button_label' => __( 'Renew', 'woocommerce' ),
					'button_url'   => self::add_utm_params_to_url_for_subscription_link(
						'https://woocommerce.com/my-account/my-subscriptions/',
						'renew'
					),
					'status'       => 'expired',
					'icon'         => 'dashicons-info',
				);

				$subscription['download_primary'] = false;
				$subscription['actions'][]        = $action;
			}

			// Mark the first action primary.
			foreach ( $subscription['actions'] as $key => $action ) {
				if ( ! empty( $action['button_label'] ) ) {
					$subscription['actions'][ $key ]['primary'] = true;
					break;
				}
			}
		}

		// Break the by-ref.
		unset( $subscription );

		// Installed products without a subscription.
		$no_subscriptions = array();
		foreach ( array_merge( $woo_plugins, $woo_themes ) as $filename => $data ) {
			if ( in_array( $data['_product_id'], $subscriptions_product_ids ) ) {
				continue;
			}

			$data['_product_url'] = '#';
			$data['_has_update']  = false;

			if ( ! empty( $updates[ $data['_product_id'] ] ) ) {
				$data['_has_update'] = version_compare( $updates[ $data['_product_id'] ]['version'], $data['Version'], '>' );

				if ( ! empty( $updates[ $data['_product_id'] ]['url'] ) ) {
					$data['_product_url'] = $updates[ $data['_product_id'] ]['url'];
				} elseif ( ! empty( $data['PluginURI'] ) ) {
					$data['_product_url'] = $data['PluginURI'];
				}
			}

			$data['_actions'] = array();

			if ( $data['_has_update'] ) {
				$action = array(
					/* translators: %s: version number */
					'message'      => sprintf( __( 'Version %s is <strong>available</strong>. To enable this update you need to <strong>purchase</strong> a new subscription.', 'woocommerce' ), esc_html( $updates[ $data['_product_id'] ]['version'] ) ),
					'button_label' => __( 'Purchase', 'woocommerce' ),
					'button_url'   => self::add_utm_params_to_url_for_subscription_link(
						$data['_product_url'],
						'purchase'
					),
					'status'       => 'expired',
					'icon'         => 'dashicons-info',
				);

				$data['_actions'][] = $action;
			} else {
				$action = array(
					/* translators: 1: subscriptions docs 2: subscriptions docs */
					'message'      => sprintf( __( 'To receive updates and support for this extension, you need to <strong>purchase</strong> a new subscription or consolidate your extensions to one connected account by <strong><a href="%1$s" title="Sharing Docs">sharing</a> or <a href="%2$s" title="Transferring Docs">transferring</a></strong> this extension to this connected account.', 'woocommerce' ), 'https://woocommerce.com/document/managing-woocommerce-com-subscriptions/#section-10', 'https://woocommerce.com/document/managing-woocommerce-com-subscriptions/#section-5' ),
					'button_label' => __( 'Purchase', 'woocommerce' ),
					'button_url'   => self::add_utm_params_to_url_for_subscription_link(
						$data['_product_url'],
						'purchase'
					),
					'status'       => 'expired',
					'icon'         => 'dashicons-info',
				);

				$data['_actions'][] = $action;
			}

			$no_subscriptions[ $filename ] = $data;
		}

		// Update the user id if it came from a migrated connection.
		if ( empty( $auth['user_id'] ) ) {
			$auth['user_id'] = get_current_user_id();
			WC_Helper_Options::update( 'auth', $auth );
		}

		// Sort alphabetically.
		uasort( $subscriptions, array( __CLASS__, '_sort_by_product_name' ) );
		uasort( $no_subscriptions, array( __CLASS__, '_sort_by_name' ) );

		// Filters.
		self::get_filters_counts( $subscriptions ); // Warm it up.
		self::_filter( $subscriptions, self::get_current_filter() );

		// We have an active connection.
		include self::get_view_filename( 'html-main.php' );
		return;
	}

	/**
	 * Add tracking parameters to buttons (Renew, Purchase, etc.) on subscriptions page
	 *
	 * @param string $url URL to product page or to https://woocommerce.com/my-account/my-subscriptions/.
	 * @param string $utm_content value of utm_content query parameter used for tracking
	 *
	 * @return string URL including utm parameters for tracking
	 */
	public static function add_utm_params_to_url_for_subscription_link( $url, $utm_content ) {
		$utm_params = 'utm_source=subscriptionsscreen&' .
						'utm_medium=product&' .
						'utm_campaign=wcaddons&' .
						'utm_content=' . $utm_content;

		// there are already some URL parameters
		if ( strpos( $url, '?' ) ) {
			return $url . '&' . $utm_params;
		}

		return $url . '?' . $utm_params;
	}

	/**
	 * Get available subscriptions filters.
	 *
	 * @return array An array of filter keys and labels.
	 */
	public static function get_filters() {
		$filters = array(
			'all'              => __( 'All', 'woocommerce' ),
			'active'           => __( 'Active', 'woocommerce' ),
			'inactive'         => __( 'Inactive', 'woocommerce' ),
			'installed'        => __( 'Installed', 'woocommerce' ),
			'update-available' => __( 'Update Available', 'woocommerce' ),
			'expiring'         => __( 'Expiring Soon', 'woocommerce' ),
			'expired'          => __( 'Expired', 'woocommerce' ),
			'download'         => __( 'Download', 'woocommerce' ),
		);

		return $filters;
	}

	/**
	 * Get counts data for the filters array.
	 *
	 * @param array $subscriptions The array of all available subscriptions.
	 *
	 * @return array Filter counts (filter => count).
	 */
	public static function get_filters_counts( $subscriptions = null ) {
		static $filters;

		if ( isset( $filters ) ) {
			return $filters;
		}

		$filters = array_fill_keys( array_keys( self::get_filters() ), 0 );
		if ( ! is_array( $subscriptions ) || empty( $subscriptions ) ) {
			return array();
		}

		foreach ( $filters as $key => $count ) {
			$_subs = $subscriptions;
			self::_filter( $_subs, $key );
			$filters[ $key ] = count( $_subs );
		}

		return $filters;
	}

	/**
	 * Get current filter.
	 *
	 * @return string The current filter.
	 */
	public static function get_current_filter() {
		$current_filter = 'all';
		$valid_filters  = array_keys( self::get_filters() );

		if ( ! empty( $_GET['filter'] ) && in_array( wp_unslash( $_GET['filter'] ), $valid_filters ) ) {
			$current_filter = wc_clean( wp_unslash( $_GET['filter'] ) );
		}

		return $current_filter;
	}

	/**
	 * Filter an array of subscriptions by $filter.
	 *
	 * @param array  $subscriptions The subscriptions array, passed by ref.
	 * @param string $filter The filter.
	 *
	 * @return void
	 */
	private static function _filter( &$subscriptions, $filter ) {
		switch ( $filter ) {
			case 'active':
				$subscriptions = wp_list_filter( $subscriptions, array( 'active' => true ) );
				break;

			case 'inactive':
				$subscriptions = wp_list_filter( $subscriptions, array( 'active' => false ) );
				break;

			case 'installed':
				foreach ( $subscriptions as $key => $subscription ) {
					if ( empty( $subscription['local']['installed'] ) ) {
						unset( $subscriptions[ $key ] );
					}
				}
				break;

			case 'update-available':
				$subscriptions = wp_list_filter( $subscriptions, array( 'has_update' => true ) );
				break;

			case 'expiring':
				$subscriptions = wp_list_filter( $subscriptions, array( 'expiring' => true ) );
				break;

			case 'expired':
				$subscriptions = wp_list_filter( $subscriptions, array( 'expired' => true ) );
				break;

			case 'download':
				foreach ( $subscriptions as $key => $subscription ) {
					if ( $subscription['local']['installed'] || $subscription['expired'] ) {
						unset( $subscriptions[ $key ] );
					}
				}
				break;
		}
	}

	/**
	 * Enqueue admin scripts and styles.
	 *
	 * @return void
	 */
	public static function admin_enqueue_scripts() {
		$screen       = get_current_screen();
		$screen_id    = $screen ? $screen->id : '';
		$wc_screen_id = 'woocommerce';

		if ( ( $wc_screen_id . '_page_wc-addons' === $screen_id || $wc_screen_id . '_page_wc-admin' === $screen_id ) && isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			wp_enqueue_style( 'woocommerce-helper', WC()->plugin_url() . '/assets/css/helper.css', array(), Constants::get_constant( 'WC_VERSION' ) );
			wp_style_add_data( 'woocommerce-helper', 'rtl', 'replace' );
		}
	}

	/**
	 * Various success/error notices.
	 *
	 * Runs during admin page render, so no headers/redirects here.
	 *
	 * @return array Array pairs of message/type strings with notices.
	 */
	private static function _get_return_notices() {
		$return_status = isset( $_GET['wc-helper-status'] ) ? wc_clean( wp_unslash( $_GET['wc-helper-status'] ) ) : null;
		$notices       = array();

		switch ( $return_status ) {
			case 'activate-success':
				$product_id   = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0;
				$subscription = self::_get_subscriptions_from_product_id( $product_id );
				$notices[]    = array(
					'type'    => 'updated',
					'message' => sprintf(
						/* translators: %s: product name */
						__( '%s activated successfully. You will now receive updates for this product.', 'woocommerce' ),
						'<strong>' . esc_html( $subscription['product_name'] ) . '</strong>'
					),
				);
				break;

			case 'activate-error':
				$product_id   = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0;
				$subscription = self::_get_subscriptions_from_product_id( $product_id );
				$notices[]    = array(
					'type'    => 'error',
					'message' => sprintf(
						/* translators: %s: product name */
						__( 'An error has occurred when activating %s. Please try again later.', 'woocommerce' ),
						'<strong>' . esc_html( $subscription['product_name'] ) . '</strong>'
					),
				);
				break;

			case 'deactivate-success':
				$product_id   = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0;
				$subscription = self::_get_subscriptions_from_product_id( $product_id );
				$local        = self::_get_local_from_product_id( $product_id );

				$message = sprintf(
					/* translators: %s: product name */
					__( 'Subscription for %s deactivated successfully. You will no longer receive updates for this product.', 'woocommerce' ),
					'<strong>' . esc_html( $subscription['product_name'] ) . '</strong>'
				);

				if ( $local && is_plugin_active( $local['_filename'] ) && current_user_can( 'activate_plugins' ) ) {
					$deactivate_plugin_url = add_query_arg(
						array(
							'page'                        => self::get_source_page(),
							'section'                     => 'helper',
							'filter'                      => self::get_current_filter(),
							'wc-helper-deactivate-plugin' => 1,
							'wc-helper-product-id'        => $subscription['product_id'],
							'wc-helper-nonce'             => wp_create_nonce( 'deactivate-plugin:' . $subscription['product_id'] ),
						),
						admin_url( 'admin.php' )
					);

					$message = sprintf(
						/* translators: %1$s: product name, %2$s: deactivate url */
						__( 'Subscription for %1$s deactivated successfully. You will no longer receive updates for this product. <a href="%2$s">Click here</a> if you wish to deactivate the plugin as well.', 'woocommerce' ),
						'<strong>' . esc_html( $subscription['product_name'] ) . '</strong>',
						esc_url( $deactivate_plugin_url )
					);
				}

				$notices[] = array(
					'message' => $message,
					'type'    => 'updated',
				);
				break;

			case 'deactivate-error':
				$product_id   = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0;
				$subscription = self::_get_subscriptions_from_product_id( $product_id );
				$notices[]    = array(
					'type'    => 'error',
					'message' => sprintf(
						/* translators: %s: product name */
						__( 'An error has occurred when deactivating the subscription for %s. Please try again later.', 'woocommerce' ),
						'<strong>' . esc_html( $subscription['product_name'] ) . '</strong>'
					),
				);
				break;

			case 'deactivate-plugin-success':
				$product_id   = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0;
				$subscription = self::_get_subscriptions_from_product_id( $product_id );
				$notices[]    = array(
					'type'    => 'updated',
					'message' => sprintf(
						/* translators: %s: product name */
						__( 'The extension %s has been deactivated successfully.', 'woocommerce' ),
						'<strong>' . esc_html( $subscription['product_name'] ) . '</strong>'
					),
				);
				break;

			case 'deactivate-plugin-error':
				$product_id   = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0;
				$subscription = self::_get_subscriptions_from_product_id( $product_id );
				$notices[]    = array(
					'type'    => 'error',
					'message' => sprintf(
						/* translators: %1$s: product name, %2$s: plugins screen url */
						__( 'An error has occurred when deactivating the extension %1$s. Please proceed to the <a href="%2$s">Plugins screen</a> to deactivate it manually.', 'woocommerce' ),
						'<strong>' . esc_html( $subscription['product_name'] ) . '</strong>',
						admin_url( 'plugins.php' )
					),
				);
				break;

			case 'helper-connected':
				$notices[] = array(
					'message' => __( 'You have successfully connected your store to WooCommerce.com', 'woocommerce' ),
					'type'    => 'updated',
				);
				break;

			case 'helper-disconnected':
				$notices[] = array(
					'message' => __( 'You have successfully disconnected your store from WooCommerce.com', 'woocommerce' ),
					'type'    => 'updated',
				);
				break;

			case 'helper-refreshed':
				$notices[] = array(
					'message' => __( 'Authentication and subscription caches refreshed successfully.', 'woocommerce' ),
					'type'    => 'updated',
				);
				break;
		}

		return $notices;
	}

	/**
	 * Various early-phase actions with possible redirects.
	 *
	 * @param object $screen WP screen object.
	 */
	public static function current_screen( $screen ) {
		$wc_screen_id = 'woocommerce';

		if ( $wc_screen_id . '_page_wc-addons' !== $screen->id && $wc_screen_id . '_page_wc-admin' !== $screen->id ) {
			return;
		}

		self::maybe_redirect_to_new_marketplace_installer();

		if ( empty( $_GET['section'] ) || 'helper' !== $_GET['section'] ) {
			return;
		}

		if ( ! empty( $_GET['wc-helper-connect'] ) ) {
			return self::_helper_auth_connect();
		}

		if ( ! empty( $_GET['wc-helper-return'] ) ) {
			return self::_helper_auth_return();
		}

		if ( ! empty( $_GET['wc-helper-disconnect'] ) ) {
			return self::_helper_auth_disconnect();
		}

		if ( ! empty( $_GET['wc-helper-refresh'] ) ) {
			return self::_helper_auth_refresh();
		}

		if ( ! empty( $_GET['wc-helper-activate'] ) ) {
			return self::_helper_subscription_activate();
		}

		if ( ! empty( $_GET['wc-helper-deactivate'] ) ) {
			return self::helper_subscription_deactivate();
		}

		if ( ! empty( $_GET['wc-helper-deactivate-plugin'] ) ) {
			return self::_helper_plugin_deactivate();
		}
	}

	/**
	 * Maybe redirect to the new Marketplace installer.
	 *
	 * @return void
	 */
	private static function maybe_redirect_to_new_marketplace_installer() {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		// Redirect requires the "install" URL parameter to be passed.
		if ( empty( $_GET['install'] ) ) {
			return;
		}

		wp_safe_redirect(
			self::get_helper_redirect_url(
				array(
					'page'    => self::get_source_page(),
					'section' => 'helper',
				)
			)
		);
	}

	/**
	 * Get helper redirect URL.
	 *
	 * @param array $args Query args.
	 * @return string
	 */
	private static function get_helper_redirect_url( $args = array() ) {
		global $current_screen;

		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		$redirect_admin_url = isset( $_GET['redirect_admin_url'] )
			? esc_url_raw(
				urldecode(
					// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
					wp_unslash( $_GET['redirect_admin_url'] )
				)
			)
			: '';
		$install_product_key = isset( $_GET['install'] ) ? sanitize_text_field( wp_unslash( $_GET['install'] ) ) : '';
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		if (
			( 'woocommerce_page_wc-addons' === $current_screen->id ||
			'woocommerce_page_wc-admin' === $current_screen->id ) &&
			(
				false === empty( $redirect_admin_url ) ||
				false === empty( $install_product_key )
			)
		) {
			if ( strpos( $redirect_admin_url, admin_url( 'admin.php' ) ) === 0 ) {
				$new_url = $redirect_admin_url;
			} else {
				$new_url = add_query_arg(
					array(
						'page' => 'wc-admin',
						'tab'  => 'my-subscriptions',
						'path' => rawurlencode( '/extensions' ),
					),
					admin_url( 'admin.php' )
				);
			}

			if ( ! empty( $install_product_key ) ) {
				$new_url = add_query_arg(
					array(
						'install' => $install_product_key,
					),
					$new_url
				);
			}
			return $new_url;
		}

		return add_query_arg(
			$args,
			admin_url( 'admin.php' )
		);
	}

	/**
	 * Initiate a new OAuth connection.
	 *
	 * @return never
	 */
	private static function _helper_auth_connect() {
		if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'connect' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			self::log( 'Could not verify nonce in _helper_auth_connect' );
			wp_die( 'Could not verify nonce' );
		}

		$redirect_url_args = array(
			'page'             => self::get_source_page(),
			'section'          => 'helper',
			'wc-helper-return' => 1,
			'wc-helper-nonce'  => wp_create_nonce( 'connect' ),
		);

		if ( isset( $_GET['install'] ) ) {
			$redirect_url_args['install'] = sanitize_text_field( wp_unslash( $_GET['install'] ) );
		}

		if ( isset( $_GET['utm_source'] ) ) {
			$redirect_url_args['utm_source'] = wc_clean( wp_unslash( $_GET['utm_source'] ) );
		}

		if ( isset( $_GET['utm_campaign'] ) ) {
			$redirect_url_args['utm_campaign'] = wc_clean( wp_unslash( $_GET['utm_campaign'] ) );
		}

		$redirect_uri = add_query_arg(
			$redirect_url_args,
			admin_url( 'admin.php' )
		);

		$request = WC_Helper_API::post(
			'oauth/request_token',
			array(
				'body' => array(
					'home_url'     => home_url(),
					'redirect_uri' => $redirect_uri,
				),
			)
		);

		$code = wp_remote_retrieve_response_code( $request );

		if ( 200 !== $code ) {
			self::log( sprintf( 'Call to oauth/request_token returned a non-200 response code (%d)', $code ) );
			wp_die( 'Something went wrong' );
		}

		$secret = json_decode( wp_remote_retrieve_body( $request ) );
		if ( empty( $secret ) ) {
			self::log( sprintf( 'Call to oauth/request_token returned an invalid body: %s', wp_remote_retrieve_body( $request ) ) );
			wp_die( 'Something went wrong' );
		}

		/**
		 * Fires when the Helper connection process is initiated.
		 */
		do_action( 'woocommerce_helper_connect_start' );

		// Ignore all previously dismissed connected notices.
		delete_metadata( 'user', 0, \Automattic\WooCommerce\Admin\PluginsHelper::DISMISS_CONNECT_NOTICE, '', true );

		$connect_url = add_query_arg(
			array(
				'home_url'           => rawurlencode( home_url() ),
				'redirect_uri'       => rawurlencode( $redirect_uri ),
				'secret'             => rawurlencode( $secret ),
				'redirect_admin_url' => isset( $_GET['redirect_admin_url'] )
					? rawurlencode(
						esc_url_raw(
							urldecode(
								// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
								wp_unslash( $_GET['redirect_admin_url'] )
							)
						)
					)
					: '',
				'wum-installed'      => WC_Woo_Update_Manager_Plugin::is_plugin_installed() ? '1' : '0',
			),
			WC_Helper_API::url( 'oauth/authorize' )
		);

		wp_redirect( esc_url_raw( $connect_url ) );
		die();
	}

	/**
	 * Return from WooCommerce.com OAuth flow.
	 *
	 * @return never
	 */
	private static function _helper_auth_return() {
		if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'connect' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			self::log( 'Could not verify nonce in _helper_auth_return' );
			wp_die( 'Something went wrong' );
		}

		// Bail if the user clicked deny.
		if ( ! empty( $_GET['deny'] ) ) {
			/**
			 * Fires when the Helper connection process is denied/cancelled.
			 */
			do_action( 'woocommerce_helper_denied' );

			wp_safe_redirect(
				self::get_helper_redirect_url(
					array(
						'page'    => self::get_source_page(),
						'section' => 'helper',
					)
				)
			);
			die();
		}

		// We do need a request token...
		if ( empty( $_GET['request_token'] ) ) {
			self::log( 'Request token not found in _helper_auth_return' );
			wp_die( 'Something went wrong' );
		}

		// Obtain an access token.
		$request = WC_Helper_API::post(
			'oauth/access_token',
			array(
				'timeout' => 30,
				'body'    => array(
					'request_token' => wp_unslash( $_GET['request_token'] ), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
					'home_url'      => home_url(),
				),
			)
		);

		$code = wp_remote_retrieve_response_code( $request );

		if ( 200 !== $code ) {
			self::log( sprintf( 'Call to oauth/access_token returned a non-200 response code (%d)', $code ) );
			wp_die( 'Something went wrong' );
		}

		$access_token = json_decode( wp_remote_retrieve_body( $request ), true );
		if ( ! $access_token ) {
			self::log( sprintf( 'Call to oauth/access_token returned an invalid body: %s', wp_remote_retrieve_body( $request ) ) );
			wp_die( 'Something went wrong' );
		}

		self::update_auth_option( $access_token['access_token'], $access_token['access_token_secret'], $access_token['site_id'], home_url() );

		/**
		 * Fires when the Helper connection process has completed successfully.
		 */
		do_action( 'woocommerce_helper_connected' );

		// Enable tracking when connected.
		if ( class_exists( 'WC_Tracker' ) ) {
			$prev_value = get_option( 'woocommerce_allow_tracking', 'no' );
			update_option( 'woocommerce_allow_tracking', 'yes' );
			WC_Tracker::send_tracking_data( true );

			// Track woocommerce_allow_tracking_toggled in case was set as 'no' before.
			if ( class_exists( 'WC_Tracks' ) && 'no' === $prev_value ) {
				WC_Tracks::track_woocommerce_allow_tracking_toggled( $prev_value, 'yes', 'wccom_connect' );
			}
		}

		// If connecting through in-app purchase, redirects back to WooCommerce.com
		// for product installation.
		if ( ! empty( $_GET['wccom-install-url'] ) ) {
			wp_redirect( wp_unslash( $_GET['wccom-install-url'] ) );
			exit;
		}

		wp_safe_redirect(
			self::get_helper_redirect_url(
				array(
					'page'             => self::get_source_page(),
					'section'          => 'helper',
					'wc-helper-status' => 'helper-connected',
				)
			)
		);
		die();
	}

	/**
	 * Disconnect from WooCommerce.com, clear OAuth tokens.
	 *
	 * @return never
	 */
	private static function _helper_auth_disconnect() {
		if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'disconnect' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			self::log( 'Could not verify nonce in _helper_auth_disconnect' );
			wp_die( 'Could not verify nonce' );
		}

		/**
		 * Fires when the Helper has been disconnected.
		 */
		do_action( 'woocommerce_helper_disconnected' );

		$redirect_uri = self::get_helper_redirect_url(
			array(
				'page'             => self::get_source_page(),
				'section'          => 'helper',
				'wc-helper-status' => 'helper-disconnected',
			)
		);

		self::disconnect();

		wp_safe_redirect( $redirect_uri );
		die();
	}

	/**
	 * User hit the Refresh button, clear all caches.
	 *
	 * @return never
	 */
	private static function _helper_auth_refresh() {
		if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'refresh' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			self::log( 'Could not verify nonce in _helper_auth_refresh' );
			wp_die( 'Could not verify nonce' );
		}

		self::refresh_helper_subscriptions();

		$redirect_uri = self::get_helper_redirect_url(
			array(
				'page'             => self::get_source_page(),
				'section'          => 'helper',
				'filter'           => self::get_current_filter(),
				'wc-helper-status' => 'helper-refreshed',
			)
		);

		wp_safe_redirect( $redirect_uri );
		die();
	}

	/**
	 * Flush helper authentication cache.
	 *
	 * @throws Exception If there is an error refreshing subscriptions.
	 *
	 * @return void
	 */
	public static function refresh_helper_subscriptions() {
		/**
		 * Fires when Helper subscriptions are refreshed.
		 *
		 * @since 8.3.0
		 */
		do_action( 'woocommerce_helper_subscriptions_refresh' );
		self::_flush_authentication_cache();
		self::_flush_subscriptions_cache();
		self::_flush_updates_cache();
		self::flush_product_usage_notice_rules_cache();
	}

	/**
	 * Active a product subscription.
	 *
	 * @return never
	 */
	private static function _helper_subscription_activate() {
		$product_key = isset( $_GET['wc-helper-product-key'] ) ? wc_clean( wp_unslash( $_GET['wc-helper-product-key'] ) ) : '';
		$product_id  = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0;

		if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'activate:' . $product_key ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			self::log( 'Could not verify nonce in _helper_subscription_activate' );
			wp_die( 'Could not verify nonce' );
		}

		try {
			$activated = self::activate_helper_subscription( $product_key, $product_id );
		} catch ( Exception $e ) {
			$activated = false;
		}

		$redirect_uri = add_query_arg(
			array(
				'page'                 => self::get_source_page(),
				'section'              => 'helper',
				'filter'               => self::get_current_filter(),
				'wc-helper-status'     => $activated ? 'activate-success' : 'activate-error',
				'wc-helper-product-id' => $product_id,
			),
			admin_url( 'admin.php' )
		);

		wp_safe_redirect( $redirect_uri );
		die();
	}

	/**
	 * Activate helper subscription.
	 *
	 * @throws Exception If the subscription could not be activated or found.
	 * @throws WC_Data_Exception If the activation fails with error details.
	 * @param string $product_key Subscription product key.
	 * @return bool True if activated, false otherwise.
	 */
	public static function activate_helper_subscription( $product_key ) {
		$subscription = self::get_subscription( $product_key );
		if ( ! $subscription ) {
			throw new Exception( __( 'Subscription not found', 'woocommerce' ) );
		}
		$product_id = $subscription['product_id'];

		// Activate subscription.
		list( $activation_response, $activated, $body ) = self::wccom_activate( $product_key );

		if ( $activated ) {
			/**
			 * Fires when the Helper activates a product successfully.
			 *
			 * @param int    $product_id Product ID being activated.
			 * @param string $product_key Subscription product key.
			 * @param array  $activation_response The response object from wp_safe_remote_request().
			 */
			do_action( 'woocommerce_helper_subscription_activate_success', $product_id, $product_key, $activation_response );
		} else {
			/**
			 * Fires when the Helper fails to activate a product.
			 *
			 * @param int    $product_id Product ID being activated.
			 * @param string $product_key Subscription product key.
			 * @param array  $activation_response The response object from wp_safe_remote_request().
			 */
			do_action( 'woocommerce_helper_subscription_activate_error', $product_id, $product_key, $activation_response );

			// Include HTTP status code and any extra data from the API response in the exception so callers can surface it.
			$status_code = function_exists( 'wp_remote_retrieve_response_code' ) ? (int) wp_remote_retrieve_response_code( $activation_response ) : (int) ( $body['data']['status'] ?? 400 );
			$error_data  = isset( $body['data'] ) && is_array( $body['data'] ) ? $body['data'] : array();
			throw new WC_Data_Exception(
				esc_html( $body['code'] ?? 'unknown_error' ),
				isset( $body['message'] ) ? esc_html( $body['message'] ) : esc_html__( 'Unknown error', 'woocommerce' ),
				(int) $status_code,
				function_exists( 'map_deep' ) ? map_deep( $error_data, 'esc_html' ) : array_map( 'esc_html', $error_data ),
			);
		}

		self::_flush_subscriptions_cache();
		self::_flush_updates_cache();
		self::flush_product_usage_notice_rules_cache();

		return $activated;
	}

	/**
	 * Activate a plugin for a product key.
	 *
	 * @throws Exception When the subscription is not found.
	 * @param string $product_key Subscription product key.
	 * @return bool True if activated, false otherwise.
	 */
	public static function activate_plugin( $product_key ) {
		$subscription = self::get_subscription( $product_key );
		if ( ! $subscription ) {
			throw new Exception( esc_html( __( 'Subscription not found', 'woocommerce' ) ) );
		}
		$product_id = $subscription['product_id'];
		$local      = self::_get_local_from_product_id( $product_id );

		if ( is_plugin_active( $local['_filename'] ) ) {
			return true;
		}

		$response = false;
		if ( $local && 'plugin' === $local['_type'] && current_user_can( 'activate_plugins' ) ) {
			$response = activate_plugin( $local['_filename'] );
			if ( is_wp_error( $response ) ) {
				self::log( sprintf( 'Error activating plugin (%s)', $response->get_error_message() ) );
			}
			$response = null === $response;
		}

		return $response;
	}

	/**
	 * Deactivate a product subscription.
	 *
	 * @return never
	 */
	private static function helper_subscription_deactivate() {
		$product_key = isset( $_GET['wc-helper-product-key'] ) ? wc_clean( wp_unslash( $_GET['wc-helper-product-key'] ) ) : '';
		$product_id  = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0;

		if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'deactivate:' . $product_key ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			self::log( 'Could not verify nonce in helper_subscription_deactivate' );
			wp_die( 'Could not verify nonce' );
		}

		try {
			$deactivated = self::deactivate_helper_subscription( $product_key );
		} catch ( Exception $e ) {
			$deactivated = false;
		}

		$redirect_uri = add_query_arg(
			array(
				'page'                 => self::get_source_page(),
				'section'              => 'helper',
				'filter'               => self::get_current_filter(),
				'wc-helper-status'     => $deactivated ? 'deactivate-success' : 'deactivate-error',
				'wc-helper-product-id' => $product_id,
			),
			admin_url( 'admin.php' )
		);

		wp_safe_redirect( $redirect_uri );
		die();
	}

	/**
	 * Deactivate a product subscription.
	 *
	 * @throws Exception If the subscription could not be deactivated or found.
	 * @param string $product_key Subscription product key.
	 * @return bool True if deactivated, false otherwise.
	 */
	public static function deactivate_helper_subscription( $product_key ) {
		$subscription = self::get_subscription( $product_key );
		if ( ! $subscription ) {
			throw new Exception( __( 'Subscription not found', 'woocommerce' ) );
		}
		$product_id = $subscription['product_id'];

		$deactivation_response = WC_Helper_API::post(
			'deactivate',
			array(
				'authenticated' => true,
				'body'          => wp_json_encode(
					array(
						'product_key' => $product_key,
					)
				),
			)
		);

		$code        = wp_remote_retrieve_response_code( $deactivation_response );
		$deactivated = 200 === $code;

		if ( $deactivated ) {
			/**
			 * Fires when the Helper activates a product successfully.
			 *
			 * @param int    $product_id Product ID being deactivated.
			 * @param string $product_key Subscription product key.
			 * @param array  $deactivation_response The response object from wp_safe_remote_request().
			 */
			do_action( 'woocommerce_helper_subscription_deactivate_success', $product_id, $product_key, $deactivation_response );
		} else {
			self::log( sprintf( 'Deactivate API call returned a non-200 response code (%d)', $code ) );

			/**
			 * Fires when the Helper fails to activate a product.
			 *
			 * @param int    $product_id Product ID being deactivated.
			 * @param string $product_key Subscription product key.
			 * @param array  $deactivation_response The response object from wp_safe_remote_request().
			 */
			do_action( 'woocommerce_helper_subscription_deactivate_error', $product_id, $product_key, $deactivation_response );

			$body = json_decode( wp_remote_retrieve_body( $deactivation_response ), true );
			throw new Exception( $body['message'] ?? __( 'Unknown error', 'woocommerce' ) );
		}

		self::_flush_subscriptions_cache();
		self::_flush_updates_cache();
		self::flush_product_usage_notice_rules_cache();

		return $deactivated;
	}

	/**
	 * Get a subscriptions install URL.
	 *
	 * @param string $product_key Subscription product key.
	 * @param string $product_slug Subscription product slug.
	 * @return string
	 */
	public static function get_subscription_install_url( $product_key, $product_slug ) {
		$install_url = add_query_arg(
			array(
				'product-key' => rawurlencode( $product_key ),
			),
			self::get_install_base_url() . "{$product_slug}/"
		);

		return WC_Helper_API::add_auth_parameters( $install_url );
	}

	/**
	 * Deactivate a plugin.
	 *
	 * @return never
	 */
	private static function _helper_plugin_deactivate() {
		$product_id  = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0;
		$deactivated = false;

		if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'deactivate-plugin:' . $product_id ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			self::log( 'Could not verify nonce in _helper_plugin_deactivate' );
			wp_die( 'Could not verify nonce' );
		}

		if ( ! current_user_can( 'activate_plugins' ) ) {
			wp_die( 'You are not allowed to manage plugins on this site.' );
		}

		$local = wp_list_filter(
			array_merge(
				self::get_local_woo_plugins(),
				self::get_local_woo_themes()
			),
			array( '_product_id' => $product_id )
		);

		// Attempt to deactivate this plugin or theme.
		if ( ! empty( $local ) ) {
			$local = array_shift( $local );
			if ( is_plugin_active( $local['_filename'] ) ) {
				deactivate_plugins( $local['_filename'] );
			}

			$deactivated = ! is_plugin_active( $local['_filename'] );
		}

		$redirect_uri = add_query_arg(
			array(
				'page'                 => self::get_source_page(),
				'section'              => 'helper',
				'filter'               => self::get_current_filter(),
				'wc-helper-status'     => $deactivated ? 'deactivate-plugin-success' : 'deactivate-plugin-error',
				'wc-helper-product-id' => $product_id,
			),
			admin_url( 'admin.php' )
		);

		wp_safe_redirect( $redirect_uri );
		die();
	}

	/**
	 * Get a local plugin/theme entry from product_id.
	 *
	 * @param int $product_id The product id.
	 *
	 * @return array|bool The array containing the local plugin/theme data or false.
	 */
	private static function _get_local_from_product_id( $product_id ) {
		$local = wp_list_filter(
			array_merge(
				self::get_local_woo_plugins(),
				self::get_local_woo_themes()
			),
			array( '_product_id' => $product_id )
		);

		if ( ! empty( $local ) ) {
			return array_shift( $local );
		}

		return false;
	}

	/**
	 * Checks whether current site has product subscription of a given ID.
	 *
	 * @since 3.7.0
	 *
	 * @param int $product_id The product id.
	 *
	 * @return bool Returns true if product subscription exists, false otherwise.
	 */
	public static function has_product_subscription( $product_id ) {
		$subscription = self::_get_subscriptions_from_product_id( $product_id, true );
		return ! empty( $subscription );
	}

	/**
	 * Get the user's connected subscriptions that are installed on the current
	 * site.
	 *
	 * @return array
	 */
	public static function get_installed_subscriptions() {
		static $installed_subscriptions = null;

		// Cache installed_subscriptions in the current request.
		if ( is_null( $installed_subscriptions ) ) {
			$auth    = WC_Helper_Options::get( 'auth' );
			$site_id = isset( $auth['site_id'] ) ? absint( $auth['site_id'] ) : 0;
			if ( 0 === $site_id ) {
				$installed_subscriptions = array();
				return $installed_subscriptions;
			}

			$installed_subscriptions = array_filter(
				self::get_subscriptions(),
				function ( $subscription ) use ( $site_id ) {
					return in_array( $site_id, $subscription['connections'], true );
				}
			);
		}

		return $installed_subscriptions;
	}

	/**
	 * Get the user's unconnected subscriptions.
	 *
	 * @return array
	 */
	public static function get_unconnected_subscriptions() {
		static $unconnected_subscriptions = null;

		// Cache unconnected_subscriptions in the current request.
		if ( is_null( $unconnected_subscriptions ) ) {
			$auth    = WC_Helper_Options::get( 'auth' );
			$site_id = isset( $auth['site_id'] ) ? absint( $auth['site_id'] ) : 0;
			if ( 0 === $site_id ) {
				$unconnected_subscriptions = array();
				return $unconnected_subscriptions;
			}

			$unconnected_subscriptions = array_filter(
				self::get_subscriptions(),
				function ( $subscription ) use ( $site_id ) {
					return empty( $subscription['connections'] );
				}
			);
		}

		return $unconnected_subscriptions;
	}

	/**
	 * Get subscription state of a given product ID.
	 *
	 * @since TBD
	 *
	 * @param int $product_id The product id.
	 *
	 * @return array Array of state_name => (bool) state
	 */
	public static function get_product_subscription_state( $product_id ) {
		$product_subscriptions = wp_list_filter( self::get_installed_subscriptions(), array( 'product_id' => $product_id ) );

		$subscription = ! empty( $product_subscriptions )
			? array_shift( $product_subscriptions )
			: array();

		return array(
			'unregistered' => empty( $subscription ),
			'expired'      => ( isset( $subscription['expired'] ) && $subscription['expired'] ),
			'expiring'     => ( isset( $subscription['expiring'] ) && $subscription['expiring'] ),
			'key'          => $subscription['product_key'] ?? '',
			'order_id'     => $subscription['order_id'] ?? '',
		);
	}

	/**
	 * Get a subscription entry from product_id. If multiple subscriptions are
	 * found with the same product id and $single is set to true, will return the
	 * first one in the list, so you can use this method to get things like extension
	 * name, version, etc.
	 *
	 * @param int  $product_id The product id.
	 * @param bool $single Whether to return a single subscription or all matching a product id.
	 *
	 * @return array|bool The array containing sub data or false.
	 */
	private static function _get_subscriptions_from_product_id( $product_id, $single = true ) {
		$subscriptions = wp_list_filter( self::get_subscriptions(), array( 'product_id' => $product_id ) );

		if ( ! empty( $subscriptions ) ) {
			return $single ? array_shift( $subscriptions ) : $subscriptions;
		}

		return false;
	}

	/**
	 * Get locally installed plugins
	 *
	 * @return array
	 */
	public static function get_local_plugins() {
		if ( ! function_exists( 'get_plugins' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}
		$plugins = get_plugins();

		$output_plugins = array();
		foreach ( $plugins as $filename => $data ) {
			array_push(
				$output_plugins,
				array(
					'_filename' => $filename,
					'_type'     => 'plugin',
					'slug'      => dirname( $filename ),
					'Version'   => $data['Version'],
				)
			);
		}

		return $output_plugins;
	}

	/**
	 * Get locally installed themes.
	 *
	 * @return array
	 */
	public static function get_local_themes() {
		if ( ! function_exists( 'wp_get_themes' ) ) {
			require_once ABSPATH . 'wp-admin/includes/theme.php';
		}
		$themes = wp_get_themes();

		$output_themes = array();
		foreach ( $themes as $theme ) {
			array_push(
				$output_themes,
				array(
					'_filename'   => $theme->get_stylesheet() . '/style.css',
					'_stylesheet' => $theme->get_stylesheet(),
					'_type'       => 'theme',
					'slug'        => $theme->get_stylesheet(),
					'Version'     => $theme->get( 'Version' ),
				)
			);
		}
		return $output_themes;
	}

	/**
	 * Obtain a list of data about locally installed Woo extensions.
	 *
	 * @return array
	 */
	public static function get_local_woo_plugins() {
		if ( ! function_exists( 'get_plugins' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		$plugins = get_plugins();

		/**
		 * Check if plugins have WC headers, if not then clear cache and fetch again.
		 * WC Headers will not be present if `wc_enable_wc_plugin_headers` hook was added after a `get_plugins` call -- for example when WC is activated/updated.
		 * Also, get_plugins call is expensive, so we should clear this cache very conservatively.
		 */
		if ( ! empty( $plugins ) && ! array_key_exists( 'Woo', current( $plugins ) ) ) {
			wp_clean_plugins_cache( false );
			$plugins = get_plugins();
		}

		$woo_plugins = array();

		// Backwards compatibility for woothemes_queue_update().
		$_compat = array();
		if ( ! empty( $GLOBALS['woothemes_queued_updates'] ) ) {
			foreach ( $GLOBALS['woothemes_queued_updates'] as $_compat_plugin ) {
				$_compat[ $_compat_plugin->file ] = array(
					'product_id' => $_compat_plugin->product_id,
					'file_id'    => $_compat_plugin->file_id,
				);
			}
		}

		foreach ( $plugins as $filename => $data ) {
			if ( empty( $data['Woo'] ) && ! empty( $_compat[ $filename ] ) ) {
				$data['Woo'] = sprintf( '%d:%s', $_compat[ $filename ]['product_id'], $_compat[ $filename ]['file_id'] );
			}

			if ( empty( $data['Woo'] ) ) {
				continue;
			}

			list( $product_id, $file_id ) = explode( ':', $data['Woo'] );
			if ( empty( $product_id ) || empty( $file_id ) ) {
				continue;
			}

			// Omit the WooCommerce plugin used on Woo Express sites.
			if ( 'WooCommerce' === $data['Name'] ) {
				continue;
			}

			$data['_filename']        = $filename;
			$data['_product_id']      = absint( $product_id );
			$data['_file_id']         = $file_id;
			$data['_type']            = 'plugin';
			$data['slug']             = dirname( $filename );
			$woo_plugins[ $filename ] = $data;
		}

		return $woo_plugins;
	}

	/**
	 * Get locally installed Woo themes.
	 *
	 * @return array
	 */
	public static function get_local_woo_themes() {
		$themes     = wp_get_themes();
		$woo_themes = array();

		foreach ( $themes as $theme ) {
			$header = $theme->get( 'Woo' );

			// Backwards compatibility for theme_info.txt.
			if ( ! $header ) {
				$txt = $theme->get_stylesheet_directory() . '/theme_info.txt';
				if ( is_readable( $txt ) ) {
					$txt = file_get_contents( $txt );
					$txt = preg_split( '#\s#', $txt );
					if ( is_array( $txt ) && count( $txt ) >= 2 ) {
						$header = sprintf( '%d:%s', $txt[0], $txt[1] );
					}
				}
			}

			if ( empty( $header ) ) {
				continue;
			}

			list( $product_id, $file_id ) = explode( ':', $header );
			if ( empty( $product_id ) || empty( $file_id ) ) {
				continue;
			}

			$data = array(
				'Name'        => $theme->get( 'Name' ),
				'Version'     => $theme->get( 'Version' ),
				'Woo'         => $header,

				'_filename'   => $theme->get_stylesheet() . '/style.css',
				'_stylesheet' => $theme->get_stylesheet(),
				'_product_id' => absint( $product_id ),
				'_file_id'    => $file_id,
				'_type'       => 'theme',
				'slug'        => dirname( $theme->get_stylesheet() ),
			);

			$woo_themes[ $data['_filename'] ] = $data;
		}

		return $woo_themes;
	}

	/**
	 * Get rules for displaying notice regarding marketplace product usage.
	 *
	 * @return array
	 *
	 * phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.Missing -- As we wrap the throw in a try/catch.
	 */
	public static function get_product_usage_notice_rules() {
		$cache_key = '_woocommerce_helper_product_usage_notice_rules';
		$data      = get_transient( $cache_key );
		if ( false !== $data ) {
			if ( is_array( $data ) ) {
				return $data;
			}
			// Cached data is corrupted, delete and fetch fresh.
			delete_transient( $cache_key );
		}

		try {
			$request = WC_Helper_API::get(
				'product-usage-notice-rules',
				array(
					'authenticated' => false,
					'timeout'       => 2,
				)
			);

			if ( is_wp_error( $request ) ) {
				set_transient( $cache_key, array(), 15 * MINUTE_IN_SECONDS );

				throw new Exception( $request->get_error_message(), (int) $request->get_error_data() );
			}

			$code = wp_remote_retrieve_response_code( $request );
			if ( 200 !== $code ) {
				set_transient( $cache_key, array(), 15 * MINUTE_IN_SECONDS );

				throw new Exception( self::get_message_for_response_code( $code ), $code );
			}

			$data = json_decode( wp_remote_retrieve_body( $request ), true );
			if ( ! is_array( $data ) ) {
				set_transient( $cache_key, array(), 15 * MINUTE_IN_SECONDS );

				throw new Exception( __( 'WooCommerce.com API returned an invalid response.', 'woocommerce' ), 422 );
			}

			set_transient( $cache_key, $data, DAY_IN_SECONDS );

			// Remove notice after successful API call as it's no longer applicable.
			self::remove_api_error_notice();
			return $data;
		} catch ( Exception $e ) {
			if ( $e->getCode() < 404 ) {
				self::remove_api_error_notice();
			} else {
				// Only show error notice in case there is no proper communication with WCCOM.
				self::log( 'Error getting product usage notice rules: ' . $e->getMessage(), 'error' );
				self::add_api_error_notice();
			}
		}

		return array();
	}

	/**
	 * Verify request hash created by WooCommerce.com.
	 *
	 * @param string $request_hash request hash to be verified.
	 * @return bool
	 */
	public static function verify_request_hash( string $request_hash ): bool {
		$request = WC_Helper_API::get(
			'verify-request-hash',
			array(
				'authenticated' => true,
				'query_string'  => '?request_hash=' . $request_hash,
			)
		);

		if ( wp_remote_retrieve_response_code( $request ) !== 200 ) {
			return false;
		}

		$data = json_decode( wp_remote_retrieve_body( $request ), true );

		return isset( $data['success'] ) && true === $data['success'];
	}

	/**
	 * Get cached connection data
	 *
	 * @return array|bool cached connection data or false connection data is not cached.
	 */
	public static function get_cached_connection_data() {
		$data = get_transient( self::CACHE_KEY_CONNECTION_DATA );
		if ( false !== $data && ! is_array( $data ) ) {
			// Cached data is corrupted, delete and return false to trigger fresh fetch.
			delete_transient( self::CACHE_KEY_CONNECTION_DATA );
			return false;
		}
		return $data;
	}

	/**
	 * Get details of the current WooCommerce.com connection.
	 *
	 * @return array|WP_Error
	 */
	public static function fetch_helper_connection_info() {
		$data = self::get_cached_connection_data();
		if ( false !== $data ) {
			if ( ! empty( $data['maybe_deleted_connection'] ) ) {
				return new WP_Error( 'deleted_connection', 'Connection may have been deleted' );
			}
			return $data;
		}

		$request = WC_Helper_API::get(
			'connection-info',
			array(
				'authenticated' => true,
				'query_string'  => '?url=' . rawurlencode( home_url() ),
			)
		);

		$status          = wp_remote_retrieve_response_code( $request );
		$body            = json_decode( wp_remote_retrieve_body( $request ), true );
		$connection_data = is_array( $body ) ? $body : array();
		$message         = $connection_data['message'] ?? '';

		if ( 200 !== $status ) {
			if ( 'Connected site not found.' === $message || 'Invalid access token' === $message ) {
				set_transient( self::CACHE_KEY_CONNECTION_DATA, array( 'maybe_deleted_connection' => true ), 1 * HOUR_IN_SECONDS );
			}
			return new WP_Error(
				'invalid_response',
				'Invalid response from WooCommerce.com',
				array( 'status' => $status )
			);
		}

		$url = $connection_data['url'] ?? '';

		if ( ! empty( $url ) ) {
			$auth        = WC_Helper_Options::get( 'auth' );
			$auth['url'] = $url;
			WC_Helper_Options::update( 'auth', $auth );
			set_transient( self::CACHE_KEY_CONNECTION_DATA, $connection_data, 1 * HOUR_IN_SECONDS );
		}

		return $connection_data;
	}

	/**
	 * Get the connected user's subscriptions.
	 *
	 * @return array
	 *
	 * phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.Missing -- As we wrap the throw in a try/catch.
	 */
	public static function get_subscriptions() {
		$cache_key = '_woocommerce_helper_subscriptions';
		$data      = get_transient( $cache_key );
		if ( false !== $data ) {
			if ( is_array( $data ) ) {
				return $data;
			}
			// Cached data is corrupted, delete and fetch fresh.
			delete_transient( $cache_key );
		}

		try {
			$request_uri = wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			$source      = '';
			if ( false !== stripos( $request_uri, 'wc/v3/marketplace/refresh' ) ) :
				$source = 'refresh-button';
			elseif ( false !== stripos( $request_uri, 'my-subscriptions' ) ) :
				$source = 'my-subscriptions';
			elseif ( false !== stripos( $request_uri, 'plugins.php' ) ) :
				$source = 'plugins';
			elseif ( false !== stripos( $request_uri, 'wc-admin' ) ) :
				$source = 'inbox-notes';
			elseif ( false !== stripos( $request_uri, 'admin-ajax.php' ) ) :
				$source = 'heartbeat-api';
			elseif ( false !== stripos( $request_uri, 'installer' ) ) :
				$source = 'wccom-site-installer';
			elseif ( defined( 'WP_CLI' ) && WP_CLI ) :
				$source = 'wc-cli';
			endif;

			// Obtain the connected user info.
			$request = WC_Helper_API::get(
				'subscriptions',
				array(
					'authenticated' => true,
					'query_string'  => '' !== $source ? esc_url( '?source=' . $source ) : '',
				)
			);

			if ( is_wp_error( $request ) ) {
				set_transient( $cache_key, array(), 15 * MINUTE_IN_SECONDS );

				throw new Exception( $request->get_error_message(), (int) $request->get_error_data() );
			}

			$code = wp_remote_retrieve_response_code( $request );
			if ( 200 !== $code ) {
				set_transient( $cache_key, array(), 15 * MINUTE_IN_SECONDS );

				throw new Exception( self::get_message_for_response_code( $code ), $code );
			}

			$data = json_decode( wp_remote_retrieve_body( $request ), true );
			if ( ! is_array( $data ) ) {
				set_transient( $cache_key, array(), 15 * MINUTE_IN_SECONDS );

				throw new Exception( __( 'WooCommerce.com API returned an invalid response.', 'woocommerce' ), 422 );
			}

			set_transient( $cache_key, $data, 3 * HOUR_IN_SECONDS );

			// Remove notice after successful API call as it's no longer applicable.
			self::remove_api_error_notice();
			return $data;
		} catch ( Exception $e ) {
			if ( $e->getCode() < 404 ) {
				self::remove_api_error_notice();
			} else {
				// Only show error notice in case there is no proper communication with WCCOM.
				self::log( 'Error getting subscriptions: ' . $e->getMessage(), 'error' );
				self::add_api_error_notice();
			}
		}

		return array();
	}

	/**
	 * Get subscription data for a given product key.
	 *
	 * @param string $product_key Subscription product key.
	 * @return array|bool The array containing sub data or false.
	 */
	public static function get_subscription( $product_key ) {
		$subscriptions = wp_list_filter(
			self::get_subscriptions(),
			array( 'product_key' => $product_key )
		);

		if ( empty( $subscriptions ) ) {
			return false;
		}

		$subscription          = array_shift( $subscriptions );
		$subscription['local'] = self::get_subscription_local_data( $subscription );
		return $subscription;
	}

	/**
	 * Get the connected user's subscription list data. Here, we merge connected
	 * subscriptions with locally installed Woo plugins and themes. We also
	 * add in information about available updates.
	 *
	 * Used by the My Subscriptions page.
	 *
	 * @return array
	 */
	public static function get_subscription_list_data() {
		// First, connected subscriptions.
		$subscriptions = self::get_subscriptions();

		// Then, installed plugins and themes, with or without an active subscription.
		$woo_plugins = self::get_local_woo_plugins();
		$woo_themes  = self::get_local_woo_themes();

		// Get the product IDs of the subscriptions.
		$subscriptions_product_ids = wp_list_pluck( $subscriptions, 'product_id' );

		// Get the site ID.
		$auth    = WC_Helper_Options::get( 'auth' );
		$site_id = isset( $auth['site_id'] ) ? absint( $auth['site_id'] ) : 0;

		// Now, merge installed products without a subscription.
		foreach ( array_merge( $woo_plugins, $woo_themes ) as $filename => $data ) {
			if ( in_array( $data['_product_id'], $subscriptions_product_ids, true ) ) {
				continue;
			}

			// We add these as subscriptions to the previous connected subscriptions list.
			$subscriptions[] = array(
				'product_key'       => '',
				'product_id'        => $data['_product_id'],
				'product_name'      => $data['Name'],
				'product_url'       => $data['PluginURI'] ?? '',
				'zip_slug'          => $data['slug'],
				'documentation_url' => '',
				'key_type'          => '',
				'key_type_label'    => '',
				'lifetime'          => false,
				'product_status'    => 'publish',
				// Connections is empty because this is not a connected subscription.
				'connections'       => array(),
				'expires'           => 0,
				'expired'           => true,
				'expiring'          => false,
				'sites_max'         => 0,
				'sites_active'      => 0,
				'autorenew'         => false,
				'maxed'             => false,
			);
		}

		// Fetch updates so we can refine subscriptions with information about updates.
		$updates = WC_Helper_Updater::get_update_data();

		// Add local data to merged subscriptions list (both locally installed and purchased).
		foreach ( $subscriptions as &$subscription ) {
			$subscription['active'] = in_array( $site_id, $subscription['connections'], true );

			$subscription['local'] = self::get_subscription_local_data( $subscription );

			$subscription['has_update'] = false;
			if ( $subscription['local']['installed'] && ! empty( $updates[ $subscription['product_id'] ] ) ) {
				$subscription['has_update'] = version_compare( $updates[ $subscription['product_id'] ]['version'], $subscription['local']['version'], '>' );
			}

			if ( ! empty( $updates[ $subscription['product_id'] ] ) ) {
				$subscription['version'] = $updates[ $subscription['product_id'] ]['version'];
			}

			// If the update endpoint returns a URL, we prefer it over the default PluginURI.
			if ( ! empty( $updates[ $subscription['product_id'] ]['url'] ) ) {
				$subscription['product_url'] = $updates[ $subscription['product_id'] ]['url'];
			}
		}

		// Sort subscriptions by name and expiration date.
		usort(
			$subscriptions,
			function ( $a, $b ) {
				$compare_value = strcasecmp( $a['product_name'], $b['product_name'] );
				if ( 0 === $compare_value ) {
					return strcasecmp( $a['expires'], $b['expires'] );
				}
				return $compare_value;
			}
		);

		// Add subscription install flags after the active and local data is set.
		foreach ( $subscriptions as &$subscription ) {
			$subscription['subscription_available'] = self::is_subscription_available( $subscription, $subscriptions );
			$subscription['subscription_installed'] = self::is_subscription_installed( $subscription, $subscriptions );
		}

		// Break the by-ref.
		unset( $subscription );

		return $subscriptions;
	}

	/**
	 * Check if a subscription is available to use.
	 * That is, is not already active and hasn't expired, and there are no other subscriptions
	 * for this product already active on this site.
	 *
	 * @param array $subscription The subscription we're checking.
	 * @param array $subscriptions The list of all the user's subscriptions.
	 * @return bool True if multiple licenses exist, false otherwise.
	 */
	public static function is_subscription_available( $subscription, $subscriptions ) {
		if ( true === $subscription['active'] ) {
			return false;
		}

		if ( true === $subscription['expired'] ) {
			return false;
		}

		$product_subscriptions = wp_list_filter(
			$subscriptions,
			array(
				'product_id' => $subscription['product_id'],
				'active'     => true,
			)
		);

		// If there are no subscriptions for this product already active on this site, then it's available.
		if ( empty( $product_subscriptions ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Check if product relating to a subscription is installed.
	 * This method will return true if the product is installed, but will exclude subscriptions for the same product that are not in use.
	 * If a product is installed and inactive, this will ensure that one subscription is marked as installed.
	 *
	 * @param array $subscription The subscription we're checking.
	 * @param array $subscriptions The list of all the user's subscriptions.
	 * @return bool True if installed, false otherwise.
	 */
	public static function is_subscription_installed( $subscription, $subscriptions ) {
		if ( false === $subscription['local']['installed'] ) {
			return false;
		}

		// If the subscription is active, then it's installed.
		if ( true === $subscription['active'] ) {
			return true;
		}

		$product_subscriptions = wp_list_filter(
			$subscriptions,
			array(
				'product_id' => $subscription['product_id'],
			)
		);
		if ( empty( $product_subscriptions ) ) {
			return false;
		}

		// If there are no other subscriptions for this product, then it's installed.
		if ( 1 === count( $product_subscriptions ) ) {
			return true;
		}

		$active_subscription = wp_list_filter(
			$product_subscriptions,
			array(
				'active' => true,
			)
		);

		// If there is another active subscription, this subscription is not installed.
		// If the current subscription is active, it would already return true above.
		if ( ! empty( $active_subscription ) ) {
			return false;
		}

		// Find subscriptions that can be activated.
		$product_subscriptions_without_maxed_connections = wp_list_filter(
			$product_subscriptions,
			array(
				'maxed' => false,
			)
		);

		if ( 0 < count( $product_subscriptions_without_maxed_connections ) ) {
			// Pick the first subscription available for activation.
			$product_subscription = array_shift( $product_subscriptions_without_maxed_connections );
		} else {
			// If there are multiple subscriptions, but no active subscriptions, then mark the first one as installed.
			$product_subscription = array_shift( $product_subscriptions );
		}

		if ( $product_subscription['product_key'] === $subscription['product_key'] ) {
			return true;
		}

		return false;
	}

	/**
	 * Add local data to a subscription.
	 *
	 * @param array $subscription The subscription data.
	 * @return array The subscription data with local data added.
	 */
	public static function get_subscription_local_data( array $subscription ) {
		$local_plugins = self::get_local_plugins();
		$local_themes  = self::get_local_themes();

		$installed_product = wp_list_filter(
			array_merge( $local_plugins, $local_themes ),
			array( 'slug' => $subscription['zip_slug'] )
		);
		$installed_product = array_shift( $installed_product );

		if ( empty( $installed_product ) ) {
			return array(
				'installed' => false,
				'active'    => false,
				'version'   => null,
				'type'      => null,
				'slug'      => null,
				'path'      => null,
			);
		}

		$local_data = array(
			'installed' => true,
			'active'    => false,
			'version'   => $installed_product['Version'],
			'type'      => $installed_product['_type'],
			'slug'      => null,
			'path'      => $installed_product['_filename'],
		);

		if ( 'plugin' === $installed_product['_type'] ) {
			$local_data['slug'] = $installed_product['slug'];
			if ( is_plugin_active( $installed_product['_filename'] ) ) {
				$local_data['active'] = true;
			} elseif ( is_multisite() && is_plugin_active_for_network( $installed_product['_filename'] ) ) {
				$local_data['active'] = true;
			}
		} elseif ( 'theme' === $installed_product['_type'] ) {
			$local_data['slug'] = $installed_product['_stylesheet'];
			if ( in_array( $installed_product['_stylesheet'], array( get_stylesheet(), get_template() ), true ) ) {
				$local_data['active'] = true;
			}
		}

		return $local_data;
	}

	/**
	 * Runs when any plugin is activated.
	 *
	 * Depending on the activated plugin attempts to look through available
	 * subscriptions and auto-activate one if possible, so the user does not
	 * need to visit the Helper UI at all after installing a new extension.
	 *
	 * @param string $filename The filename of the activated plugin.
	 *
	 * @return void
	 */
	public static function activated_plugin( $filename ) {
		$plugins = self::get_local_woo_plugins();

		// Not a local woo plugin.
		if ( empty( $plugins[ $filename ] ) ) {
			return;
		}

		// Make sure we have a connection.
		$auth = WC_Helper_Options::get( 'auth' );
		if ( empty( $auth ) ) {
			return;
		}

		$plugin       = $plugins[ $filename ];
		$product_id   = $plugin['_product_id'];
		$subscription = self::get_available_subscription( $product_id );

		self::_flush_subscriptions_cache();
		self::_flush_updates_cache();

		// No valid subscription found.
		if ( ! $subscription ) {
			return;
		}

		$product_key                                    = $subscription['product_key'];
		list( $activation_response, $activated, $body ) = self::wccom_activate( $product_key );

		if ( $activated ) {
			self::log( 'Auto-activated a subscription for ' . $filename );
			/**
			 * Fires when the Helper activates a product successfully.
			 *
			 * @param int    $product_id Product ID being activated.
			 * @param string $product_key Subscription product key.
			 * @param array  $activation_response The response object from wp_safe_remote_request().
			 * @since 9.7
			 */
			do_action( 'woocommerce_helper_subscription_activate_success', $product_id, $product_key, $activation_response );
		} else {
			self::log( 'Could not activate a subscription upon plugin activation: ' . $filename );

			/**
			 * Fires when the Helper fails to activate a product.
			 *
			 * @param int    $product_id Product ID being activated.
			 * @param string $product_key Subscription product key.
			 * @param array  $activation_response The response object from wp_safe_remote_request().
			 * @since 9.7
			 */
			do_action( 'woocommerce_helper_subscription_activate_error', $product_id, $product_key, $activation_response );
		}
	}

	/**
	 * Connect theme to the WCCOM.
	 *
	 * Depending on the activated theme attempts to look through available
	 * subscriptions and auto-activate one if possible, so the user does not
	 * need to visit the Helper UI at all after installing a new extension.
	 *
	 * @param string $product_id The product id of the activated theme.
	 *
	 * @return void
	 */
	public static function connect_theme( $product_id ) {
		// Make sure we have a connection.
		$auth = WC_Helper_Options::get( 'auth' );
		if ( empty( $auth ) ) {
			return;
		}

		wp_clean_themes_cache( false );
		$themes = self::get_local_woo_themes();

		$themes = array_filter(
			$themes,
			function ( $theme ) use ( $product_id ) {
				return $theme['_product_id'] === $product_id;
			}
		);

		if ( empty( $themes ) ) {
			return;
		}

		$theme = reset( $themes );

		$subscription = self::get_available_subscription( $product_id );

		// No valid subscription found.
		if ( ! $subscription ) {
			return;
		}

		$product_key                                    = $subscription['product_key'];
		list( $activation_response, $activated, $body ) = self::wccom_activate( $product_key );

		if ( $activated ) {
			self::log( 'Auto-activated a subscription for ' . $theme['Name'] );
			/**
			 * Fires when the Helper activates a product successfully.
			 *
			 * @param int    $product_id Product ID being activated.
			 * @param string $product_key Subscription product key.
			 * @param array  $activation_response The response object from wp_safe_remote_request().
			 */
			do_action( 'woocommerce_helper_subscription_activate_success', $product_id, $product_key, $activation_response );
		} else {
			self::log( 'Could not activate a subscription for theme: ' . $theme['Name'] );

			/**
			 * Fires when the Helper fails to activate a product.
			 *
			 * @param int    $product_id Product ID being activated.
			 * @param string $product_key Subscription product key.
			 * @param array  $activation_response The response object from wp_safe_remote_request().
			 */
			do_action( 'woocommerce_helper_subscription_activate_error', $product_id, $product_key, $activation_response );
		}

		self::_flush_subscriptions_cache();
		self::_flush_updates_cache();
	}

	/**
	 * Runs when any plugin is deactivated.
	 *
	 * When a user deactivates a plugin, attempt to deactivate any subscriptions
	 * associated with the extension.
	 *
	 * @param string $filename The filename of the deactivated plugin.
	 *
	 * @return void
	 */
	public static function deactivated_plugin( $filename ) {
		$plugins = self::get_local_woo_plugins();

		// Not a local woo plugin.
		if ( empty( $plugins[ $filename ] ) ) {
			return;
		}

		// Make sure we have a connection.
		$auth = WC_Helper_Options::get( 'auth' );
		if ( empty( $auth ) ) {
			return;
		}

		$plugin        = $plugins[ $filename ];
		$product_id    = $plugin['_product_id'];
		$subscriptions = self::_get_subscriptions_from_product_id( $product_id, false );
		$site_id       = absint( $auth['site_id'] );

		// No valid subscriptions for this product.
		if ( empty( $subscriptions ) ) {
			return;
		}

		$deactivated = 0;

		foreach ( $subscriptions as $subscription ) {
			// Don't touch subscriptions that aren't activated on this site.
			if ( ! in_array( $site_id, $subscription['connections'], true ) ) {
				continue;
			}

			$product_key           = $subscription['product_key'];
			$deactivation_response = WC_Helper_API::post(
				'deactivate',
				array(
					'authenticated' => true,
					'body'          => wp_json_encode(
						array(
							'product_key' => $product_key,
						)
					),
				)
			);

			if ( wp_remote_retrieve_response_code( $deactivation_response ) === 200 ) {
				++$deactivated;

				/**
				 * Fires when the Helper activates a product successfully.
				 *
				 * @param int    $product_id Product ID being deactivated.
				 * @param string $product_key Subscription product key.
				 * @param array  $deactivation_response The response object from wp_safe_remote_request().
				 */
				do_action( 'woocommerce_helper_subscription_deactivate_success', $product_id, $product_key, $deactivation_response );
			} else {
				/**
				 * Fires when the Helper fails to activate a product.
				 *
				 * @param int    $product_id Product ID being deactivated.
				 * @param string $product_key Subscription product key.
				 * @param array  $deactivation_response The response object from wp_safe_remote_request().
				 */
				do_action( 'woocommerce_helper_subscription_deactivate_error', $product_id, $product_key, $deactivation_response );
			}
		}

		self::_flush_subscriptions_cache();
		self::_flush_updates_cache();

		if ( $deactivated ) {
			self::log( sprintf( 'Auto-deactivated %d subscription(s) for %s', $deactivated, $filename ) );
		}
	}

	/**
	 * Various Helper-related admin notices.
	 *
	 * @return void
	 */
	public static function admin_notices() {
		if ( apply_filters( 'woocommerce_helper_suppress_admin_notices', false ) ) {
			return;
		}

		$screen    = get_current_screen();
		$screen_id = $screen ? $screen->id : '';

		if ( 'update-core' !== $screen_id ) {
			return;
		}

		// Don't nag if Woo doesn't have an update available.
		if ( ! self::_woo_core_update_available() ) {
			return;
		}

		// Add a note about available extension updates if Woo core has an update available.
		$notice = self::_get_extensions_update_notice();
		if ( ! empty( $notice ) ) {
			echo '<div class="updated woocommerce-message"><p>' . $notice . '</p></div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		}
	}

	/**
	 * Get an update notice if one or more Woo extensions has an update available.
	 *
	 * @return string|null The update notice or null if everything is up to date.
	 */
	private static function _get_extensions_update_notice() {
		$plugins   = self::get_local_woo_plugins();
		$updates   = WC_Helper_Updater::get_update_data();
		$available = 0;

		foreach ( $plugins as $data ) {
			if ( empty( $updates[ $data['_product_id'] ] ) ) {
				continue;
			}

			$product_id = $data['_product_id'];
			if ( version_compare( $updates[ $product_id ]['version'], $data['Version'], '>' ) ) {
				++$available;
			}
		}

		if ( ! $available ) {
			return;
		}

		return sprintf(
			/* translators: %1$s: helper url, %2$d: number of extensions */
			_n( 'Note: You currently have <a href="%1$s">%2$d paid extension</a> which should be updated first before updating WooCommerce.', 'Note: You currently have <a href="%1$s">%2$d paid extensions</a> which should be updated first before updating WooCommerce.', $available, 'woocommerce' ),
			admin_url( 'admin.php?page=' . self::get_source_page() . ' &section=helper' ),
			$available
		);
	}

	/**
	 * Whether WooCommerce has an update available.
	 *
	 * @return bool True if a Woo core update is available.
	 */
	private static function _woo_core_update_available() {
		$updates = get_site_transient( 'update_plugins' );
		if ( empty( $updates->response ) ) {
			return false;
		}

		if ( empty( $updates->response['woocommerce/woocommerce.php'] ) ) {
			return false;
		}

		$data = $updates->response['woocommerce/woocommerce.php'];
		if ( version_compare( Constants::get_constant( 'WC_VERSION' ), $data->new_version, '>=' ) ) {
			return false;
		}

		return true;
	}

	/**
	 * Flush subscriptions cache.
	 *
	 * @return void
	 */
	public static function _flush_subscriptions_cache() {
		delete_transient( '_woocommerce_helper_subscriptions' );
	}

	/**
	 * Flush product-usage-notice-rules cache.
	 *
	 * @return void
	 */
	public static function flush_product_usage_notice_rules_cache() {
		delete_transient( '_woocommerce_helper_product_usage_notice_rules' );
	}

	/**
	 * Flush connection data cache.
	 *
	 * @return void
	 */
	public static function flush_connection_data_cache() {
		delete_transient( self::CACHE_KEY_CONNECTION_DATA );
	}

	/**
	 * Flush auth cache.
	 *
	 * @return bool
	 */
	public static function _flush_authentication_cache() {
		$request = WC_Helper_API::get(
			'oauth/me',
			array(
				'authenticated' => true,
				'timeout'       => 30,
			)
		);

		if ( wp_remote_retrieve_response_code( $request ) !== 200 ) {
			return false;
		}

		$user_data = json_decode( wp_remote_retrieve_body( $request ), true );
		if ( ! $user_data ) {
			return false;
		}

		WC_Helper_Options::update(
			'auth_user_data',
			array(
				'name'  => $user_data['name'],
				'email' => $user_data['email'],
			)
		);

		return true;
	}

	/**
	 * Flush updates cache.
	 *
	 * @return void
	 */
	private static function _flush_updates_cache() {
		WC_Helper_Updater::flush_updates_cache();
	}

	/**
	 * Sort subscriptions by the product_name.
	 *
	 * @param array $a Subscription array.
	 * @param array $b Subscription array.
	 *
	 * @return int
	 */
	public static function _sort_by_product_name( $a, $b ) {
		return strcmp( $a['product_name'], $b['product_name'] );
	}

	/**
	 * Sort subscriptions by the Name.
	 *
	 * @param array $a Product array.
	 * @param array $b Product array.
	 *
	 * @return int
	 */
	public static function _sort_by_name( $a, $b ) {
		return strcmp( $a['Name'], $b['Name'] );
	}

	/**
	 * Log a helper event.
	 *
	 * @param string $message Log message.
	 * @param string $level Optional, defaults to info, valid levels: emergency|alert|critical|error|warning|notice|info|debug.
	 *
	 * @return void
	 */
	public static function log( $message, $level = 'info' ) {
		if ( ! Constants::is_true( 'WP_DEBUG' ) ) {
			return;
		}

		if ( ! isset( self::$log ) ) {
			self::$log = wc_get_logger();
		}

		self::$log->log( $level, $message, array( 'source' => 'helper' ) );
	}

	/**
	 * Handles WC Helper disconnect tasks.
	 *
	 * @return void
	 */
	public static function disconnect() {
		WC_Helper_API::post(
			'oauth/invalidate_token',
			array(
				'authenticated' => true,
			)
		);

		$data = WC_Helper_Options::get( 'auth_user_data' );
		WC_Helper_Options::update( 'last_disconnected_user_data', $data );
		// Ignore all previously dismissed disconnect notices.
		delete_metadata( 'user', 0, PluginsHelper::DISMISS_DISCONNECT_NOTICE, '', true );

		WC_Helper_Options::update( 'auth', array() );
		WC_Helper_Options::update( 'auth_user_data', array() );

		self::_flush_subscriptions_cache();
		self::_flush_updates_cache();
		self::flush_product_usage_notice_rules_cache();
		self::flush_connection_data_cache();
	}

	/**
	 * Checks if `access_token` exists in `auth` option.
	 *
	 * @return bool
	 */
	public static function is_site_connected(): bool {
		$auth = WC_Helper_Options::get( 'auth' );

		// If `access_token` is empty, there's no active connection.
		return ! empty( $auth['access_token'] );
	}

	/**
	 * Allows to connect with WCCOM using application password. used it to connect via CLI
	 *
	 * @param string $password The application password.
	 *
	 * @return void|WP_Error
	 */
	public static function connect_with_password( string $password ) {
		$request = WC_Helper_API::post(
			'connect',
			array(
				'headers'       => array(
					'X-API-Key'    => $password,
					'Content-Type' => 'application/json',
				),
				'body'          => wp_json_encode( array( 'home_url' => home_url() ) ),
				'authenticated' => false,
			)
		);

		$code = wp_remote_retrieve_response_code( $request );

		if ( $code === 403 ) {
			$message = 'Invalid password';
			self::log( $message );

			return new WP_Error( 'connect-with-password-invalid-password', $message );
		} elseif ( $code !== 200 ) {
			$message = sprintf( 'Call to /connect returned a non-200 response code (%d)', $code );
			self::log( $message );

			return new WP_Error( 'connect-with-password-' . $code, $message );
		}

		$access_data = json_decode( wp_remote_retrieve_body( $request ), true );
		if ( empty( $access_data['access_token'] ) || empty( $access_data['access_token_secret'] ) ) {
			$message = sprintf( 'Call to /connect returned an invalid body: %s', wp_remote_retrieve_body( $request ) );
			self::log( $message );

			return new WP_Error( 'connect-with-password-invalid-response', $message );
		}

		self::update_auth_option( $access_data['access_token'], $access_data['access_token_secret'], $access_data['site_id'], home_url() );
	}

	/**
	 * Updates auth options and flushes cache
	 *
	 * @param string $access_token The access token.
	 * @param string $access_token_secret The secret access token.
	 * @param int    $site_id The site id returned by the API.
	 * @param string $home_url Home url of the site.
	 *
	 * @return void
	 */
	public static function update_auth_option( string $access_token, string $access_token_secret, int $site_id, string $home_url ): void {
		WC_Helper_Options::update(
			'auth',
			array(
				'access_token'        => $access_token,
				'access_token_secret' => $access_token_secret,
				'site_id'             => $site_id,
				'url'                 => $home_url,
				'user_id'             => get_current_user_id(),
				'updated'             => time(),
			)
		);

		// Obtain the connected user info.
		if ( ! self::_flush_authentication_cache() ) {
			self::log( 'Could not obtain connected user info in _helper_auth_return.' );
			WC_Helper_Options::update( 'auth', array() );
			wp_die( 'Something went wrong. Could not obtain connected user info in _helper_auth_return.' );
		}

		self::_flush_subscriptions_cache();
		self::_flush_updates_cache();
		self::flush_product_usage_notice_rules_cache();
	}

	/**
	 * Get WooCommerce.com base URL.
	 *
	 * @return string
	 */
	public static function get_woocommerce_com_base_url() {
		/**
		 * Filter the base URL used to install the Woo hosted plugins.
		 *
		 * @since 8.7.0
		 */
		return trailingslashit( apply_filters( 'woo_com_base_url', 'https://woocommerce.com/' ) );
	}


	/**
	 * Get base URL for plugin auto installer.
	 *
	 * @return string
	 */
	public static function get_install_base_url() {
		return self::get_woocommerce_com_base_url() . 'auto-install-init/';
	}

	/**
	 * Retrieve notice for connected store.
	 *
	 * @return array An array containing notice data.
	 */
	public static function get_notices() {
		$cache_key   = '_woocommerce_helper_notices';
		$cached_data = get_transient( $cache_key );

		if ( false !== $cached_data ) {
			if ( is_array( $cached_data ) ) {
				return $cached_data;
			}
			// Cached data is corrupted, delete and fetch fresh.
			delete_transient( $cache_key );
		}

		// Fetch notice data for connected store.
		$request = WC_Helper_API::get(
			'notices',
			array(
				'authenticated' => true,
			)
		);

		if ( 200 !== wp_remote_retrieve_response_code( $request ) ) {
			set_transient( $cache_key, array(), 15 * MINUTE_IN_SECONDS );
			return array();
		}

		$data = json_decode( wp_remote_retrieve_body( $request ), true );

		if ( empty( $data ) || ! is_array( $data ) ) {
			$data = array();
		}

		set_transient( $cache_key, $data, 1 * HOUR_IN_SECONDS );
		return $data;
	}

	/**
	 * Activate the product subscription to WCCOM
	 *
	 * @param string $product_key the product key to be activated.
	 *
	 * @return array
	 */
	protected static function wccom_activate( $product_key ): array {
		$activation_response = WC_Helper_API::post(
			'activate',
			array(
				'authenticated' => true,
				'body'          => wp_json_encode(
					array(
						'product_key' => $product_key,
					)
				),
			)
		);

		$activated = wp_remote_retrieve_response_code( $activation_response ) === 200;
		$body      = json_decode( wp_remote_retrieve_body( $activation_response ), true );

		if ( ! $activated && ! empty( $body['code'] ) && 'already_connected' === $body['code'] ) {
			$activated = true;
		}

		return array( $activation_response, $activated, $body );
	}

	/**
	 * Get subscriptions for a product if it is available
	 *
	 * @param string|int $product_id the product id to get subscriptions for.
	 *
	 * @return mixed|null
	 */
	protected static function get_available_subscription( $product_id ) {
		$subscriptions = self::_get_subscriptions_from_product_id( $product_id, false );

		// No valid subscriptions for this product.
		if ( empty( $subscriptions ) ) {
			return null;
		}

		$subscription = null;
		foreach ( $subscriptions as $_sub ) {

			// Don't attempt to activate expired subscriptions.
			if ( $_sub['expired'] ) {
				continue;
			}

			// No more sites available in this subscription.
			if ( isset( $_sub['maxed'] ) && $_sub['maxed'] ) {
				continue;
			}

			// Looks good.
			$subscription = $_sub;
			break;
		}

		return $subscription;
	}

	/**
	 * Gets a user-friendly error message based on the HTTP response code.
	 *
	 * @param int $code The HTTP response code.
	 * @return string The user-friendly error message.
	 */
	protected static function get_message_for_response_code( int $code ): string {
		if ( 429 === $code ) {
			return __( 'You have exceeded the request limit. Please try again after a few minutes.', 'woocommerce' );
		} elseif ( 403 === $code ) {
			return __( 'Authentication failed. Please try again after a few minutes. If the issue persists, disconnect your store from WooCommerce.com and reconnect.', 'woocommerce' );
		}

		// translators: %d: HTTP status code.
		return sprintf( __( 'WooCommerce.com API returned HTTP status code %d.', 'woocommerce' ), $code );
	}
}

WC_Helper::load();
PK     tS\|j  j  "  helper/class-wc-helper-updater.phpnu [        <?php
/**
 * The update helper for WooCommerce.com plugins.
 *
 * @class WC_Helper_Updater
 * @package WooCommerce\Admin\Helper
 */

use Automattic\WooCommerce\Admin\PluginsHelper;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper_Updater Class
 *
 * Contains the logic to fetch available updates and hook into Core's update
 * routines to serve WooCommerce.com-provided packages.
 */
class WC_Helper_Updater {

	/**
	 * Loads the class, runs on init.
	 */
	public static function load() {
		add_action( 'pre_set_site_transient_update_plugins', array( __CLASS__, 'transient_update_plugins' ), 21, 1 );
		add_action( 'pre_set_site_transient_update_themes', array( __CLASS__, 'transient_update_themes' ), 21, 1 );
		add_action( 'upgrader_process_complete', array( __CLASS__, 'upgrader_process_complete' ) );
		add_action( 'upgrader_pre_download', array( __CLASS__, 'block_expired_updates' ), 10, 2 );
		add_action( 'admin_init', array( __CLASS__, 'add_hook_for_modifying_update_notices' ) );
	}

	/**
	 * Add the hook for modifying default WPCore update notices on the plugins management page.
	 */
	public static function add_hook_for_modifying_update_notices() {
		if ( ! WC_Woo_Update_Manager_Plugin::is_plugin_active() || ! WC_Helper::is_site_connected() ) {
			add_action( 'load-plugins.php', array( __CLASS__, 'setup_update_plugins_messages' ), 11 );
		}
		if ( WC_Helper::is_site_connected() ) {
			add_action( 'load-plugins.php', array( __CLASS__, 'setup_message_for_expired_and_expiring_subscriptions' ), 11 );
			add_action( 'load-plugins.php', array( __CLASS__, 'setup_message_for_plugins_without_subscription' ), 11 );
		}
	}

	/**
	 * Add the hook for modifying default WPCore update notices on the plugins management page.
	 * This is for plugins with expired or expiring subscriptions.
	 */
	public static function setup_message_for_expired_and_expiring_subscriptions() {
		foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) {
			add_action( 'in_plugin_update_message-' . $plugin['_filename'], array( __CLASS__, 'display_notice_for_expired_and_expiring_subscriptions' ), 10, 2 );
		}
	}

	/**
	 * Add the hook for modifying default WPCore update notices on the plugins management page.
	 * This is for plugins without a subscription.
	 */
	public static function setup_message_for_plugins_without_subscription() {
		foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) {
			add_action( 'in_plugin_update_message-' . $plugin['_filename'], array( __CLASS__, 'display_notice_for_plugins_without_subscription' ), 10, 2 );
		}
	}

	/**
	 * Runs in a cron thread, or in a visitor thread if triggered
	 * by _maybe_update_plugins(), or in an auto-update thread.
	 *
	 * @param object $transient The update_plugins transient object.
	 *
	 * @return object The same or a modified version of the transient.
	 */
	public static function transient_update_plugins( $transient ) {
		$update_data = self::get_update_data();

		foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) {
			if ( empty( $update_data[ $plugin['_product_id'] ] ) ) {
				continue;
			}

			$data     = $update_data[ $plugin['_product_id'] ];
			$filename = $plugin['_filename'];

			$item = array(
				'id'             => 'woocommerce-com-' . $plugin['_product_id'],
				'slug'           => 'woocommerce-com-' . $data['slug'],
				'plugin'         => $filename,
				'new_version'    => $data['version'],
				'url'            => $data['url'],
				'package'        => '',
				'upgrade_notice' => $data['upgrade_notice'],
			);

			/**
			 * Filters the Woo plugin data before saving it in transient used for updates.
			 *
			 * @since 8.7.0
			 *
			 * @param array $item Plugin item to modify.
			 * @param array $data Subscription data fetched from Helper API for the plugin.
			 * @param int   $product_id Woo product id assigned to the plugin.
			 */
			$item = apply_filters( 'update_woo_com_subscription_details', $item, $data, $plugin['_product_id'] );

			if ( isset( $data['requires_php'] ) ) {
				$item['requires_php'] = $data['requires_php'];
			}

			if ( $transient instanceof stdClass ) {
				if ( version_compare( $plugin['Version'], $data['version'], '<' ) ) {
					$transient->response[ $filename ] = (object) $item;
					unset( $transient->no_update[ $filename ] );
				} else {
					$transient->no_update[ $filename ] = (object) $item;
					unset( $transient->response[ $filename ] );
				}
			}
		}

		if ( $transient instanceof stdClass ) {
			$translations            = self::get_translations_update_data();
			$transient->translations = array_merge( isset( $transient->translations ) ? $transient->translations : array(), $translations );
		}

		return $transient;
	}

	/**
	 * Runs on pre_set_site_transient_update_themes, provides custom
	 * packages for WooCommerce.com-hosted extensions.
	 *
	 * @param object $transient The update_themes transient object.
	 *
	 * @return object The same or a modified version of the transient.
	 */
	public static function transient_update_themes( $transient ) {
		$update_data = self::get_update_data();

		foreach ( WC_Helper::get_local_woo_themes() as $theme ) {
			if ( empty( $update_data[ $theme['_product_id'] ] ) ) {
				continue;
			}

			$data = $update_data[ $theme['_product_id'] ];
			$slug = $theme['_stylesheet'];

			$item = array(
				'theme'       => $slug,
				'new_version' => $data['version'],
				'url'         => $data['url'],
				'package'     => '',
			);

			/**
			 * Filters the Woo plugin data before saving it in transient used for updates.
			 *
			 * @since 8.7.0
			 *
			 * @param array $item Plugin item to modify.
			 * @param array $data Subscription data fetched from Helper API for the plugin.
			 * @param int   $product_id Woo product id assigned to the plugin.
			 */
			$item = apply_filters( 'update_woo_com_subscription_details', $item, $data, $theme['_product_id'] );

			if ( version_compare( $theme['Version'], $data['version'], '<' ) ) {
				$transient->response[ $slug ] = $item;
			} else {
				unset( $transient->response[ $slug ] );
				$transient->checked[ $slug ] = $data['version'];
			}
		}

		return $transient;
	}

	/**
	 * Runs on load-plugins.php, adds a hook to show a custom plugin update message for WooCommerce.com hosted plugins.
	 *
	 * @return void.
	 */
	public static function setup_update_plugins_messages() {
		$is_site_connected = WC_Helper::is_site_connected();
		foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) {
			$filename = $plugin['_filename'];
			if ( $is_site_connected ) {
				add_action( 'in_plugin_update_message-' . $filename, array( __CLASS__, 'add_install_marketplace_plugin_message' ), 10, 2 );
			} else {
				add_action( 'in_plugin_update_message-' . $filename, array( __CLASS__, 'add_connect_woocom_plugin_message' ) );
			}
		}
	}

	/**
	 * Runs on in_plugin_update_message-{file-name}, show a message to connect to woocommerce.com for unconnected stores
	 *
	 * @return void.
	 */
	public static function add_connect_woocom_plugin_message() {
		$connect_page_url = add_query_arg(
			array(
				'page'         => 'wc-admin',
				'tab'          => 'my-subscriptions',
				'path'         => rawurlencode( '/extensions' ),
				'utm_source'   => 'pu',
				'utm_campaign' => 'pu_plugin_screen_connect',
			),
			admin_url( 'admin.php' )
		);

		printf(
			wp_kses(
			/* translators: 1: Woo Update Manager plugin install URL */
				__( ' <a href="%1$s" class="woocommerce-connect-your-store">Connect your store</a> to woocommerce.com to update.', 'woocommerce' ),
				array(
					'a' => array(
						'href'  => array(),
						'class' => array(),
					),
				)
			),
			esc_url( $connect_page_url ),
		);
	}

	/**
	 * Runs on in_plugin_update_message-{file-name}, show a message to install the Woo Marketplace plugin, on plugin update notification,
	 * if the Woo Marketplace plugin isn't already installed.
	 *
	 * @param object $plugin_data TAn array of plugin metadata.
	 * @param object $response  An object of metadata about the available plugin update.
	 *
	 * @return void.
	 */
	public static function add_install_marketplace_plugin_message( $plugin_data, $response ) {
		if ( ! empty( $response->package ) || WC_Woo_Update_Manager_Plugin::is_plugin_active() ) {
			return;
		}

		if ( ! WC_Woo_Update_Manager_Plugin::is_plugin_installed() ) {
			printf(
				wp_kses(
					/* translators: 1: Woo Update Manager plugin install URL */
					__( ' <a href="%1$s">Install WooCommerce.com Update Manager</a> to update.', 'woocommerce' ),
					array(
						'a' => array(
							'href' => array(),
						),
					)
				),
				esc_url( WC_Woo_Update_Manager_Plugin::generate_install_url() ),
			);
			return;
		}

		if ( ! WC_Woo_Update_Manager_Plugin::is_plugin_active() ) {
			esc_html_e( ' Activate WooCommerce.com Update Manager to update.', 'woocommerce' );
		}
	}

	/**
	 * Runs on in_plugin_update_message-{file-name}, show a message if plugins subscription expired or expiring soon.
	 *
	 * @param object $plugin_data An array of plugin metadata.
	 * @param object $response  An object of metadata about the available plugin update.
	 *
	 * @return void.
	 */
	public static function display_notice_for_expired_and_expiring_subscriptions( $plugin_data, $response ) {
		// Extract product ID from the response.
		$product_id = preg_replace( '/[^0-9]/', '', $response->id );

		$installed_or_unconnected = array_merge(
			WC_Helper::get_installed_subscriptions(),
			WC_Helper::get_unconnected_subscriptions()
		);

		// Product subscriptions.
		$subscriptions = wp_list_filter( $installed_or_unconnected, array( 'product_id' => $product_id ) );
		if ( empty( $subscriptions ) ) {
			return;
		}

		$expired_subscription = current(
			array_filter(
				$subscriptions,
				function ( $subscription ) {
					return ! empty( $subscription['expired'] ) && ! $subscription['lifetime'];
				}
			)
		);

		$expiring_subscription = current(
			array_filter(
				$subscriptions,
				function ( $subscription ) {
					return ! empty( $subscription['expiring'] ) && ! $subscription['autorenew'];
				}
			)
		);

		// Prepare the expiry notice based on subscription status.
		$expiry_notice = '';
		if ( ! empty( $expired_subscription ) ) {

			$renew_link = add_query_arg(
				array(
					'add-to-cart'  => $product_id,
					'utm_source'   => 'pu',
					'utm_campaign' => 'pu_plugin_screen_renew',
				),
				PluginsHelper::WOO_CART_PAGE_URL
			);

			/* translators: 1: Product regular price */
			$product_price = ! empty( $expired_subscription['product_regular_price'] ) ? sprintf( __( 'for %s ', 'woocommerce' ), esc_html( $expired_subscription['product_regular_price'] ) ) : '';

			$expiry_notice = sprintf(
			/* translators: 1: URL to My Subscriptions page 2: Product price */
				__( ' Your subscription expired, <a href="%1$s" class="woocommerce-renew-subscription">renew %2$s</a>to update.', 'woocommerce' ),
				esc_url( $renew_link ),
				$product_price
			);
		} elseif ( ! empty( $expiring_subscription ) ) {
			$renew_link = add_query_arg(
				array(
					'utm_source'   => 'pu',
					'utm_campaign' => 'pu_plugin_screen_enable_autorenew',
				),
				PluginsHelper::WOO_SUBSCRIPTION_PAGE_URL
			);

			$expiry_notice = sprintf(
			/* translators: 1: Expiry date 1: URL to My Subscriptions page */
				__( ' Your subscription expires on %1$s, <a href="%2$s" class="woocommerce-enable-autorenew">enable auto-renew</a> to continue receiving updates.', 'woocommerce' ),
				date_i18n( 'F jS', $expiring_subscription['expires'] ),
				esc_url( $renew_link )
			);
		}

		// Display the expiry notice.
		if ( ! empty( $expiry_notice ) ) {
			echo wp_kses(
				$expiry_notice,
				array(
					'a' => array(
						'href'  => array(),
						'class' => array(),
					),
				)
			);
		}
	}

	/**
	 * Runs on in_plugin_update_message-{file-name}, show a message if plugin is without a subscription.
	 * Only Woo local plugins are passed to this function.
	 *
	 * @see setup_message_for_plugins_without_subscription
	 * @param object $plugin_data An array of plugin metadata.
	 * @param object $response  An object of metadata about the available plugin update.
	 *
	 * @return void.
	 */
	public static function display_notice_for_plugins_without_subscription( $plugin_data, $response ) {
		// Extract product ID from the response.
		$product_id = preg_replace( '/[^0-9]/', '', $response->id );

		if ( WC_Helper::has_product_subscription( $product_id ) ) {
			return;
		}

		// Prepare the expiry notice based on subscription status.
		$purchase_link = add_query_arg(
			array(
				'add-to-cart'  => $product_id,
				'utm_source'   => 'pu',
				'utm_campaign' => 'pu_plugin_screen_purchase',
			),
			PluginsHelper::WOO_CART_PAGE_URL,
		);

		$notice = sprintf(
			/* translators: 1: URL to My Subscriptions page */
			__( ' You don\'t have a subscription, <a href="%1$s" class="woocommerce-purchase-subscription">subscribe</a> to update.', 'woocommerce' ),
			esc_url( $purchase_link ),
		);

		// Display the expiry notice.
		echo wp_kses(
			$notice,
			array(
				'a' => array(
					'href'  => array(),
					'class' => array(),
				),
			)
		);
	}

	/**
	 * Get update data for all plugins.
	 *
	 * @return array Update data {product_id => data}
	 * @see get_update_data
	 */
	public static function get_available_extensions_downloads_data() {
		$payload = array();

		// Scan subscriptions.
		$subscriptions = WC_Helper::get_subscriptions();

		foreach ( $subscriptions as $subscription ) {
			$payload[ $subscription['product_id'] ] = array(
				'product_id' => $subscription['product_id'],
				'file_id'    => '',
			);
		}

		// Scan local plugins which may or may not have a subscription.
		foreach ( WC_Helper::get_local_woo_plugins() as $data ) {
			if ( ! isset( $payload[ $data['_product_id'] ] ) ) {
				$payload[ $data['_product_id'] ] = array(
					'product_id' => $data['_product_id'],
				);
			}

			$payload[ $data['_product_id'] ]['file_id'] = $data['_file_id'];
		}

		return self::_update_check( $payload );
	}

	/**
	 * Get update data for all extensions.
	 *
	 * Scans through all subscriptions for the connected user, as well
	 * as all Woo extensions without a subscription, and obtains update
	 * data for each product.
	 *
	 * @return array Update data {product_id => data}
	 */
	public static function get_update_data() {
		$payload = array();

		// Scan subscriptions.
		$subscriptions = WC_Helper::get_subscriptions();

		foreach ( $subscriptions as $subscription ) {
			$payload[ $subscription['product_id'] ] = array(
				'product_id' => $subscription['product_id'],
				'file_id'    => '',
			);
		}

		// Scan local plugins which may or may not have a subscription.
		foreach ( WC_Helper::get_local_woo_plugins() as $data ) {
			if ( ! isset( $payload[ $data['_product_id'] ] ) ) {
				$payload[ $data['_product_id'] ] = array(
					'product_id' => $data['_product_id'],
				);
			}

			$payload[ $data['_product_id'] ]['file_id'] = $data['_file_id'];
		}

		// Scan local themes.
		foreach ( WC_Helper::get_local_woo_themes() as $data ) {
			if ( ! isset( $payload[ $data['_product_id'] ] ) ) {
				$payload[ $data['_product_id'] ] = array(
					'product_id' => $data['_product_id'],
				);
			}

			$payload[ $data['_product_id'] ]['file_id'] = $data['_file_id'];
		}

		return self::_update_check( $payload );
	}

	/**
	 * Get translations updates information.
	 *
	 * Scans through all subscriptions for the connected user, as well
	 * as all Woo extensions without a subscription, and obtains update
	 * data for each product.
	 *
	 * @return array Update data {product_id => data}
	 */
	public static function get_translations_update_data() {
		$payload = array();

		$installed_translations = wp_get_installed_translations( 'plugins' );

		$locales = array_values( get_available_languages() );
		/**
		 * Filters the locales requested for plugin translations.
		 *
		 * @since 3.7.0
		 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales.
		 *
		 * @param array $locales Plugin locales. Default is all available locales of the site.
		 */
		$locales = apply_filters( 'plugins_update_check_locales', $locales );
		$locales = array_unique( $locales );

		// No locales, the response will be empty, we can return now.
		if ( empty( $locales ) ) {
			return array();
		}

		// Scan local plugins which may or may not have a subscription.
		$plugins            = WC_Helper::get_local_woo_plugins();
		$active_woo_plugins = array_intersect( array_keys( $plugins ), get_option( 'active_plugins', array() ) );

		/*
		* Use only plugins that are subscribed to the automatic translations updates.
		*/
		$active_for_translations = array_filter(
			$active_woo_plugins,
			function ( $plugin ) use ( $plugins ) {
				/**
				 * Filters the plugins that are subscribed to the automatic translations updates.
				 *
				 * @since 3.7.0
				 */
				return apply_filters( 'woocommerce_translations_updates_for_' . $plugins[ $plugin ]['slug'], false );
			}
		);

		// Nothing to check for, exit.
		if ( empty( $active_for_translations ) ) {
			return array();
		}

		if ( wp_doing_cron() ) {
			$timeout = 30;
		} else {
			// Three seconds, plus one extra second for every 10 plugins.
			$timeout = 3 + (int) ( count( $active_for_translations ) / 10 );
		}

		$request_body = array(
			'locales' => $locales,
			'plugins' => array(),
		);

		foreach ( $active_for_translations as $active_plugin ) {
			$plugin                                     = $plugins[ $active_plugin ];
			$request_body['plugins'][ $plugin['slug'] ] = array( 'version' => $plugin['Version'] );
		}

		$raw_response = wp_remote_post(
			'https://translate.wordpress.com/api/translations-updates/woocommerce',
			array(
				'body'    => wp_json_encode( $request_body ),
				'headers' => array( 'Content-Type: application/json' ),
				'timeout' => $timeout,
			)
		);

		// Something wrong happened on the translate server side.
		$response_code = wp_remote_retrieve_response_code( $raw_response );
		if ( 200 !== $response_code ) {
			return array();
		}

		$response = json_decode( wp_remote_retrieve_body( $raw_response ), true );

		// API error, api returned but something was wrong.
		if ( array_key_exists( 'success', $response ) && false === $response['success'] ) {
			return array();
		}

		$translations = array();

		foreach ( $response['data'] as $plugin_name => $language_packs ) {
			foreach ( $language_packs as $language_pack ) {
				// Maybe we have this language pack already installed so lets check revision date.
				if ( array_key_exists( $plugin_name, $installed_translations ) && array_key_exists( $language_pack['wp_locale'], $installed_translations[ $plugin_name ] ) ) {
					$installed_translation_revision_time = new DateTime( $installed_translations[ $plugin_name ][ $language_pack['wp_locale'] ]['PO-Revision-Date'] );
					$new_translation_revision_time       = new DateTime( $language_pack['last_modified'] );
					// Skip if translation language pack is not newer than what is installed already.
					if ( $new_translation_revision_time <= $installed_translation_revision_time ) {
						continue;
					}
				}
				$translations[] = array(
					'type'       => 'plugin',
					'slug'       => $plugin_name,
					'language'   => $language_pack['wp_locale'],
					'version'    => $language_pack['version'],
					'updated'    => $language_pack['last_modified'],
					'package'    => $language_pack['package'],
					'autoupdate' => true,
				);
			}
		}

		return $translations;
	}

	/**
	 * Validates cached update data and checks if it matches the expected hash.
	 *
	 * Ensures the cached data is properly structured and corresponds to the current
	 * payload to prevent fatal errors and avoid stale cache returns.
	 *
	 * @since 10.3.6
	 *
	 * @param mixed  $data The data retrieved from the transient.
	 * @param string $hash The expected hash to compare against.
	 * @return bool True if the data is valid and hash matches, false otherwise.
	 */
	private static function should_use_cached_update_data( $data, $hash ) {
		if ( ! is_array( $data ) ) {
			return false;
		}

		if ( ! isset( $data['hash'], $data['products'] ) ) {
			return false;
		}

		if ( ! is_string( $data['hash'] ) || ! is_array( $data['products'] ) ) {
			return false;
		}

		return hash_equals( $hash, $data['hash'] );
	}

	/**
	 * Run an update check API call.
	 *
	 * The call is cached based on the payload (product ids, file ids). If
	 * the payload changes, the cache is going to miss.
	 *
	 * @param array $payload Information about the plugin to update.
	 * @return array Update data for each requested product.
	 */
	private static function _update_check( $payload ) {
		if ( empty( $payload ) ) {
			return array();
		}
		ksort( $payload );
		$hash = md5( wp_json_encode( $payload ) );

		$cache_key = '_woocommerce_helper_updates';
		$data      = get_transient( $cache_key );

		if ( self::should_use_cached_update_data( $data, $hash ) ) {
			return $data['products'];
		}

		$data = array(
			'hash'     => $hash,
			'updated'  => time(),
			'products' => array(),
			'errors'   => array(),
		);

		// Detect if this is a manual refresh button click.
		$request_uri = wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		$source      = '';
		if ( stripos( $request_uri, 'wc/v3/marketplace/refresh' ) !== false ) {
			$source = 'refresh-button';
		}

		$request_body = array( 'products' => $payload );
		if ( ! empty( $source ) ) {
			$request_body['source'] = $source;
		}

		if ( WC_Helper::is_site_connected() ) {
			$request = WC_Helper_API::post(
				'update-check',
				array(
					'body'          => wp_json_encode( $request_body ),
					'authenticated' => true,
				)
			);
		} else {
			$request = WC_Helper_API::post(
				'update-check-public',
				array(
					'body' => wp_json_encode( $request_body ),
				)
			);
		}

		if ( wp_remote_retrieve_response_code( $request ) !== 200 ) {
			$data['errors'][] = 'http-error';
		} else {
			$data['products'] = json_decode( wp_remote_retrieve_body( $request ), true );
		}

		set_transient( $cache_key, $data, 12 * HOUR_IN_SECONDS );
		return $data['products'];
	}

	/**
	 * Get the number of products that have updates.
	 *
	 * @return int The number of products with updates.
	 */
	public static function get_updates_count() {
		$cache_key = '_woocommerce_helper_updates_count';
		$count     = get_transient( $cache_key );
		if ( false !== $count ) {
			return $count;
		}

		// Don't fetch any new data since this function in high-frequency.
		if ( ! get_transient( '_woocommerce_helper_subscriptions' ) ) {
			return 0;
		}

		if ( ! get_transient( '_woocommerce_helper_updates' ) ) {
			return 0;
		}

		$count       = 0;
		$update_data = self::get_update_data();

		if ( empty( $update_data ) ) {
			set_transient( $cache_key, $count, 12 * HOUR_IN_SECONDS );
			return $count;
		}

		// Scan local plugins.
		foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) {
			if ( empty( $update_data[ $plugin['_product_id'] ] ) ) {
				continue;
			}

			if ( ! is_plugin_active( $plugin['_filename'] ) ) {
				continue;
			}

			if ( version_compare( $plugin['Version'], $update_data[ $plugin['_product_id'] ]['version'], '<' ) ) {
				++$count;
			}
		}

		// Scan local themes.
		foreach ( WC_Helper::get_local_woo_themes() as $theme ) {
			if ( empty( $update_data[ $theme['_product_id'] ] ) ) {
				continue;
			}

			if ( get_stylesheet() !== $theme['_stylesheet'] ) {
				continue;
			}

			if ( version_compare( $theme['Version'], $update_data[ $theme['_product_id'] ]['version'], '<' ) ) {
				++$count;
			}
		}

		set_transient( $cache_key, $count, 12 * HOUR_IN_SECONDS );

		return $count;
	}

	/**
	 * Get the update count to based on the status of the site.
	 *
	 * @return int
	 */
	public static function get_updates_count_based_on_site_status() {
		if ( ! WC_Helper::is_site_connected() ) {
			return 0;
		}

		$count = self::get_updates_count() ?? 0;
		if ( ! WC_Woo_Update_Manager_Plugin::is_plugin_installed() || ! WC_Woo_Update_Manager_Plugin::is_plugin_active() ) {
			++$count;
		}

		return $count;
	}

	/**
	 * Get the type of woo connect notice to be shown in the WC Settings and Marketplace pages.
	 * - If a store is connected to woocommerce.com or has no installed woo plugins, return 'none'.
	 * - If a store has installed woo plugins but no updates, return 'short'.
	 * - If a store has an installed woo plugin with update, return 'long'.
	 *
	 * @return string The notice type, 'none', 'short', or 'long'.
	 */
	public static function get_woo_connect_notice_type() {
		if ( WC_Helper::is_site_connected() ) {
			return 'none';
		}

		$woo_plugins = WC_Helper::get_local_woo_plugins();

		if ( empty( $woo_plugins ) ) {
			return 'none';
		}

		$update_data = self::get_update_data();

		if ( empty( $update_data ) ) {
			return 'short';
		}

		// Scan local plugins.
		foreach ( $woo_plugins as $plugin ) {
			if ( empty( $update_data[ $plugin['_product_id'] ] ) ) {
				continue;
			}

			if ( version_compare( $plugin['Version'], $update_data[ $plugin['_product_id'] ]['version'], '<' ) ) {
				return 'long';
			}
		}

		return 'short';
	}

	/**
	 * Return the updates count markup.
	 *
	 * @return string Updates count markup, empty string if no updates avairable.
	 */
	public static function get_updates_count_html() {
		$count      = self::get_updates_count_based_on_site_status();
		$count_html = sprintf( ' <span class="update-plugins count-%d"><span class="update-count">%d</span></span>', $count, number_format_i18n( $count ) );

		return $count_html;
	}

	/**
	 * Flushes cached update data.
	 */
	public static function flush_updates_cache() {
		delete_transient( '_woocommerce_helper_updates' );
		delete_transient( '_woocommerce_helper_updates_count' );
		delete_site_transient( 'update_plugins' );
		delete_site_transient( 'update_themes' );
	}

	/**
	 * Fires when a user successfully updated a theme or a plugin.
	 */
	public static function upgrader_process_complete() {
		delete_transient( '_woocommerce_helper_updates_count' );
	}

	/**
	 * Hooked into the upgrader_pre_download filter in order to better handle error messaging around expired
	 * plugin updates. Initially we were using an empty string, but the error message that no_package
	 * results in does not fit the cause.
	 *
	 * @since 4.1.0
	 * @param bool   $reply Holds the current filtered response.
	 * @param string $package The path to the package file for the update.
	 * @return false|WP_Error False to proceed with the update as normal, anything else to be returned instead of updating.
	 */
	public static function block_expired_updates( $reply, $package ) {
		// Don't override a reply that was set already.
		if ( false !== $reply ) {
			return $reply;
		}

		// Only for packages with expired subscriptions.
		if ( 0 !== strpos( $package, 'woocommerce-com-expired-' ) ) {
			return false;
		}

		return new WP_Error(
			'woocommerce_subscription_expired',
			sprintf(
				// translators: %s: URL of WooCommerce.com subscriptions tab.
				__( 'Please visit the <a href="%s" target="_blank">subscriptions page</a> and renew to continue receiving updates.', 'woocommerce' ),
				esc_url( admin_url( 'admin.php?page=wc-admin&tab=my-subscriptions&path=%2Fextensions' ) )
			)
		);
	}
}

WC_Helper_Updater::load();
PK     tS\5'    -  helper/class-wc-woo-update-manager-plugin.phpnu [        <?php
/**
 * A utility class for Woo Update Manager plugin.
 *
 * @class WC_Woo_Update_Manager_Plugin
 * @package WooCommerce\Admin\Helper
 */

use Automattic\WooCommerce\Admin\PageController;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper_Plugin Class
 *
 * Contains the logic to manage the Woo Update Manager plugin.
 */
class WC_Woo_Update_Manager_Plugin {
	const WOO_UPDATE_MANAGER_PLUGIN_MAIN_FILE = 'woo-update-manager/woo-update-manager.php';
	const WOO_UPDATE_MANAGER_DOWNLOAD_URL     = 'https://woocommerce.com/product-download/woo-update-manager';
	const WOO_UPDATE_MANAGER_SLUG             = 'woo-update-manager';

	/**
	 * Loads the class, runs on init.
	 *
	 * @return void
	 */
	public static function load(): void {
		add_action( 'admin_notices', array( __CLASS__, 'show_woo_update_manager_install_notice' ) );
	}

	/**
	 * Check if the Woo Update Manager plugin is active.
	 *
	 * @return bool
	 */
	public static function is_plugin_active(): bool {
		return is_plugin_active_for_network( self::WOO_UPDATE_MANAGER_PLUGIN_MAIN_FILE ) || is_plugin_active( self::WOO_UPDATE_MANAGER_PLUGIN_MAIN_FILE );
	}

	/**
	 * Check if the Woo Update Manager plugin is installed.
	 *
	 * @return bool
	 */
	public static function is_plugin_installed(): bool {
		return file_exists( WP_PLUGIN_DIR . '/' . self::WOO_UPDATE_MANAGER_PLUGIN_MAIN_FILE );
	}

	/**
	 * Generate the URL to install the Woo Update Manager plugin.
	 *
	 * @return string
	 */
	public static function generate_install_url(): string {
		$install_url = WC_Helper::get_install_base_url() . self::WOO_UPDATE_MANAGER_SLUG . '/';

		return WC_Helper_API::add_auth_parameters( $install_url );
	}

	/**
	 * Get the id of the Woo Update Manager plugin.
	 *
	 * @return int
	 */
	public static function get_plugin_slug(): string {
		return self::WOO_UPDATE_MANAGER_SLUG;
	}

	/**
	 * Show a notice on the WC admin pages to install or activate the Woo Update Manager plugin.
	 *
	 * @return void
	 */
	public static function show_woo_update_manager_install_notice(): void {
		if ( ! current_user_can( 'install_plugins' ) ) {
			return;
		}

		if ( ! WC_Helper::is_site_connected() ) {
			return;
		}

		if ( ! PageController::is_admin_or_embed_page() ) {
			return;
		}

		if ( self::is_plugin_installed() && self::is_plugin_active() ) {
			return;
		}

		if ( ! self::is_plugin_installed() ) {

			if ( self::install_admin_notice_dismissed() ) {
				return;
			}

			include __DIR__ . '/views/html-notice-woo-updater-not-installed.php';
			return;
		}

		if ( self::activate_admin_notice_dismissed() ) {
			return;
		}

		include __DIR__ . '/views/html-notice-woo-updater-not-activated.php';
	}

	/**
	 * Check if the installation notice has been dismissed.
	 *
	 * @return bool
	 */
	protected static function install_admin_notice_dismissed(): bool {
		return get_user_meta( get_current_user_id(), 'dismissed_woo_updater_not_installed_notice', true );
	}

	/**
	 * Check if the activation notice has been dismissed.
	 *
	 * @return bool
	 */
	protected static function activate_admin_notice_dismissed(): bool {
		return get_user_meta( get_current_user_id(), 'dismissed_woo_updater_not_activated_notice', true );
	}
}

WC_Woo_Update_Manager_Plugin::load();
PK     tS\Բ(    "  helper/class-wc-helper-options.phpnu [        <?php
/**
 * WooCommerce Admin Helper Options
 *
 * @package WooCommerce\Admin\Helper
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper_Options Class
 *
 * An interface to the woocommerce_helper_data entry in the wp_options table.
 */
class WC_Helper_Options {
	/**
	 * The option name used to store the helper data.
	 *
	 * @var string
	 */
	private static $option_name = 'woocommerce_helper_data';

	/**
	 * Update an option by key
	 *
	 * All helper options are grouped in a single options entry. This method
	 * is not thread-safe, use with caution.
	 *
	 * @param string $key The key to update.
	 * @param mixed  $value The new option value.
	 *
	 * @return bool True if the option has been updated.
	 */
	public static function update( $key, $value ) {
		$options         = get_option( self::$option_name, array() );
		$options[ $key ] = $value;
		return update_option( self::$option_name, $options, true );
	}

	/**
	 * Get an option by key
	 *
	 * @see self::update
	 *
	 * @param string $key The key to fetch.
	 * @param mixed  $default The default option to return if the key does not exist.
	 *
	 * @return mixed An option or the default.
	 */
	public static function get( $key, $default = false ) {
		$options = get_option( self::$option_name, array() );
		if ( is_array( $options ) && array_key_exists( $key, $options ) ) {
			return $options[ $key ];
		}

		return $default;
	}
}
PK     tS\{ |    !  helper/class-wc-helper-compat.phpnu [        <?php
/**
 * WooCommerce Admin Helper Compat
 *
 * @package WooCommerce\Admin\Helper
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper_Compat Class
 *
 * Some level of compatibility with the legacy WooCommerce Helper plugin.
 */
class WC_Helper_Compat {

	/**
	 * Loads the class, runs on init.
	 */
	public static function load() {
		add_action( 'woocommerce_helper_loaded', array( __CLASS__, 'helper_loaded' ) );
	}

	/**
	 * Runs during woocommerce_helper_loaded
	 */
	public static function helper_loaded() {
		// Stop the nagging about WooThemes Updater
		remove_action( 'admin_notices', 'woothemes_updater_notice' );

		// A placeholder dashboard menu for legacy helper users.
		add_action( 'admin_menu', array( __CLASS__, 'admin_menu' ) );

		if ( empty( $GLOBALS['woothemes_updater'] ) ) {
			return;
		}

		self::remove_actions();
		self::migrate_connection();
		self::deactivate_plugin();
	}

	/**
	 * Remove legacy helper actions (notices, menus, etc.)
	 */
	public static function remove_actions() {
		// Remove WooThemes Updater notices
		remove_action( 'network_admin_notices', array( $GLOBALS['woothemes_updater']->admin, 'maybe_display_activation_notice' ) );
		remove_action( 'admin_notices', array( $GLOBALS['woothemes_updater']->admin, 'maybe_display_activation_notice' ) );
		remove_action( 'network_admin_menu', array( $GLOBALS['woothemes_updater']->admin, 'register_settings_screen' ) );
		remove_action( 'admin_menu', array( $GLOBALS['woothemes_updater']->admin, 'register_settings_screen' ) );
	}

	/**
	 * Attempt to migrate a legacy connection to a new one.
	 */
	public static function migrate_connection() {
		// Don't attempt to migrate if attempted before.
		if ( WC_Helper_Options::get( 'did-migrate' ) ) {
			return;
		}

		$auth = WC_Helper_Options::get( 'auth' );
		if ( ! empty( $auth ) ) {
			return;
		}

		WC_Helper::log( 'Attempting oauth/migrate' );
		WC_Helper_Options::update( 'did-migrate', true );

		$master_key = get_option( 'woothemes_helper_master_key' );
		if ( empty( $master_key ) ) {
			WC_Helper::log( 'Master key not found, aborting' );
			return;
		}

		$request = WC_Helper_API::post(
			'oauth/migrate',
			array(
				'body' => array(
					'home_url'   => home_url(),
					'master_key' => $master_key,
				),
			)
		);

		if ( is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) !== 200 ) {
			WC_Helper::log( 'Call to oauth/migrate returned a non-200 response code' );
			return;
		}

		$request_token = json_decode( wp_remote_retrieve_body( $request ) );
		if ( empty( $request_token ) ) {
			WC_Helper::log( 'Call to oauth/migrate returned an empty token' );
			return;
		}

		// Obtain an access token.
		$request = WC_Helper_API::post(
			'oauth/access_token',
			array(
				'body' => array(
					'request_token' => $request_token,
					'home_url'      => home_url(),
					'migrate'       => true,
				),
			)
		);

		if ( is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) !== 200 ) {
			WC_Helper::log( 'Call to oauth/access_token returned a non-200 response code' );
			return;
		}

		$access_token = json_decode( wp_remote_retrieve_body( $request ), true );
		if ( empty( $access_token ) ) {
			WC_Helper::log( 'Call to oauth/access_token returned an invalid token' );
			return;
		}

		WC_Helper_Options::update(
			'auth',
			array(
				'access_token'        => $access_token['access_token'],
				'access_token_secret' => $access_token['access_token_secret'],
				'site_id'             => $access_token['site_id'],
				'user_id'             => null, // Set this later
				'updated'             => time(),
			)
		);

		// Obtain the connected user info.
		if ( ! WC_Helper::_flush_authentication_cache() ) {
			WC_Helper::log( 'Could not obtain connected user info in migrate_connection' );
			WC_Helper_Options::update( 'auth', array() );
			return;
		}
	}

	/**
	 * Attempt to deactivate the legacy helper plugin.
	 */
	public static function deactivate_plugin() {
		include_once ABSPATH . 'wp-admin/includes/plugin.php';
		if ( ! function_exists( 'deactivate_plugins' ) ) {
			return;
		}

		if ( is_plugin_active( 'woothemes-updater/woothemes-updater.php' ) ) {
			deactivate_plugins( 'woothemes-updater/woothemes-updater.php' );

			// Notify the user when the plugin is deactivated.
			add_action( 'pre_current_active_plugins', array( __CLASS__, 'plugin_deactivation_notice' ) );
		}
	}

	/**
	 * Display admin notice directing the user where to go.
	 */
	public static function plugin_deactivation_notice() {
		?>
		<div id="message" class="error is-dismissible">
			<p><?php printf( __( 'The WooCommerce Helper plugin is no longer needed. <a href="%s">Manage subscriptions</a> from the extensions tab instead.', 'woocommerce' ), esc_url( admin_url( 'admin.php?page=wc-addons&section=helper' ) ) ); ?></p>
		</div>
		<?php
	}

	/**
	 * Register menu item.
	 */
	public static function admin_menu() {
		// No additional menu items for users who did not have a connected helper before.
		$master_key = get_option( 'woothemes_helper_master_key' );
		if ( empty( $master_key ) ) {
			return;
		}

		// Do not show the menu item if user has already seen the new screen.
		$auth = WC_Helper_Options::get( 'auth' );
		if ( ! empty( $auth['user_id'] ) ) {
			return;
		}

		add_dashboard_page( __( 'WooCommerce Helper', 'woocommerce' ), __( 'WooCommerce Helper', 'woocommerce' ), 'manage_options', 'woothemes-helper', array( __CLASS__, 'render_compat_menu' ) );
	}

	/**
	 * Render the legacy helper compat view.
	 */
	public static function render_compat_menu() {
		$helper_url = add_query_arg(
			array(
				'page'    => 'wc-addons',
				'section' => 'helper',
			),
			admin_url( 'admin.php' )
		);
		include WC_Helper::get_view_filename( 'html-helper-compat.php' );
	}
}

WC_Helper_Compat::load();
PK     tS\<j.  .  &  helper/class-wc-plugin-api-updater.phpnu [        <?php
/**
 * Updates the Product API response from WP.org.
 *
 * @class WC_Plugin_Api_Updater
 * @package WooCommerce\Admin\Helper
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class WC_Plugin_Api_Updater
 */
class WC_Plugin_Api_Updater {

	/**
	 * Loads the class, runs on init.
	 */
	public static function load() {
		add_filter( 'plugins_api', array( __CLASS__, 'plugins_api' ), 20, 3 );
		add_filter( 'themes_api', array( __CLASS__, 'themes_api' ), 20, 3 );
	}

	/**
	 * Plugin information callback for Woo extensions.
	 *
	 * @param object $response The response core needs to display the modal.
	 * @param string $action The requested plugins_api() action.
	 * @param object $args Arguments passed to plugins_api().
	 *
	 * @return object An updated $response.
	 */
	public static function plugins_api( $response, $action, $args ) {
		if ( 'plugin_information' !== $action ) {
			return $response;
		}

		return self::override_products_api_response( $response, $action, $args );
	}

	/**
	 * Theme information callback for Woo themes.
	 *
	 * @param object $response The response core needs to display the modal.
	 * @param string $action The requested themes_api() action.
	 * @param object $args Arguments passed to themes_api().
	 */
	public static function themes_api( $response, $action, $args ) {
		if ( 'theme_information' !== $action ) {
			return $response;
		}

		return self::override_products_api_response( $response, $action, $args );
	}

	/**
	 * Override the products API to fetch data from the Helper API if it's a Woo product.
	 *
	 * @param object $response The response core needs to display the modal.
	 * @param string $action The requested action.
	 * @param object $args Arguments passed to the API.
	 */
	public static function override_products_api_response( $response, $action, $args ) {
		if ( empty( $args->slug ) ) {
			return $response;
		}

		// Only for slugs that start with woocommerce-com-.
		if ( 0 !== strpos( $args->slug, 'woocommerce-com-' ) ) {
			return $response;
		}

		$clean_slug = str_replace( 'woocommerce-com-', '', $args->slug );

		// Look through update data by slug.
		$update_data = WC_Helper_Updater::get_update_data();
		$products    = wp_list_filter( $update_data, array( 'slug' => $clean_slug ) );

		if ( empty( $products ) ) {
			return $response;
		}

		$product_id        = array_keys( $products );
		$product_id        = array_shift( $product_id );
		$is_site_connected = WC_Helper::is_site_connected();
		$endpoint          = add_query_arg(
			array( 'product_id' => absint( $product_id ) ),
			'info'
		);
		// Fetch the product information from the Helper API.
		$request = WC_Helper_API::get(
			$endpoint,
			array( 'authenticated' => $is_site_connected )
		);

		// If we tried to authenticate and failed, try again without authentication.
		if ( is_wp_error( $request ) && $is_site_connected ) {
			$request = WC_Helper_API::get( $endpoint );
		}

		$results = json_decode( wp_remote_retrieve_body( $request ), true );
		if ( ! empty( $results ) ) {
			$response = (object) $results;
		}

		return $response;
	}
}

WC_Plugin_Api_Updater::load();
PK     tS\" 
  
  )  helper/class-wc-woo-helper-connection.phpnu [        <?php
/**
 * A utility class to handle WooCommerce.com connection.
 *
 * @class WC_Woo_Update_Manager_Plugin
 * @package WooCommerce\Admin\Helper
 */

declare( strict_types = 1 );

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper_Plugin Class
 *
 * Contains the logic to manage WooCommerce.com Helper Connection.
 */
class WC_Woo_Helper_Connection {
	/**
	 * Get the notice for the connection URL mismatch.
	 *
	 * @return string The notice for the connection URL mismatch.
	 */
	public static function get_connection_url_notice(): string {
		$connection_data = WC_Helper::get_cached_connection_data();
		if ( false === $connection_data || ! empty( $connection_data['maybe_deleted_connection'] ) || false === ( $connection_data['alert_url_mismatch'] ?? false ) ) {
			return '';
		}

		$auth     = WC_Helper_Options::get( 'auth' );
		$url_raw  = is_array( $auth ) ? ( $auth['url'] ?? '' ) : '';
		$url      = esc_html( rtrim( $url_raw, '/' ) );
		$home_url = esc_html( rtrim( home_url(), '/' ) );
		if ( empty( $url ) || $home_url === $url ) {
			return '';
		}

		return sprintf(
		/* translators: 1: WooCommerce.com connection URL, 2: home URL */
			__( 'Your site is currently connected to WooCommerce.com using <b>%1$s</b>, but your actual site URL is <b>%2$s</b>. To fix this, please reconnect your site to <b>WooCommerce.com</b> to ensure everything works correctly.', 'woocommerce' ),
			$url,
			$home_url
		);
	}

	/**
	 * Get the notice for a deleted connection on WCCOM
	 *
	 * @return string The notice for a deleted connection on WCCOM.
	 *
	 * @since 10.6.0
	 */
	public static function get_deleted_connection_notice(): string {
		$connection_data = WC_Helper::get_cached_connection_data();
		if ( false === $connection_data || empty( $connection_data['maybe_deleted_connection'] ) ) {
			return '';
		}

		$home_url = esc_html( rtrim( home_url(), '/' ) );

		return sprintf(
		/* translators: 1: home URL */
			__( 'There is no connection for <b>%1$s</b> on WooCommerce.com. The connection may have been deleted. To fix this, please reconnect your site to <b>WooCommerce.com</b> to ensure everything works correctly.', 'woocommerce' ),
			$home_url
		);
	}

	/**
	 * Check if the site has and linked host-plan orders.
	 *
	 * @return bool
	 */
	public static function has_host_plan_orders(): bool {
		$subscriptions = WC_Helper::get_subscriptions();
		foreach ( $subscriptions as $subscription ) {
			if ( isset( $subscription['included_in_host_plan'] ) && true === (bool) $subscription['included_in_host_plan'] ) {
				return true;
			}
		}

		return false;
	}
}
PK     tS\S)  )     helper/class-wc-helper-admin.phpnu [        <?php
/**
 * WooCommerce Admin Helper - React admin interface
 *
 * @package WooCommerce\Admin\Helper
 */

use Automattic\WooCommerce\Internal\Admin\Marketplace;
use Automattic\WooCommerce\Admin\PluginsHelper;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper Class
 *
 * The main entry-point for all things related to the Helper.
 * The Helper manages the connection between the store and
 * an account on WooCommerce.com.
 */
class WC_Helper_Admin {
	/**
	 * Clear cache tool identifier.
	 */
	const CACHE_TOOL_ID = 'clear_woocommerce_helper_cache';

	/**
	 * Loads the class, runs on init
	 *
	 * @return void
	 */
	public static function load() {
		if ( is_admin() ) {
			$is_wc_home_or_in_app_marketplace = (
				isset( $_GET['page'] ) && 'wc-admin' === $_GET['page'] //phpcs:ignore WordPress.Security.NonceVerification.Recommended
			);

			if ( $is_wc_home_or_in_app_marketplace ) {
				add_filter( 'woocommerce_admin_shared_settings', array( __CLASS__, 'add_marketplace_settings' ) );
			}

			add_filter( 'woocommerce_debug_tools', array( __CLASS__, 'register_cache_clear_tool' ) );
		}

		add_filter( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );
	}

	/**
	 * Pushes settings onto the WooCommerce Admin global settings object (wcSettings).
	 *
	 * @param mixed $settings The settings object we're amending.
	 *
	 * @return mixed $settings
	 */
	public static function add_marketplace_settings( $settings ) {
		if ( ! WC_Helper::is_site_connected() && isset( $_GET['connect'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			wp_safe_redirect( self::get_connection_url() );
			exit;
		}

		$auth_user_data  = WC_Helper_Options::get( 'auth_user_data', array() );
		$auth_user_email = isset( $auth_user_data['email'] ) ? $auth_user_data['email'] : '';

		// Get the all installed themes and plugins. Knowing this will help us decide to show Add to Store button on product cards.
		$installed_products = array_merge( WC_Helper::get_local_plugins(), WC_Helper::get_local_themes() );
		$installed_products = array_map(
			function ( $product ) {
				return $product['slug'];
			},
			$installed_products
		);

		$blog_name = get_bloginfo( 'name' );

		$settings['wccomHelper'] = array(
			'isConnected'                => WC_Helper::is_site_connected(),
			'connectURL'                 => self::get_connection_url(),
			'reConnectURL'               => self::get_connection_url( true ),
			'userEmail'                  => $auth_user_email,
			'userAvatar'                 => get_avatar_url( $auth_user_email, array( 'size' => '48' ) ),
			'storeCountry'               => wc_get_base_location()['country'],
			'storeName'                  => $blog_name ? $blog_name : '',
			'inAppPurchaseURLParams'     => WC_Admin_Addons::get_in_app_purchase_url_params(),
			'installedProducts'          => $installed_products,
			'mySubscriptionsTabLoaded'   => WC_Helper_Options::get( 'my_subscriptions_tab_loaded' ),
			'wooUpdateManagerInstalled'  => WC_Woo_Update_Manager_Plugin::is_plugin_installed(),
			'wooUpdateManagerActive'     => WC_Woo_Update_Manager_Plugin::is_plugin_active(),
			'wooUpdateManagerInstallUrl' => WC_Woo_Update_Manager_Plugin::generate_install_url(),
			'wooUpdateManagerPluginSlug' => WC_Woo_Update_Manager_Plugin::WOO_UPDATE_MANAGER_SLUG,
			'dismissNoticeNonce'         => wp_create_nonce( 'dismiss_notice' ),
			'trackingAllowed'            => 'yes' === get_option( 'woocommerce_allow_tracking' ),
		);

		// This data is only used in the `Extensions` screen, so only populate it there.
		// More specifically, it's used in `My Subscriptions`, however, switching tabs doesn't require
		// a page reload, so we just check for `path` (/extensions), rather than `tab` (my-subscriptions).
		if ( ! empty( $_GET['path'] ) && '/extensions' === $_GET['path'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$settings['wccomHelper']['wooUpdateCount']          = WC_Helper_Updater::get_updates_count_based_on_site_status();
			$settings['wccomHelper']['connected_notice']        = PluginsHelper::get_wccom_connected_notice( $auth_user_email );
			$settings['wccomHelper']['woocomConnectNoticeType'] = WC_Helper_Updater::get_woo_connect_notice_type();

			if ( WC_Helper::is_site_connected() ) {
				$settings['wccomHelper']['subscription_expired_notice']  = PluginsHelper::get_expired_subscription_notice( false );
				$settings['wccomHelper']['subscription_expiring_notice'] = PluginsHelper::get_expiring_subscription_notice( false );
				$settings['wccomHelper']['subscription_missing_notice']  = PluginsHelper::get_missing_subscription_notice();
				$settings['wccomHelper']['connection_url_notice']        = WC_Woo_Helper_Connection::get_connection_url_notice();
				$settings['wccomHelper']['has_host_plan_orders']         = WC_Woo_Helper_Connection::has_host_plan_orders();
				$settings['wccomHelper']['maybe_deleted_connection']     = WC_Woo_Helper_Connection::get_deleted_connection_notice();
			} else {
				$settings['wccomHelper']['disconnected_notice'] = PluginsHelper::get_wccom_disconnected_notice();
			}
		}

		return $settings;
	}

	/**
	 * Generates the URL for connecting or disconnecting the store to/from WooCommerce.com.
	 * Approach taken from existing helper code that isn't exposed.
	 *
	 * @param bool $reconnect indicate if the site is being reconnected.
	 *
	 * @return string
	 */
	public static function get_connection_url( $reconnect = false ) {
		// Default to wc-addons, although this can be changed from the frontend
		// in the function `connectUrl()` within marketplace functions.tsx.
		$connect_url_args = array(
			'page'    => 'wc-addons',
			'section' => 'helper',
		);

		// No active connection.
		if ( WC_Helper::is_site_connected() && ! $reconnect ) {
			$connect_url_args['wc-helper-disconnect'] = 1;
			$connect_url_args['wc-helper-nonce']      = wp_create_nonce( 'disconnect' );
		} else {
			$connect_url_args['wc-helper-connect'] = 1;
			$connect_url_args['wc-helper-nonce']   = wp_create_nonce( 'connect' );
		}

		if ( ! empty( $_GET['utm_source'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$connect_url_args['utm_source'] = wc_clean( wp_unslash( $_GET['utm_source'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		}

		if ( ! empty( $_GET['utm_campaign'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$connect_url_args['utm_campaign'] = wc_clean( wp_unslash( $_GET['utm_campaign'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		}

		return add_query_arg(
			$connect_url_args,
			admin_url( 'admin.php' )
		);
	}

	/**
	 * Registers the REST routes for the featured products and product
	 * previews endpoints.
	 */
	public static function register_rest_routes() {
		/* Used by the WooCommerce > Extensions > Discover page. */
		register_rest_route(
			'wc/v3',
			'/marketplace/featured',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'get_featured' ),
				'permission_callback' => array( __CLASS__, 'get_permission' ),
			)
		);

		/* Used to show previews of products in a modal in in-app marketplace. */
		register_rest_route(
			'wc/v1',
			'/marketplace/product-preview',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'get_product_preview' ),
				'permission_callback' => array( __CLASS__, 'get_permission' ),
			)
		);
	}

	/**
	 * The Extensions page can only be accessed by users with the manage_woocommerce
	 * capability. So the API mimics that behavior.
	 */
	public static function get_permission() {
		return current_user_can( 'manage_woocommerce' );
	}

	/**
	 * Fetch featured products from WooCommerce.com and serve them
	 * as JSON.
	 */
	public static function get_featured() {
		$featured = WC_Admin_Addons::fetch_featured();

		if ( is_wp_error( $featured ) ) {
			wp_send_json_error( array( 'message' => $featured->get_error_message() ) );
		}

		wp_send_json( $featured );
	}

	/**
	 * Fetch data for product previews from WooCommerce.com.
	 *
	 * @param WP_REST_Request $request Request object.
	 */
	public static function get_product_preview( $request ) {
		$product_id = (int) $request->get_param( 'product_id' );

		if ( ! $product_id ) {
			wp_send_json_error(
				array(
					'message' => __( 'Missing product ID', 'woocommerce' ),
				),
				400
			);
		}

		$product_preview = WC_Admin_Addons::fetch_product_preview( $product_id );

		if ( ! $product_preview ) {
			wp_send_json_error(
				array(
					'message' => __( 'We couldn\'t find a preview for this product.', 'woocommerce' ),
				),
				404
			);
		}

		if ( is_wp_error( $product_preview ) ) {
			wp_send_json_error(
				array(
					'message' => $product_preview->get_error_message(),
				)
			);
		}

		if (
			! isset( $product_preview['css'] )
			|| ! is_string( $product_preview['css'] )
			|| ! isset( $product_preview['html'] )
			|| ! is_string( $product_preview['html'] )
		) {
			wp_send_json_error(
				array(
					'message' => __(
						'API response is missing required elements, or they are in the wrong form.',
						'woocommerce'
					),
				),
				500
			);
		}

		$sanitized_product_preview = array(
			'css'  => WC_Helper_Sanitization::sanitize_css( $product_preview['css'] ),
			'html' => WC_Helper_Sanitization::sanitize_html( $product_preview['html'] ),
		);

		wp_send_json( $sanitized_product_preview );
	}

	/**
	 * Register the cache clearing tool on the WooCommerce > Status > Tools page.
	 *
	 * @param array $debug_tools Available debug tool registrations.
	 * @return array Filtered debug tool registrations.
	 */
	public static function register_cache_clear_tool( $debug_tools ) {
		$debug_tools[ self::CACHE_TOOL_ID ] = array(
			'name'     => __( 'Clear WooCommerce.com cache', 'woocommerce' ),
			'button'   => __( 'Clear', 'woocommerce' ),
			'desc'     => sprintf(
				__( 'This tool will empty the WooCommerce.com data cache, used in WooCommerce Extensions.', 'woocommerce' ),
			),
			'callback' => array( __CLASS__, 'run_clear_cache_tool' ),
		);

		return $debug_tools;
	}


	/**
	 * "Clear" helper cache by invalidating it.
	 */
	public static function run_clear_cache_tool() {
		WC_Helper::_flush_subscriptions_cache();
		WC_Helper::flush_product_usage_notice_rules_cache();
		WC_Helper::flush_connection_data_cache();
		WC_Helper_Updater::flush_updates_cache();

		return __( 'Helper cache cleared.', 'woocommerce' );
	}
}

WC_Helper_Admin::load();
PK     tS\g\'  \'  ,  helper/class-wc-helper-subscriptions-api.phpnu [        <?php
/**
 * WooCommerce Admin Helper - React admin interface
 *
 * @package WooCommerce\Admin\Helper
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Helper_Subscriptions_API
 *
 * The main entry-point for all things related to the Marketplace Subscriptions API.
 * The Subscriptions API manages WooCommerce.com Subscriptions.
 */
class WC_Helper_Subscriptions_API {

	/**
	 * Loads the class, runs on init
	 *
	 * @return void
	 */
	public static function load() {
		add_filter( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );
	}

	/**
	 * Registers the REST routes for the Marketplace Subscriptions API.
	 * These endpoints are used by the Marketplace Subscriptions React UI.
	 */
	public static function register_rest_routes() {
		register_rest_route(
			'wc/v3',
			'/marketplace/refresh',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'refresh' ),
				'permission_callback' => array( __CLASS__, 'get_permission' ),
			)
		);
		register_rest_route(
			'wc/v3',
			'/marketplace/subscriptions',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'get_subscriptions' ),
				'permission_callback' => array( __CLASS__, 'get_permission' ),
			)
		);
		register_rest_route(
			'wc/v3',
			'/marketplace/subscriptions/connect',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'connect' ),
				'permission_callback' => array( __CLASS__, 'get_permission' ),
				'args'                => array(
					'product_key' => array(
						'required' => true,
						'type'     => 'string',
					),
				),
			)
		);
		register_rest_route(
			'wc/v3',
			'/marketplace/subscriptions/activate-plugin',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'activate_plugin' ),
				'permission_callback' => array( __CLASS__, 'get_permission' ),
				'args'                => array(
					'product_key' => array(
						'required' => true,
						'type'     => 'string',
					),
				),
			)
		);
		register_rest_route(
			'wc/v3',
			'/marketplace/subscriptions/disconnect',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'disconnect' ),
				'permission_callback' => array( __CLASS__, 'get_permission' ),
				'args'                => array(
					'product_key' => array(
						'required' => true,
						'type'     => 'string',
					),
				),
			)
		);
		register_rest_route(
			'wc/v3',
			'/marketplace/subscriptions/activate',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'activate' ),
				'permission_callback' => array( __CLASS__, 'get_permission' ),
				'args'                => array(
					'product_key' => array(
						'required' => true,
						'type'     => 'string',
					),
				),
			)
		);

		register_rest_route(
			'wc/v3',
			'/marketplace/subscriptions/install-url',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'install_url' ),
				'permission_callback' => array( __CLASS__, 'get_permission' ),
				'args'                => array(
					'product_key' => array(
						'required' => true,
						'type'     => 'string',
					),
				),
			)
		);
	}

	/**
	 * The Extensions page can only be accessed by users with the manage_woocommerce
	 * capability. So the API mimics that behavior.
	 */
	public static function get_permission() {
		return current_user_can( 'manage_woocommerce' );
	}

	/**
	 * Fetch subscriptions from WooCommerce.com and serve them
	 * as JSON.
	 */
	public static function get_subscriptions() {
		// If the site is connected, mark the time when the my subscriptions tab is first loaded.
		if ( WC_Helper::is_site_connected() === true && empty( WC_Helper_Options::get( 'my_subscriptions_tab_loaded' ) ) ) {
			WC_Helper_Options::update( 'my_subscriptions_tab_loaded', date( 'Y-m-d H:i:s' ) );
		}

		$subscriptions = WC_Helper::get_subscription_list_data();
		wp_send_json(
			array_values(
				$subscriptions
			)
		);
	}

	/**
	 * Refresh account and subscriptions from WooCommerce.com and serve subscriptions
	 * as JSON.
	 */
	public static function refresh() {
		try {
			WC_Helper::refresh_helper_subscriptions();
			WC_Helper::get_subscriptions();
			WC_Helper::get_product_usage_notice_rules();
			WC_Helper::fetch_helper_connection_info();
			self::get_subscriptions();
		} catch ( Exception $e ) {
			wp_send_json_error(
				array(
					'message' => $e->getMessage(),
				),
				400
			);
		}
	}

	/**
	 * Connect a WooCommerce.com subscription.
	 *
	 * @param WP_REST_Request $request Request object.
	 */
	public static function connect( $request ) {
		$product_key = $request->get_param( 'product_key' );
		try {
			$success = WC_Helper::activate_helper_subscription( $product_key );
		} catch ( Exception $e ) {
			$error_data = array(
				'message' => $e->getMessage(),
			);

			if ( $e instanceof WC_Data_Exception ) {
				$error_data['code'] = $e->getErrorCode();
				// Include extra data from the exception so the client can render contextual UI (e.g. maxed out sites list).
				$error_data['data'] = $e->getErrorData();
				$status_code        = (int) $e->getCode();
				if ( 100 > $status_code || 599 < $status_code ) {
					$status_code = 400;
				}
			} else {
				$status_code = 400;
			}

			wp_send_json_error( $error_data, $status_code );
		}
		if ( $success ) {
			wp_send_json_success(
				array(
					'message' => __( 'Your subscription has been connected.', 'woocommerce' ),
				)
			);
		} else {
			wp_send_json_error(
				array(
					'message' => __( 'There was an error connecting your subscription. Please try again.', 'woocommerce' ),
				),
				400
			);
		}
	}

	/**
	 * Activate a plugin for a WooCommerce.com subscription.
	 *
	 * @param WP_REST_Request $request Request object.
	 */
	public static function activate_plugin( $request ) {
		$product_key = $request->get_param( 'product_key' );
		try {
			$success = WC_Helper::activate_plugin( $product_key );
		} catch ( Exception $e ) {
			wp_send_json_error(
				array(
					'message' => $e->getMessage(),
				),
				400
			);
		}
		if ( $success ) {
			wp_send_json_success(
				array(
					'message' => __( 'The plugin for your subscription has been activated.', 'woocommerce' ),
				)
			);
		} else {
			wp_send_json_error(
				array(
					'message' => __( 'The plugin for your subscription couldn\'t be activated.', 'woocommerce' ),
				),
				400
			);
		}
	}

	/**
	 * Disconnect a WooCommerce.com subscription.
	 *
	 * @param WP_REST_Request $request Request object.
	 */
	public static function disconnect( $request ) {
		$product_key = $request->get_param( 'product_key' );
		try {
			$success = WC_Helper::deactivate_helper_subscription( $product_key );
		} catch ( Exception $e ) {
			wp_send_json_error(
				array(
					'message' => $e->getMessage(),
				),
				400
			);
		}
		if ( $success ) {
			wp_send_json_success(
				array(
					'message' => __( 'Your subscription has been disconnected.', 'woocommerce' ),
				)
			);
		} else {
			wp_send_json_error(
				array(
					'message' => __( 'There was an error disconnecting your subscription. Please try again.', 'woocommerce' ),
				),
				400
			);
		}
	}

	/**
	 * Activate a WooCommerce.com product.
	 * This activates the plugin/theme on the site.
	 *
	 * @param WP_REST_Request $request Request object.
	 */
	public static function activate( $request ) {
		$product_key  = $request->get_param( 'product_key' );
		$subscription = WC_Helper::get_subscription( $product_key );

		if ( ! $subscription ) {
			wp_send_json_error(
				array(
					'message' => __( 'We couldn\'t find a subscription for this product.', 'woocommerce' ),
				),
				400
			);
		}

		if ( true !== $subscription['local']['installed'] || ! isset( $subscription['local']['active'] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'This product is not installed.', 'woocommerce' ),
				),
				400
			);
		}

		if ( true === $subscription['local']['active'] ) {
			wp_send_json_success(
				array(
					'message' => __( 'This product is already active.', 'woocommerce' ),
				),
			);
		}

		if ( 'plugin' === $subscription['product_type'] ) {
			$success = activate_plugin( $subscription['local']['path'] );
			if ( is_wp_error( $success ) ) {
				wp_send_json_error(
					array(
						'message' => __( 'There was an error activating this plugin.', 'woocommerce' ),
					),
					400
				);
			}
		} elseif ( 'theme' === $subscription['product_type'] ) {
			switch_theme( $subscription['local']['slug'] );
			$theme = wp_get_theme();
			if ( $subscription['local']['slug'] !== $theme->get_stylesheet() ) {
				wp_send_json_error(
					array(
						'message' => __( 'There was an error activating this theme.', 'woocommerce' ),
					),
					400
				);
			}
		}

		wp_send_json_success(
			array(
				'message' => __( 'This product has been activated.', 'woocommerce' ),
			),
		);
	}

	/**
	 * Get the install URL for a WooCommerce.com product.
	 *
	 * @param WP_REST_Request $request Request object.
	 */
	public static function install_url( $request ) {
		$product_key  = $request->get_param( 'product_key' );
		$subscription = WC_Helper::get_subscription( $product_key );

		if ( ! $subscription ) {
			wp_send_json_error(
				array(
					'message' => __( 'We couldn\'t find a subscription for this product.', 'woocommerce' ),
				),
				400
			);
		}

		if ( true === $subscription['local']['installed'] ) {
			wp_send_json_success(
				array(
					'message' => __( 'This product is already installed.', 'woocommerce' ),
				),
			);
		}

		$install_url = WC_Helper::get_subscription_install_url(
			$subscription['product_key'],
			$subscription['product_slug']
		);

		if ( ! $install_url ) {
			wp_send_json_error(
				array(
					'message' => __( 'There was an error getting the install URL for this product.', 'woocommerce' ),
				),
				400
			);
		}

		wp_send_json_success(
			array(
				'url' => $install_url,
			),
		);
	}
}

WC_Helper_Subscriptions_API::load();
PK     tS\_`      class-wc-admin-post-types.phpnu [        <?php
/**
 * Post Types Admin
 *
 * @package  WooCommerce\Admin
 * @version  3.3.0
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Enums\ProductStockStatus;
use Automattic\WooCommerce\Enums\ProductType;
use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;
use Automattic\WooCommerce\Utilities\NumberUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Admin_Post_Types', false ) ) {
	new WC_Admin_Post_Types();
	return;
}

/**
 * WC_Admin_Post_Types Class.
 *
 * Handles the edit posts views and some functionality on the edit post screen for WC post types.
 */
class WC_Admin_Post_Types {

	/**
	 * Constructor.
	 */
	public function __construct() {
		include_once __DIR__ . '/class-wc-admin-meta-boxes.php';

		if ( ! function_exists( 'duplicate_post_plugin_activation' ) ) {
			include_once __DIR__ . '/class-wc-admin-duplicate-product.php';
		}

		// Load correct list table classes for current screen.
		add_action( 'current_screen', array( $this, 'setup_screen' ) );
		add_action( 'check_ajax_referer', array( $this, 'setup_screen' ) );

		// Admin notices.
		add_filter( 'post_updated_messages', array( $this, 'post_updated_messages' ) );
		add_filter( 'woocommerce_order_updated_messages', array( $this, 'order_updated_messages' ) );
		add_filter( 'bulk_post_updated_messages', array( $this, 'bulk_post_updated_messages' ), 10, 2 );
		add_action(
			'admin_notices',
			function () {
				$this->maybe_display_warning_for_password_protected_coupon();
			}
		);

		// Disable Auto Save.
		add_action( 'admin_print_scripts', array( $this, 'disable_autosave' ) );

		// Extra post data and screen elements.
		add_action( 'edit_form_top', array( $this, 'edit_form_top' ) );
		add_filter( 'enter_title_here', array( $this, 'enter_title_here' ), 1, 2 );
		add_action( 'edit_form_after_title', array( $this, 'edit_form_after_title' ) );
		add_filter( 'default_hidden_meta_boxes', array( $this, 'hidden_meta_boxes' ), 10, 2 );
		add_action( 'post_submitbox_misc_actions', array( $this, 'product_data_visibility' ) );

		include_once __DIR__ . '/class-wc-admin-upload-downloadable-product.php';

		// Hide template for CPT archive.
		add_filter( 'theme_page_templates', array( $this, 'hide_cpt_archive_templates' ), 10, 3 );
		add_action( 'edit_form_top', array( $this, 'show_cpt_archive_notice' ) );

		// Add a post display state for special WC pages.
		add_filter( 'display_post_states', array( $this, 'add_display_post_states' ), 10, 2 );

		// Bulk / quick edit.
		add_action( 'bulk_edit_custom_box', array( $this, 'bulk_edit' ), 10, 2 );
		add_action( 'quick_edit_custom_box', array( $this, 'quick_edit' ), 10, 2 );
		add_action( 'save_post', array( $this, 'bulk_and_quick_edit_hook' ), 10, 2 );
		add_action( 'woocommerce_product_bulk_and_quick_edit', array( $this, 'bulk_and_quick_edit_save_post' ), 10, 2 );
	}

	/**
	 * Looks at the current screen and loads the correct list table handler.
	 *
	 * @since 3.3.0
	 */
	public function setup_screen() {
		global $wc_list_table;

		$request_data = $this->request_data();

		$screen_id = false;

		if ( function_exists( 'get_current_screen' ) ) {
			$screen    = get_current_screen();
			$screen_id = isset( $screen, $screen->id ) ? $screen->id : '';
		}

		if ( ! empty( $request_data['screen'] ) ) {
			$screen_id = wc_clean( wp_unslash( $request_data['screen'] ) );
		}

		switch ( $screen_id ) {
			case 'edit-shop_order':
				include_once __DIR__ . '/list-tables/class-wc-admin-list-table-orders.php';
				$wc_list_table = new WC_Admin_List_Table_Orders();
				break;
			case 'edit-shop_coupon':
				include_once __DIR__ . '/list-tables/class-wc-admin-list-table-coupons.php';
				$wc_list_table = new WC_Admin_List_Table_Coupons();
				break;
			case 'edit-product':
				include_once __DIR__ . '/list-tables/class-wc-admin-list-table-products.php';
				$wc_list_table = new WC_Admin_List_Table_Products();
				break;
		}

		// Ensure the table handler is only loaded once. Prevents multiple loads if a plugin calls check_ajax_referer many times.
		remove_action( 'current_screen', array( $this, 'setup_screen' ) );
		remove_action( 'check_ajax_referer', array( $this, 'setup_screen' ) );
	}

	/**
	 * Change messages when a post type is updated.
	 *
	 * @param  array $messages Array of messages.
	 * @return array
	 */
	public function post_updated_messages( $messages ) {
		global $post;

		$messages['product'] = array(
			0  => '', // Unused. Messages start at index 1.
			/* translators: %1$s: Product link opening tag. %2$s: Product link closing tag.*/
			1  => sprintf( __( 'Product updated. %1$sView Product%2$s', 'woocommerce' ), '<a id="woocommerce-product-updated-message-view-product__link" href="' . esc_url( get_permalink( $post->ID ) ) . '">', '</a>' ),
			2  => __( 'Custom field updated.', 'woocommerce' ),
			3  => __( 'Custom field deleted.', 'woocommerce' ),
			4  => __( 'Product updated.', 'woocommerce' ),
			5  => __( 'Revision restored.', 'woocommerce' ),
			/* translators: %1$s: Product link opening tag. %2$s: Product link closing tag.*/
			6  => sprintf( __( 'Product published. %1$sView Product%2$s', 'woocommerce' ), '<a id="woocommerce-product-updated-message-view-product__link" href="' . esc_url( get_permalink( $post->ID ) ) . '">', '</a>' ),
			7  => __( 'Product saved.', 'woocommerce' ),
			/* translators: %s: product url */
			8  => sprintf( __( 'Product submitted. <a target="_blank" href="%s">Preview product</a>', 'woocommerce' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
			9  => sprintf(
				/* translators: 1: date 2: product url */
				__( 'Product scheduled for: %1$s. <a target="_blank" href="%2$s">Preview product</a>', 'woocommerce' ),
				'<strong>' . date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $post->post_date ) ) . '</strong>',
				esc_url( get_permalink( $post->ID ) )
			),
			/* translators: %s: product url */
			10 => sprintf( __( 'Product draft updated. <a target="_blank" href="%s">Preview product</a>', 'woocommerce' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
		);

		$messages = $this->order_updated_messages( $messages );

		$messages['shop_coupon'] = array(
			0  => '', // Unused. Messages start at index 1.
			1  => __( 'Coupon updated.', 'woocommerce' ),
			2  => __( 'Custom field updated.', 'woocommerce' ),
			3  => __( 'Custom field deleted.', 'woocommerce' ),
			4  => __( 'Coupon updated.', 'woocommerce' ),
			5  => __( 'Revision restored.', 'woocommerce' ),
			6  => __( 'Coupon updated.', 'woocommerce' ),
			7  => __( 'Coupon saved.', 'woocommerce' ),
			8  => __( 'Coupon submitted.', 'woocommerce' ),
			9  => sprintf(
				/* translators: %s: date */
				__( 'Coupon scheduled for: %s.', 'woocommerce' ),
				'<strong>' . date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $post->post_date ) ) . '</strong>'
			),
			10 => __( 'Coupon draft updated.', 'woocommerce' ),
		);

		return $messages;
	}

	/**
	 * Add messages when an order is updated.
	 *
	 * @param array $messages Array of messages.
	 *
	 * @return array
	 */
	public function order_updated_messages( array $messages ) {
		global $post, $theorder;

		if ( ! isset( $theorder ) || ! $theorder instanceof WC_Abstract_Order ) {
			if ( ! isset( $post ) || 'shop_order' !== $post->post_type ) {
				return $messages;
			} else {
				\Automattic\WooCommerce\Utilities\OrderUtil::init_theorder_object( $post );
			}
		}

		$messages['shop_order'] = array(
			0  => '', // Unused. Messages start at index 1.
			1  => __( 'Order updated.', 'woocommerce' ),
			2  => __( 'Custom field updated.', 'woocommerce' ),
			3  => __( 'Custom field deleted.', 'woocommerce' ),
			4  => __( 'Order updated.', 'woocommerce' ),
			5  => __( 'Revision restored.', 'woocommerce' ),
			6  => __( 'Order updated.', 'woocommerce' ),
			7  => __( 'Order saved.', 'woocommerce' ),
			8  => __( 'Order submitted.', 'woocommerce' ),
			9  => sprintf(
			/* translators: %s: date */
				__( 'Order scheduled for: %s.', 'woocommerce' ),
				'<strong>' . date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $theorder->get_date_created() ?? $post->post_date ) ) . '</strong>'
			),
			10 => __( 'Order draft updated.', 'woocommerce' ),
			11 => __( 'Order updated and sent.', 'woocommerce' ),
		);

		return $messages;
	}

	/**
	 * Specify custom bulk actions messages for different post types.
	 *
	 * @param  array $bulk_messages Array of messages.
	 * @param  array $bulk_counts Array of how many objects were updated.
	 * @return array
	 */
	public function bulk_post_updated_messages( $bulk_messages, $bulk_counts ) {
		$bulk_messages['product'] = array(
			/* translators: %s: product count */
			'updated'   => _n( '%s product updated.', '%s products updated.', $bulk_counts['updated'], 'woocommerce' ),
			/* translators: %s: product count */
			'locked'    => _n( '%s product not updated, somebody is editing it.', '%s products not updated, somebody is editing them.', $bulk_counts['locked'], 'woocommerce' ),
			/* translators: %s: product count */
			'deleted'   => _n( '%s product permanently deleted.', '%s products permanently deleted.', $bulk_counts['deleted'], 'woocommerce' ),
			/* translators: %s: product count */
			'trashed'   => _n( '%s product moved to the Trash.', '%s products moved to the Trash.', $bulk_counts['trashed'], 'woocommerce' ),
			/* translators: %s: product count */
			'untrashed' => _n( '%s product restored from the Trash.', '%s products restored from the Trash.', $bulk_counts['untrashed'], 'woocommerce' ),
		);

		$bulk_messages['shop_order'] = array(
			/* translators: %s: order count */
			'updated'   => _n( '%s order updated.', '%s orders updated.', $bulk_counts['updated'], 'woocommerce' ),
			/* translators: %s: order count */
			'locked'    => _n( '%s order not updated, somebody is editing it.', '%s orders not updated, somebody is editing them.', $bulk_counts['locked'], 'woocommerce' ),
			/* translators: %s: order count */
			'deleted'   => _n( '%s order permanently deleted.', '%s orders permanently deleted.', $bulk_counts['deleted'], 'woocommerce' ),
			/* translators: %s: order count */
			'trashed'   => _n( '%s order moved to the Trash.', '%s orders moved to the Trash.', $bulk_counts['trashed'], 'woocommerce' ),
			/* translators: %s: order count */
			'untrashed' => _n( '%s order restored from the Trash.', '%s orders restored from the Trash.', $bulk_counts['untrashed'], 'woocommerce' ),
		);

		$bulk_messages['shop_coupon'] = array(
			/* translators: %s: coupon count */
			'updated'   => _n( '%s coupon updated.', '%s coupons updated.', $bulk_counts['updated'], 'woocommerce' ),
			/* translators: %s: coupon count */
			'locked'    => _n( '%s coupon not updated, somebody is editing it.', '%s coupons not updated, somebody is editing them.', $bulk_counts['locked'], 'woocommerce' ),
			/* translators: %s: coupon count */
			'deleted'   => _n( '%s coupon permanently deleted.', '%s coupons permanently deleted.', $bulk_counts['deleted'], 'woocommerce' ),
			/* translators: %s: coupon count */
			'trashed'   => _n( '%s coupon moved to the Trash.', '%s coupons moved to the Trash.', $bulk_counts['trashed'], 'woocommerce' ),
			/* translators: %s: coupon count */
			'untrashed' => _n( '%s coupon restored from the Trash.', '%s coupons restored from the Trash.', $bulk_counts['untrashed'], 'woocommerce' ),
		);

		return $bulk_messages;
	}

	/**
	 * Shows a warning when editing a password-protected coupon.
	 *
	 * @since 9.2.0
	 */
	private function maybe_display_warning_for_password_protected_coupon() {
		if ( ! function_exists( 'get_current_screen' ) || 'shop_coupon' !== get_current_screen()->id ) {
			return;
		}

		if ( ! isset( $GLOBALS['post'] ) || 'shop_coupon' !== $GLOBALS['post']->post_type ) {
			return;
		}

		wp_admin_notice(
			__(
				'This coupon is password protected. WooCommerce does not support password protection for coupons. You can temporarily hide a coupon by making it private. Alternatively, usage limits and restrictions can be configured below.',
				'woocommerce'
			),
			array(
				'type'               => 'warning',
				'id'                 => 'wc-password-protected-coupon-warning',
				'additional_classes' => empty( $GLOBALS['post']->post_password ) ? array( 'hidden' ) : array(),
			)
		);
	}

	/**
	 * Custom bulk edit - form.
	 *
	 * @param string $column_name Column being shown.
	 * @param string $post_type Post type being shown.
	 */
	public function bulk_edit( $column_name, $post_type ) {
		if ( 'price' !== $column_name || 'product' !== $post_type ) {
			return;
		}

		$shipping_class = get_terms(
			'product_shipping_class',
			array(
				'hide_empty' => false,
			)
		);

		include WC()->plugin_path() . '/includes/admin/views/html-bulk-edit-product.php';
	}

	/**
	 * Custom quick edit - form.
	 *
	 * @param string $column_name Column being shown.
	 * @param string $post_type Post type being shown.
	 */
	public function quick_edit( $column_name, $post_type ) {
		if ( 'price' !== $column_name || 'product' !== $post_type ) {
			return;
		}

		$shipping_class = get_terms(
			'product_shipping_class',
			array(
				'hide_empty' => false,
			)
		);

		include WC()->plugin_path() . '/includes/admin/views/html-quick-edit-product.php';
	}

	/**
	 * Offers a way to hook into save post without causing an infinite loop
	 * when quick/bulk saving product info.
	 *
	 * @since 3.0.0
	 * @param int    $post_id Post ID being saved.
	 * @param object $post Post object being saved.
	 */
	public function bulk_and_quick_edit_hook( $post_id, $post ) {
		remove_action( 'save_post', array( $this, 'bulk_and_quick_edit_hook' ) );
		do_action( 'woocommerce_product_bulk_and_quick_edit', $post_id, $post );
		add_action( 'save_post', array( $this, 'bulk_and_quick_edit_hook' ), 10, 2 );
	}

	/**
	 * Quick and bulk edit saving.
	 *
	 * @param int    $post_id Post ID being saved.
	 * @param object $post Post object being saved.
	 * @return int
	 */
	public function bulk_and_quick_edit_save_post( $post_id, $post ) {
		$request_data = $this->request_data();

		// If this is an autosave, our form has not been submitted, so we don't want to do anything.
		if ( Constants::is_true( 'DOING_AUTOSAVE' ) ) {
			return $post_id;
		}

		// Don't save revisions and autosaves.
		if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) || 'product' !== $post->post_type || ! current_user_can( 'edit_post', $post_id ) ) {
			return $post_id;
		}

		// Check nonce.
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
		if ( ! isset( $request_data['woocommerce_quick_edit_nonce'] ) || ! wp_verify_nonce( $request_data['woocommerce_quick_edit_nonce'], 'woocommerce_quick_edit_nonce' ) ) {
			return $post_id;
		}

		// Get the product and save.
		$product = wc_get_product( $post );

		if ( ! empty( $request_data['woocommerce_quick_edit'] ) ) { // WPCS: input var ok.
			$this->quick_edit_save( $post_id, $product );
		} else {
			$this->bulk_edit_save( $post_id, $product );
		}

		return $post_id;
	}

	/**
	 * Quick edit.
	 *
	 * @param int        $post_id Post ID being saved.
	 * @param WC_Product $product Product object.
	 */
	private function quick_edit_save( $post_id, $product ) {
		$request_data = $this->request_data();

		$data_store        = $product->get_data_store();
		$old_regular_price = $product->get_regular_price();
		$old_sale_price    = $product->get_sale_price();
		$input_to_props    = array(
			'_weight'     => 'weight',
			'_length'     => 'length',
			'_width'      => 'width',
			'_height'     => 'height',
			'_visibility' => 'catalog_visibility',
			'_tax_class'  => 'tax_class',
			'_tax_status' => 'tax_status',
		);

		foreach ( $input_to_props as $input_var => $prop ) {
			if ( isset( $request_data[ $input_var ] ) ) {
				$product->{"set_{$prop}"}( wc_clean( wp_unslash( $request_data[ $input_var ] ) ) );
			}
		}

		if ( isset( $request_data['_sku'] ) ) {
			$sku = $product->get_sku();
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
			$new_sku = (string) wc_clean( $request_data['_sku'] );

			if ( $new_sku !== $sku ) {
				if ( ! empty( $new_sku ) ) {
					$unique_sku = wc_product_has_unique_sku( $post_id, $new_sku );
					if ( $unique_sku ) {
						$product->set_sku( wc_clean( wp_unslash( $new_sku ) ) );
					}
				} else {
					$product->set_sku( '' );
				}
			}
		}

		if ( ! empty( $request_data['_shipping_class'] ) ) {
			if ( '_no_shipping_class' === $request_data['_shipping_class'] ) {
				$product->set_shipping_class_id( 0 );
			} else {
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
				$shipping_class_id = $data_store->get_shipping_class_id_by_slug( wc_clean( $request_data['_shipping_class'] ) );
				$product->set_shipping_class_id( $shipping_class_id );
			}
		}

		if ( ! empty( $request_data['_tax_class'] ) ) {
			$tax_class = sanitize_title( wp_unslash( $request_data['_tax_class'] ) );
			if ( 'standard' === $tax_class ) {
				$tax_class = '';
			}
			$product->set_tax_class( $tax_class );
		}

		$product->set_featured( isset( $request_data['_featured'] ) );

		if ( $product->is_type( ProductType::SIMPLE ) || $product->is_type( ProductType::EXTERNAL ) ) {

			if ( isset( $request_data['_regular_price'] ) ) {
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
				$new_regular_price = ( '' === $request_data['_regular_price'] ) ? '' : wc_format_decimal( $request_data['_regular_price'] );
				$product->set_regular_price( $new_regular_price );
			} else {
				$new_regular_price = null;
			}

			if ( isset( $request_data['_sale_price'] ) ) {
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
				$new_sale_price = ( '' === $request_data['_sale_price'] ) ? '' : wc_format_decimal( $request_data['_sale_price'] );
				$product->set_sale_price( $new_sale_price );
			} else {
				$new_sale_price = null;
			}

			// Handle price - remove dates and set to lowest.
			$price_changed = false;

			if ( ! is_null( $new_regular_price ) && $new_regular_price !== $old_regular_price ) {
				$price_changed = true;
			} elseif ( ! is_null( $new_sale_price ) && $new_sale_price !== $old_sale_price ) {
				$price_changed = true;
			}

			if ( $price_changed ) {
				$product->set_date_on_sale_to( '' );
				$product->set_date_on_sale_from( '' );
			}
		}

		if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() && isset( $request_data['_cogs_value'] ) ) {
			$cogs_value = $request_data['_cogs_value'];
			$cogs_value = '' === $cogs_value ? null : (float) wc_format_decimal( $cogs_value );
			$product->set_cogs_value( $cogs_value );
		}

		// Handle Stock Data.
		// phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		$manage_stock = ! empty( $request_data['_manage_stock'] ) && ProductType::GROUPED !== $product->get_type() ? 'yes' : 'no';
		$backorders   = ! empty( $request_data['_backorders'] ) ? wc_clean( $request_data['_backorders'] ) : 'no';
		if ( ! empty( $request_data['_stock_status'] ) ) {
			$stock_status = wc_clean( $request_data['_stock_status'] );
		} else {
			$stock_status = $product->is_type( ProductType::VARIABLE ) ? null : ProductStockStatus::IN_STOCK;
		}
		// phpcs:enable WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

		$product->set_manage_stock( $manage_stock );

		if ( ProductType::EXTERNAL !== $product->get_type() ) {
			$product->set_backorders( $backorders );
		}

		if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
			$stock_amount = 'yes' === $manage_stock && isset( $request_data['_stock'] ) && is_numeric( wp_unslash( $request_data['_stock'] ) ) ? wc_stock_amount( wp_unslash( $request_data['_stock'] ) ) : '';
			$product->set_stock_quantity( $stock_amount );
		}

		$product = $this->maybe_update_stock_status( $product, $stock_status );

		$product->save();

		do_action( 'woocommerce_product_quick_edit_save', $product );
	}

	/**
	 * Bulk edit.
	 *
	 * @param int        $post_id Post ID being saved.
	 * @param WC_Product $product Product object.
	 */
	public function bulk_edit_save( $post_id, $product ) {
		// phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash

		$request_data = $this->request_data();

		$data_store = $product->get_data_store();

		if ( ! empty( $request_data['change_weight'] ) && isset( $request_data['_weight'] ) ) {
			$product->set_weight( wc_clean( wp_unslash( $request_data['_weight'] ) ) );
		}

		if ( ! empty( $request_data['change_dimensions'] ) ) {
			if ( isset( $request_data['_length'] ) ) {
				$product->set_length( wc_clean( wp_unslash( $request_data['_length'] ) ) );
			}
			if ( isset( $request_data['_width'] ) ) {
				$product->set_width( wc_clean( wp_unslash( $request_data['_width'] ) ) );
			}
			if ( isset( $request_data['_height'] ) ) {
				$product->set_height( wc_clean( wp_unslash( $request_data['_height'] ) ) );
			}
		}

		if ( ! empty( $request_data['_tax_status'] ) ) {
			$product->set_tax_status( wc_clean( $request_data['_tax_status'] ) );
		}

		if ( ! empty( $request_data['_tax_class'] ) ) {
			$tax_class = sanitize_title( wp_unslash( $request_data['_tax_class'] ) );
			if ( 'standard' === $tax_class ) {
				$tax_class = '';
			}
			$product->set_tax_class( $tax_class );
		}

		if ( ! empty( $request_data['_shipping_class'] ) ) {
			if ( '_no_shipping_class' === $request_data['_shipping_class'] ) {
				$product->set_shipping_class_id( 0 );
			} else {
				$shipping_class_id = $data_store->get_shipping_class_id_by_slug( wc_clean( $request_data['_shipping_class'] ) );
				$product->set_shipping_class_id( $shipping_class_id );
			}
		}

		if ( ! empty( $request_data['_visibility'] ) ) {
			$product->set_catalog_visibility( wc_clean( $request_data['_visibility'] ) );
		}

		if ( ! empty( $request_data['_featured'] ) ) {
			// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			$product->set_featured( wp_unslash( $request_data['_featured'] ) );
			// phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		}

		if ( ! empty( $request_data['_sold_individually'] ) ) {
			if ( 'yes' === $request_data['_sold_individually'] ) {
				$product->set_sold_individually( 'yes' );
			} else {
				$product->set_sold_individually( '' );
			}
		}

		/**
		 * Handle price - remove dates and set to lowest.
		 *
		 * @param array $product_types Array of product types that can change price.
		 *
		 * @since 3.0.0
		 */
		$change_price_product_types    = apply_filters( 'woocommerce_bulk_edit_save_price_product_types', array( ProductType::SIMPLE, ProductType::EXTERNAL ) );
		$can_product_type_change_price = false;
		foreach ( $change_price_product_types as $product_type ) {
			if ( $product->is_type( $product_type ) ) {
				$can_product_type_change_price = true;
				break;
			}
		}

		if ( $can_product_type_change_price ) {
			$regular_price_changed = $this->set_new_price( $product, 'regular' );
			$sale_price_changed    = $this->set_new_price( $product, 'sale' );

			if ( $regular_price_changed || $sale_price_changed ) {
				$product->set_date_on_sale_to( '' );
				$product->set_date_on_sale_from( '' );

				if ( $product->get_regular_price() < $product->get_sale_price() ) {
					$product->set_sale_price( '' );
				}
			}
		}

		// Handle Stock Data.
		$was_managing_stock = $product->get_manage_stock() ? 'yes' : 'no';
		$backorders         = $product->get_backorders();
		$backorders         = ! empty( $request_data['_backorders'] ) ? wc_clean( $request_data['_backorders'] ) : $backorders;

		if ( ! empty( $request_data['_manage_stock'] ) ) {
			$manage_stock = 'yes' === wc_clean( $request_data['_manage_stock'] ) && ProductType::GROUPED !== $product->get_type() ? 'yes' : 'no';
		} else {
			$manage_stock = $was_managing_stock;
		}

		$stock_amount = 'yes' === $manage_stock && ! empty( $request_data['change_stock'] ) && isset( $request_data['_stock'] ) ? wc_stock_amount( $request_data['_stock'] ) : $product->get_stock_quantity();

		$product->set_manage_stock( $manage_stock );

		if ( ProductType::EXTERNAL !== $product->get_type() ) {
			$product->set_backorders( $backorders );
		}

		if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
			$change_stock = absint( $request_data['change_stock'] );
			switch ( $change_stock ) {
				case 2:
					wc_update_product_stock( $product, $stock_amount, 'increase', true );
					break;
				case 3:
					wc_update_product_stock( $product, $stock_amount, 'decrease', true );
					break;
				default:
					wc_update_product_stock( $product, $stock_amount, 'set', true );
					break;
			}
		} else {
			// Reset values if WooCommerce Setting - Manage Stock status is disabled.
			$product->set_stock_quantity( '' );
			$product->set_manage_stock( 'no' );
		}

		$stock_status = empty( $request_data['_stock_status'] ) ? null : wc_clean( $request_data['_stock_status'] );
		$product      = $this->maybe_update_stock_status( $product, $stock_status );

		if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() ) {
			$this->maybe_update_cogs_value( $product, $request_data );
		}

		$product->save();

		do_action( 'woocommerce_product_bulk_edit_save', $product );

		// phpcs:enable WordPress.Security.ValidatedSanitizedInput.MissingUnslash
	}

	/**
	 * Disable the auto-save functionality for Orders.
	 */
	public function disable_autosave() {
		global $post;

		if ( $post instanceof WP_Post && in_array( get_post_type( $post->ID ), wc_get_order_types( 'order-meta-boxes' ), true ) ) {
			wp_dequeue_script( 'autosave' );
		}
	}

	/**
	 * Output extra data on post forms.
	 *
	 * @param WP_Post $post Current post object.
	 */
	public function edit_form_top( $post ) {
		echo '<input type="hidden" id="original_post_title" name="original_post_title" value="' . esc_attr( $post->post_title ) . '" />';
	}

	/**
	 * Change title boxes in admin.
	 *
	 * @param string  $text Text to shown.
	 * @param WP_Post $post Current post object.
	 * @return string
	 */
	public function enter_title_here( $text, $post ) {
		switch ( $post->post_type ) {
			case 'product':
				$text = esc_html__( 'Product name', 'woocommerce' );
				break;
			case 'shop_coupon':
				$text = esc_html__( 'Coupon code', 'woocommerce' );
				break;
		}
		return $text;
	}

	/**
	 * Print coupon description textarea field.
	 *
	 * @param WP_Post $post Current post object.
	 */
	public function edit_form_after_title( $post ) {
		// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
		if ( 'shop_coupon' === $post->post_type ) {
			?>
			<textarea id="woocommerce-coupon-description" name="excerpt" cols="5" rows="2" placeholder="<?php esc_attr_e( 'Description (optional)', 'woocommerce' ); ?>"><?php echo $post->post_excerpt; ?></textarea>
			<?php
		}
		// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
	}

	/**
	 * Hidden default Meta-Boxes.
	 *
	 * @param  array  $hidden Hidden boxes.
	 * @param  object $screen Current screen.
	 * @return array
	 */
	public function hidden_meta_boxes( $hidden, $screen ) {
		if ( 'product' === $screen->post_type && 'post' === $screen->base ) {
			$hidden = array_merge( $hidden, array( 'postcustom' ) );
		}

		return $hidden;
	}

	/**
	 * Output product visibility options.
	 */
	public function product_data_visibility() {
		global $post, $thepostid, $product_object;

		if ( 'product' !== $post->post_type ) {
			return;
		}

		$thepostid          = $post->ID;
		$product_object     = $thepostid ? wc_get_product( $thepostid ) : new WC_Product();
		$current_visibility = $product_object->get_catalog_visibility();
		$current_featured   = wc_bool_to_string( $product_object->get_featured() );
		$visibility_options = wc_get_product_visibility_options();
		?>
		<div class="misc-pub-section" id="catalog-visibility">
			<?php esc_html_e( 'Catalog visibility:', 'woocommerce' ); ?>
			<strong id="catalog-visibility-display">
				<?php

				echo isset( $visibility_options[ $current_visibility ] ) ? esc_html( $visibility_options[ $current_visibility ] ) : esc_html( $current_visibility );

				if ( 'yes' === $current_featured ) {
					echo ', ' . esc_html__( 'Featured', 'woocommerce' );
				}
				?>
			</strong>

			<a href="#catalog-visibility" class="edit-catalog-visibility hide-if-no-js"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a>

			<div id="catalog-visibility-select" class="hide-if-js">

				<input type="hidden" name="current_visibility" id="current_visibility" value="<?php echo esc_attr( $current_visibility ); ?>" />
				<input type="hidden" name="current_featured" id="current_featured" value="<?php echo esc_attr( $current_featured ); ?>" />

				<?php
				echo '<p>' . esc_html__( 'This setting determines which shop pages products will be listed on.', 'woocommerce' ) . '</p>';

				foreach ( $visibility_options as $name => $label ) {
					echo '<input type="radio" name="_visibility" id="_visibility_' . esc_attr( $name ) . '" value="' . esc_attr( $name ) . '" ' . checked( $current_visibility, $name, false ) . ' data-label="' . esc_attr( $label ) . '" /> <label for="_visibility_' . esc_attr( $name ) . '" class="selectit">' . esc_html( $label ) . '</label><br />';
				}

				echo '<br /><input type="checkbox" name="_featured" id="_featured" ' . checked( $current_featured, 'yes', false ) . ' /> <label for="_featured">' . esc_html__( 'This is a featured product', 'woocommerce' ) . '</label><br />';
				?>
				<p>
					<a href="#catalog-visibility" class="save-post-visibility hide-if-no-js button"><?php esc_html_e( 'OK', 'woocommerce' ); ?></a>
					<a href="#catalog-visibility" class="cancel-post-visibility hide-if-no-js"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></a>
				</p>
			</div>
		</div>
		<?php
	}

	/**
	 * Grant downloadable file access to any newly added files on any existing.
	 * orders for this product that have previously been granted downloadable file access.
	 *
	 * @param int   $product_id product identifier.
	 * @param int   $variation_id optional product variation identifier.
	 * @param array $downloadable_files newly set files.
	 * @deprecated 3.3.0 and moved to post-data class.
	 */
	public function process_product_file_download_paths( $product_id, $variation_id, $downloadable_files ) {
		wc_deprecated_function( 'WC_Admin_Post_Types::process_product_file_download_paths', '3.3', '' );
		WC_Post_Data::process_product_file_download_paths( $product_id, $variation_id, $downloadable_files );
	}

	/**
	 * When editing the shop page, we should hide templates.
	 *
	 * @param array   $page_templates Templates array.
	 * @param string  $theme Classname.
	 * @param WP_Post $post The current post object.
	 * @return array
	 */
	public function hide_cpt_archive_templates( $page_templates, $theme, $post ) {
		$shop_page_id = wc_get_page_id( 'shop' );

		if ( $post && absint( $post->ID ) === $shop_page_id ) {
			$page_templates = array();
		}

		return $page_templates;
	}

	/**
	 * Show a notice above the CPT archive.
	 *
	 * @param WP_Post $post The current post object.
	 */
	public function show_cpt_archive_notice( $post ) {
		$shop_page_id = wc_get_page_id( 'shop' );

		if ( $post && absint( $post->ID ) === $shop_page_id ) {
			echo '<div class="notice notice-info">';
			/* translators: %s: URL to read more about the shop page. */
			echo '<p>' . sprintf( wp_kses_post( __( 'This is the WooCommerce shop page. The shop page is a special archive that lists your products. <a href="%s">You can read more about this here</a>.', 'woocommerce' ) ), 'https://woocommerce.com/document/woocommerce-pages/#section-4' ) . '</p>';
			echo '</div>';
		}
	}

	/**
	 * Add a post display state for special WC pages in the page list table.
	 *
	 * @param array   $post_states An array of post display states.
	 * @param WP_Post $post        The current post object.
	 */
	public function add_display_post_states( $post_states, $post ) {
		if ( wc_get_page_id( 'shop' ) === $post->ID ) {
			$post_states['wc_page_for_shop'] = __( 'Shop Page', 'woocommerce' );
		}

		if ( wc_get_page_id( 'cart' ) === $post->ID ) {
			$post_states['wc_page_for_cart'] = __( 'Cart Page', 'woocommerce' );
		}

		if ( wc_get_page_id( 'checkout' ) === $post->ID ) {
			$post_states['wc_page_for_checkout'] = __( 'Checkout Page', 'woocommerce' );
		}

		if ( wc_get_page_id( 'myaccount' ) === $post->ID ) {
			$post_states['wc_page_for_myaccount'] = __( 'My Account Page', 'woocommerce' );
		}

		if ( wc_get_page_id( 'terms' ) === $post->ID ) {
			$post_states['wc_page_for_terms'] = __( 'Terms and Conditions Page', 'woocommerce' );
		}

		return $post_states;
	}

	/**
	 * Apply product type constraints to stock status.
	 *
	 * @param WC_Product  $product The product whose stock status will be adjusted.
	 * @param string|null $stock_status The stock status to use for adjustment, or null if no new stock status has been supplied in the request.
	 * @return WC_Product The supplied product, or the synced product if it was a variable product.
	 */
	private function maybe_update_stock_status( $product, $stock_status ) {
		if ( $product->is_type( ProductType::EXTERNAL ) ) {
			// External products are always in stock.
			$product->set_stock_status( ProductStockStatus::IN_STOCK );
		} elseif ( isset( $stock_status ) ) {
			if ( $product->is_type( ProductType::VARIABLE ) && ! $product->get_manage_stock() ) {
				// Stock status is determined by children.
				foreach ( $product->get_children() as $child_id ) {
					$child = wc_get_product( $child_id );
					if ( ! $product->get_manage_stock() ) {
						$child->set_stock_status( $stock_status );
						$child->save();
					}
				}
				$product = WC_Product_Variable::sync( $product, false );
			} else {
				$product->set_stock_status( $stock_status );
			}
		}

		return $product;
	}

	/**
	 * Set the new regular or sale price if requested.
	 *
	 * @param WC_Product $product The product to set the new price for.
	 * @param string     $price_type 'regular' or 'sale'.
	 * @return bool true if a new price has been set, false otherwise.
	 */
	private function set_new_price( $product, $price_type ) {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended

		$request_data = $this->request_data();

		if ( empty( $request_data[ "change_{$price_type}_price" ] ) || ! isset( $request_data[ "_{$price_type}_price" ] ) ) {
			return false;
		}

		$old_price     = $product->{"get_{$price_type}_price"}();
		$old_price     = '' === $old_price ? (float) $product->get_regular_price() : (float) $old_price;
		$price_changed = false;

		$change_price  = absint( $request_data[ "change_{$price_type}_price" ] );
		$raw_price     = wc_clean( wp_unslash( $request_data[ "_{$price_type}_price" ] ) );
		$is_percentage = (bool) strstr( $raw_price, '%' );
		$price         = wc_format_decimal( $raw_price );

		switch ( $change_price ) {
			case 1:
				if ( empty( $price ) ) {
					$new_price = $product->get_regular_price();
				} else {
					$new_price = $price;
				}
				break;
			case 2:
				if ( $is_percentage ) {
					$percent   = $price / 100;
					$new_price = $old_price + ( $old_price * $percent );
				} elseif ( ! empty( $price ) ) {
					$new_price = $old_price + $price;
				}
				break;
			case 3:
				if ( $is_percentage ) {
					$percent   = $price / 100;
					$new_price = max( 0, $old_price - ( $old_price * $percent ) );
				} elseif ( ! empty( $price ) ) {
					$new_price = max( 0, $old_price - $price );
				}
				break;
			case 4:
				if ( 'sale' !== $price_type ) {
					break;
				}
				$regular_price = $product->get_regular_price();
				if ( $is_percentage && is_numeric( $regular_price ) ) {
					$percent   = $price / 100;
					$new_price = max( 0, $regular_price - ( NumberUtil::round( $regular_price * $percent, wc_get_price_decimals() ) ) );
				} else {
					$new_price = max( 0, (float) $regular_price - (float) $price );
				}
				break;

			default:
				break;
		}

		if ( isset( $new_price ) && $new_price !== $old_price ) {
			$price_changed = true;
			$new_price     = NumberUtil::round( $new_price, wc_get_price_decimals() );
			$product->{"set_{$price_type}_price"}( $new_price );
		}

		return $price_changed;

		// phpcs:disable WordPress.Security.NonceVerification.Recommended
	}

	/**
	 * Get the current request data ($_REQUEST superglobal).
	 * This method is added to ease unit testing.
	 *
	 * @return array The $_REQUEST superglobal.
	 */
	protected function request_data() {
		return $_REQUEST;
	}

	/**
	 * Update the Cost of Goods Sold value coming from a bulk edit for a product.
	 *
	 * @param WC_Product $product The product to update.
	 * @param array      $request_data The current request data.
	 */
	private function maybe_update_cogs_value( WC_Product $product, array $request_data ) {
		$change_cogs_value = absint( $request_data['change_cogs_value'] );
		if ( 1 !== $change_cogs_value ) {
			return;
		}

		$cogs_value = wc_clean( wp_unslash( $request_data['_cogs_value'] ?? '' ) );
		$product->set_cogs_value( '' === $cogs_value ? null : (float) wc_format_decimal( $cogs_value ) );
	}
}

new WC_Admin_Post_Types();
PK     tS\].3^      woocommerce-legacy-reports.phpnu [        <?php
declare( strict_types = 1 );

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

// This will be the main plugin file after moving the legacy reports to a separate plugin.

if ( ! function_exists( 'woocommerce_legacy_reports_init' ) ) {
	/**
	 * Initialize the WooCommerce legacy reports.
	 */
	function woocommerce_legacy_reports_init() {
		require_once __DIR__ . '/class-wc-admin-reports.php';

		WC_Admin_Reports::register_hook_handlers();
	}

	add_action( 'woocommerce_init', 'woocommerce_legacy_reports_init' );
}
PK     tS\ o`    0  meta-boxes/class-wc-meta-box-order-downloads.phpnu [        <?php
/**
 * Order Downloads
 *
 * @package     WooCommerce\Admin\Meta Boxes
 * @version     2.1.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Meta_Box_Order_Downloads Class.
 */
class WC_Meta_Box_Order_Downloads {

	/**
	 * Output the metabox.
	 *
	 * @param WC_Order|WP_Post $post Post or order object.
	 */
	public static function output( $post ) {
		if ( $post instanceof WC_Order ) {
			$order_id = $post->get_id();
		} else {
			$order_id = $post->ID;
		}
		?>
		<div class="order_download_permissions wc-metaboxes-wrapper">

			<div class="wc-metaboxes">
				<?php
				$data_store           = WC_Data_Store::load( 'customer-download' );
				$download_permissions = array();
				if ( 0 !== $order_id ) {
					$download_permissions = $data_store->get_downloads(
						array(
							'order_id' => $order_id,
							'orderby'  => 'product_id',
						)
					);
				}

				$product      = null;
				$loop         = 0;
				$file_counter = 1;

				if ( $download_permissions && count( $download_permissions ) > 0 ) {
					foreach ( $download_permissions as $download ) {
						if ( ! $product || $product->get_id() !== $download->get_product_id() ) {
							$product      = wc_get_product( $download->get_product_id() );
							$file_counter = 1;
						}

						// don't show permissions to files that have since been removed.
						if ( ! $product || ! $product->exists() || ! $product->has_file( $download->get_download_id() ) ) {
							continue;
						}

						// Show file title instead of count if set.
						$file       = $product->get_file( $download->get_download_id() );
						// translators: file name.
						$file_count = isset( $file['name'] ) ? $file['name'] : sprintf( __( 'File %d', 'woocommerce' ), $file_counter );

						include __DIR__ . '/views/html-order-download-permission.php';

						$loop++;
						$file_counter++;
					}
				}
				?>
			</div>

			<div class="toolbar">
				<p class="buttons">
					<select id="grant_access_id" class="wc-product-search" name="grant_access_id[]" multiple="multiple" style="width: 400px;" data-placeholder="<?php esc_attr_e( 'Search for a downloadable product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_downloadable_products_and_variations"></select>
					<button type="button" class="button grant_access">
						<?php esc_html_e( 'Grant access', 'woocommerce' ); ?>
					</button>
				</p>
				<div class="clear"></div>
			</div>

		</div>
		<?php
	}

	/**
	 * Save meta box data.
	 *
	 * @param int     $post_id Post ID.
	 * @param WP_Post $post Post object.
	 */
	public static function save( $post_id, $post ) {
		if ( isset( $_POST['permission_id'] ) ) {
			$permission_ids      = $_POST['permission_id'];
			$downloads_remaining = $_POST['downloads_remaining'];
			$access_expires      = $_POST['access_expires'];
			$max                 = max( array_keys( $permission_ids ) );

			for ( $i = 0; $i <= $max; $i ++ ) {
				if ( ! isset( $permission_ids[ $i ] ) ) {
					continue;
				}
				$download = new WC_Customer_Download( $permission_ids[ $i ] );
				$download->set_downloads_remaining( wc_clean( $downloads_remaining[ $i ] ) );
				$download->set_access_expires( array_key_exists( $i, $access_expires ) && '' !== $access_expires[ $i ] ? strtotime( $access_expires[ $i ] ) : '' );
				$download->save();
			}
		}
	}
}
PK     tS\\z  z  +  meta-boxes/class-wc-meta-box-order-data.phpnu [        <?php
/**
 * Order Data
 *
 * Functions for displaying the order data meta box.
 *
 * @package     WooCommerce\Admin\Meta Boxes
 * @version     2.2.0
 */

use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Internal\Utilities\Users;
use Automattic\WooCommerce\Utilities\OrderUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Meta_Box_Order_Data Class.
 */
class WC_Meta_Box_Order_Data {

	/**
	 * Billing fields.
	 *
	 * @var array
	 */
	protected static $billing_fields = array();

	/**
	 * Shipping fields.
	 *
	 * @var array
	 */
	protected static $shipping_fields = array();

	/**
	 * Get billing fields for the meta box.
	 *
	 * @param \WC_Order $order Order object.
	 * @param string    $context Context of fields (view or edit).
	 * @return array
	 */
	protected static function get_billing_fields( $order = false, $context = 'edit' ) {
		/**
		 * Provides an opportunity to modify the list of order billing fields displayed on the admin.
		 *
		 * @since 1.4.0
		 *
		 * @param array Billing fields.
		 * @param WC_Order|false $order Order object.
		 * @param string $context Context of fields (view or edit).
		 */
		return apply_filters(
			'woocommerce_admin_billing_fields',
			array(
				'first_name' => array(
					'label' => __( 'First name', 'woocommerce' ),
					'show'  => false,
				),
				'last_name'  => array(
					'label' => __( 'Last name', 'woocommerce' ),
					'show'  => false,
				),
				'company'    => array(
					'label' => __( 'Company', 'woocommerce' ),
					'show'  => false,
				),
				'address_1'  => array(
					'label' => __( 'Address line 1', 'woocommerce' ),
					'show'  => false,
				),
				'address_2'  => array(
					'label' => __( 'Address line 2', 'woocommerce' ),
					'show'  => false,
				),
				'city'       => array(
					'label' => __( 'City', 'woocommerce' ),
					'show'  => false,
				),
				'postcode'   => array(
					'label' => __( 'Postcode / ZIP', 'woocommerce' ),
					'show'  => false,
				),
				'country'    => array(
					'label'   => __( 'Country / Region', 'woocommerce' ),
					'show'    => false,
					'class'   => 'js_field-country select short',
					'type'    => 'select',
					'options' => array( '' => __( 'Select a country / region&hellip;', 'woocommerce' ) ) + WC()->countries->get_countries(),
				),
				'state'      => array(
					'label' => __( 'State / County', 'woocommerce' ),
					'class' => 'js_field-state select short',
					'show'  => false,
				),
				'email'      => array(
					'label' => __( 'Email address', 'woocommerce' ),
				),
				'phone'      => array(
					'label' => __( 'Phone', 'woocommerce' ),
				),
			),
			$order,
			$context
		);
	}

	/**
	 * Get shipping fields for the meta box.
	 *
	 * @param \WC_Order $order Order object.
	 * @param string    $context Context of fields (view or edit).
	 * @return array
	 */
	protected static function get_shipping_fields( $order = false, $context = 'edit' ) {
		/**
		 * Provides an opportunity to modify the list of order shipping fields displayed on the admin.
		 *
		 * @since 1.4.0
		 *
		 * @param array Shipping fields.
		 * @param WC_Order|false $order Order object.
		 * @param string $context Context of fields (view or edit).
		 */
		return apply_filters(
			'woocommerce_admin_shipping_fields',
			array(
				'first_name' => array(
					'label' => __( 'First name', 'woocommerce' ),
					'show'  => false,
				),
				'last_name'  => array(
					'label' => __( 'Last name', 'woocommerce' ),
					'show'  => false,
				),
				'company'    => array(
					'label' => __( 'Company', 'woocommerce' ),
					'show'  => false,
				),
				'address_1'  => array(
					'label' => __( 'Address line 1', 'woocommerce' ),
					'show'  => false,
				),
				'address_2'  => array(
					'label' => __( 'Address line 2', 'woocommerce' ),
					'show'  => false,
				),
				'city'       => array(
					'label' => __( 'City', 'woocommerce' ),
					'show'  => false,
				),
				'postcode'   => array(
					'label' => __( 'Postcode / ZIP', 'woocommerce' ),
					'show'  => false,
				),
				'country'    => array(
					'label'   => __( 'Country / Region', 'woocommerce' ),
					'show'    => false,
					'type'    => 'select',
					'class'   => 'js_field-country select short',
					'options' => array( '' => __( 'Select a country / region&hellip;', 'woocommerce' ) ) + WC()->countries->get_countries(),
				),
				'state'      => array(
					'label' => __( 'State / County', 'woocommerce' ),
					'class' => 'js_field-state select short',
					'show'  => false,
				),
				'phone'      => array(
					'label' => __( 'Phone', 'woocommerce' ),
				),
			),
			$order,
			$context
		);
	}

	/**
	 * Init billing and shipping fields we display + save. Maintained for backwards compat.
	 */
	public static function init_address_fields() {
		self::$billing_fields  = self::get_billing_fields();
		self::$shipping_fields = self::get_shipping_fields();
	}

	/**
	 * Output the metabox.
	 *
	 * @param WP_Post|WC_Order $post Post or order object.
	 */
	public static function output( $post ) {
		global $theorder;

		OrderUtil::init_theorder_object( $post );

		$order = $theorder;

		if ( WC()->payment_gateways() ) {
			$payment_gateways = WC()->payment_gateways->payment_gateways();
		} else {
			$payment_gateways = array();
		}

		$payment_method = $order->get_payment_method();

		$order_type_object = get_post_type_object( $order->get_type() );
		wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );
		?>
		<style type="text/css">
			#post-body-content, #titlediv { display:none }
		</style>
		<div class="panel-wrap woocommerce">
			<input name="post_title" type="hidden" value="<?php echo esc_attr( empty( $order->get_title() ) ? __( 'Order', 'woocommerce' ) : $order->get_title() ); ?>" />
			<input name="post_status" type="hidden" value="<?php echo esc_attr( $order->get_status() ); ?>" />
			<div id="order_data" class="panel woocommerce-order-data">
				<div class="order_data_header">
					<div class="order_data_header_column">
						<h2 class="woocommerce-order-data__heading">
							<?php

							printf(
								/* translators: 1: order type 2: order number */
								esc_html__( '%1$s #%2$s details', 'woocommerce' ),
								esc_html( $order_type_object->labels->singular_name ),
								esc_html( $order->get_order_number() )
							);

							?>
						</h2>
						<p class="woocommerce-order-data__meta order_number">
							<?php

							$meta_list = array();

							if ( $payment_method && 'other' !== $payment_method ) {
								$payment_method_string = sprintf(
									/* translators: %s: payment method */
									__( 'Payment via %s', 'woocommerce' ),
									esc_html( isset( $payment_gateways[ $payment_method ] ) ? $payment_gateways[ $payment_method ]->get_title() : $payment_method )
								);

								$transaction_id = $order->get_transaction_id();
								if ( $transaction_id ) {

									$to_add = null;
									if ( isset( $payment_gateways[ $payment_method ] ) ) {
										$url = $payment_gateways[ $payment_method ]->get_transaction_url( $order );
										if ( $url ) {
											$to_add .= ' (<a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $transaction_id ) . '</a>)';
										}
									}

									$to_add                 = $to_add ?? ' (' . esc_html( $transaction_id ) . ')';
									$payment_method_string .= $to_add;
								}

								$meta_list[] = $payment_method_string;
							}

							if ( $order->get_date_paid() ) {
								$meta_list[] = sprintf(
									/* translators: 1: date 2: time */
									__( 'Paid on %1$s @ %2$s', 'woocommerce' ),
									wc_format_datetime( $order->get_date_paid() ),
									wc_format_datetime( $order->get_date_paid(), get_option( 'time_format' ) )
								);
							}

							$ip_address = $order->get_customer_ip_address();
							if ( $ip_address ) {
								$meta_list[] = sprintf(
									/* translators: %s: IP address */
									__( 'Customer IP: %s', 'woocommerce' ),
									'<span class="woocommerce-Order-customerIP">' . esc_html( $ip_address ) . '</span>'
								);
							}

							echo wp_kses_post( implode( '. ', $meta_list ) );

							?>
						</p>
					</div>
					<div class="order_data_header_column">
						<?php
							/**
							 * Hook allowing extenders to render custom content
							 * besides the Order header.
							 *
							 * @param $order WC_Order The order object being displayed.
							 * @since 9.9.0
							 */
							do_action( 'woocommerce_admin_order_data_header_right', $order );
						?>
					</div>
				</div>
				<?php
					/**
					 * Hook allowing extenders to render custom content
					 * within the Order details box.
					 *
					 * This allows urgent notices or other important
					 * order-related info to be displayed upfront in
					 * the order page. Example: display a notice if
					 * the order is disputed.
					 *
					 * @param $order WC_Order The order object being displayed.
					 * @since 7.9.0
					 */
					do_action( 'woocommerce_admin_order_data_after_payment_info', $order );
				?>
				<div class="order_data_column_container">
					<div class="order_data_column">
						<h3><?php esc_html_e( 'General', 'woocommerce' ); ?></h3>

						<p class="form-field form-field-wide">
							<?php
							$order_date_created_localised = ! is_null( $order->get_date_created() ) ? $order->get_date_created()->getOffsetTimestamp() : '';
							?>
							<label for="order_date"><?php esc_html_e( 'Date created:', 'woocommerce' ); ?></label>
							<input type="text" class="date-picker" name="order_date" maxlength="10" value="<?php echo esc_attr( date_i18n( 'Y-m-d', $order_date_created_localised ) ); ?>" pattern="<?php echo esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ); // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment ?>" />@
							&lrm;
							<input type="number" class="hour" placeholder="<?php esc_attr_e( 'h', 'woocommerce' ); ?>" name="order_date_hour" min="0" max="23" step="1" value="<?php echo esc_attr( date_i18n( 'H', $order_date_created_localised ) ); ?>" pattern="([01]?[0-9]{1}|2[0-3]{1})" />:
							<input type="number" class="minute" placeholder="<?php esc_attr_e( 'm', 'woocommerce' ); ?>" name="order_date_minute" min="0" max="59" step="1" value="<?php echo esc_attr( date_i18n( 'i', $order_date_created_localised ) ); ?>" pattern="[0-5]{1}[0-9]{1}" />
							<input type="hidden" name="order_date_second" value="<?php echo esc_attr( date_i18n( 's', $order_date_created_localised ) ); ?>" />
						</p>

						<p class="form-field form-field-wide wc-order-status">
							<label for="order_status">
								<?php
								esc_html_e( 'Status:', 'woocommerce' );
								if ( $order->needs_payment() ) {
									printf(
										'<a href="%s">%s</a>',
										esc_url( $order->get_checkout_payment_url() ),
										esc_html__( 'Customer payment page &rarr;', 'woocommerce' )
									);
								}
								?>
							</label>
							<select id="order_status" name="order_status" class="wc-enhanced-select">
								<?php
								$statuses = wc_get_order_statuses();
								foreach ( $statuses as $status => $status_name ) {
									echo '<option value="' . esc_attr( $status ) . '" ' . selected( $status, 'wc-' . $order->get_status( 'edit' ), false ) . '>' . esc_html( $status_name ) . '</option>';
								}
								?>
							</select>
						</p>

						<p class="form-field form-field-wide wc-customer-user">
							<!--email_off--> <!-- Disable CloudFlare email obfuscation -->
							<label for="customer_user">
								<?php
								esc_html_e( 'Customer:', 'woocommerce' );
								if ( $order->get_user_id( 'edit' ) ) {
									$args = array(
										'post_status'    => 'all',
										'post_type'      => 'shop_order',
										'_customer_user' => $order->get_user_id( 'edit' ),
									);
									printf(
										'<a href="%s">%s</a>',
										esc_url( add_query_arg( $args, admin_url( 'edit.php' ) ) ),
										' ' . esc_html__( 'View other orders &rarr;', 'woocommerce' )
									);
									printf(
										'<a href="%s">%s</a>',
										esc_url( add_query_arg( 'user_id', $order->get_user_id( 'edit' ), admin_url( 'user-edit.php' ) ) ),
										' ' . esc_html__( 'Profile &rarr;', 'woocommerce' )
									);
								}
								?>
							</label>
							<?php
							$user_string = '';
							$user_id     = '';
							if ( $order->get_user_id() ) {
								$user_id = absint( $order->get_user_id() );
								$user    = Users::get_user_in_current_site( $user_id );

								if ( ! is_wp_error( $user ) ) {
									$customer = new WC_Customer( $user_id );
									/* translators: 1: user display name 2: user ID 3: user email */
									$user_string = sprintf(
									/* translators: 1: customer name, 2 customer id, 3: customer email */
										esc_html__( '%1$s (#%2$s &ndash; %3$s)', 'woocommerce' ),
										$customer->get_first_name() . ' ' . $customer->get_last_name(),
										$customer->get_id(),
										$customer->get_email()
									);
								} else {
									// print customer not available in the current site.
									$user_string = esc_html__( '(Not available)', 'woocommerce' );
								}
							}
							?>
							<select class="wc-customer-search" id="customer_user" name="customer_user" data-placeholder="<?php esc_attr_e( 'Guest', 'woocommerce' ); ?>" data-allow_clear="true">
								<?php
								// phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment
								/**
								 * Filter to customize the display of the currently selected customer for an order in the order edit page.
								 * This is the same filter used in the ajax call for customer search in the same metabox.
								 *
								 * @since 7.2.0 (this instance of the filter)
								 *
								 * @param array @user_info An array containing one item with the name and email of the user currently selected as the customer for the order.
								 */
								?>
								<option value="<?php echo esc_attr( $user_id ); ?>" selected="selected"><?php echo esc_html( htmlspecialchars( wp_kses_post( current( apply_filters( 'woocommerce_json_search_found_customers', array( $user_string ) ) ) ) ) ); ?></option>
								<?php // phpcs:enable WooCommerce.Commenting.CommentHooks.MissingHookComment ?>
							</select>
							<!--/email_off-->
						</p>
						<?php do_action( 'woocommerce_admin_order_data_after_order_details', $order ); // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment ?>
					</div>
					<div class="order_data_column">
						<h3>
							<?php esc_html_e( 'Billing', 'woocommerce' ); ?>
							<a href="#" class="edit_address"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a>
							<span>
								<a href="#" class="load_customer_billing" style="display:none;"><?php esc_html_e( 'Load billing address', 'woocommerce' ); ?></a>
							</span>
						</h3>
						<div class="address">
							<?php
							// Display values.
							$user = Users::get_user_in_current_site( $order->get_user_id() );

							$details_not_available_message = __( 'Details are not available for this customer as this user does not exist in the current site.', 'woocommerce' );
							// If the user is not a guest and is not a valid user in the current site, print details not available.
							if ( $order->get_user_id() !== 0 && is_wp_error( $user ) ) {
								echo '<p>' . esc_html( $details_not_available_message ) . '</p>';
							} else {
								if ( $order->get_formatted_billing_address() ) {
									echo '<p>' . wp_kses( $order->get_formatted_billing_address(), array( 'br' => array() ) ) . '</p>';
								} else {
									echo '<p class="none_set"><strong>' . esc_html__( 'Address:', 'woocommerce' ) . '</strong> ' . esc_html__( 'No billing address set.', 'woocommerce' ) . '</p>';
								}

								$billing_fields = self::get_billing_fields( $order, 'view' );

								foreach ( $billing_fields as $key => $field ) {
									if ( isset( $field['show'] ) && false === $field['show'] ) {
										continue;
									}

									$field_name = 'billing_' . $key;

									if ( isset( $field['value'] ) ) {
										$field_value = $field['value'];
									} elseif ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
										$field_value = $order->{"get_$field_name"}( 'edit' );
									} else {
										$field_value = $order->get_meta( '_' . $field_name );
									}

									if ( 'billing_phone' === $field_name ) {
										$field_value = wc_make_phone_clickable( $field_value );
									} elseif ( 'billing_email' === $field_name ) {
										$field_value = '<a href="' . esc_url( 'mailto:' . $field_value ) . '">' . $field_value . '</a>';
									} else {
										$field_value = make_clickable( esc_html( $field_value ) );
									}

									if ( $field_value || '0' === $field_value ) {
										echo '<p><strong>' . esc_html( $field['label'] ) . ':</strong> ' . wp_kses_post( $field_value ) . '</p>';
									}
								}
							}
							?>
						</div>

						<div class="edit_address">
							<?php
							// Display form.
							$billing_fields = self::get_billing_fields( $order, 'edit' );

							foreach ( $billing_fields as $key => $field ) {
								if ( ! isset( $field['type'] ) ) {
									$field['type'] = 'text';
								}
								if ( ! isset( $field['id'] ) ) {
									$field['id'] = '_billing_' . $key;
								}

								$field_name = 'billing_' . $key;

								// Check if the user is a valid user in the current site.
								// If not, set the value to an empty string.
								// This is to prevent the user from being able to view the billing address of a user that does not exist.
								// If the user is not a guest and is not a valid user in the current site, print details not available.
								if ( $order->get_user_id() !== 0 && is_wp_error( $user ) ) {
									$field['value'] = '';
								} elseif ( ! isset( $field['value'] ) ) {
									if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
										$field['value'] = $order->{"get_$field_name"}( 'edit' );
									} else {
										$field['value'] = $order->get_meta( '_' . $field_name );
									}
								}

								switch ( $field['type'] ) {
									case 'select':
										woocommerce_wp_select( $field, $order );
										break;
									case 'checkbox':
										woocommerce_wp_checkbox( $field, $order );
										break;
									default:
										woocommerce_wp_text_input( $field, $order );
										break;
								}
							}
							?>
							<p class="form-field form-field-wide">
								<label><?php esc_html_e( 'Payment method:', 'woocommerce' ); ?></label>
								<select name="_payment_method" id="_payment_method" class="first">
									<option value=""><?php esc_html_e( 'N/A', 'woocommerce' ); ?></option>
									<?php
									$found_method = false;

									foreach ( $payment_gateways as $gateway ) {
										if ( 'yes' === $gateway->enabled ) {
											echo '<option value="' . esc_attr( $gateway->id ) . '" ' . selected( $payment_method, $gateway->id, false ) . '>' . esc_html( $gateway->get_title() ) . '</option>';
											if ( $payment_method === $gateway->id ) {
												$found_method = true;
											}
										}
									}

									if ( ! $found_method && ! empty( $payment_method ) ) {
										echo '<option value="' . esc_attr( $payment_method ) . '" selected="selected">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
									} else {
										echo '<option value="other">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
									}
									?>
								</select>
							</p>
							<?php

							woocommerce_wp_text_input(
								array(
									'id'    => '_transaction_id',
									'label' => __( 'Transaction ID', 'woocommerce' ),
									'value' => $order->get_transaction_id( 'edit' ),
								),
								$order
							);
							?>

						</div>
						<?php do_action( 'woocommerce_admin_order_data_after_billing_address', $order ); // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment ?>
					</div>
					<div class="order_data_column">
						<h3>
							<?php esc_html_e( 'Shipping', 'woocommerce' ); ?>
							<a href="#" class="edit_address"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a>
							<span>
								<a href="#" class="load_customer_shipping" style="display:none;"><?php esc_html_e( 'Load shipping address', 'woocommerce' ); ?></a>
								<a href="#" class="billing-same-as-shipping" style="display:none;"><?php esc_html_e( 'Copy billing address', 'woocommerce' ); ?></a>
							</span>
						</h3>
						<div class="address">
							<?php
							// Display values.
							// If the user is not a guest and is not a valid user in the current site, print details not available.
							if ( $order->get_user_id() !== 0 && is_wp_error( $user ) ) {
								echo '<p>' . esc_html( $details_not_available_message ) . '</p>';
							} else {
								if ( $order->get_formatted_shipping_address() ) {
									echo '<p>' . wp_kses( $order->get_formatted_shipping_address(), array( 'br' => array() ) ) . '</p>';
								} else {
									echo '<p class="none_set"><strong>' . esc_html__( 'Address:', 'woocommerce' ) . '</strong> ' . esc_html__( 'No shipping address set.', 'woocommerce' ) . '</p>';
								}

								$shipping_fields = self::get_shipping_fields( $order, 'view' );

								if ( ! empty( $shipping_fields ) ) {
									foreach ( $shipping_fields as $key => $field ) {
										if ( isset( $field['show'] ) && false === $field['show'] ) {
											continue;
										}

										$field_name = 'shipping_' . $key;

										if ( isset( $field['value'] ) ) {
											$field_value = $field['value'];
										} elseif ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
											$field_value = $order->{"get_$field_name"}( 'edit' );
										} else {
											$field_value = $order->get_meta( '_' . $field_name );
										}

										if ( 'shipping_phone' === $field_name ) {
											$field_value = wc_make_phone_clickable( $field_value );
										}

										if ( $field_value || '0' === $field_value ) {
											echo '<p><strong>' . esc_html( $field['label'] ) . ':</strong> ' . wp_kses_post( $field_value ) . '</p>';
										}
									}
								}

								if ( apply_filters( 'woocommerce_enable_order_notes_field', 'yes' === get_option( 'woocommerce_enable_order_comments', 'yes' ) ) && $order->get_customer_note() ) { // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
									echo '<p class="order_note"><strong>' . esc_html( __( 'Customer provided note:', 'woocommerce' ) ) . '</strong> ' . wp_kses( nl2br( esc_html( wc_wptexturize_order_note( $order->get_customer_note() ) ) ), array( 'br' => array() ) ) . '</p>';
								}
							}
							?>
						</div>
						<div class="edit_address">
							<?php
							// Display form.
							$shipping_fields = self::get_shipping_fields( $order, 'edit' );

							if ( ! empty( $shipping_fields ) ) {
								foreach ( $shipping_fields as $key => $field ) {
									if ( ! isset( $field['type'] ) ) {
										$field['type'] = 'text';
									}
									if ( ! isset( $field['id'] ) ) {
										$field['id'] = '_shipping_' . $key;
									}

									$field_name = 'shipping_' . $key;

									// Check if the user is a valid user in the current site.
									// If not, set the value to an empty string.
									// This is to prevent the user from being able to view the shipping address of a user that does not exist.
									// If the user is not a guest and is not a valid user in the current site, print details not available.
									if ( $order->get_user_id() !== 0 && is_wp_error( $user ) ) {
										$field['value'] = '';
									} elseif ( ! isset( $field['value'] ) ) {
										if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
											$field['value'] = $order->{"get_$field_name"}( 'edit' );
										} else {
											$field['value'] = $order->get_meta( '_' . $field_name );
										}
									}

									switch ( $field['type'] ) {
										case 'select':
											woocommerce_wp_select( $field, $order );
											break;
										case 'checkbox':
											woocommerce_wp_checkbox( $field, $order );
											break;
										default:
											woocommerce_wp_text_input( $field, $order );
											break;
									}
								}
							}

							/**
							 * Allows 3rd parties to alter whether the customer note should be displayed on the admin.
							 *
							 * @since 2.1.0
							 *
							 * @param bool TRUE if the note should be displayed. FALSE otherwise.
							 */
							if ( apply_filters( 'woocommerce_enable_order_notes_field', 'yes' === get_option( 'woocommerce_enable_order_comments', 'yes' ) ) ) :
								?>
								<p class="form-field form-field-wide">
									<label for="customer_note"><?php esc_html_e( 'Customer provided note', 'woocommerce' ); ?>:</label>
									<textarea rows="1" cols="40" name="customer_note" tabindex="6" id="excerpt" placeholder="<?php esc_attr_e( 'Customer notes about the order', 'woocommerce' ); ?>"><?php echo wp_kses( $order->get_customer_note(), array( 'br' => array() ) ); ?></textarea>
								</p>
							<?php endif; ?>
						</div>

						<?php do_action( 'woocommerce_admin_order_data_after_shipping_address', $order ); // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment ?>
					</div>
				</div>
				<div class="clear"></div>
			</div>
		</div>
		<?php
	}

	/**
	 * Save meta box data.
	 *
	 * @param int $order_id Order ID.
	 * @throws Exception Required request data is missing.
	 */
	public static function save( $order_id ) {
		// phpcs:disable WordPress.Security.NonceVerification.Missing

		if ( ! isset( $_POST['order_status'] ) ) {
			throw new Exception( __( 'Order status is missing.', 'woocommerce' ), 400 );
		}

		if ( ! isset( $_POST['_payment_method'] ) ) {
			throw new Exception( __( 'Payment method is missing.', 'woocommerce' ), 400 );
		}

		// Ensure gateways are loaded in case they need to insert data into the emails.
		WC()->payment_gateways();
		WC()->shipping();

		// Get order object.
		$order = wc_get_order( $order_id );
		$props = array();

		// Create order key.
		if ( ! $order->get_order_key() ) {
			$props['order_key'] = wc_generate_order_key();
		}

		// Update customer.
		$customer_id = isset( $_POST['customer_user'] ) ? absint( $_POST['customer_user'] ) : 0;

		$selected_customer = Users::get_user_in_current_site( $customer_id );

		// Only update the customer ID if it's a guest (0) or if it's a different customer that exists in the current site.
		// If the customer doesn't exist in the current site (is_wp_error), we won't update the customer ID.
		$is_valid_guest_or_new_customer = $customer_id !== $order->get_customer_id() && ( 0 === $customer_id || ! is_wp_error( $selected_customer ) );
		if ( $is_valid_guest_or_new_customer ) {
			$props['customer_id'] = $customer_id;
		}

		// Update billing fields.
		$billing_fields = self::get_billing_fields( $order, 'edit' );

		// Only update billing fields if the order is for a valid user in the current site.
		// This is to prevent the user from being able to update the billing address of a user that does not exist in the current site.
		$save_metadata_for_guest_user_or_a_valid_user = 0 === $customer_id || ! is_wp_error( $selected_customer );

		if ( ! empty( $billing_fields ) && $save_metadata_for_guest_user_or_a_valid_user ) {
			foreach ( $billing_fields as $key => $field ) {
				if ( ! isset( $field['id'] ) ) {
					$field['id'] = '_billing_' . $key;
				}

				if ( ! isset( $_POST[ $field['id'] ] ) ) {
					continue;
				}

				$value = wc_clean( wp_unslash( $_POST[ $field['id'] ] ) );

				// Update a field if it includes an update callback.
				if ( isset( $field['update_callback'] ) ) {
					call_user_func( $field['update_callback'], $field['id'], $value, $order );
				} elseif ( is_callable( array( $order, 'set_billing_' . $key ) ) ) {
					$props[ 'billing_' . $key ] = $value;
				} else {
					$order->update_meta_data( $field['id'], $value );
				}
			}
		}

		// Update shipping fields.
		$shipping_fields = self::get_shipping_fields( $order, 'edit' );

		// Only update shipping fields if the order is for a valid user in the current site.
		// This is to prevent the user from being able to update the shipping address of a user that does not exist in the current site.
		if ( ! empty( $shipping_fields ) && $save_metadata_for_guest_user_or_a_valid_user ) {
			foreach ( $shipping_fields as $key => $field ) {
				if ( ! isset( $field['id'] ) ) {
					$field['id'] = '_shipping_' . $key;
				}

				if ( ! isset( $_POST[ $field['id'] ] ) ) {
					continue;
				}

				$value = isset( $_POST[ $field['id'] ] ) ? wc_clean( wp_unslash( $_POST[ $field['id'] ] ) ) : '';

				// Update a field if it includes an update callback.
				if ( isset( $field['update_callback'] ) ) {
					call_user_func( $field['update_callback'], $field['id'], $value, $order );
				} elseif ( is_callable( array( $order, 'set_shipping_' . $key ) ) ) {
					$props[ 'shipping_' . $key ] = $value;
				} else {
					$order->update_meta_data( $field['id'], $value );
				}
			}
		}

		if ( isset( $_POST['_transaction_id'] ) ) {
			$props['transaction_id'] = wc_clean( wp_unslash( $_POST['_transaction_id'] ) );
		}

		// Payment method handling.
		if ( $order->get_payment_method() !== wc_clean( wp_unslash( $_POST['_payment_method'] ) ) ) {
			$methods              = WC()->payment_gateways->payment_gateways();
			$payment_method       = wc_clean( wp_unslash( $_POST['_payment_method'] ) );
			$payment_method_title = $payment_method;

			if ( isset( $methods ) && isset( $methods[ $payment_method ] ) ) {
				$payment_method_title = $methods[ $payment_method ]->get_title();
			}

			if ( 'other' === $payment_method ) {
				$payment_method_title = esc_html__( 'Other', 'woocommerce' );
			}

			$props['payment_method']       = $payment_method;
			$props['payment_method_title'] = $payment_method_title;
		}

		// Update date.
		if ( empty( $_POST['order_date'] ) ) {
			$date = time();
		} else {
			if ( ! isset( $_POST['order_date_hour'] ) || ! isset( $_POST['order_date_minute'] ) || ! isset( $_POST['order_date_second'] ) ) {
				throw new Exception( __( 'Order date, hour, minute and/or second are missing.', 'woocommerce' ), 400 );
			}
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput
			$date = gmdate( 'Y-m-d H:i:s', strtotime( $_POST['order_date'] . ' ' . (int) $_POST['order_date_hour'] . ':' . (int) $_POST['order_date_minute'] . ':' . (int) $_POST['order_date_second'] ) );
		}

		$props['date_created'] = $date;

		// Set created via prop if new post.
		if ( isset( $_POST['original_post_status'] ) && OrderStatus::AUTO_DRAFT === $_POST['original_post_status'] ) {
			$props['created_via'] = 'admin';
		}

		// Customer note.
		if ( isset( $_POST['customer_note'] ) ) {
			$props['customer_note'] = sanitize_textarea_field( wp_unslash( $_POST['customer_note'] ) );
		}

		// Save order data.
		$order->set_props( $props );
		$order->set_status( wc_clean( wp_unslash( $_POST['order_status'] ) ), '', true );
		$order->save();

		// phpcs:enable WordPress.Security.NonceVerification.Missing
	}
}
PK     tS\    3  meta-boxes/class-wc-meta-box-product-categories.phpnu [        <?php
/**
 * Product Categories meta box
 *
 * Display the product categories meta box.
 *
 * @package     WooCommerce\Admin\Meta Boxes
 * @version     7.5.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Meta_Box_Product_Categories Class.
 */
class WC_Meta_Box_Product_Categories {

	/**
	 * Output the metabox.
	 *
	 * @param WP_Post $post Current post object.
	 * @param array   $box {
	 *     Categories meta box arguments.
	 *
	 *     @type string   $id       Meta box 'id' attribute.
	 *     @type string   $title    Meta box title.
	 *     @type callable $callback Meta box display callback.
	 *     @type array    $args {
	 *         Extra meta box arguments.
	 *
	 *         @type string $taxonomy Taxonomy. Default 'category'.
	 *     }
	 * }
	 */
	public static function output( $post, $box ) {
		$categories_count = (int) wp_count_terms( 'product_cat' );

		/**
		 * Filters the category metabox search threshold, for when to render the typeahead field.
		 *
		 * @since 7.6.0
		 *
		 * @param number $threshold The default threshold.
		 * @returns number The threshold that will be used.
		 */
		if ( $categories_count <= apply_filters( 'woocommerce_product_category_metabox_search_threshold', 5 ) && function_exists( 'post_categories_meta_box' ) ) {
			return post_categories_meta_box( $post, $box );
		}

		$defaults = array( 'taxonomy' => 'category' );
		if ( ! isset( $box['args'] ) || ! is_array( $box['args'] ) ) {
			$args = array();
		} else {
			$args = $box['args'];
		}
		$parsed_args         = wp_parse_args( $args, $defaults );
		$tax_name            = $parsed_args['taxonomy'];
		$selected_categories = wp_get_object_terms( $post->ID, 'product_cat' );
		?>
		<div id="taxonomy-<?php echo esc_attr( $tax_name ); ?>-metabox"></div>
		<?php foreach ( (array) $selected_categories as $term ) { ?>
			<input
				type="hidden"
				value="<?php echo esc_attr( $term->term_id ); ?>"
				name="tax_input[<?php esc_attr( $tax_name ); ?>][]"
				data-name="<?php echo esc_attr( $term->name ); ?>"
			/>
			<?php
		}
	}
}
PK     tS\n<L  L  #  meta-boxes/views/html-order-fee.phpnu [        <?php
/**
 * Shows an order item fee
 *
 * @var object $item The item being displayed
 * @var int $item_id The id of the item being displayed
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<tr class="fee <?php echo ( ! empty( $class ) ) ? esc_attr( $class ) : ''; ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
	<td class="thumb"><div></div></td>

	<td class="name">
		<div class="view">
			<?php echo esc_html( $item->get_name() ? $item->get_name() : __( 'Fee', 'woocommerce' ) ); ?>
		</div>
		<div class="edit" style="display: none;">
			<input type="text" placeholder="<?php esc_attr_e( 'Fee name', 'woocommerce' ); ?>" name="order_item_name[<?php echo absint( $item_id ); ?>]" value="<?php echo ( $item->get_name() ) ? esc_attr( $item->get_name() ) : ''; ?>" />
			<input type="hidden" class="order_item_id" name="order_item_id[]" value="<?php echo esc_attr( $item_id ); ?>" />
			<input type="hidden" name="order_item_tax_class[<?php echo absint( $item_id ); ?>]" value="<?php echo esc_attr( $item->get_tax_class() ); ?>" />
		</div>
		<?php do_action( 'woocommerce_after_order_fee_item_name', $item_id, $item, null ); ?>
	</td>

	<?php do_action( 'woocommerce_admin_order_item_values', null, $item, absint( $item_id ) ); ?>

	<?php if ( $cogs_is_enabled ) : ?>
	<td class="item_cost_of_goods"></td>
	<?php endif; ?>

	<td class="item_cost" width="1%">&nbsp;</td>
	<td class="quantity" width="1%">&nbsp;</td>

	<td class="line_cost" width="1%">
		<div class="view">
			<?php
			echo wc_price( $item->get_total(), array( 'currency' => $order->get_currency() ) );

			if ( $refunded = -1 * $order->get_total_refunded_for_item( $item_id, 'fee' ) ) {
				echo '<small class="refunded">' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>';
			}
			?>
		</div>
		<div class="edit" style="display: none;">
			<input type="text" name="line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" />
		</div>
		<div class="refund" style="display: none;">
			<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_total wc_input_price" />
		</div>
	</td>

	<?php
	if ( ( $tax_data = $item->get_taxes() ) && wc_tax_enabled() ) {
		foreach ( $order_taxes as $tax_item ) {
			$tax_item_id    = $tax_item->get_rate_id();
			$tax_item_total = isset( $tax_data['total'][ $tax_item_id ] ) ? $tax_data['total'][ $tax_item_id ] : '';
			?>
			<td class="line_tax" width="1%">
				<div class="view">
					<?php
					echo ( '' !== $tax_item_total ) ? wc_price( wc_round_tax_total( $tax_item_total ), array( 'currency' => $order->get_currency() ) ) : '&ndash;';

					if ( $refunded = -1 * $order->get_tax_refunded_for_item( $item_id, $tax_item_id, 'fee' ) ) {
						echo '<small class="refunded">' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>';
					}
					?>
				</div>
				<div class="edit" style="display: none;">
					<input type="text" name="line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo ( isset( $tax_item_total ) ) ? esc_attr( wc_format_localized_price( $tax_item_total ) ) : ''; ?>" class="line_tax wc_input_price" />
				</div>
				<div class="refund" style="display: none;">
					<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
				</div>
			</td>
			<?php
		}
	}
	?>
	<td class="wc-order-edit-line-item">
		<?php if ( $order->is_editable() ) : ?>
			<div class="wc-order-edit-line-item-actions">
				<a class="edit-order-item tips" href="#" data-tip="<?php esc_attr_e( 'Edit fee', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'Edit fee', 'woocommerce' ); ?>"></a><a class="delete-order-item tips" href="#" data-tip="<?php esc_attr_e( 'Delete fee', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'Delete fee', 'woocommerce' ); ?>"></a>
			</div>
		<?php endif; ?>
	</td>
</tr>
PK     tS\IVY  Y  %  meta-boxes/views/html-order-items.phpnu [        <?php
/**
 * Order items HTML for meta box.
 *
 * @package WooCommerce\Admin
 */

use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;

defined( 'ABSPATH' ) || exit;

/**
 * Allow plugins to determine whether refunds UI should be rendered in the template.
 *
 * @since 6.4.0
 *
 * @param bool     $render_refunds If the refunds UI should be rendered.
 * @param int      $order_id       The Order ID.
 * @param WC_Order $order          The Order object.
 */
$render_refunds = (bool) apply_filters( 'woocommerce_admin_order_should_render_refunds', 0 < $order->get_total() - $order->get_total_refunded() || 0 < absint( $order->get_item_count() - $order->get_item_count_refunded() ), $order->get_id(), $order );

global $wpdb;

$payment_gateway     = wc_get_payment_gateway_by_order( $order );
$line_items          = $order->get_items( apply_filters( 'woocommerce_admin_order_item_types', 'line_item' ) );
$discounts           = $order->get_items( 'discount' );
$line_items_fee      = $order->get_items( 'fee' );
$line_items_shipping = $order->get_items( 'shipping' );
$cogs_is_enabled     = wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled();

if ( wc_tax_enabled() ) {
	$order_taxes      = $order->get_taxes();
	$tax_classes      = WC_Tax::get_tax_classes();
	$classes_options  = wc_get_product_tax_class_options();
	$show_tax_columns = count( $order_taxes ) === 1;
}
?>
<div class="woocommerce_order_items_wrapper wc-order-items-editable">
	<table cellpadding="0" cellspacing="0" class="woocommerce_order_items">
		<thead>
			<tr>
				<th class="item sortable" colspan="2" data-sort="string-ins"><?php esc_html_e( 'Item', 'woocommerce' ); ?></th>
				<?php do_action( 'woocommerce_admin_order_item_headers', $order ); ?>
				<?php if ( $cogs_is_enabled ) : ?>
					<th class="item_cost_of_goods sortable" data-sort="float"><?php esc_html_e( 'Cost', 'woocommerce' ); ?></th>
				<?php endif; ?>
				<th class="item_cost sortable" data-sort="float"><?php esc_html_e( 'Price', 'woocommerce' ); ?></th>
				<th class="quantity sortable" data-sort="int"><?php esc_html_e( 'Qty', 'woocommerce' ); ?></th>
				<th class="line_cost sortable" data-sort="float"><?php esc_html_e( 'Total', 'woocommerce' ); ?></th>
				<?php
				if ( ! empty( $order_taxes ) ) :
					foreach ( $order_taxes as $tax_id => $tax_item ) :
						$tax_class      = wc_get_tax_class_by_tax_id( $tax_item['rate_id'] );
						$tax_class_name = isset( $classes_options[ $tax_class ] ) ? $classes_options[ $tax_class ] : __( 'Tax', 'woocommerce' );
						$column_label   = ! empty( $tax_item['label'] ) ? $tax_item['label'] : __( 'Tax', 'woocommerce' );
						/* translators: %1$s: tax item name %2$s: tax class name  */
						$column_tip = sprintf( esc_html__( '%1$s (%2$s)', 'woocommerce' ), $tax_item['name'], $tax_class_name );
						?>
						<th class="line_tax tips" data-tip="<?php echo esc_attr( $column_tip ); ?>">
							<?php echo esc_attr( $column_label ); ?>
							<input type="hidden" class="order-tax-id" name="order_taxes[<?php echo esc_attr( $tax_id ); ?>]" value="<?php echo esc_attr( $tax_item['rate_id'] ); ?>">
							<?php if ( $order->is_editable() ) : ?>
								<a class="delete-order-tax" href="#" data-rate_id="<?php echo esc_attr( $tax_id ); ?>"></a>
							<?php endif; ?>
						</th>
						<?php
					endforeach;
				endif;
				?>
				<th class="wc-order-edit-line-item" width="1%">&nbsp;</th>
			</tr>
		</thead>
		<tbody id="order_line_items">
			<?php
			foreach ( $line_items as $item_id => $item ) {
				do_action( 'woocommerce_before_order_item_' . $item->get_type() . '_html', $item_id, $item, $order );

				include __DIR__ . '/html-order-item.php';

				do_action( 'woocommerce_order_item_' . $item->get_type() . '_html', $item_id, $item, $order );
			}
			do_action( 'woocommerce_admin_order_items_after_line_items', $order->get_id() );
			?>
		</tbody>
		<tbody id="order_fee_line_items">
			<?php
			foreach ( $line_items_fee as $item_id => $item ) {
				include __DIR__ . '/html-order-fee.php';
			}
			do_action( 'woocommerce_admin_order_items_after_fees', $order->get_id() );
			?>
		</tbody>
		<tbody id="order_shipping_line_items">
			<?php
			$shipping_methods = WC()->shipping() ? WC()->shipping()->load_shipping_methods() : array();
			foreach ( $line_items_shipping as $item_id => $item ) {
				include __DIR__ . '/html-order-shipping.php';
			}
			do_action( 'woocommerce_admin_order_items_after_shipping', $order->get_id() );
			?>
		</tbody>
		<tbody id="order_refunds">
			<?php
			$refunds = $order->get_refunds();

			if ( $refunds ) {
				foreach ( $refunds as $refund ) {
					include __DIR__ . '/html-order-refund.php';
				}
				do_action( 'woocommerce_admin_order_items_after_refunds', $order->get_id() );
			}
			?>
		</tbody>
	</table>
</div>
<div class="wc-order-data-row wc-order-totals-items wc-order-items-editable">
	<?php
	$coupons = $order->get_items( 'coupon' );
	if ( $coupons ) :
		?>
		<div class="wc-used-coupons">
			<ul class="wc_coupon_list">
				<li><strong><?php esc_html_e( 'Coupon(s)', 'woocommerce' ); ?></strong></li>
				<?php
				foreach ( $coupons as $item_id => $item ) :
					$coupon_info = $item->get_meta( 'coupon_info' );
					if ( $coupon_info ) {
						$coupon_info = json_decode( $coupon_info, true );
						$post_id     = $coupon_info[0]; //phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
					} else {
						$post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' AND post_date < %s LIMIT 1;", wc_sanitize_coupon_code( $item->get_code() ), $order->get_date_created()->format( 'Y-m-d H:i:s' ) ) ); // phpcs:disable WordPress.WP.GlobalVariablesOverride.Prohibited
					}
					$class = $order->is_editable() ? 'code editable' : 'code';
					?>
					<li class="<?php echo esc_attr( $class ); ?>">
						<?php if ( $post_id ) : ?>
							<?php
							$post_url = apply_filters(
								'woocommerce_admin_order_item_coupon_url',
								add_query_arg(
									array(
										'post'   => $post_id,
										'action' => 'edit',
									),
									admin_url( 'post.php' )
								),
								$item,
								$order
							);
							?>
							<a href="<?php echo esc_url( $post_url ); ?>" class="tips" data-tip="<?php echo esc_attr( wc_price( $item->get_discount(), array( 'currency' => $order->get_currency() ) ) ); ?>">
								<span><?php echo esc_html( $item->get_code() ); ?></span>
							</a>
						<?php else : ?>
							<span class="tips" data-tip="<?php echo esc_attr( wc_price( $item->get_discount(), array( 'currency' => $order->get_currency() ) ) ); ?>">
								<span><?php echo esc_html( $item->get_code() ); ?></span>
							</span>
						<?php endif; ?>
						<?php if ( $order->is_editable() ) : ?>
							<a class="remove-coupon" href="javascript:void(0)" aria-label="Remove" data-code="<?php echo esc_attr( $item->get_code() ); ?>"></a>
						<?php endif; ?>
					</li>
				<?php endforeach; ?>
			</ul>
		</div>
	<?php endif; ?>
	<table class="wc-order-totals">
			<tr>
				<td class="label"><?php esc_html_e( 'Items Subtotal:', 'woocommerce' ); ?></td>
				<td width="1%"></td>
				<td class="total">
					<?php echo wc_price( $order->get_subtotal(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				</td>
			</tr>
		<?php if ( 0 < $order->get_total_discount() ) : ?>
			<tr>
				<td class="label"><?php esc_html_e( 'Discount:', 'woocommerce' ); ?></td>
				<td width="1%"></td>
				<td class="total">-
					<?php echo wc_price( $order->get_total_discount(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				</td>
			</tr>
		<?php endif; ?>
		<?php if ( abs( $order->get_total_fees() ) > 0 ) : ?>
			<tr>
				<td class="label"><?php esc_html_e( 'Fees:', 'woocommerce' ); ?></td>
				<td width="1%"></td>
				<td class="total">
					<?php echo wc_price( $order->get_total_fees(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				</td>
			</tr>
		<?php endif; ?>

		<?php do_action( 'woocommerce_admin_order_totals_after_discount', $order->get_id() ); ?>

		<?php if ( $order->get_shipping_methods() ) : ?>
			<tr>
				<td class="label"><?php esc_html_e( 'Shipping:', 'woocommerce' ); ?></td>
				<td width="1%"></td>
				<td class="total">
					<?php echo wc_price( $order->get_shipping_total(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				</td>
			</tr>
		<?php endif; ?>

		<?php do_action( 'woocommerce_admin_order_totals_after_shipping', $order->get_id() ); ?>

		<?php if ( wc_tax_enabled() ) : ?>
			<?php foreach ( $order->get_tax_totals() as $code => $tax_total ) : ?>
				<tr>
					<td class="label"><?php echo esc_html( $tax_total->label ); ?>:</td>
					<td width="1%"></td>
					<td class="total">
						<?php
							// We use wc_round_tax_total here because tax may need to be round up or round down depending upon settings, whereas wc_price alone will always round it down.
							echo wc_price( wc_round_tax_total( $tax_total->amount ), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
						?>
					</td>
				</tr>
			<?php endforeach; ?>
		<?php endif; ?>

		<?php do_action( 'woocommerce_admin_order_totals_after_tax', $order->get_id() ); ?>

		<tr>
			<td class="label"><?php esc_html_e( 'Order Total', 'woocommerce' ); ?>:</td>
			<td width="1%"></td>
			<td class="total">
				<?php echo wc_price( $order->get_total(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
			</td>
		</tr>

	</table>

	<div class="clear"></div>

	<?php if ( in_array( $order->get_status(), array( OrderStatus::PROCESSING, OrderStatus::COMPLETED, OrderStatus::REFUNDED ), true ) && ! empty( $order->get_date_paid() ) ) : ?>

		<table class="wc-order-totals" style="border-top: 1px solid #999; margin-top:12px; padding-top:12px">
			<tr>
				<td class="<?php echo $order->get_total_refunded() ? 'label' : 'label label-highlight'; ?>"><?php esc_html_e( 'Paid', 'woocommerce' ); ?>: <br /></td>
				<td width="1%"></td>
				<td class="total">
					<?php echo wc_price( $order->get_total(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				</td>
			</tr>
			<tr>
				<td>
					<span class="description">
					<?php
					if ( $order->get_payment_method_title() ) {
						/* translators: 1: payment date. 2: payment method */
						echo esc_html( sprintf( __( '%1$s via %2$s', 'woocommerce' ), $order->get_date_paid()->date_i18n( get_option( 'date_format' ) ), $order->get_payment_method_title() ) );
					} else {
						echo esc_html( $order->get_date_paid()->date_i18n( get_option( 'date_format' ) ) );
					}
					?>
					</span>
				</td>
				<td colspan="2"></td>
			</tr>
		</table>

	<div class="clear"></div>

	<?php endif; ?>

	<?php if ( $order->get_total_refunded() ) : ?>
		<table class="wc-order-totals" style="border-top: 1px solid #999; margin-top:12px; padding-top:12px">
			<tr>
				<td class="label refunded-total"><?php esc_html_e( 'Refunded', 'woocommerce' ); ?>:</td>
				<td width="1%"></td>
				<td class="total refunded-total">-<?php echo wc_price( $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
			</tr>

			<?php do_action( 'woocommerce_admin_order_totals_after_refunded', $order->get_id() ); ?>

			<tr>
				<td class="label label-highlight"><?php esc_html_e( 'Net Payment', 'woocommerce' ); ?>:</td>
				<td width="1%"></td>
				<td class="total">
				<?php echo wc_price( $order->get_total() - $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				</td>
			</tr>

		</table>
	<?php endif; ?>

	<?php if ( $cogs_is_enabled ) : ?>
		<div class="clear"></div>

		<table class="wc-order-totals">
			<tr>
				<td class="label cost-total"><?php esc_html_e( 'Cost Total', 'woocommerce' ); ?>:</td>
				<td width="1%"></td>
				<td class="total cost-total">
					<?php echo wp_kses_post( $order->get_cogs_total_value_html() ); ?>
				</td>
			</tr>
		</table>
	<?php endif; ?>

	<div class="clear"></div>

	<table class="wc-order-totals">
		<?php do_action( 'woocommerce_admin_order_totals_after_total', $order->get_id() ); ?>
	</table>

	<div class="clear"></div>
</div>
<div class="wc-order-data-row wc-order-bulk-actions wc-order-data-row-toggle">
	<p class="add-items">
		<?php if ( $order->is_editable() ) : ?>
			<button type="button" class="button add-line-item"><?php esc_html_e( 'Add item(s)', 'woocommerce' ); ?></button>
			<?php if ( wc_coupons_enabled() ) : ?>
				<button type="button" class="button add-coupon"><?php esc_html_e( 'Apply coupon', 'woocommerce' ); ?></button>
			<?php endif; ?>
		<?php else : ?>
			<span class="description"><?php echo wc_help_tip( __( 'To edit this order change the status back to "Pending payment"', 'woocommerce' ) ); ?> <?php esc_html_e( 'This order is no longer editable.', 'woocommerce' ); ?></span>
		<?php endif; ?>
		<?php if ( $render_refunds ) : ?>
			<button type="button" class="button refund-items"><?php esc_html_e( 'Refund', 'woocommerce' ); ?></button>
		<?php endif; ?>
		<?php
			// Allow adding custom buttons.
			do_action( 'woocommerce_order_item_add_action_buttons', $order );
		?>
		<?php if ( $order->is_editable() ) : ?>
			<button type="button" class="button button-primary calculate-action"><?php esc_html_e( 'Recalculate', 'woocommerce' ); ?></button>
		<?php endif; ?>
	</p>
</div>
<div class="wc-order-data-row wc-order-add-item wc-order-data-row-toggle" style="display:none;">
	<button type="button" class="button add-order-item"><?php esc_html_e( 'Add product(s)', 'woocommerce' ); ?></button>
	<button type="button" class="button add-order-fee"><?php esc_html_e( 'Add fee', 'woocommerce' ); ?></button>
	<button type="button" class="button add-order-shipping"><?php esc_html_e( 'Add shipping', 'woocommerce' ); ?></button>
	<?php if ( wc_tax_enabled() ) : ?>
		<button type="button" class="button add-order-tax"><?php esc_html_e( 'Add tax', 'woocommerce' ); ?></button>
	<?php endif; ?>
	<?php
		// Allow adding custom buttons.
		do_action( 'woocommerce_order_item_add_line_buttons', $order );
	?>
	<button type="button" class="button cancel-action"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>
	<button type="button" class="button button-primary save-action"><?php esc_html_e( 'Save', 'woocommerce' ); ?></button>
</div>
<?php if ( $render_refunds ) : ?>
<div class="wc-order-data-row wc-order-refund-items wc-order-data-row-toggle" style="display: none;">
	<table class="wc-order-totals">
		<?php if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) : ?>
			<tr>
				<td class="label"><label for="restock_refunded_items"><?php esc_html_e( 'Restock refunded items', 'woocommerce' ); ?>:</label></td>
				<td class="total"><input type="checkbox" id="restock_refunded_items" name="restock_refunded_items" <?php checked( apply_filters( 'woocommerce_restock_refunded_items', true ) ); ?> /></td>
			</tr>
		<?php endif; ?>
		<tr>
			<td class="label"><?php esc_html_e( 'Amount already refunded', 'woocommerce' ); ?>:</td>
			<td class="total">-<?php echo wc_price( $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
		</tr>
		<tr>
			<td class="label"><?php esc_html_e( 'Total available to refund', 'woocommerce' ); ?>:</td>
			<td class="total"><?php echo wc_price( $order->get_total() - $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
		</tr>
		<tr>
			<td class="label">
				<label for="refund_amount">
					<?php echo wc_help_tip( __( 'Refund the line items above. This will show the total amount to be refunded', 'woocommerce' ) ); ?>
					<?php esc_html_e( 'Refund amount', 'woocommerce' ); ?>:
				</label>
			</td>
			<td class="total">
				<input type="text" id="refund_amount" name="refund_amount" class="wc_input_price"
				<?php
				if ( wc_tax_enabled() ) {
					// If taxes are enabled, using this refund amount can cause issues due to taxes not being refunded also.
					// The refunds should be added to the line items, not the order as a whole.
					echo 'readonly';
				}
				?>
				/>
				<div class="clear"></div>
			</td>
		</tr>
		<tr>
			<td class="label">
				<label for="refund_reason">
					<?php echo wc_help_tip( __( 'Note: the refund reason will be visible by the customer.', 'woocommerce' ) ); ?>
					<?php esc_html_e( 'Reason for refund (optional):', 'woocommerce' ); ?>
				</label>
			</td>
			<td class="total">
				<input type="text" id="refund_reason" name="refund_reason" />
				<div class="clear"></div>
			</td>
		</tr>
	</table>
	<div class="clear"></div>
	<div class="refund-actions">
		<?php
		$refund_amount = '<span class="wc-order-refund-amount">' . wc_price( 0, array( 'currency' => $order->get_currency() ) ) . '</span>';
		$gateway_name  = false !== $payment_gateway ? ( ! empty( $payment_gateway->method_title ) ? $payment_gateway->method_title : $payment_gateway->get_title() ) : __( 'Payment gateway', 'woocommerce' );

		if ( false !== $payment_gateway && $payment_gateway->can_refund_order( $order ) ) {
			/* translators: refund amount, gateway name */
			echo '<button type="button" class="button button-primary do-api-refund">' . sprintf( esc_html__( 'Refund %1$s via %2$s', 'woocommerce' ), wp_kses_post( $refund_amount ), esc_html( $gateway_name ) ) . '</button>';
		}
		?>
		<?php /* translators: refund amount  */ ?>
		<button type="button" class="button button-primary do-manual-refund tips" data-tip="<?php esc_attr_e( 'You will need to manually issue a refund through your payment gateway after using this.', 'woocommerce' ); ?>"><?php printf( esc_html__( 'Refund %s manually', 'woocommerce' ), wp_kses_post( $refund_amount ) ); ?></button>
		<button type="button" class="button cancel-action"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>
		<input type="hidden" id="refunded_amount" name="refunded_amount" value="<?php echo esc_attr( $order->get_total_refunded() ); ?>" />
		<div class="clear"></div>
	</div>
</div>
<?php endif; ?>

<script type="text/template" id="tmpl-wc-modal-add-products">
	<div class="wc-backbone-modal">
		<div class="wc-backbone-modal-content">
			<section class="wc-backbone-modal-main" role="main">
				<header class="wc-backbone-modal-header">
					<h1><?php esc_html_e( 'Add products', 'woocommerce' ); ?></h1>
					<button class="modal-close modal-close-link dashicons dashicons-no-alt">
						<span class="screen-reader-text">Close modal panel</span>
					</button>
				</header>
				<article>
					<form action="" method="post">
						<table class="widefat">
							<thead>
								<tr>
									<th><?php esc_html_e( 'Product', 'woocommerce' ); ?></th>
									<th><?php esc_html_e( 'Quantity', 'woocommerce' ); ?></th>
								</tr>
							</thead>
							<?php
								$row = '
									<td><select class="wc-product-search" name="item_id" data-allow_clear="true" data-display_stock="true" data-exclude_type="variable" data-placeholder="' . esc_attr__( 'Search for a product&hellip;', 'woocommerce' ) . '"></select></td>
									<td><input type="number" step="1" min="0" max="9999" autocomplete="off" name="item_qty" placeholder="1" size="4" class="quantity" /></td>';
							?>
							<tbody data-row="<?php echo esc_attr( $row ); ?>">
								<tr>
									<?php echo $row; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
								</tr>
							</tbody>
						</table>
					</form>
				</article>
				<footer>
					<div class="inner">
						<button id="btn-ok" class="button button-primary button-large"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
					</div>
				</footer>
			</section>
		</div>
	</div>
	<div class="wc-backbone-modal-backdrop modal-close"></div>
</script>

<script type="text/template" id="tmpl-wc-modal-add-tax">
	<div class="wc-backbone-modal">
		<div class="wc-backbone-modal-content">
			<section class="wc-backbone-modal-main" role="main">
				<header class="wc-backbone-modal-header">
					<h1><?php esc_html_e( 'Add tax', 'woocommerce' ); ?></h1>
					<button class="modal-close modal-close-link dashicons dashicons-no-alt">
						<span class="screen-reader-text">Close modal panel</span>
					</button>
				</header>
				<article>
					<form action="" method="post">
						<table class="widefat">
							<thead>
								<tr>
									<th>&nbsp;</th>
									<th><?php esc_html_e( 'Rate name', 'woocommerce' ); ?></th>
									<th><?php esc_html_e( 'Tax class', 'woocommerce' ); ?></th>
									<th><?php esc_html_e( 'Rate code', 'woocommerce' ); ?></th>
									<th><?php esc_html_e( 'Rate %', 'woocommerce' ); ?></th>
								</tr>
							</thead>
						<?php
						$rates = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates ORDER BY tax_rate_name LIMIT 100" );
						foreach ( $rates as $rate ) {
							echo '
									<tr>
										<td><input type="radio" id="add_order_tax_' . absint( $rate->tax_rate_id ) . '" name="add_order_tax" value="' . absint( $rate->tax_rate_id ) . '" /></td>
										<td><label for="add_order_tax_' . absint( $rate->tax_rate_id ) . '">' . esc_html( WC_Tax::get_rate_label( $rate ) ) . '</label></td>
										<td>' . ( isset( $classes_options[ $rate->tax_rate_class ] ) ? esc_html( $classes_options[ $rate->tax_rate_class ] ) : '-' ) . '</td>
										<td>' . esc_html( WC_Tax::get_rate_code( $rate ) ) . '</td>
										<td>' . esc_html( WC_Tax::get_rate_percent( $rate ) ) . '</td>
									</tr>
								';
						}
						?>
						</table>
						<?php if ( absint( $wpdb->get_var( "SELECT COUNT(tax_rate_id) FROM {$wpdb->prefix}woocommerce_tax_rates;" ) ) > 100 ) : ?>
							<p>
								<label for="manual_tax_rate_id"><?php esc_html_e( 'Or, enter tax rate ID:', 'woocommerce' ); ?></label><br/>
								<input type="number" name="manual_tax_rate_id" id="manual_tax_rate_id" step="1" placeholder="<?php esc_attr_e( 'Optional', 'woocommerce' ); ?>" />
							</p>
						<?php endif; ?>
					</form>
				</article>
				<footer>
					<div class="inner">
						<button id="btn-ok" class="button button-primary button-large"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
					</div>
				</footer>
			</section>
		</div>
	</div>
	<div class="wc-backbone-modal-backdrop modal-close"></div>
</script>
PK     tS\\<9    )  meta-boxes/views/html-order-item-meta.phpnu [        <?php
/**
 * Shows an order item meta
 *
 * @package WooCommerce\Admin
 * @var object $item The item being displayed
 * @var int $item_id The id of the item being displayed
 */
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$hidden_order_itemmeta = apply_filters(
	'woocommerce_hidden_order_itemmeta',
	array(
		'_qty',
		'_tax_class',
		'_product_id',
		'_variation_id',
		'_line_subtotal',
		'_line_subtotal_tax',
		'_line_total',
		'_line_tax',
		'method_id',
		'cost',
		'_reduced_stock',
		'_restock_refunded_items',
	)
);
?><div class="view">
	<?php
	$meta_data = $item->get_all_formatted_meta_data( '' );
	if ( $meta_data ) :
		?>
		<table cellspacing="0" class="display_meta">
			<?php
			foreach ( $meta_data as $meta_id => $meta ) :
				if ( in_array( $meta->key, $hidden_order_itemmeta, true ) ) {
					continue;
				}
				?>
				<tr>
					<th><?php echo wp_kses_post( $meta->display_key ); ?>:</th>
					<td><?php echo wp_kses_post( force_balance_tags( $meta->display_value ) ); ?></td>
				</tr>
			<?php endforeach; ?>
		</table>
	<?php endif; ?>
</div>
<div class="edit" style="display: none;">
	<table class="meta" cellspacing="0">
		<tbody class="meta_items">
			<?php if ( $meta_data ) : ?>
				<?php
				foreach ( $meta_data as $meta_id => $meta ) :
					if ( in_array( $meta->key, $hidden_order_itemmeta, true ) ) {
						continue;
					}
					?>
					<tr data-meta_id="<?php echo esc_attr( $meta_id ); ?>">
						<td>
							<input type="text" maxlength="255" placeholder="<?php esc_attr_e( 'Name (required)', 'woocommerce' ); ?>" name="meta_key[<?php echo esc_attr( $item_id ); ?>][<?php echo esc_attr( $meta_id ); ?>]" value="<?php echo esc_attr( $meta->key ); ?>" />
							<textarea placeholder="<?php esc_attr_e( 'Value (required)', 'woocommerce' ); ?>" name="meta_value[<?php echo esc_attr( $item_id ); ?>][<?php echo esc_attr( $meta_id ); ?>]"><?php echo esc_textarea( rawurldecode( $meta->value ) ); ?></textarea>
						</td>
						<td width="1%"><button class="remove_order_item_meta button">&times;</button></td>
					</tr>
				<?php endforeach; ?>
			<?php endif; ?>
		</tbody>
		<tfoot>
			<tr>
				<td colspan="4"><button class="add_order_item_meta button"><?php esc_html_e( 'Add&nbsp;meta', 'woocommerce' ); ?></button></td>
			</tr>
		</tfoot>
	</table>
</div>
PK     tS\    /  meta-boxes/views/html-product-data-advanced.phpnu [        <?php
/**
 * Product advanced data panel.
 *
 * @package WooCommerce\Admin
 * @var WC_Product $product_object
 */

use Automattic\WooCommerce\Utilities\FeaturesUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div id="advanced_product_data" class="panel woocommerce_options_panel hidden">

	<div class="options_group hide_if_external hide_if_grouped">
		<?php
		woocommerce_wp_textarea_input(
			array(
				'id'          => '_purchase_note',
				'value'       => $product_object->get_purchase_note( 'edit' ),
				'label'       => __( 'Purchase note', 'woocommerce' ),
				'desc_tip'    => true,
				'description' => __( 'Enter an optional note to send the customer after purchase.', 'woocommerce' ),
			)
		);
		?>
	</div>

	<div class="options_group">
		<?php
		woocommerce_wp_text_input(
			array(
				'id'                => 'menu_order',
				'value'             => $product_object->get_menu_order( 'edit' ),
				'label'             => __( 'Menu order', 'woocommerce' ),
				'desc_tip'          => true,
				'description'       => __( 'Custom ordering position.', 'woocommerce' ),
				'type'              => 'number',
				'custom_attributes' => array(
					'step' => '1',
				),
			)
		);
		?>
	</div>

	<?php if ( post_type_supports( 'product', 'comments' ) ) : ?>
		<div class="options_group reviews">
			<?php
				woocommerce_wp_checkbox(
					array(
						'id'      => 'comment_status',
						'value'   => $product_object->get_reviews_allowed( 'edit' ) ? 'open' : 'closed',
						'label'   => __( 'Enable reviews', 'woocommerce' ),
						'cbvalue' => 'open',
					)
				);
				do_action( 'woocommerce_product_options_reviews' );
			?>
		</div>
	<?php endif; ?>
	<?php if ( FeaturesUtil::feature_is_enabled( 'point_of_sale' ) ) : ?>
		<?php $is_pos_supported = $product_object->is_type( array( 'simple', 'variable' ) ) && ! $product_object->is_downloadable(); ?>
		<div class="options_group" id="pos_visibility_supported" <?php echo $is_pos_supported ? '' : 'style="display: none;"'; ?>>
			<?php
			$visible_in_pos = ! has_term( 'pos-hidden', 'pos_product_visibility', $product_object->get_id() );
			woocommerce_wp_checkbox(
				array(
					'id'          => '_visible_in_pos',
					'value'       => $visible_in_pos ? 'yes' : 'no',
					'label'       => __( 'Available for POS', 'woocommerce' ),
					'desc_tip'    => true,
					'description' => __( 'Controls whether this product appears in the Point of Sale system.', 'woocommerce' ),
				)
			);
			?>
		</div>
		<div class="options_group" id="pos_visibility_unsupported" <?php echo $is_pos_supported ? 'style="display: none;"' : ''; ?>>
			<?php
			woocommerce_wp_note(
				array(
					'id'      => '_pos_visibility_note',
					'label'   => __( 'Point of Sale', 'woocommerce' ),
					'message' => __( 'This product type is not currently supported.', 'woocommerce' ),
				)
			);
			?>
		</div>
	<?php endif; ?>

	<?php do_action( 'woocommerce_product_options_advanced' ); ?>
</div>
PK     tS\    +  meta-boxes/views/html-product-attribute.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div data-taxonomy="<?php echo esc_attr( $attribute->get_taxonomy() ); ?>" class="woocommerce_attribute wc-metabox postbox closed <?php echo esc_attr( implode( ' ', $metabox_class ) ); ?>" rel="<?php echo esc_attr( $attribute->get_position() ); ?>">
	<h3>
		<div class="handlediv" title="<?php esc_attr_e( 'Click to toggle', 'woocommerce' ); ?>"></div>
		<div class="tips sort" data-tip="<?php esc_attr_e( 'Drag and drop to set admin attribute order', 'woocommerce' ); ?>"></div>
		<a href="#" class="remove_row delete"><?php esc_html_e( 'Remove', 'woocommerce' ); ?></a>
		<strong class="attribute_name<?php echo esc_attr( $attribute->get_name() === '' ? ' placeholder' : '' ); ?>"><?php echo esc_html( $attribute->get_name() !== '' ? wc_attribute_label( $attribute->get_name() ) : __( 'New attribute', 'woocommerce' ) ); ?></strong>
	</h3>
	<div class="woocommerce_attribute_data wc-metabox-content hidden">
		<?php require __DIR__ . '/html-product-attribute-inner.php'; ?>
	</div>
</div>
PK     tS\_A  A  4  meta-boxes/views/html-product-variation-download.phpnu [        <?php
/**
 * Template used to form individual rows within the downloadable files table for variables.
 *
 * @package WooCommerce\Admin\Views
 *
 * @var bool   $disabled_download Indicates if the current downloadable file is disabled.
 * @var array  $file              Product download data.
 * @var string $key               Product download key.
 * @var int    $variation_id      Variation ID.
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<tr>
	<td class="file_name">
		<input type="text" class="input_text" placeholder="<?php esc_attr_e( 'File name', 'woocommerce' ); ?>" name="_wc_variation_file_names[<?php echo esc_attr( $variation_id ); ?>][]" value="<?php echo esc_attr( $file['name'] ); ?>" />
		<input type="hidden" name="_wc_variation_file_hashes[<?php echo esc_attr( $variation_id ); ?>][]" value="<?php echo esc_attr( $key ); ?>" />
	</td>
	<td class="file_url">
		<input type="text" class="input_text" placeholder="<?php esc_attr_e( 'https://', 'woocommerce' ); ?>" name="_wc_variation_file_urls[<?php echo esc_attr( $variation_id ); ?>][]" value="<?php echo esc_attr( $file['file'] ); ?>" />
		<?php if ( $disabled_download ) : ?>
			<span class="disabled">*</span>
		<?php endif; ?>
	</td>
	<td class="file_url_choose" width="1%"><a href="#" class="button upload_file_button" data-choose="<?php esc_attr_e( 'Choose file', 'woocommerce' ); ?>" data-update="<?php esc_attr_e( 'Insert file URL', 'woocommerce' ); ?>"><?php esc_html_e( 'Choose file', 'woocommerce' ); ?></a></td>
	<td width="1%"><a href="#" class="delete"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a></td>
</tr>
PK     tS\HU    *  meta-boxes/views/html-product-download.phpnu [        <?php
/**
 * Template used to form individual rows within the downloadable files table.
 *
 * @package WooCommerce\Admin\Views
 *
 * @var bool   $disabled_download Indicates if the current downloadable file is disabled.
 * @var array  $file              Product download data.
 * @var string $key               Product download key.
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<tr>
	<td class="sort"></td>
	<td class="file_name">
		<input type="text" class="input_text" placeholder="<?php esc_attr_e( 'File name', 'woocommerce' ); ?>" name="_wc_file_names[]" value="<?php echo esc_attr( $file['name'] ); ?>" />
		<input type="hidden" name="_wc_file_hashes[]" value="<?php echo esc_attr( $key ); ?>" />
	</td>
	<td class="file_url">
		<input type="text" class="input_text" placeholder="<?php esc_attr_e( 'https://', 'woocommerce' ); ?>" name="_wc_file_urls[]" value="<?php echo esc_attr( $file['file'] ); ?>" />
		<?php if ( $disabled_download ) : ?>
			<span class="disabled">*</span>
		<?php endif; ?>
	</td>
	<td class="file_url_choose" width="1%"><a href="#" class="button upload_file_button" data-choose="<?php esc_attr_e( 'Choose file', 'woocommerce' ); ?>" data-update="<?php esc_attr_e( 'Insert file URL', 'woocommerce' ); ?>"><?php echo esc_html__( 'Choose file', 'woocommerce' ); ?></a></td>
	<td width="1%"><a href="#" class="delete"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a></td>
</tr>
PK     tS\eh    3  meta-boxes/views/html-order-download-permission.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div class="wc-metabox closed">
	<h3 class="fixed">
		<button type="button" data-permission_id="<?php echo esc_attr( $download->get_id() ); ?>" rel="<?php echo esc_attr( $download->get_product_id() ) . ',' . esc_attr( $download->get_download_id() ); ?>" class="revoke_access button"><?php esc_html_e( 'Revoke access', 'woocommerce' ); ?></button>
		<div class="handlediv" aria-label="<?php esc_attr_e( 'Click to toggle', 'woocommerce' ); ?>"></div>
		<strong>
			<?php
			printf(
				'#%s &mdash; %s &mdash; %s: %s &mdash; ',
				esc_html( $product->get_id() ),
				esc_html( apply_filters( 'woocommerce_admin_download_permissions_title', $product->get_name(), $download->get_product_id(), $download->get_order_id(), $download->get_order_key(), $download->get_download_id() ) ),
				esc_html( $file_count ),
				esc_html( wc_get_filename_from_url( $product->get_file_download_path( $download->get_download_id() ) ) )
			);
			printf( _n( 'Downloaded %s time', 'Downloaded %s times', $download->get_download_count(), 'woocommerce' ), esc_html( $download->get_download_count() ) )
			?>
		</strong>
	</h3>
	<table cellpadding="0" cellspacing="0" class="wc-metabox-content">
		<tbody>
			<tr>
				<td>
					<label><?php esc_html_e( 'Downloads remaining', 'woocommerce' ); ?></label>
					<input type="hidden" name="permission_id[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $download->get_id() ); ?>" />
					<input type="number" step="1" min="0" class="short" name="downloads_remaining[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $download->get_downloads_remaining() ); ?>" placeholder="<?php esc_attr_e( 'Unlimited', 'woocommerce' ); ?>" />
				</td>
				<td>
					<label><?php esc_html_e( 'Access expires', 'woocommerce' ); ?></label>
					<input type="text" class="short date-picker" name="access_expires[<?php echo esc_attr( $loop ); ?>]" value="<?php echo ! is_null( $download->get_access_expires() ) ? esc_attr( date_i18n( 'Y-m-d', $download->get_access_expires()->getTimestamp() ) ) : ''; ?>" maxlength="10" placeholder="<?php esc_attr_e( 'Never', 'woocommerce' ); ?>" pattern="<?php echo esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ); ?>" />
				</td>
				<td>
					<label><?php esc_html_e( 'Customer download link', 'woocommerce' ); ?></label>
					<?php
					$download_link = add_query_arg(
						array(
							'download_file' => $download->get_product_id(),
							'order'         => $download->get_order_key(),
							'email'         => urlencode( $download->get_user_email() ),
							'key'           => $download->get_download_id(),
						),
						trailingslashit( home_url() )
					);
					?>
					<a id="copy-download-link" class="button" href="<?php echo esc_url( $download_link ); ?>" data-tip="<?php esc_attr_e( 'Copied!', 'woocommerce' ); ?>" data-tip-failed="<?php esc_attr_e( 'Copying to clipboard failed. You should be able to right-click the button and copy.', 'woocommerce' ); ?>"><?php esc_html_e( 'Copy link', 'woocommerce' ); ?></a>
				</td>
				<td>
					<label><?php esc_html_e( 'Customer download log', 'woocommerce' ); ?></label>
					<?php
					$report_url = add_query_arg(
						'permission_id',
						rawurlencode( $download->get_id() ),
						admin_url( 'admin.php?page=wc-reports&tab=orders&report=downloads' )
					);
					echo '<a class="button" href="' . esc_url( $report_url ) . '">';
					esc_html_e( 'View report', 'woocommerce' );
					echo '</a>';
					?>
				</td>
			</tr>
		</tbody>
	</table>
</div>
PK     tS\~
M.  M.  $  meta-boxes/views/html-order-item.phpnu [        <?php
/**
 * Shows an order item
 *
 * @package WooCommerce\Admin
 * @var WC_Order_Item $item The item being displayed
 * @var int $item_id The id of the item being displayed
 */

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;

$product      = $item->get_product();
$product_link = $product ? admin_url( 'post.php?post=' . $item->get_product_id() . '&action=edit' ) : '';
$thumbnail    = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnail', $product->get_image( 'thumbnail', array( 'title' => '' ), false ), $item_id, $item ) : '';
$row_class    = apply_filters( 'woocommerce_admin_html_order_item_class', ! empty( $class ) ? $class : '', $item, $order );
$wc_price_arg = array( 'currency' => $order->get_currency() );
$is_visible   = $product && $product->is_visible();

/**
 * Filter the order item name.
 *
 * @since 9.9.0
 * @param string $item_name The order item's name.
 * @param WC_Order_Item $item The order item object.
 * @param bool $is_visible Item's product visibility in the catalog.
 */
$item_name = apply_filters( 'woocommerce_order_item_name', $item->get_name(), $item, $is_visible );

?>
<tr class="item <?php echo esc_attr( $row_class ); ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
	<td class="thumb">
		<?php echo '<div class="wc-order-item-thumbnail">' . wp_kses_post( $thumbnail ) . '</div>'; ?>
	</td>
	<td class="name" data-sort-value="<?php echo esc_attr( $item_name ); ?>">
		<?php
		echo $product_link ? '<a href="' . esc_url( $product_link ) . '" class="wc-order-item-name">' . wp_kses_post( $item_name ) . '</a>' : '<div class="wc-order-item-name">' . wp_kses_post( $item_name ) . '</div>';

		if ( $product && $product->get_sku() ) {
			echo '<div class="wc-order-item-sku"><strong>' . esc_html__( 'SKU:', 'woocommerce' ) . '</strong> ' . esc_html( $product->get_sku() ) . '</div>';
		}

		if ( $item->get_variation_id() ) {
			echo '<div class="wc-order-item-variation"><strong>' . esc_html__( 'Variation ID:', 'woocommerce' ) . '</strong> ';
			if ( 'product_variation' === get_post_type( $item->get_variation_id() ) ) {
				echo esc_html( $item->get_variation_id() );
			} else {
				/* translators: %s: variation id */
				printf( esc_html__( '%s (No longer exists)', 'woocommerce' ), esc_html( $item->get_variation_id() ) );
			}
			echo '</div>';
		}
		?>
		<input type="hidden" class="order_item_id" name="order_item_id[]" value="<?php echo esc_attr( $item_id ); ?>" />
		<input type="hidden" name="order_item_tax_class[<?php echo absint( $item_id ); ?>]" value="<?php echo esc_attr( $item->get_tax_class() ); ?>" />

		<?php do_action( 'woocommerce_before_order_itemmeta', $item_id, $item, $product ); ?>
		<?php require __DIR__ . '/html-order-item-meta.php'; ?>
		<?php do_action( 'woocommerce_after_order_itemmeta', $item_id, $item, $product ); ?>
	</td>

	<?php do_action( 'woocommerce_admin_order_item_values', $product, $item, absint( $item_id ) ); ?>

	<?php if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() ) : ?>
		<td class="item_cost_of_goods" width="1%" data-sort-value="<?php echo esc_attr( $item->get_cogs_value() ); ?>">
			<?php $tooltip_text = $item->get_cogs_value_per_unit_tooltip_text(); ?>
			<div class="view"
			<?php
			if ( $tooltip_text ) {
				echo " title='" . esc_attr( $tooltip_text ) . "'"; }
			?>
			>
				<?php
				echo wp_kses_post( $item->get_cogs_value_html() );

				$refunded_cost = $order->get_cogs_refunded_for_item( $item_id );
				echo wp_kses_post( $item->get_cogs_refund_value_html( $refunded_cost, $wc_price_arg, $order ) );
				?>
			</div>
		</td>
	<?php endif; ?>
	<td class="item_cost" width="1%" data-sort-value="<?php echo esc_attr( $order->get_item_subtotal( $item, false, true ) ); ?>">
		<div class="view">
			<?php
			echo wc_price( $order->get_item_subtotal( $item, false, true ), $wc_price_arg ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			?>
		</div>
	</td>
	<td class="quantity" width="1%">
		<div class="view">
			<?php
			echo '<small class="times">&times;</small> ' . esc_html( $item->get_quantity() );

			$refunded_qty = -1 * $order->get_qty_refunded_for_item( $item_id );

			if ( $refunded_qty ) {
				echo '<small class="refunded">' . esc_html( $refunded_qty * -1 ) . '</small>';
			}
			?>
		</div>
		<?php
			$step = $product ? $product->get_purchase_quantity_step() : 1;

			/**
			* Filter to change the product quantity stepping in the order editor of the admin area.
			*
			* @since   5.8.0
			* @param   string      $step    The current step amount to be used in the quantity editor.
			* @param   WC_Product  $product The product that is being edited.
			* @param   string      $context The context in which the quantity editor is shown, 'edit' or 'refund'.
			*/
			$step_edit   = apply_filters( 'woocommerce_quantity_input_step_admin', $step, $product, 'edit' );
			$step_refund = apply_filters( 'woocommerce_quantity_input_step_admin', $step, $product, 'refund' );

			/**
			* Filter to change the product quantity minimum in the order editor of the admin area.
			*
			* @since   5.8.0
			* @param   string      $step    The current minimum amount to be used in the quantity editor.
			* @param   WC_Product  $product The product that is being edited.
			* @param   string      $context The context in which the quantity editor is shown, 'edit' or 'refund'.
			*/
			$min_edit   = apply_filters( 'woocommerce_quantity_input_min_admin', '0', $product, 'edit' );
			$min_refund = apply_filters( 'woocommerce_quantity_input_min_admin', '0', $product, 'refund' );
		?>
		<div class="edit" style="display: none;">
			<input type="number" step="<?php echo esc_attr( $step_edit ); ?>" min="<?php echo esc_attr( $min_edit ); ?>" autocomplete="off" name="order_item_qty[<?php echo absint( $item_id ); ?>]" placeholder="0" value="<?php echo esc_attr( $item->get_quantity() ); ?>" data-qty="<?php echo esc_attr( $item->get_quantity() ); ?>" size="4" class="quantity" />
		</div>
		<div class="refund" style="display: none;">
			<input type="number" step="<?php echo esc_attr( $step_refund ); ?>" min="<?php echo esc_attr( $min_refund ); ?>" max="<?php echo absint( $item->get_quantity() ); ?>" autocomplete="off" name="refund_order_item_qty[<?php echo absint( $item_id ); ?>]" placeholder="0" size="4" class="refund_order_item_qty" />
		</div>
	</td>
	<td class="line_cost" width="1%" data-sort-value="<?php echo esc_attr( $item->get_total() ); ?>">
		<div class="view">
			<?php
			echo wc_price( $item->get_total(), $wc_price_arg ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped

			if ( $item->get_subtotal() !== $item->get_total() ) {
				/* translators: %s: discount amount */
				echo '<span class="wc-order-item-discount">' . sprintf( esc_html__( '%s discount', 'woocommerce' ), wc_price( wc_format_decimal( $item->get_subtotal() - $item->get_total(), '' ), $wc_price_arg ) ) . '</span>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			}

			$refunded = -1 * $order->get_total_refunded_for_item( $item_id );

			if ( $refunded ) {
				echo '<small class="refunded">' . wc_price( $refunded, $wc_price_arg ) . '</small>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			}
			?>
		</div>
		<div class="edit" style="display: none;">
			<div class="split-input">
				<div class="input">
					<label><?php esc_attr_e( 'Before discount', 'woocommerce' ); ?></label>
					<input type="text" name="line_subtotal[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_subtotal() ) ); ?>" class="line_subtotal wc_input_price" data-subtotal="<?php echo esc_attr( wc_format_localized_price( $item->get_subtotal() ) ); ?>" />
				</div>
				<div class="input">
					<label><?php esc_attr_e( 'Total', 'woocommerce' ); ?></label>
					<input type="text" name="line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" data-tip="<?php esc_attr_e( 'After pre-tax discounts.', 'woocommerce' ); ?>" data-total="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" />
				</div>
			</div>
		</div>
		<div class="refund" style="display: none;">
			<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_total wc_input_price" />
		</div>
	</td>

	<?php
	$tax_data = wc_tax_enabled() ? $item->get_taxes() : false;

	if ( $tax_data ) {
		foreach ( $order_taxes as $tax_item ) {
			$tax_item_id       = $tax_item->get_rate_id();
			$tax_item_total    = isset( $tax_data['total'][ $tax_item_id ] ) ? $tax_data['total'][ $tax_item_id ] : '';
			$tax_item_subtotal = isset( $tax_data['subtotal'][ $tax_item_id ] ) ? $tax_data['subtotal'][ $tax_item_id ] : '';

			?>
			<td class="line_tax" width="1%">
				<div class="view">
					<?php
					if ( '' !== $tax_item_total ) {
						echo wc_price( wc_round_tax_total( $tax_item_total ), $wc_price_arg ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
					} else {
						echo '&ndash;';
					}

					$refunded = -1 * $order->get_tax_refunded_for_item( $item_id, $tax_item_id );

					if ( $refunded ) {
						echo '<small class="refunded">' . wc_price( $refunded, $wc_price_arg ) . '</small>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
					}
					?>
				</div>
				<div class="edit" style="display: none;">
					<div class="split-input">
						<div class="input">
							<label><?php esc_attr_e( 'Before discount', 'woocommerce' ); ?></label>
							<input type="text" name="line_subtotal_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $tax_item_subtotal ) ); ?>" class="line_subtotal_tax wc_input_price" data-subtotal_tax="<?php echo esc_attr( wc_format_localized_price( $tax_item_subtotal ) ); ?>" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
						</div>
						<div class="input">
							<label><?php esc_attr_e( 'Total', 'woocommerce' ); ?></label>
							<input type="text" name="line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $tax_item_total ) ); ?>" class="line_tax wc_input_price" data-total_tax="<?php echo esc_attr( wc_format_localized_price( $tax_item_total ) ); ?>" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
						</div>
					</div>
				</div>
				<div class="refund" style="display: none;">
					<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
				</div>
			</td>
			<?php
		}
	}
	?>
	<td class="wc-order-edit-line-item" width="1%">
		<div class="wc-order-edit-line-item-actions">
			<?php if ( $order->is_editable() ) : ?>
				<a class="edit-order-item tips" href="#" data-tip="<?php esc_attr_e( 'Edit item', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'Edit item', 'woocommerce' ); ?>"></a><a class="delete-order-item tips" href="#" data-tip="<?php esc_attr_e( 'Delete item', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'Delete item', 'woocommerce' ); ?>"></a>
			<?php endif; ?>
		</div>
	</td>
</tr>
PK     tS\HB?(  ?(  .  meta-boxes/views/html-product-data-general.phpnu [        <?php
/**
 * Product general data panel.
 *
 * @package WooCommerce\Admin
 */

use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Enums\ProductTaxStatus;

?>
<div id="general_product_data" class="panel woocommerce_options_panel">

	<div class="options_group show_if_external">
		<?php
		woocommerce_wp_text_input(
			array(
				'id'          => '_product_url',
				'value'       => is_callable( array( $product_object, 'get_product_url' ) ) ? $product_object->get_product_url( 'edit' ) : '',
				'label'       => __( 'Product URL', 'woocommerce' ),
				'placeholder' => 'https://',
				'description' => __( 'Enter the external URL to the product.', 'woocommerce' ),
			)
		);

		woocommerce_wp_text_input(
			array(
				'id'          => '_button_text',
				'value'       => is_callable( array( $product_object, 'get_button_text' ) ) ? $product_object->get_button_text( 'edit' ) : '',
				'label'       => __( 'Button text', 'woocommerce' ),
				'placeholder' => _x( 'Buy product', 'placeholder', 'woocommerce' ),
				'description' => __( 'This text will be shown on the button linking to the external product.', 'woocommerce' ),
			)
		);

		do_action( 'woocommerce_product_options_external' );
		?>
	</div>

	<?php
		$cogs_controller = wc_get_container()->get( CostOfGoodsSoldController::class );
		$cogs_is_enabled = $cogs_controller->feature_is_enabled();
	?>
	<div class="options_group pricing show_if_simple show_if_external hidden<?php echo $cogs_is_enabled ? ' show_if_variable' : ''; ?>">
		<?php if ( $cogs_is_enabled ) : ?>
			<span class="show_if_simple show_if_external">
		<?php endif; ?>
		<?php
			woocommerce_wp_text_input(
				array(
					'id'        => '_regular_price',
					'value'     => $product_object->get_regular_price( 'edit' ),
					'label'     => __( 'Regular price', 'woocommerce' ) . ' (' . get_woocommerce_currency_symbol() . ')',
					'data_type' => 'price',
				)
			);

			woocommerce_wp_text_input(
				array(
					'id'          => '_sale_price',
					'value'       => $product_object->get_sale_price( 'edit' ),
					'data_type'   => 'price',
					'label'       => __( 'Sale price', 'woocommerce' ) . ' (' . get_woocommerce_currency_symbol() . ')',
					'description' => '<a href="#" class="sale_schedule">' . __( 'Schedule', 'woocommerce' ) . '</a>',
				)
			);

			$sale_price_dates_from_timestamp = $product_object->get_date_on_sale_from( 'edit' ) ? $product_object->get_date_on_sale_from( 'edit' )->getOffsetTimestamp() : false;
			$sale_price_dates_to_timestamp   = $product_object->get_date_on_sale_to( 'edit' ) ? $product_object->get_date_on_sale_to( 'edit' )->getOffsetTimestamp() : false;

			$sale_price_dates_from = $sale_price_dates_from_timestamp ? date_i18n( 'Y-m-d', $sale_price_dates_from_timestamp ) : '';
			$sale_price_dates_to   = $sale_price_dates_to_timestamp ? date_i18n( 'Y-m-d', $sale_price_dates_to_timestamp ) : '';

			// phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment

			/**
			 * Hook to customize the regular expression that validates dates entered in the WooCommerce admin editors.
			 *
			 * @param string $pattern Default pattern to use.
			 */
			$date_input_html_pattern = apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' );

			echo '<p class="form-field sale_price_dates_fields">
					<label for="_sale_price_dates_from">' . esc_html__( 'Sale price dates', 'woocommerce' ) . '</label>
					<input type="text" class="short" name="_sale_price_dates_from" id="_sale_price_dates_from" value="' . esc_attr( $sale_price_dates_from ) . '" placeholder="' . esc_html( _x( 'From&hellip;', 'placeholder', 'woocommerce' ) ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( $date_input_html_pattern ) . '" />
					<input type="text" class="short" name="_sale_price_dates_to" id="_sale_price_dates_to" value="' . esc_attr( $sale_price_dates_to ) . '" placeholder="' . esc_html( _x( 'To&hellip;', 'placeholder', 'woocommerce' ) ) . '  YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( $date_input_html_pattern ) . '" />
					<a href="#" class="description cancel_sale_schedule">' . esc_html__( 'Cancel', 'woocommerce' ) . '</a>' . wc_help_tip( __( 'The sale will start at 00:00:00 of "From" date and end at 23:59:59 of "To" date.', 'woocommerce' ) ) . '
				</p>';

			/**
			 * Action that allows to render additional fields for price related settings in the product editor.
			 */
			do_action( 'woocommerce_product_options_pricing' );

			// phpcs:enable WooCommerce.Commenting.CommentHooks.MissingSinceComment
			?>
		<?php if ( $cogs_is_enabled ) : ?>
			</span>
		<?php endif; ?>
		<?php if ( $cogs_is_enabled ) : ?>
			<span class="show_if_simple show_if_variable show_if_external hidden">
				<?php
				$is_variable = $product_object instanceof WC_Product_Variable;

				woocommerce_wp_text_input(
					array(
						'id'          => '_cogs_value',
						'value'       => $product_object->get_cogs_value() ?? '',
						'label'       => __( 'Cost of goods', 'woocommerce' ) . ' (' . get_woocommerce_currency_symbol() . ')',
						'data_type'   => 'price',
						'desc_tip'    => 'true',
						'placeholder' => '0',
						'description' => $cogs_controller->get_general_cost_edit_field_tooltip( $is_variable ),
					)
				);
				?>
			</span>
		<?php endif; ?>
	</div>

	<div class="options_group show_if_downloadable hidden">
		<div class="form-field downloadable_files">
			<label><?php esc_html_e( 'Downloadable files', 'woocommerce' ); ?></label>
			<table class="widefat">
				<thead>
					<tr>
						<th class="sort">&nbsp;</th>
						<th><?php esc_html_e( 'Name', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the name of the download shown to the customer.', 'woocommerce' ) ); ?></th>
						<th colspan="2"><?php esc_html_e( 'File URL', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the URL or absolute path to the file which customers will get access to. URLs entered here should already be encoded.', 'woocommerce' ) ); ?></th>
						<th>&nbsp;</th>
					</tr>
				</thead>
				<tbody>
					<?php
					$downloadable_files       = $product_object->get_downloads( 'edit' );
					$disabled_downloads_count = 0;

					if ( $downloadable_files ) {
						foreach ( $downloadable_files as $key => $file ) {
							$disabled_download         = isset( $file['enabled'] ) && false === $file['enabled'];
							$disabled_downloads_count += (int) $disabled_download;
							include __DIR__ . '/html-product-download.php';
						}
					}
					?>
				</tbody>
				<tfoot>
					<tr>
						<th colspan="2">
							<a href="#" class="button insert" data-row="
							<?php
								$key               = '';
								$file              = array(
									'file' => '',
									'name' => '',
								);
								$disabled_download = false;
								ob_start();
								require __DIR__ . '/html-product-download.php';
								echo esc_attr( ob_get_clean() );
								?>
							"><?php esc_html_e( 'Add File', 'woocommerce' ); ?></a>
						</th>
						<th colspan="3">
							<?php if ( $disabled_downloads_count ) : ?>
								<span class="disabled">*</span>
								<?php
									printf(
										/* translators: 1: opening link tag, 2: closing link tag. */
										esc_html__( 'The indicated downloads have been disabled (invalid location or filetype&mdash;%1$slearn more%2$s).', 'woocommerce' ),
										'<a href="https://woocommerce.com/document/approved-download-directories" target="_blank">',
										'</a>'
									);
								?>
							<?php endif; ?>
						</th>
					</tr>
				</tfoot>
			</table>
		</div>
		<?php
		woocommerce_wp_text_input(
			array(
				'id'                => '_download_limit',
				'value'             => -1 === $product_object->get_download_limit( 'edit' ) ? '' : $product_object->get_download_limit( 'edit' ),
				'label'             => __( 'Download limit', 'woocommerce' ),
				'placeholder'       => __( 'Unlimited', 'woocommerce' ),
				'description'       => __( 'Leave blank for unlimited re-downloads.', 'woocommerce' ),
				'type'              => 'number',
				'custom_attributes' => array(
					'step' => '1',
					'min'  => '0',
				),
			)
		);

		woocommerce_wp_text_input(
			array(
				'id'                => '_download_expiry',
				'value'             => -1 === $product_object->get_download_expiry( 'edit' ) ? '' : $product_object->get_download_expiry( 'edit' ),
				'label'             => __( 'Download expiry', 'woocommerce' ),
				'placeholder'       => __( 'Never', 'woocommerce' ),
				'description'       => __( 'Enter the number of days before a download link expires, or leave blank.', 'woocommerce' ),
				'type'              => 'number',
				'custom_attributes' => array(
					'step' => '1',
					'min'  => '0',
				),
			)
		);

		do_action( 'woocommerce_product_options_downloads' );
		?>
	</div>

	<?php if ( wc_tax_enabled() ) : ?>
		<div class="options_group show_if_simple show_if_external show_if_variable">
			<?php
			woocommerce_wp_select(
				array(
					'id'          => '_tax_status',
					'value'       => $product_object->get_tax_status( 'edit' ),
					'label'       => __( 'Tax status', 'woocommerce' ),
					'options'     => array(
						ProductTaxStatus::TAXABLE  => __( 'Taxable', 'woocommerce' ),
						ProductTaxStatus::SHIPPING => __( 'Shipping only', 'woocommerce' ),
						ProductTaxStatus::NONE     => _x( 'None', 'Tax status', 'woocommerce' ),
					),
					'desc_tip'    => 'true',
					'description' => __( 'Define whether or not the entire product is taxable, or just the cost of shipping it.', 'woocommerce' ),
				)
			);

			woocommerce_wp_select(
				array(
					'id'          => '_tax_class',
					'value'       => $product_object->get_tax_class( 'edit' ),
					'label'       => __( 'Tax class', 'woocommerce' ),
					'options'     => wc_get_product_tax_class_options(),
					'desc_tip'    => 'true',
					'description' => __( 'Choose a tax class for this product. Tax classes are used to apply different tax rates specific to certain types of product.', 'woocommerce' ),
				)
			);

			do_action( 'woocommerce_product_options_tax' );
			?>
		</div>
	<?php endif; ?>

	<?php do_action( 'woocommerce_product_options_general_product_data' ); ?>
</div>
PK     tS\    (  meta-boxes/views/html-order-shipping.phpnu [        <?php
/**
 * Shows a shipping line
 *
 * @package WooCommerce\Admin
 *
 * @var object $item The item being displayed
 * @var int $item_id The id of the item being displayed
 *
 * @package WooCommerce\Admin\Views
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<tr class="shipping <?php echo ( ! empty( $class ) ) ? esc_attr( $class ) : ''; ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
	<td class="thumb"><div></div></td>

	<td class="name">
		<div class="view">
			<?php echo esc_html( $item->get_name() ? $item->get_name() : __( 'Shipping', 'woocommerce' ) ); ?>
		</div>
		<div class="edit" style="display: none;">
			<input type="hidden" name="shipping_method_id[]" value="<?php echo esc_attr( $item_id ); ?>" />
			<input type="text" class="shipping_method_name" placeholder="<?php esc_attr_e( 'Shipping name', 'woocommerce' ); ?>" name="shipping_method_title[<?php echo esc_attr( $item_id ); ?>]" value="<?php echo esc_attr( $item->get_name() ); ?>" />
			<select class="shipping_method" name="shipping_method[<?php echo esc_attr( $item_id ); ?>]">
				<optgroup label="<?php esc_attr_e( 'Shipping method', 'woocommerce' ); ?>">
					<option value=""><?php esc_html_e( 'N/A', 'woocommerce' ); ?></option>
					<?php
					$found_method = false;

					foreach ( $shipping_methods as $method ) {
						$is_active = $item->get_method_id() === $method->id;

						echo '<option value="' . esc_attr( $method->id ) . '" ' . selected( true, $is_active, false ) . '>' . esc_html( $method->get_method_title() ) . '</option>';

						if ( $is_active ) {
							$found_method = true;
						}
					}

					if ( ! $found_method && $item->get_method_id() ) {
						echo '<option value="' . esc_attr( $item->get_method_id() ) . '" selected="selected">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
					} else {
						echo '<option value="other">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
					}
					?>
				</optgroup>
			</select>
		</div>

		<?php do_action( 'woocommerce_before_order_itemmeta', $item_id, $item, null ); ?>
		<?php require __DIR__ . '/html-order-item-meta.php'; ?>
		<?php do_action( 'woocommerce_after_order_itemmeta', $item_id, $item, null ); ?>
	</td>

	<?php do_action( 'woocommerce_admin_order_item_values', null, $item, absint( $item_id ) ); ?>

	<?php if ( $cogs_is_enabled ) : ?>
	<td class="item_cost_of_goods"></td>
	<?php endif; ?>
	<td class="item_cost" width="1%">&nbsp;</td>
	<td class="quantity" width="1%">&nbsp;</td>

	<td class="line_cost" width="1%">
		<div class="view">
			<?php
			echo wp_kses_post( wc_price( $item->get_total(), array( 'currency' => $order->get_currency() ) ) );
			$refunded = -1 * $order->get_total_refunded_for_item( $item_id, 'shipping' );
			if ( $refunded ) {
				echo wp_kses_post( '<small class="refunded">' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>' );
			}
			?>
		</div>
		<div class="edit" style="display: none;">
			<input type="text" name="shipping_cost[<?php echo esc_attr( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" />
		</div>
		<div class="refund" style="display: none;">
			<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_total wc_input_price" />
		</div>
	</td>

	<?php
	$tax_data = $item->get_taxes();
	if ( $tax_data && wc_tax_enabled() ) {
		foreach ( $order_taxes as $tax_item ) {
			$tax_item_id    = $tax_item->get_rate_id();
			$tax_item_total = isset( $tax_data['total'][ $tax_item_id ] ) ? $tax_data['total'][ $tax_item_id ] : '';
			?>
			<td class="line_tax" width="1%">
				<div class="view">
					<?php
					echo wp_kses_post( ( '' !== $tax_item_total ) ? wc_price( $tax_item_total, array( 'currency' => $order->get_currency() ) ) : '&ndash;' );
					$refunded = -1 * $order->get_tax_refunded_for_item( $item_id, $tax_item_id, 'shipping' );
					if ( $refunded ) {
						echo wp_kses_post( '<small class="refunded">' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>' );
					}
					?>
				</div>
				<div class="edit" style="display: none;">
					<input type="text" name="shipping_taxes[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo ( isset( $tax_item_total ) ) ? esc_attr( wc_format_localized_price( $tax_item_total ) ) : ''; ?>" class="line_tax wc_input_price" />
				</div>
				<div class="refund" style="display: none;">
					<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
				</div>
			</td>
			<?php
		}
	}
	?>
	<td class="wc-order-edit-line-item">
		<?php if ( $order->is_editable() ) : ?>
			<div class="wc-order-edit-line-item-actions">
				<a class="edit-order-item tips" href="#" data-tip="<?php esc_attr_e( 'Edit shipping', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'Edit shipping', 'woocommerce' ); ?>"></a><a class="delete-order-item tips" href="#" data-tip="<?php esc_attr_e( 'Delete shipping', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'Delete shipping', 'woocommerce' ); ?>"></a>
			</div>
		<?php endif; ?>
	</td>
</tr>
PK     tS\ru    %  meta-boxes/views/html-order-notes.phpnu [        <?php
/**
 * Order notes HTML for meta box.
 *
 * @package WooCommerce\Admin
 */

defined( 'ABSPATH' ) || exit;

?>
<ul class="order_notes">
	<?php
	if ( $notes ) {
		foreach ( $notes as $note ) {
			$css_class   = array( 'note' );
			$css_class[] = $note->customer_note ? 'customer-note' : '';
			$css_class[] = 'system' === $note->added_by ? 'system-note' : '';
			$css_class   = apply_filters( 'woocommerce_order_note_class', array_filter( $css_class ), $note );
			?>
			<li rel="<?php echo absint( $note->id ); ?>" class="<?php echo esc_attr( implode( ' ', $css_class ) ); ?>">
				<div class="note_content">
					<?php
					$content = wp_kses_post( $note->content );
					$content = wc_wptexturize_order_note( $content );
					// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- the content goes through wp_kses_post above.
					echo wpautop( $content );
					?>
				</div>
				<p class="meta">
					<abbr class="exact-date" title="<?php echo esc_attr( $note->date_created->date( 'Y-m-d H:i:s' ) ); ?>">
						<?php
						/* translators: %1$s: note date %2$s: note time */
						echo esc_html( sprintf( __( '%1$s at %2$s', 'woocommerce' ), $note->date_created->date_i18n( wc_date_format() ), $note->date_created->date_i18n( wc_time_format() ) ) );
						?>
					</abbr>
					<?php
					if ( 'system' !== $note->added_by ) :
						/* translators: %s: note author */
						echo esc_html( sprintf( ' ' . __( 'by %s', 'woocommerce' ), $note->added_by ) );
					endif;
					?>
					<a href="#" class="delete_note" role="button"><?php esc_html_e( 'Delete note', 'woocommerce' ); ?></a>
				</p>
			</li>
			<?php
		}
	} else {
		?>
		<li class="no-items"><?php esc_html_e( 'There are no notes yet.', 'woocommerce' ); ?></li>
		<?php
	}
	?>
</ul>
PK     tS\V5    1  meta-boxes/views/html-product-attribute-inner.phpnu [        <?php
/**
 * Product attribute table for reuse.
 *
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>

<table cellpadding="0" cellspacing="0">
	<tbody>
	<tr>
		<td class="attribute_name">
			<label><?php esc_html_e( 'Name', 'woocommerce' ); ?>:</label>

			<?php if ( $attribute->is_taxonomy() ) : ?>
				<strong><?php echo esc_html( wc_attribute_label( $attribute->get_name() ) ); ?></strong>
				<input type="hidden" name="attribute_names[<?php echo esc_attr( $i ); ?>]" value="<?php echo esc_attr( $attribute->get_name() ); ?>" />
			<?php else : ?>
				<input type="text" class="attribute_name" name="attribute_names[<?php echo esc_attr( $i ); ?>]" value="<?php echo esc_attr( $attribute->get_name() ); ?>" placeholder="<?php esc_attr_e( 'e.g. length or weight', 'woocommerce' ); ?>" />
			<?php endif; ?>
			<input type="hidden" name="attribute_position[<?php echo esc_attr( $i ); ?>]" class="attribute_position" value="<?php echo esc_attr( $attribute->get_position() ); ?>" />
		</td>
		<td rowspan="3">
			<label><?php esc_html_e( 'Value(s)', 'woocommerce' ); ?>:</label>
			<?php
			if ( $attribute->is_taxonomy() && $attribute->get_taxonomy_object() ) {
				$attribute_taxonomy = $attribute->get_taxonomy_object();
				$attribute_types    = wc_get_attribute_types();

				if ( ! array_key_exists( $attribute_taxonomy->attribute_type, $attribute_types ) ) {
					$attribute_taxonomy->attribute_type = 'select';
				}

				if ( 'select' === $attribute_taxonomy->attribute_type ) {
					$attribute_orderby = ! empty( $attribute_taxonomy->attribute_orderby ) ? $attribute_taxonomy->attribute_orderby : 'name';
					/**
					* Filter the length (number of terms) rendered in the list.
					*
					* @since 8.8.0
					* @param int $term_limit The maximum number of terms to display in the list.
					*/
					$term_limit = absint( apply_filters( 'woocommerce_admin_terms_metabox_datalimit', 50 ) );
					?>
					<select multiple="multiple"
							data-minimum_input_length="0"
							data-limit="<?php echo esc_attr( $term_limit ); ?>" data-return_id="id"
							data-placeholder="<?php esc_attr_e( 'Select values', 'woocommerce' ); ?>"
							data-orderby="<?php echo esc_attr( $attribute_orderby ); ?>"
							class="multiselect attribute_values wc-taxonomy-term-search"
							name="attribute_values[<?php echo esc_attr( $i ); ?>][]"
							data-taxonomy="<?php echo esc_attr( $attribute->get_taxonomy() ); ?>">
						<?php
						$selected_terms = $attribute->get_terms();
						if ( $selected_terms ) {
							foreach ( $selected_terms as $selected_term ) {
								/**
								 * Filter the selected attribute term name.
								 *
								 * @since 3.4.0
								 * @param string  $name Name of selected term.
								 * @param array   $term The selected term object.
								 */
								echo '<option value="' . esc_attr( $selected_term->term_id ) . '" selected="selected">' . esc_html( apply_filters( 'woocommerce_product_attribute_term_name', $selected_term->name, $selected_term ) ) . '</option>';
							}
						}
						?>
					</select>
					<button class="button plus select_all_attributes"><?php esc_html_e( 'Select all', 'woocommerce' ); ?></button>
					<button class="button minus select_no_attributes"><?php esc_html_e( 'Select none', 'woocommerce' ); ?></button>
					<button class="button fr plus add_new_attribute"><?php esc_html_e( 'Create value', 'woocommerce' ); ?></button>
					<?php
				}

				/**
				 * Hook to display custom attribute terms.
				 *
				 * @since 3.4.0
				 * @param array|null $attribute_taxonomy Attribute taxonomy object.
				 * @param int $i Attribute index.
				 * @param WC_Product_Attribute $attribute Attribute object.
				 */
				do_action( 'woocommerce_product_option_terms', $attribute_taxonomy, $i, $attribute );
			} else {
				?>
				<textarea name="attribute_values[<?php echo esc_attr( $i ); ?>]" cols="5" rows="5"><?php echo esc_textarea( wc_implode_text_attributes( $attribute->get_options() ) ); ?></textarea>
				<?php
			}
			?>
		</td>
	</tr>
	<tr>
		<td>
			<label><input type="checkbox" class="woocommerce_attribute_visible_on_product_page checkbox" <?php checked( $attribute->get_visible(), true ); ?> name="attribute_visibility[<?php echo esc_attr( $i ); ?>]" value="1" /> <?php esc_html_e( 'Visible on the product page', 'woocommerce' ); ?></label>
		</td>
	</tr>
	<tr>
		<td>
			<div class="enable_variation show_if_variable">
				<label><input type="checkbox" class="woocommerce_attribute_used_for_variations checkbox" <?php checked( $attribute->get_variation(), true ); ?> name="attribute_variation[<?php echo esc_attr( $i ); ?>]" value="1" /> <?php esc_html_e( 'Used for variations', 'woocommerce' ); ?></label>
			</div>
		</td>
	</tr>
	<?php
	/**
	 * Hook to display custom attribute terms.
	 *
	 * @since 3.4.0
	 * @param WC_Product_Attribute $attribute Attribute object.
	 * @param int $i Attribute index.
	 */
	do_action( 'woocommerce_after_product_attribute_settings', $attribute, $i );
	?>
	</tbody>
</table>
PK     tS\&
$7  7  1  meta-boxes/views/html-product-data-variations.phpnu [        <?php
/**
 * Product data variations
 *
 * @package WooCommerce\Admin\Metaboxes\Views
 */

use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$add_attributes_img_url = WC_ADMIN_IMAGES_FOLDER_URL . '/icons/info.svg';
$background_img_url     = WC_ADMIN_IMAGES_FOLDER_URL . '/product_data/no-variation-background-image.svg';
$arrow_img_url          = WC_ADMIN_IMAGES_FOLDER_URL . '/product_data/no-variation-arrow.svg';
?>
<div id="variable_product_options" class="panel wc-metaboxes-wrapper hidden">
	<div id="variable_product_options_inner">
		<?php if ( ! isset( $variation_attributes ) || ! is_array( $variation_attributes ) || count( $variation_attributes ) === 0 ) : ?>

		<div class="add-attributes-container">
			<div class="add-attributes-message">
				<img src="<?php echo esc_url( $add_attributes_img_url ); ?>" />
				<p>
					<?php
						echo wp_kses_post(
							sprintf(
								/* translators: %1$s: url for attributes tab, %2$s: url for variable product documentation */
								__( 'Add some attributes in the <a class="variations-add-attributes-link" href="%1$s">Attributes</a> tab to generate variations. Make sure to check the <b>Used for variations</b> box. <a class="variations-learn-more-link" href="%2$s" target="_blank" rel="noreferrer">Learn more</a>', 'woocommerce' ),
								esc_url( '#product_attributes' ),
								esc_url( 'https://woocommerce.com/document/variable-product/' )
							)
						);
					?>
				</p>
			</div>
		</div>

		<?php else : ?>

			<div class="toolbar toolbar-variations-defaults">
				<div class="variations-defaults">
					<strong><?php esc_html_e( 'Default Form Values', 'woocommerce' ); ?>: <?php echo wc_help_tip( __( 'Choose a default form value if you want a certain variation already selected when a user visits the product page.', 'woocommerce' ) ); ?></strong>
					<?php
					foreach ( $variation_attributes as $attribute ) {
						$selected_value = isset( $default_attributes[ sanitize_title( $attribute->get_name() ) ] ) ? $default_attributes[ sanitize_title( $attribute->get_name() ) ] : '';
						?>
						<select name="default_attribute_<?php echo esc_attr( sanitize_title( $attribute->get_name() ) ); ?>" data-current="<?php echo esc_attr( $selected_value ); ?>">
							<?php /* translators: WooCommerce attribute label */ ?>
							<option value=""><?php echo esc_html( sprintf( __( 'No default %s&hellip;', 'woocommerce' ), wc_attribute_label( $attribute->get_name() ) ) ); ?></option>
							<?php if ( $attribute->is_taxonomy() ) : ?>
								<?php foreach ( $attribute->get_terms() as $option ) : ?>
									<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
									<option <?php selected( $selected_value, $option->slug ); ?> value="<?php echo esc_attr( $option->slug ); ?>"><?php echo esc_html( apply_filters( 'woocommerce_variation_option_name', $option->name, $option, $attribute->get_name(), $product_object ) ); ?></option>
									<?php /* phpcs:enable */ ?>
								<?php endforeach; ?>
							<?php else : ?>
								<?php foreach ( $attribute->get_options() as $option ) : ?>
									<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
									<option <?php selected( $selected_value, $option ); ?> value="<?php echo esc_attr( $option ); ?>"><?php echo esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute->get_name(), $product_object ) ); ?></option>
									<?php /* phpcs:enable */ ?>
								<?php endforeach; ?>
							<?php endif; ?>
						</select>
						<?php
					}
					?>
				</div>
				<div class="clear"></div>
			</div>

			<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
			<?php do_action( 'woocommerce_variable_product_before_variations' ); ?>
			<?php /* phpcs:enable */ ?>

			<div class="toolbar toolbar-top">
				<button type="button" class="button generate_variations"><?php esc_html_e( 'Generate variations', 'woocommerce' ); ?></button>
				<button type="button" class="button add_variation_manually"><?php esc_html_e( 'Add manually', 'woocommerce' ); ?></button>
				<select id="field_to_edit" class="select variation_actions hidden">
					<option value="bulk_actions" disabled>Bulk actions</option>
					<option value="delete_all"><?php esc_html_e( 'Delete all variations', 'woocommerce' ); ?></option>
					<optgroup label="<?php esc_attr_e( 'Status', 'woocommerce' ); ?>">
						<option value="toggle_enabled"><?php esc_html_e( 'Toggle &quot;Enabled&quot;', 'woocommerce' ); ?></option>
						<option value="toggle_downloadable"><?php esc_html_e( 'Toggle &quot;Downloadable&quot;', 'woocommerce' ); ?></option>
						<option value="toggle_virtual"><?php esc_html_e( 'Toggle &quot;Virtual&quot;', 'woocommerce' ); ?></option>
					</optgroup>
					<optgroup label="<?php esc_attr_e( 'Pricing', 'woocommerce' ); ?>">
						<option value="variable_regular_price"><?php esc_html_e( 'Set regular prices', 'woocommerce' ); ?></option>
						<option value="variable_regular_price_increase"><?php esc_html_e( 'Increase regular prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
						<option value="variable_regular_price_decrease"><?php esc_html_e( 'Decrease regular prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
						<option value="variable_sale_price"><?php esc_html_e( 'Set sale prices', 'woocommerce' ); ?></option>
						<option value="variable_sale_price_increase"><?php esc_html_e( 'Increase sale prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
						<option value="variable_sale_price_decrease"><?php esc_html_e( 'Decrease sale prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
						<option value="variable_sale_schedule"><?php esc_html_e( 'Set scheduled sale dates', 'woocommerce' ); ?></option>
					</optgroup>
					<?php if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() ) : ?>
						<optgroup label="<?php esc_attr_e( 'Cost of goods', 'woocommerce' ); ?>">
							<option value="variable_unset_cogs_value"><?php esc_html_e( 'Remove custom costs', 'woocommerce' ); ?></option>
						</optgroup>
					<?php endif; ?>
					<optgroup label="<?php esc_attr_e( 'Inventory', 'woocommerce' ); ?>">
						<option value="toggle_manage_stock"><?php esc_html_e( 'Toggle &quot;Manage stock&quot;', 'woocommerce' ); ?></option>
						<option value="variable_stock"><?php esc_html_e( 'Stock', 'woocommerce' ); ?></option>
						<option value="variable_stock_status_instock"><?php esc_html_e( 'Set Status - In stock', 'woocommerce' ); ?></option>
						<option value="variable_stock_status_outofstock"><?php esc_html_e( 'Set Status - Out of stock', 'woocommerce' ); ?></option>
						<option value="variable_stock_status_onbackorder"><?php esc_html_e( 'Set Status - On backorder', 'woocommerce' ); ?></option>
						<option value="variable_low_stock_amount"><?php esc_html_e( 'Low stock threshold', 'woocommerce' ); ?></option>
					</optgroup>
					<optgroup label="<?php esc_attr_e( 'Shipping', 'woocommerce' ); ?>">
						<option value="variable_length"><?php esc_html_e( 'Length', 'woocommerce' ); ?></option>
						<option value="variable_width"><?php esc_html_e( 'Width', 'woocommerce' ); ?></option>
						<option value="variable_height"><?php esc_html_e( 'Height', 'woocommerce' ); ?></option>
						<option value="variable_weight"><?php esc_html_e( 'Weight', 'woocommerce' ); ?></option>
					</optgroup>
					<optgroup label="<?php esc_attr_e( 'Downloadable products', 'woocommerce' ); ?>">
						<option value="variable_download_limit"><?php esc_html_e( 'Download limit', 'woocommerce' ); ?></option>
						<option value="variable_download_expiry"><?php esc_html_e( 'Download expiry', 'woocommerce' ); ?></option>
					</optgroup>
					<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
					<?php do_action( 'woocommerce_variable_product_bulk_edit_actions' ); ?>
					<?php /* phpcs:enable */ ?>
				</select>

				<div class="variations-pagenav">
					<?php /* translators: variations count */ ?>
					<span class="displaying-num"><?php echo esc_html( sprintf( _n( '%s item', '%s items', $variations_count, 'woocommerce' ), $variations_count ) ); ?></span>
					<span class="expand-close">
						(<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>)
					</span>
					<span class="pagination-links">
						<a class="first-page disabled" title="<?php esc_attr_e( 'Go to the first page', 'woocommerce' ); ?>" href="#">&laquo;</a>
						<a class="prev-page disabled" title="<?php esc_attr_e( 'Go to the previous page', 'woocommerce' ); ?>" href="#">&lsaquo;</a>
						<span class="paging-select">
							<label for="current-page-selector-1" class="screen-reader-text"><?php esc_html_e( 'Select Page', 'woocommerce' ); ?></label>
							<select class="page-selector" id="current-page-selector-1" title="<?php esc_attr_e( 'Current page', 'woocommerce' ); ?>">
								<?php for ( $i = 1; $i <= $variations_total_pages; $i++ ) : ?>
									<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
									<option value="<?php echo $i; // WPCS: XSS ok. ?>"><?php echo $i; // WPCS: XSS ok. ?></option>
									<?php /* phpcs:enable */ ?>
								<?php endfor; ?>
							</select>
							<?php echo esc_html_x( 'of', 'number of pages', 'woocommerce' ); ?> <span class="total-pages"><?php echo esc_html( $variations_total_pages ); ?></span>
						</span>
						<a class="next-page" title="<?php esc_attr_e( 'Go to the next page', 'woocommerce' ); ?>" href="#">&rsaquo;</a>
						<a class="last-page" title="<?php esc_attr_e( 'Go to the last page', 'woocommerce' ); ?>" href="#">&raquo;</a>
					</span>
				</div>
				<div class="clear"></div>
			</div>

			<div class="add-variation-container">
				<div class="arrow-image-wrapper">
					<img src="<?php echo esc_url( $arrow_img_url ); ?>" />
				</div>
				<img src="<?php echo esc_url( $background_img_url ); ?>" />
				<p>
					<?php
					esc_html_e(
						'No variations yet. Generate them from all added attributes or add a new variation manually.',
						'woocommerce'
					);
					?>
				</p>
			</div>

			<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
			<div class="woocommerce_variations wc-metaboxes" data-attributes="<?php echo wc_esc_json( wp_json_encode( wc_list_pluck( $variation_attributes, 'get_data' ) ) ); // WPCS: XSS ok. ?>" data-total="<?php echo esc_attr( $variations_count ); ?>" data-total_pages="<?php echo esc_attr( $variations_total_pages ); ?>" data-page="1" data-edited="false"></div>
			<?php /* phpcs:enable */ ?>

			<div class="toolbar">
				<button type="button" class="button-primary save-variation-changes" disabled="disabled"><?php esc_html_e( 'Save changes', 'woocommerce' ); ?></button>
				<button type="button" class="button cancel-variation-changes" disabled="disabled"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>

				<div class="variations-pagenav">
					<?php /* translators: variations count*/ ?>
					<span class="displaying-num"><?php echo esc_html( sprintf( _n( '%s item', '%s items', $variations_count, 'woocommerce' ), $variations_count ) ); ?></span>
					<span class="expand-close">
						(<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>)
					</span>
					<span class="pagination-links">
						<a class="first-page disabled" title="<?php esc_attr_e( 'Go to the first page', 'woocommerce' ); ?>" href="#">&laquo;</a>
						<a class="prev-page disabled" title="<?php esc_attr_e( 'Go to the previous page', 'woocommerce' ); ?>" href="#">&lsaquo;</a>
						<span class="paging-select">
							<label for="current-page-selector-1" class="screen-reader-text"><?php esc_html_e( 'Select Page', 'woocommerce' ); ?></label>
							<select class="page-selector" id="current-page-selector-1" title="<?php esc_attr_e( 'Current page', 'woocommerce' ); ?>">
								<?php for ( $i = 1; $i <= $variations_total_pages; $i++ ) : ?>
									<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
									<option value="<?php echo $i; // WPCS: XSS ok. ?>"><?php echo $i; // WPCS: XSS ok. ?></option>
									<?php /* phpcs:enable */ ?>
								<?php endfor; ?>
							</select>
							<?php echo esc_html_x( 'of', 'number of pages', 'woocommerce' ); ?> <span class="total-pages"><?php echo esc_html( $variations_total_pages ); ?></span>
						</span>
						<a class="next-page" title="<?php esc_attr_e( 'Go to the next page', 'woocommerce' ); ?>" href="#">&rsaquo;</a>
						<a class="last-page" title="<?php esc_attr_e( 'Go to the last page', 'woocommerce' ); ?>" href="#">&raquo;</a>
					</span>
				</div>
				<div class="clear"></div>
			</div>

		<?php endif; ?>
	</div>
</div>
<script type="text/template" id="tmpl-wc-modal-set-price-variations">
	<div class="wc-backbone-modal">
		<div class="wc-backbone-modal-content">
			<div class="components-modal__content woocommerce-set-price-variations" role="document">
				<div class="components-modal__header">
					<h2><?php echo esc_attr( $modal_title ); ?></h2>
				</div>
				<div class="woocommerce-usage-modal__wrapper">
					<div class="woocommerce-usage-modal__message">
						<span><?php esc_html_e( 'Add price to all variations that don\'t have a price', 'woocommerce' ); ?> (<?php echo esc_attr( get_woocommerce_currency_symbol() ); ?> <?php echo esc_textarea( get_woocommerce_currency() ); ?>)</span>
						<input type="text" class="components-text-control__input wc_input_variations_price"/>
					</div>
					<div class="woocommerce-usage-modal__actions">
						<button class="modal-close components-button is-secondary"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>
						<button class="modal-close button components-button add_variations_price_button button-primary" disabled><?php esc_html_e( 'Add prices', 'woocommerce' ); ?></button>
					</div>
				</div>
			</div>
		</div>
	</div>
	<div class="wc-backbone-modal-backdrop modal-close"></div>
</script>
PK     tS\"V3	
  	
  &  meta-boxes/views/html-order-refund.phpnu [        <?php
/**
 * Show order refund
 *
 * @var object $refund The refund object.
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

$who_refunded = new WP_User( $refund->get_refunded_by() );
?>
<tr class="refund <?php echo ( ! empty( $class ) ) ? esc_attr( $class ) : ''; ?>" data-order_refund_id="<?php echo esc_attr( $refund->get_id() ); ?>">
	<td class="thumb"><div></div></td>

	<td class="name">
		<?php
		if ( $who_refunded->exists() ) {
			printf(
				/* translators: 1: refund id 2: refund date 3: username */
				esc_html__( 'Refund #%1$s - %2$s by %3$s', 'woocommerce' ),
				esc_html( $refund->get_id() ),
				esc_html( wc_format_datetime( $refund->get_date_created(), get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) ) ),
				sprintf(
					'<abbr class="refund_by" title="%1$s">%2$s</abbr>',
					/* translators: 1: ID who refunded */
					sprintf( esc_attr__( 'ID: %d', 'woocommerce' ), absint( $who_refunded->ID ) ),
					esc_html( $who_refunded->display_name )
				)
			);
		} else {
			printf(
				/* translators: 1: refund id 2: refund date */
				esc_html__( 'Refund #%1$s - %2$s', 'woocommerce' ),
				esc_html( $refund->get_id() ),
				esc_html( wc_format_datetime( $refund->get_date_created(), get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) ) )
			);
		}
		?>
		<?php if ( $refund->get_reason() ) : ?>
			<p class="description"><?php echo esc_html( $refund->get_reason() ); ?></p>
		<?php endif; ?>
		<input type="hidden" class="order_refund_id" name="order_refund_id[]" value="<?php echo esc_attr( $refund->get_id() ); ?>" />

		<?php do_action( 'woocommerce_after_order_refund_item_name', $refund ); ?>
	</td>

	<?php do_action( 'woocommerce_admin_order_item_values', null, $refund, $refund->get_id() ); ?>

	<?php if ( $cogs_is_enabled ) : ?>
	<td class="item_cost_of_goods"></td>
	<?php endif; ?>

	<td class="item_cost" width="1%">&nbsp;</td>
	<td class="quantity" width="1%">&nbsp;</td>

	<td class="line_cost" width="1%">
		<div class="view">
			<?php
			echo wp_kses_post(
				wc_price( '-' . $refund->get_amount(), array( 'currency' => $refund->get_currency() ) )
			);
			?>
		</div>
	</td>

	<?php
	if ( wc_tax_enabled() ) :
		$total_taxes = count( $order_taxes );
		?>
		<?php for ( $i = 0;  $i < $total_taxes; $i++ ) : ?>
			<td class="line_tax" width="1%"></td>
		<?php endfor; ?>
	<?php endif; ?>

	<td class="wc-order-edit-line-item">
		<div class="wc-order-edit-line-item-actions">
			<a class="delete_refund" href="#"></a>
		</div>
	</td>
</tr>
PK     tS\Ƃ    /  meta-boxes/views/html-product-data-shipping.phpnu [        <?php
use Automattic\WooCommerce\Utilities\I18nUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div id="shipping_product_data" class="panel woocommerce_options_panel hidden">
	<div class="options_group">
		<?php
		if ( wc_product_weight_enabled() ) {
			woocommerce_wp_text_input(
				array(
					'id'          => '_weight',
					'value'       => $product_object->get_weight( 'edit' ),
					'label'       => sprintf(
						/* translators: %s: Weight unit */
						__( 'Weight (%s)', 'woocommerce' ),
						I18nUtil::get_weight_unit_label( get_option( 'woocommerce_weight_unit', 'kg' ) )
					),
					'placeholder' => wc_format_localized_decimal( 0 ),
					'desc_tip'    => true,
					'description' => __( 'Weight in decimal form', 'woocommerce' ),
					'type'        => 'text',
					'data_type'   => 'decimal',
				)
			);
		}

		if ( wc_product_dimensions_enabled() ) {
			?>
			<p class="form-field dimensions_field">
				<label for="product_length">
					<?php
					printf(
						/* translators: WooCommerce dimension unit */
						esc_html__( 'Dimensions (%s)', 'woocommerce' ),
						esc_html( I18nUtil::get_dimensions_unit_label( get_option( 'woocommerce_dimension_unit' ) ) )
					);
					?>
				</label>
				<span class="wrap">
					<input id="product_length" placeholder="<?php esc_attr_e( 'Length', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="_length" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_length( 'edit' ) ) ); ?>" />
					<input id="product_width" placeholder="<?php esc_attr_e( 'Width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="_width" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_width( 'edit' ) ) ); ?>" />
					<input id="product_height" placeholder="<?php esc_attr_e( 'Height', 'woocommerce' ); ?>" class="input-text wc_input_decimal last" size="6" type="text" name="_height" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_height( 'edit' ) ) ); ?>" />
				</span>
				<?php echo wc_help_tip( __( 'LxWxH in decimal form', 'woocommerce' ) ); ?>
			</p>
			<?php
		}

		do_action( 'woocommerce_product_options_dimensions' );
		?>
	</div>

	<div class="options_group">
		<?php
		$args = array(
			'taxonomy'         => 'product_shipping_class',
			'hide_empty'       => 0,
			'show_option_none' => __( 'No shipping class', 'woocommerce' ),
			'name'             => 'product_shipping_class',
			'id'               => 'product_shipping_class',
			'selected'         => $product_object->get_shipping_class_id( 'edit' ),
			'class'            => 'select short',
			'orderby'          => 'name',
		);
		?>
		<p class="form-field shipping_class_field">
			<label for="product_shipping_class"><?php esc_html_e( 'Shipping class', 'woocommerce' ); ?></label>
			<?php wp_dropdown_categories( $args ); ?>
			<?php echo wc_help_tip( __( 'Shipping classes are used by certain shipping methods to group similar products.', 'woocommerce' ) ); ?>
		</p>
		<?php

		do_action( 'woocommerce_product_options_shipping' );
		?>
	</div>
	<?php do_action( 'woocommerce_product_options_shipping_product_data' ); ?>
</div>
PK     tS\yk  k  )  meta-boxes/views/html-variation-admin.phpnu [        <?php
/**
 * Outputs a variation for editing.
 *
 * @package WooCommerce\Admin
 * @var int $variation_id
 * @var WP_POST $variation
 * @var WC_Product_Variation $variation_object
 * @var array $variation_data array of variation data @deprecated 4.4.0.
 */

use Automattic\WooCommerce\Utilities\I18nUtil;

defined( 'ABSPATH' ) || exit;

?>
<div class="woocommerce_variation wc-metabox closed">
	<h3>
		<a href="javascript:void(0)" class="edit_variation edit"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a>
		<a href="#" class="remove_variation delete" rel="<?php echo esc_attr( $variation_id ); ?>"><?php esc_html_e( 'Remove', 'woocommerce' ); ?></a>
		<div class="tips sort" data-tip="<?php esc_attr_e( 'Drag and drop, or click to set admin variation order', 'woocommerce' ); ?>"></div>
		<strong>#<?php echo esc_html( $variation_id ); ?> </strong>
		<?php
		$attribute_values = $variation_object->get_attributes( 'edit' );

		foreach ( $product_object->get_attributes( 'edit' ) as $attribute ) {
			if ( ! $attribute->get_variation() ) {
				continue;
			}
			$selected_value = isset( $attribute_values[ sanitize_title( $attribute->get_name() ) ] ) ? $attribute_values[ sanitize_title( $attribute->get_name() ) ] : '';
			?>
			<select name="attribute_<?php echo esc_attr( sanitize_title( $attribute->get_name() ) . "[{$loop}]" ); ?>">
				<option value="">
					<?php
					/* translators: %s: attribute label */
					printf( esc_html__( 'Any %s&hellip;', 'woocommerce' ), wc_attribute_label( $attribute->get_name() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
					?>
				</option>
				<?php if ( $attribute->is_taxonomy() ) : ?>
					<?php foreach ( $attribute->get_terms() as $option ) : ?>
						<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
						<option <?php selected( $selected_value, $option->slug ); ?> value="<?php echo esc_attr( $option->slug ); ?>"><?php echo esc_html( apply_filters( 'woocommerce_variation_option_name', $option->name, $option, $attribute->get_name(), $product_object ) ); ?></option>
						<?php /* phpcs:enable */ ?>
					<?php endforeach; ?>
				<?php else : ?>
					<?php foreach ( $attribute->get_options() as $option ) : ?>
						<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
						<option <?php selected( $selected_value, $option ); ?> value="<?php echo esc_attr( $option ); ?>"><?php echo esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute->get_name(), $product_object ) ); ?></option>
						<?php /* phpcs:enable */ ?>
					<?php endforeach; ?>
				<?php endif; ?>
			</select>
			<?php
		}
		?>
		<input type="hidden" class="variable_post_id" name="variable_post_id[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $variation_id ); ?>" />
		<input type="hidden" class="variation_menu_order" name="variation_menu_order[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $variation_object->get_menu_order( 'edit' ) ); ?>" />

		<?php
		/**
		 * Variations header action.
		 *
		 * @since 3.6.0
		 *
		 * @param WP_Post $variation Post data.
		 * @param int     $loop      Position in the loop.
		 */
		do_action( 'woocommerce_variation_header', $variation, $loop );
		?>
	</h3>
	<div class="woocommerce_variable_attributes wc-metabox-content" style="display: none;">
		<div class="data">
			<div class="form-flex-box">
				<p class="form-row upload_image">
					<a href="#" class="upload_image_button tips <?php echo $variation_object->get_image_id( 'edit' ) ? 'remove' : ''; ?>" data-tip="<?php echo $variation_object->get_image_id( 'edit' ) ? esc_attr__( 'Remove this image', 'woocommerce' ) : esc_attr__( 'Upload an image', 'woocommerce' ); ?>" rel="<?php echo esc_attr( $variation_id ); ?>">
						<img src="<?php echo $variation_object->get_image_id( 'edit' ) ? esc_url( wp_get_attachment_thumb_url( $variation_object->get_image_id( 'edit' ) ) ) : esc_url( wc_placeholder_img_src() ); ?>" /><input type="hidden" name="upload_image_id[<?php echo esc_attr( $loop ); ?>]" class="upload_image_id" value="<?php echo esc_attr( $variation_object->get_image_id( 'edit' ) ); ?>" />
					</a>
				</p>
				<div class="form-row form-row-last">
				<?php
				if ( wc_product_sku_enabled() ) {
					woocommerce_wp_text_input(
						array(
							'id'            => "variable_sku{$loop}",
							'name'          => "variable_sku[{$loop}]",
							'value'         => $variation_object->get_sku( 'edit' ),
							'placeholder'   => $variation_object->get_sku(),
							'label'         => '<abbr title="' . esc_attr__( 'Stock Keeping Unit', 'woocommerce' ) . '">' . esc_html__( 'SKU', 'woocommerce' ) . '</abbr>',
							'desc_tip'      => true,
							'description'   => __( 'SKU refers to a Stock-keeping unit, a unique identifier for each distinct product and service that can be purchased.', 'woocommerce' ),
							'wrapper_class' => 'form-row',
						)
					);
				}
				woocommerce_wp_text_input(
					array(
						'id'            => "variable_global_unique_id{$loop}",
						'name'          => "variable_global_unique_id[{$loop}]",
						'value'         => $variation_object->get_global_unique_id( 'edit' ),
						'placeholder'   => $variation_object->get_global_unique_id(),
						// translators: %1$s GTIN %2$s UPC %3$s EAN %4$s ISBN.
						'label'         => sprintf( __( '%1$s, %2$s, %3$s, or %4$s', 'woocommerce' ), '<abbr title="' . esc_attr__( 'Global Trade Item Number', 'woocommerce' ) . '">' . esc_html__( 'GTIN', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'Universal Product Code', 'woocommerce' ) . '">' . esc_html__( 'UPC', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'European Article Number', 'woocommerce' ) . '">' . esc_html__( 'EAN', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'International Standard Book Number', 'woocommerce' ) . '">' . esc_html__( 'ISBN', 'woocommerce' ) . '</abbr>' ),
						'desc_tip'      => true,
						'description'   => __( 'Enter a barcode or any other identifier unique to this product. It can help you list this product on other channels or marketplaces.', 'woocommerce' ),
						'wrapper_class' => 'form-row',
					)
				);
				?>
				</div>
			</div>
			<p class="form-row form-row-full options">
				<label>
					<?php esc_html_e( 'Enabled', 'woocommerce' ); ?>
					<input type="checkbox" class="checkbox" name="variable_enabled[<?php echo esc_attr( $loop ); ?>]" <?php checked( in_array( $variation_object->get_status( 'edit' ), array( 'publish', false ), true ), true ); ?> />
				</label>
				<label class="tips" data-tip="<?php esc_attr_e( 'Enable this option if access is given to a downloadable file upon purchase of a product', 'woocommerce' ); ?>">
					<?php esc_html_e( 'Downloadable', 'woocommerce' ); ?>
					<input type="checkbox" class="checkbox variable_is_downloadable" name="variable_is_downloadable[<?php echo esc_attr( $loop ); ?>]" <?php checked( $variation_object->get_downloadable( 'edit' ), true ); ?> />
				</label>
				<label class="tips" data-tip="<?php esc_attr_e( 'Enable this option if a product is not shipped or there is no shipping cost', 'woocommerce' ); ?>">
					<?php esc_html_e( 'Virtual', 'woocommerce' ); ?>
					<input type="checkbox" class="checkbox variable_is_virtual" name="variable_is_virtual[<?php echo esc_attr( $loop ); ?>]" <?php checked( $variation_object->get_virtual( 'edit' ), true ); ?> />
				</label>

				<?php if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) : ?>
					<label class="tips" data-tip="<?php esc_attr_e( 'Enable this option to enable stock management at variation level', 'woocommerce' ); ?>">
						<?php esc_html_e( 'Manage stock?', 'woocommerce' ); ?>
						<input type="checkbox" class="checkbox variable_manage_stock" name="variable_manage_stock[<?php echo esc_attr( $loop ); ?>]" <?php checked( $variation_object->get_manage_stock(), true ); // Use view context so 'parent' is considered. ?> />
					</label>
				<?php endif; ?>

				<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
				<?php do_action( 'woocommerce_variation_options', $loop, $variation_data, $variation ); ?>
				<?php /* phpcs:enable */ ?>
			</p>

			<div class="variable_pricing">
				<?php
				$label = sprintf(
					/* translators: %s: currency symbol */
					__( 'Regular price (%s)', 'woocommerce' ),
					get_woocommerce_currency_symbol()
				);

				woocommerce_wp_text_input(
					array(
						'id'            => "variable_regular_price_{$loop}",
						'name'          => "variable_regular_price[{$loop}]",
						'value'         => wc_format_localized_price( $variation_object->get_regular_price( 'edit' ) ),
						'label'         => $label,
						'data_type'     => 'price',
						'wrapper_class' => 'form-row form-row-first',
						'placeholder'   => __( 'Variation price (required)', 'woocommerce' ),
					)
				);

				$label = sprintf(
					/* translators: %s: currency symbol */
					__( 'Sale price (%s)', 'woocommerce' ),
					get_woocommerce_currency_symbol()
				);

				woocommerce_wp_text_input(
					array(
						'id'            => "variable_sale_price{$loop}",
						'name'          => "variable_sale_price[{$loop}]",
						'value'         => wc_format_localized_price( $variation_object->get_sale_price( 'edit' ) ),
						'data_type'     => 'price',
						'label'         => $label . ' <a href="#" class="sale_schedule">' . esc_html__( 'Schedule', 'woocommerce' ) . '</a><a href="#" class="cancel_sale_schedule hidden">' . esc_html__( 'Cancel schedule', 'woocommerce' ) . '</a>',
						'wrapper_class' => 'form-row form-row-last',
					)
				);

				$sale_price_dates_from_timestamp = $variation_object->get_date_on_sale_from( 'edit' ) ? $variation_object->get_date_on_sale_from( 'edit' )->getOffsetTimestamp() : false;
				$sale_price_dates_to_timestamp   = $variation_object->get_date_on_sale_to( 'edit' ) ? $variation_object->get_date_on_sale_to( 'edit' )->getOffsetTimestamp() : false;

				$sale_price_dates_from = $sale_price_dates_from_timestamp ? date_i18n( 'Y-m-d', $sale_price_dates_from_timestamp ) : '';
				$sale_price_dates_to   = $sale_price_dates_to_timestamp ? date_i18n( 'Y-m-d', $sale_price_dates_to_timestamp ) : '';

				/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
				echo '<div class="form-field sale_price_dates_fields hidden">
					<p class="form-row form-row-first">
						<label>' . esc_html__( 'Sale start date', 'woocommerce' ) . '</label>
						<input type="text" class="sale_price_dates_from" name="variable_sale_price_dates_from[' . esc_attr( $loop ) . ']" value="' . esc_attr( $sale_price_dates_from ) . '" placeholder="' . esc_attr_x( 'From&hellip;', 'placeholder', 'woocommerce' ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
					</p>
					<p class="form-row form-row-last">
						<label>' . esc_html__( 'Sale end date', 'woocommerce' ) . '</label>
						<input type="text" class="sale_price_dates_to" name="variable_sale_price_dates_to[' . esc_attr( $loop ) . ']" value="' . esc_attr( $sale_price_dates_to ) . '" placeholder="' . esc_attr_x( 'To&hellip;', 'placeholder', 'woocommerce' ) . '  YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
					</p>
				</div>';
				/* phpcs: enable */

				/**
				 * Variation options pricing action.
				 *
				 * @since 2.5.0
				 *
				 * @param int     $loop           Position in the loop.
				 * @param array   $variation_data Variation data.
				 * @param WP_Post $variation      Post data.
				 */
				do_action( 'woocommerce_variation_options_pricing', $loop, $variation_data, $variation );
				?>
			</div>

			<?php if ( ! is_null( $base_cost ) ) : ?>
				<div class="variable_pricing">
					<?php
					$label = sprintf(
						/* translators: %s: currency symbol */
						__( 'Cost (%s)', 'woocommerce' ),
						get_woocommerce_currency_symbol()
					);

					$variation_cogs = $variation_object->get_cogs_value();
					woocommerce_wp_text_input(
						array(
							'id'                 => "variable_cost_value_{$loop}",
							'name'               => "variable_cost_value[{$loop}]",
							'value'              => is_null( $variation_cogs ) ? '' : wc_format_localized_price( $variation_cogs ),
							'label'              => $label,
							'data_type'          => 'price',
							'wrapper_class'      => 'form-row form-row-first variation-cost-field',
							'description_hidden' => ! is_null( $variation_cogs ),
							'description'        => array(
								__( 'Add the amount it costs you to buy or make this product. Leave blank to use the default value from "General".', 'woocommerce' ),
								__( 'You can specify a <a href="#" class="switch-to-general-tab">default value</a> for all variations', 'woocommerce' ),
							),
							'placeholder'        =>
								/* Translators: %s = cost of the item (monetary value) */
								sprintf( __( '%s (default)', 'woocommerce' ), wc_format_localized_price( $base_cost ) ),
						)
					);
					?>
				</div>
			<?php endif; ?>

			<?php if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) : ?>
				<div class="show_if_variation_manage_stock form-row form-row-full" style="display: none;">
					<?php
					woocommerce_wp_text_input(
						array(
							'id'                => "variable_stock{$loop}",
							'name'              => "variable_stock[{$loop}]",
							'value'             => wc_stock_amount( $variation_object->get_stock_quantity( 'edit' ) ),
							'label'             => __( 'Stock quantity', 'woocommerce' ),
							'desc_tip'          => true,
							'description'       => __( "Enter a number to set stock quantity at the variation level. Use a variation's 'Manage stock?' check box above to enable/disable stock management at the variation level.", 'woocommerce' ),
							'type'              => 'number',
							'custom_attributes' => array(
								'step' => 'any',
							),
							'data_type'         => 'stock',
							'wrapper_class'     => 'form-row form-row-first',
						)
					);

					echo '<input type="hidden" name="variable_original_stock[' . esc_attr( $loop ) . ']" value="' . esc_attr( wc_stock_amount( $variation_object->get_stock_quantity( 'edit' ) ) ) . '" />';

					woocommerce_wp_select(
						array(
							'id'            => "variable_backorders{$loop}",
							'name'          => "variable_backorders[{$loop}]",
							'value'         => $variation_object->get_backorders( 'edit' ),
							'label'         => __( 'Allow backorders?', 'woocommerce' ),
							'options'       => wc_get_product_backorder_options(),
							'desc_tip'      => true,
							'description'   => __( 'If managing stock, this controls whether or not backorders are allowed. If enabled, stock quantity can go below 0.', 'woocommerce' ),
							'wrapper_class' => 'form-row form-row-last',
						)
					);

					$low_stock_placeholder = ( $product_object->get_manage_stock() && '' !== $product_object->get_low_stock_amount() )
						? sprintf(
							/* translators: %d: Amount of stock left */
							esc_attr__( 'Parent product\'s threshold (%d)', 'woocommerce' ),
							esc_attr( $product_object->get_low_stock_amount() )
						)
						: sprintf(
							/* translators: %d: Amount of stock left */
							esc_attr__( 'Store-wide threshold (%d)', 'woocommerce' ),
							esc_attr( get_option( 'woocommerce_notify_low_stock_amount' ) )
						);

					woocommerce_wp_text_input(
						array(
							'id'                => "variable_low_stock_amount{$loop}",
							'name'              => "variable_low_stock_amount[{$loop}]",
							'value'             => $variation_object->get_low_stock_amount( 'edit' ),
							'placeholder'       => $low_stock_placeholder,
							'label'             => __( 'Low stock threshold', 'woocommerce' ),
							'desc_tip'          => true,
							'description'       => __( 'When variation stock reaches this amount you will be notified by email. The default value for all variations can be set in the product Inventory tab. The shop default value can be set in Settings > Products > Inventory.', 'woocommerce' ),
							'type'              => 'number',
							'custom_attributes' => array(
								'step' => 'any',
							),
							'wrapper_class'     => 'form-row',
						)
					);

					/**
					 * Variation options inventory action.
					 *
					 * @since 2.5.0
					 *
					 * @param int     $loop           Position in the loop.
					 * @param array   $variation_data Variation data.
					 * @param WP_Post $variation      Post data.
					 */
					do_action( 'woocommerce_variation_options_inventory', $loop, $variation_data, $variation );
					?>
				</div>
			<?php endif; ?>

			<div>
				<?php
				woocommerce_wp_select(
					array(
						'id'            => "variable_stock_status{$loop}",
						'name'          => "variable_stock_status[{$loop}]",
						'value'         => $variation_object->get_stock_status( 'edit' ),
						'label'         => __( 'Stock status', 'woocommerce' ),
						'options'       => wc_get_product_stock_status_options(),
						'desc_tip'      => true,
						'description'   => __( 'Controls whether or not the product is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce' ),
						'wrapper_class' => 'form-row form-row-full variable_stock_status',
					)
				);

				if ( wc_product_weight_enabled() ) {
					$label = sprintf(
						/* translators: %s: Weight unit */
						__( 'Weight (%s)', 'woocommerce' ),
						I18nUtil::get_weight_unit_label( get_option( 'woocommerce_weight_unit', 'kg' ) )
					);

					woocommerce_wp_text_input(
						array(
							'id'            => "variable_weight{$loop}",
							'name'          => "variable_weight[{$loop}]",
							'value'         => wc_format_localized_decimal( $variation_object->get_weight( 'edit' ) ),
							'placeholder'   => wc_format_localized_decimal( $product_object->get_weight() ),
							'label'         => $label,
							'desc_tip'      => true,
							'description'   => __( 'Weight in decimal form', 'woocommerce' ),
							'type'          => 'text',
							'data_type'     => 'decimal',
							'wrapper_class' => 'form-row form-row-first hide_if_variation_virtual',
						)
					);
				}

				if ( wc_product_dimensions_enabled() ) {
					$parent_length = wc_format_localized_decimal( $product_object->get_length() );
					$parent_width  = wc_format_localized_decimal( $product_object->get_width() );
					$parent_height = wc_format_localized_decimal( $product_object->get_height() );

					?>
					<p class="form-field form-row dimensions_field hide_if_variation_virtual form-row-last">
						<label for="product_length">
							<?php
							printf(
								/* translators: %s dimension unit */
								esc_html__( 'Dimensions (L&times;W&times;H) (%s)', 'woocommerce' ),
								esc_html( I18nUtil::get_dimensions_unit_label( get_option( 'woocommerce_dimension_unit' ) ) )
							);
							?>
						</label>
						<?php echo wc_help_tip( __( 'Length x width x height in decimal form', 'woocommerce' ) ); ?>
						<span class="wrap">
							<input id="product_length" placeholder="<?php echo $parent_length ? esc_attr( $parent_length ) : esc_attr__( 'Length', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="variable_length[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_length( 'edit' ) ) ); ?>" />
							<input placeholder="<?php echo $parent_width ? esc_attr( $parent_width ) : esc_attr__( 'Width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="variable_width[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_width( 'edit' ) ) ); ?>" />
							<input placeholder="<?php echo $parent_height ? esc_attr( $parent_height ) : esc_attr__( 'Height', 'woocommerce' ); ?>" class="input-text wc_input_decimal last" size="6" type="text" name="variable_height[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_height( 'edit' ) ) ); ?>" />
						</span>
					</p>
					<?php
				}

				/**
				 * Variation options dimensions action.
				 *
				 * @since 2.5.0
				 *
				 * @param int     $loop           Position in the loop.
				 * @param array   $variation_data Variation data.
				 * @param WP_Post $variation      Post data.
				 */
				do_action( 'woocommerce_variation_options_dimensions', $loop, $variation_data, $variation );
				?>
			</div>

			<div>
				<p class="form-row hide_if_variation_virtual form-row-full">
					<label><?php esc_html_e( 'Shipping class', 'woocommerce' ); ?></label>
					<?php
					wp_dropdown_categories(
						array(
							'taxonomy'         => 'product_shipping_class',
							'hide_empty'       => 0,
							'show_option_none' => __( 'Same as parent', 'woocommerce' ),
							'name'             => 'variable_shipping_class[' . $loop . ']',
							'id'               => '',
							'selected'         => $variation_object->get_shipping_class_id( 'edit' ),
						)
					);
					?>
				</p>

				<?php
				if ( wc_tax_enabled() ) {
					woocommerce_wp_select(
						array(
							'id'            => "variable_tax_class{$loop}",
							'name'          => "variable_tax_class[{$loop}]",
							'value'         => $variation_object->get_tax_class( 'edit' ),
							'label'         => __( 'Tax class', 'woocommerce' ),
							'options'       => array( 'parent' => __( 'Same as parent', 'woocommerce' ) ) + wc_get_product_tax_class_options(),
							'desc_tip'      => 'true',
							'description'   => __( 'Choose a tax class for this product. Tax classes are used to apply different tax rates specific to certain types of product.', 'woocommerce' ),
							'wrapper_class' => 'form-row form-row-full',
						)
					);

					/**
					 * Variation options tax action.
					 *
					 * @since 2.5.0
					 *
					 * @param int     $loop           Position in the loop.
					 * @param array   $variation_data Variation data.
					 * @param WP_Post $variation      Post data.
					 */
					do_action( 'woocommerce_variation_options_tax', $loop, $variation_data, $variation );
				}
				?>
			</div>
			<div>
				<?php
				woocommerce_wp_textarea_input(
					array(
						'id'            => "variable_description{$loop}",
						'name'          => "variable_description[{$loop}]",
						'value'         => $variation_object->get_description( 'edit' ),
						'label'         => __( 'Description', 'woocommerce' ),
						'desc_tip'      => true,
						'description'   => __( 'Enter an optional description for this variation.', 'woocommerce' ),
						'wrapper_class' => 'form-row form-row-full',
					)
				);
				?>
			</div>
			<div class="show_if_variation_downloadable" style="display: none;">
				<div class="form-row form-row-full downloadable_files">
					<label><?php esc_html_e( 'Downloadable files', 'woocommerce' ); ?></label>
					<table class="widefat">
						<thead>
							<div>
								<th><?php esc_html_e( 'Name', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the name of the download shown to the customer.', 'woocommerce' ) ); ?></th>
								<th colspan="2"><?php esc_html_e( 'File URL', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the URL or absolute path to the file which customers will get access to. URLs entered here should already be encoded.', 'woocommerce' ) ); ?></th>
								<th>&nbsp;</th>
							</div>
						</thead>
						<tbody>
							<?php
							$downloadable_files       = $variation_object->get_downloads( 'edit' );
							$disabled_downloads_count = 0;

							if ( $downloadable_files ) {
								foreach ( $downloadable_files as $key => $file ) {
									$disabled_download         = isset( $file['enabled'] ) && false === $file['enabled'];
									$disabled_downloads_count += (int) $disabled_download;
									include __DIR__ . '/html-product-variation-download.php';
								}
							}
							?>
						</tbody>
						<tfoot>
							<div>
								<th colspan="1">
									<a href="#" class="button insert" data-row="
									<?php
									$key               = '';
									$file              = array(
										'file' => '',
										'name' => '',
									);
									$disabled_download = false;
									ob_start();
									require __DIR__ . '/html-product-variation-download.php';
									echo esc_attr( ob_get_clean() );
									?>
									"><?php esc_html_e( 'Add file', 'woocommerce' ); ?></a>
								</th>
								<th colspan="3">
									<?php if ( $disabled_downloads_count ) : ?>
										<span class="disabled">*</span>
										<?php
										printf(
											/* translators: 1: opening link tag, 2: closing link tag. */
											esc_html__( 'The indicated downloads have been disabled (invalid location or filetype&mdash;%1$slearn more%2$s).', 'woocommerce' ),
											'<a href="https://woocommerce.com/document/approved-download-directories" target="_blank">',
											'</a>'
										);
										?>
									<?php endif; ?>
								</th>
							</div>
						</tfoot>
					</table>
				</div>
			</div>
			<div class="show_if_variation_downloadable" style="display: none;">
				<?php
				woocommerce_wp_text_input(
					array(
						'id'                => "variable_download_limit{$loop}",
						'name'              => "variable_download_limit[{$loop}]",
						'value'             => $variation_object->get_download_limit( 'edit' ) < 0 ? '' : $variation_object->get_download_limit( 'edit' ),
						'label'             => __( 'Download limit', 'woocommerce' ),
						'placeholder'       => __( 'Unlimited', 'woocommerce' ),
						'description'       => __( 'Leave blank for unlimited re-downloads.', 'woocommerce' ),
						'type'              => 'number',
						'desc_tip'          => true,
						'custom_attributes' => array(
							'step' => '1',
							'min'  => '0',
						),
						'wrapper_class'     => 'form-row form-row-first',
					)
				);

				woocommerce_wp_text_input(
					array(
						'id'                => "variable_download_expiry{$loop}",
						'name'              => "variable_download_expiry[{$loop}]",
						'value'             => $variation_object->get_download_expiry( 'edit' ) < 0 ? '' : $variation_object->get_download_expiry( 'edit' ),
						'label'             => __( 'Download expiry', 'woocommerce' ),
						'placeholder'       => __( 'Never', 'woocommerce' ),
						'description'       => __( 'Enter the number of days before a download link expires, or leave blank.', 'woocommerce' ),
						'type'              => 'number',
						'desc_tip'          => true,
						'custom_attributes' => array(
							'step' => '1',
							'min'  => '0',
						),
						'wrapper_class'     => 'form-row form-row-last',
					)
				);

				/**
				 * Variation options download action.
				 *
				 * @since 2.5.0
				 *
				 * @param int     $loop           Position in the loop.
				 * @param array   $variation_data Variation data.
				 * @param WP_Post $variation      Post data.
				 */
				do_action( 'woocommerce_variation_options_download', $loop, $variation_data, $variation );
				?>
			</div>
			<?php /* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */ ?>
			<?php do_action( 'woocommerce_product_after_variable_attributes', $loop, $variation_data, $variation ); ?>
			<?php /* phpcs:enable */ ?>
		</div>
	</div>
</div>
PK     tS\    6  meta-boxes/views/html-product-data-linked-products.phpnu [        <?php
/**
 * Linked product options.
 *
 * @package WooCommerce\Admin
 */

use Automattic\WooCommerce\Enums\ProductType;

defined( 'ABSPATH' ) || exit;

// In WP 7.0, we made the inputs wider.
// @see https://github.com/woocommerce/woocommerce/pull/63779/changes#diff-dfef13b204157e98982fb3af978fbabfaa7f6bedd31bf02f2c9070718d59642eR8402-R8408.
$version = get_bloginfo( 'version' );

if ( $version ) {
	$version_parts = explode( '-', $version );
	$version       = count( $version_parts ) > 1 ? $version_parts[0] : $version;
}

$width = $version && version_compare( $version, '7.0', '>=' ) ? 'width: 55%;' : 'width: 50%;';
?>
<div id="linked_product_data" class="panel woocommerce_options_panel hidden">

	<div class="options_group show_if_grouped">
		<p class="form-field">
			<label for="grouped_products"><?php esc_html_e( 'Grouped products', 'woocommerce' ); ?></label>
			<select class="wc-product-search" multiple="multiple" style="<?php echo esc_attr( $width ); ?>" id="grouped_products" name="grouped_products[]" data-sortable="true" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products" data-exclude="<?php echo intval( $post->ID ); ?>">
				<?php
				$product_ids = $product_object->is_type( ProductType::GROUPED ) ? $product_object->get_children( 'edit' ) : array();

				if ( ! empty( $product_ids ) ) {
					// Prime caches to reduce future queries.
					_prime_post_caches( $product_ids );
				}

				foreach ( $product_ids as $product_id ) {
					$product = wc_get_product( $product_id );
					if ( is_object( $product ) ) {
						echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
					}
				}
				?>
			</select> <?php echo wc_help_tip( __( 'This lets you choose which products are part of this group.', 'woocommerce' ) ); // WPCS: XSS ok. ?>
		</p>
	</div>

	<div class="options_group">
		<p class="form-field">
			<label for="upsell_ids"><?php esc_html_e( 'Upsells', 'woocommerce' ); ?></label>
			<select class="wc-product-search" multiple="multiple" style="<?php echo esc_attr( $width ); ?>" id="upsell_ids" name="upsell_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-exclude="<?php echo intval( $post->ID ); ?>">
				<?php
				$product_ids = $product_object->get_upsell_ids( 'edit' );

				if ( ! empty( $product_ids ) ) {
					// Prime caches to reduce future queries.
					_prime_post_caches( $product_ids );
				}

				foreach ( $product_ids as $product_id ) {
					$product = wc_get_product( $product_id );
					if ( is_object( $product ) ) {
						echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
					}
				}
				?>
			</select> <?php echo wc_help_tip( __( 'Upsells are products which you recommend instead of the currently viewed product, for example, products that are more profitable or better quality or more expensive.', 'woocommerce' ) ); // WPCS: XSS ok. ?>
		</p>

		<p class="form-field hide_if_grouped hide_if_external">
			<label for="crosssell_ids"><?php esc_html_e( 'Cross-sells', 'woocommerce' ); ?></label>
			<select class="wc-product-search" multiple="multiple" style="<?php echo esc_attr( $width ); ?>" id="crosssell_ids" name="crosssell_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-exclude="<?php echo intval( $post->ID ); ?>">
				<?php
				$product_ids = $product_object->get_cross_sell_ids( 'edit' );

				if ( ! empty( $product_ids ) ) {
					// Prime caches to reduce future queries.
					_prime_post_caches( $product_ids );
				}

				foreach ( $product_ids as $product_id ) {
					$product = wc_get_product( $product_id );
					if ( is_object( $product ) ) {
						echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
					}
				}
				?>
			</select> <?php echo wc_help_tip( __( 'Cross-sells are products which you promote in the cart, based on the current product.', 'woocommerce' ) ); // WPCS: XSS ok. ?>
		</p>
	</div>

	<?php do_action( 'woocommerce_product_options_related' ); ?>
</div>
PK     tS\Bպ	  	  ,  meta-boxes/views/html-product-data-panel.phpnu [        <?php
/**
 * Product data meta box.
 *
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>

<div class="panel-wrap product_data">

	<span class="product-data-wrapper type_box hidden"> &mdash;
		<label for="product-type">
			<select id="product-type" name="product-type">
				<optgroup label="<?php esc_attr_e( 'Product Type', 'woocommerce' ); ?>">
				<?php foreach ( wc_get_product_types() as $value => $label ) : ?>
					<option value="<?php echo esc_attr( $value ); ?>" <?php echo selected( $product_object->get_type(), $value, false ); ?>><?php echo esc_html( $label ); ?></option>
				<?php endforeach; ?>
				</optgroup>
			</select>
			<span class="woocommerce-product-type-tip"></span>
		</label>

		<?php
		foreach ( self::get_product_type_options() as $key => $option ) :
			if ( metadata_exists( 'post', $post->ID, '_' . $key ) ) {
				$selected_value = is_callable( array( $product_object, "is_$key" ) ) ? $product_object->{"is_$key"}() : 'yes' === get_post_meta( $post->ID, '_' . $key, true );
			} else {
				$selected_value = 'yes' === ( isset( $option['default'] ) ? $option['default'] : 'no' );
			}
			?>
			<label for="<?php echo esc_attr( $option['id'] ); ?>" class="<?php echo esc_attr( $option['wrapper_class'] ); ?> tips has-checkbox" data-tip="<?php echo esc_attr( $option['description'] ); ?>">
				<input type="checkbox" name="<?php echo esc_attr( $option['id'] ); ?>" id="<?php echo esc_attr( $option['id'] ); ?>" data-product-type-option-id="<?php echo esc_attr( $option['id'] ); ?>" <?php echo checked( $selected_value, true, false ); ?> />
				<?php echo esc_html( $option['label'] ); ?>
			</label>
		<?php endforeach; ?>
	</span>

	<ul class="product_data_tabs wc-tabs">
		<?php foreach ( self::get_product_data_tabs() as $key => $tab ) : ?>
			<li class="<?php echo esc_attr( $key ); ?>_options <?php echo esc_attr( $key ); ?>_tab <?php echo esc_attr( isset( $tab['class'] ) ? implode( ' ', (array) $tab['class'] ) : '' ); ?>">
				<a href="#<?php echo esc_attr( $tab['target'] ); ?>"><span><?php echo esc_html( $tab['label'] ); ?></span></a>
			</li>
		<?php endforeach; ?>
		<?php do_action( 'woocommerce_product_write_panel_tabs' ); ?>
	</ul>

	<?php
		self::output_tabs();
		self::output_variations();
		do_action( 'woocommerce_product_data_panels' );
		wc_do_deprecated_action( 'woocommerce_product_write_panels', array(), '2.6', 'Use woocommerce_product_data_panels action instead.' );
	?>
	<div class="clear"></div>
</div>
PK     tS\5i	  i	  1  meta-boxes/views/html-product-data-attributes.phpnu [        <?php
/**
 * Displays the attributes tab in the product data meta box.
 *
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

global $wc_product_attributes;
// Array of defined attribute taxonomies.
$attribute_taxonomies = wc_get_attribute_taxonomies();
// Product attributes - taxonomies and custom, ordered, with visibility and variation attributes set.
$product_attributes = $product_object->get_attributes( 'edit' );
?>
<div id="product_attributes" class="panel wc-metaboxes-wrapper hidden">
	<div class="toolbar toolbar-top">
		<div id="message" class="inline notice woocommerce-message is-dismissible">
			<p class="help">
				<?php
				esc_html_e(
					'Add descriptive pieces of information that customers can use to search for this product on your store, such as “Material” or “Size”.',
					'woocommerce'
				);
				?>
				<button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'woocommerce' ); ?></span></button>
			</p>
		</div>
		<span class="expand-close">
			<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>
		</span>
		<div class="actions">
			<button type="button" class="button add_custom_attribute"><?php esc_html_e( 'Add new', 'woocommerce' ); ?></button>
			<select class="wc-attribute-search" data-placeholder="<?php esc_attr_e( 'Add existing', 'woocommerce' ); ?>" data-minimum-input-length="0">
			</select>
		</div>
	</div>
	<div class="product_attributes wc-metaboxes">
		<?php
		$i = -1;

		foreach ( $product_attributes as $attribute ) {
			$i++;
			$metabox_class = array();

			if ( $attribute->is_taxonomy() ) {
				$metabox_class[] = 'taxonomy';
				$metabox_class[] = $attribute->get_name();
			}

			include __DIR__ . '/html-product-attribute.php';
		}
		?>
	</div>
	<div class="toolbar toolbar-buttons">
		<span class="expand-close">
			<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>
		</span>
		<button type="button" aria-disabled="true" class="button save_attributes button-primary disabled"><?php esc_html_e( 'Save attributes', 'woocommerce' ); ?></button>
	</div>
	<?php do_action( 'woocommerce_product_options_attributes' ); ?>
</div>
PK     tS\ɁP      0  meta-boxes/views/html-product-data-inventory.phpnu [        <?php
/**
 * Displays the inventory tab in the product data meta box.
 *
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div id="inventory_product_data" class="panel woocommerce_options_panel hidden">
	<div class="options_group">
		<?php
		$info_img_url = WC_ADMIN_IMAGES_FOLDER_URL . '/icons/info.svg';

		if ( wc_product_sku_enabled() ) {
			woocommerce_wp_text_input(
				array(
					'id'          => '_sku',
					'value'       => $product_object->get_sku( 'edit' ),
					'label'       => '<abbr title="' . esc_attr__( 'Stock Keeping Unit', 'woocommerce' ) . '">' . esc_html__( 'SKU', 'woocommerce' ) . '</abbr>',
					'desc_tip'    => true,
					'description' => __( 'SKU refers to a Stock-keeping unit, a unique identifier for each distinct product and service that can be purchased.', 'woocommerce' ),
				)
			);
		}

		do_action( 'woocommerce_product_options_sku' );

		woocommerce_wp_text_input(
			array(
				'id'          => '_global_unique_id',
				'value'       => $product_object->get_global_unique_id( 'edit' ),
				// translators: %1$s GTIN %2$s UPC %3$s EAN %4$s ISBN.
				'label'       => sprintf( __( '%1$s, %2$s, %3$s, or %4$s', 'woocommerce' ), '<abbr title="' . esc_attr__( 'Global Trade Item Number', 'woocommerce' ) . '">' . esc_html__( 'GTIN', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'Universal Product Code', 'woocommerce' ) . '">' . esc_html__( 'UPC', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'European Article Number', 'woocommerce' ) . '">' . esc_html__( 'EAN', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'International Standard Book Number', 'woocommerce' ) . '">' . esc_html__( 'ISBN', 'woocommerce' ) . '</abbr>' ),
				'desc_tip'    => true,
				'description' => __( 'Enter a barcode or any other identifier unique to this product. It can help you list this product on other channels or marketplaces.', 'woocommerce' ),
			)
		);

		do_action( 'woocommerce_product_options_global_unique_id' );

		?>
		<div class="inline notice woocommerce-message show_if_variable">
			<img class="info-icon" src="<?php echo esc_url( $info_img_url ); ?>" />
			<p>
				<?php esc_html_e( 'Settings below apply to all variations without manual stock management enabled. ', 'woocommerce' ); ?> <a target="_blank" href="https://woocommerce.com/document/variable-product/"><?php esc_html_e( 'Learn more', 'woocommerce' ); ?></a>
			</p>
		</div>
		<?php

		if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {

			woocommerce_wp_checkbox(
				array(
					'id'            => '_manage_stock',
					'value'         => $product_object->get_manage_stock( 'edit' ) ? 'yes' : 'no',
					'wrapper_class' => 'show_if_simple show_if_variable',
					'label'         => __( 'Stock management', 'woocommerce' ),
					'description'   => __( 'Track stock quantity for this product', 'woocommerce' ),
				)
			);

			do_action( 'woocommerce_product_options_stock' );

			echo '<div class="stock_fields show_if_simple show_if_variable">';

			/**
			 * Filters product default stock amount.
			 *
			 * @since 10.6.0
			 *
			 * @param int $default_stock_amount Default stock amount. Default is 1.
			 */
			$default_stock_amount = apply_filters( 'woocommerce_product_stock_default_amount', 1 );

			woocommerce_wp_text_input(
				array(
					'id'                => '_stock',
					'value'             => wc_stock_amount( $product_object->get_stock_quantity( 'edit' ) ?? $default_stock_amount ),
					'label'             => __( 'Quantity', 'woocommerce' ),
					'desc_tip'          => true,
					'description'       => __( 'Stock quantity. If this is a variable product this value will be used to control stock for all variations, unless you define stock at variation level.', 'woocommerce' ),
					'type'              => 'number',
					'custom_attributes' => array(
						'step' => 'any',
					),
					'data_type'         => 'stock',
				)
			);

			echo '<input type="hidden" name="_original_stock" value="' . esc_attr( wc_stock_amount( $product_object->get_stock_quantity( 'edit' ) ) ) . '" />';

			$backorder_args = array(
				'id'      => '_backorders',
				'value'   => $product_object->get_backorders( 'edit' ),
				'label'   => __( 'Allow backorders?', 'woocommerce' ),
				'options' => wc_get_product_backorder_options(),
			);

			/**
			 * Allow 3rd parties to control whether "Allow backorder?" option will use radio buttons or a select.
			 *
			 * @since 7.6.0
			 *
			 * @param bool If false, "Allow backorders?" will be shown as a select. Default: it will use radio buttons.
			 */
			if ( apply_filters( 'woocommerce_product_allow_backorder_use_radio', true ) ) {
				woocommerce_wp_radio( $backorder_args );
			} else {
				woocommerce_wp_select( $backorder_args );
			}

			woocommerce_wp_text_input(
				array(
					'id'                => '_low_stock_amount',
					'value'             => $product_object->get_low_stock_amount( 'edit' ),
					'placeholder'       => sprintf(
						/* translators: %d: Amount of stock left */
						esc_attr__( 'Store-wide threshold (%d)', 'woocommerce' ),
						esc_attr( get_option( 'woocommerce_notify_low_stock_amount' ) )
					),
					'label'             => __( 'Low stock threshold', 'woocommerce' ),
					'desc_tip'          => true,
					'description'       => __( 'When product stock reaches this amount you will be notified by email. It is possible to define different values for each variation individually. The shop default value can be set in Settings > Products > Inventory.', 'woocommerce' ),
					'type'              => 'number',
					'custom_attributes' => array(
						'step' => 'any',
					),
				)
			);

			do_action( 'woocommerce_product_options_stock_fields' );

			echo '</div>';
		} else {

			woocommerce_wp_note(
				array(
					'id'               => '_manage_stock_disabled',
					'label'            => __( 'Stock management', 'woocommerce' ),
					'label-aria-label' => __( 'Stock management disabled in store settings', 'woocommerce' ),
					'message'          => sprintf(
						/* translators: %s: url for store settings */
						__( 'Disabled in <a href="%s" aria-label="stock management store settings">store settings</a>.', 'woocommerce' ),
						esc_url( 'admin.php?page=wc-settings&tab=products&section=inventory' )
					),
					'wrapper_class'    => 'show_if_simple show_if_variable',
				)
			);

		}

		$stock_status_options = wc_get_product_stock_status_options();
		$stock_status_count   = count( $stock_status_options );
		$stock_status_args    = array(
			'id'            => '_stock_status',
			'value'         => $product_object->get_stock_status( 'edit' ),
			'wrapper_class' => 'stock_status_field hide_if_variable hide_if_external hide_if_grouped',
			'label'         => __( 'Stock status', 'woocommerce' ),
			'options'       => $stock_status_options,
			'desc_tip'      => true,
			'description'   => __( 'Controls whether or not the product is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce' ),
		);

		/**
		 * Allow 3rd parties to control whether the "Stock status" option will use radio buttons or a select.
		 *
		 * @since 7.6.0
		 *
		 * @param bool If false, the "Stock status" will be shown as a select. Default: it will use radio buttons.
		 */
		if ( apply_filters( 'woocommerce_product_stock_status_use_radio', $stock_status_count <= 3 && $stock_status_count >= 1 ) ) {
			woocommerce_wp_radio( $stock_status_args );
		} else {
			woocommerce_wp_select( $stock_status_args );
		}

		do_action( 'woocommerce_product_options_stock_status' );
		?>
	</div>

	<div class="inventory_sold_individually options_group show_if_simple show_if_variable">
		<?php
		woocommerce_wp_checkbox(
			array(
				'id'            => '_sold_individually',
				'value'         => $product_object->get_sold_individually( 'edit' ) ? 'yes' : 'no',
				'wrapper_class' => 'show_if_simple show_if_variable',
				'label'         => __( 'Sold individually', 'woocommerce' ),
				'description'   => __( 'Limit purchases to 1 item per order', 'woocommerce' ),
			)
		);

		echo wc_help_tip( __( 'Check to let customers to purchase only 1 item in a single order. This is particularly useful for items that have limited quantity, for example art or handmade goods.', 'woocommerce' ) );

		do_action( 'woocommerce_product_options_sold_individually' );
		?>
	</div>

	<?php do_action( 'woocommerce_product_options_inventory_product_data' ); ?>
</div>
PK     tS\Aѳ    .  meta-boxes/class-wc-meta-box-order-actions.phpnu [        <?php
/**
 * Order Actions
 *
 * Functions for displaying the order actions meta box.
 *
 * @package     WooCommerce\Admin\Meta Boxes
 * @version     2.1.0
 */

use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Internal\Admin\Orders\PageController;
use Automattic\WooCommerce\Internal\Orders\OrderNoteGroup;
use Automattic\WooCommerce\Utilities\OrderUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Meta_Box_Order_Actions Class.
 */
class WC_Meta_Box_Order_Actions {

	/**
	 * Output the metabox.
	 *
	 * @param WP_Post|WC_Order $post Post or order object.
	 */
	public static function output( $post ) {
		global $theorder;

		OrderUtil::init_theorder_object( $post );
		$order = $theorder;

		$order_id      = $order->get_id();
		$order_actions = self::get_available_order_actions_for_order( $order );
		?>
		<ul class="order_actions submitbox">

			<?php
			/**
			 * Fires at the start of order actions meta box rendering.
			 *
			 * @since 2.1.0
			 */
			do_action( 'woocommerce_order_actions_start', $order_id );
			?>


			<li class="wide" id="actions">
				<select name="wc_order_action">
					<option value=""><?php esc_html_e( 'Choose an action...', 'woocommerce' ); ?></option>
					<?php foreach ( $order_actions as $action => $title ) { ?>
						<option value="<?php echo esc_attr( $action ); ?>"><?php echo esc_html( $title ); ?></option>
					<?php } ?>
				</select>
				<button class="button wc-reload"><span><?php esc_html_e( 'Apply', 'woocommerce' ); ?></span></button>
			</li>

			<li class="wide">
				<div id="delete-action">
					<?php
					if ( current_user_can( 'delete_post', $order_id ) ) {

						if ( ! EMPTY_TRASH_DAYS ) {
							$delete_text = __( 'Delete permanently', 'woocommerce' );
						} else {
							$delete_text = __( 'Move to Trash', 'woocommerce' );
						}
						?>
						<a class="submitdelete deletion" href="<?php echo esc_url( self::get_trash_or_delete_order_link( $order_id ) ); ?>"><?php echo esc_html( $delete_text ); ?></a>
						<?php
					}
					?>
				</div>

				<button type="submit" class="button save_order button-primary" name="save" value="<?php echo OrderStatus::AUTO_DRAFT === $order->get_status() ? esc_attr__( 'Create', 'woocommerce' ) : esc_attr__( 'Update', 'woocommerce' ); ?>"><?php echo OrderStatus::AUTO_DRAFT === $order->get_status() ? esc_html__( 'Create', 'woocommerce' ) : esc_html__( 'Update', 'woocommerce' ); ?></button>
			</li>

			<?php
			/**
			 * Fires at the end of order actions meta box rendering.
			 *
			 * @since 2.1.0
			 */
			do_action( 'woocommerce_order_actions_end', $order_id );
			?>

		</ul>
		<?php
	}

	/**
	 * Forms a trash/delete order URL.
	 *
	 * @param int $order_id The order ID for which we want a trash/delete URL.
	 *
	 * @return string
	 */
	private static function get_trash_or_delete_order_link( int $order_id ): string {
		if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
			$order_type      = wc_get_order( $order_id )->get_type();
			$order_list_url  = wc_get_container()->get( PageController::class )->get_base_page_url( $order_type );
			$trash_order_url = add_query_arg(
				array(
					'action'           => 'trash',
					'id'               => array( $order_id ),
					'_wp_http_referer' => $order_list_url,
				),
				$order_list_url
			);

			return wp_nonce_url( $trash_order_url, 'bulk-orders' );
		}

		return get_delete_post_link( $order_id );
	}

	/**
	 * Save meta box data.
	 *
	 * @param int     $post_id Post ID.
	 * @param WP_Post $post Post Object.
	 */
	public static function save( $post_id, $post ) {
		// Order data saved, now get it so we can manipulate status.
		$order = wc_get_order( $post_id );

		// Handle button actions.
		if ( ! empty( $_POST['wc_order_action'] ) ) { // @codingStandardsIgnoreLine

			$action = wc_clean( wp_unslash( $_POST['wc_order_action'] ) ); // @codingStandardsIgnoreLine

			if ( 'send_order_details' === $action ) {
				/**
				 * Fires before an order email is resent.
				 *
				 * @since 1.0.0
				 */
				do_action( 'woocommerce_before_resend_order_emails', $order, 'customer_invoice' );

				// Send the customer invoice email.
				WC()->payment_gateways();
				WC()->shipping();
				WC()->mailer()->customer_invoice( $order );

				// Note the event.
				$order->add_order_note( __( 'Order details manually sent to customer.', 'woocommerce' ), false, true, array( 'note_group' => OrderNoteGroup::EMAIL_NOTIFICATION ) );

				/**
				 * Fires after an order email has been resent.
				 *
				 * @since 1.0.0
				 */
				do_action( 'woocommerce_after_resend_order_email', $order, 'customer_invoice' );

				// Change the post saved message.
				add_filter( 'redirect_post_location', array( __CLASS__, 'set_email_sent_message' ) );

			} elseif ( 'send_order_details_admin' === $action ) {

				do_action( 'woocommerce_before_resend_order_emails', $order, 'new_order' );

				WC()->payment_gateways();
				WC()->shipping();
				add_filter( 'woocommerce_new_order_email_allows_resend', '__return_true' );
				WC()->mailer()->emails['WC_Email_New_Order']->trigger( $order->get_id(), $order, true );
				remove_filter( 'woocommerce_new_order_email_allows_resend', '__return_true' );

				do_action( 'woocommerce_after_resend_order_email', $order, 'new_order' );

				// Change the post saved message.
				add_filter( 'redirect_post_location', array( __CLASS__, 'set_email_sent_message' ) );

			} elseif ( 'regenerate_download_permissions' === $action ) {

				$data_store = WC_Data_Store::load( 'customer-download' );
				$data_store->delete_by_order_id( $post_id );
				wc_downloadable_product_permissions( $post_id, true );

			} elseif ( ! did_action( 'woocommerce_order_action_' . sanitize_title( $action ) ) ) {

					do_action( 'woocommerce_order_action_' . sanitize_title( $action ), $order );
			}
		}
	}

	/**
	 * Set the correct message ID.
	 *
	 * @param string $location Location.
	 * @since  2.3.0
	 * @static
	 * @return string
	 */
	public static function set_email_sent_message( $location ) {
		return add_query_arg( 'message', 11, $location );
	}

	/**
	 * Get the available order actions for a given order.
	 *
	 * @since 5.8.0
	 *
	 * @param WC_Order|null $order The order object or null if no order is available.
	 *
	 * @return array
	 */
	private static function get_available_order_actions_for_order( $order ) {
		$actions = array(
			'send_order_details'              => __( 'Send order details to customer', 'woocommerce' ),
			'send_order_details_admin'        => __( 'Resend new order notification', 'woocommerce' ),
			'regenerate_download_permissions' => __( 'Regenerate download permissions', 'woocommerce' ),
		);

		/**
		 * Filter: woocommerce_order_actions
		 * Allows filtering of the available order actions for an order.
		 *
		 * @since 2.1.0 Filter was added.
		 * @since 5.8.0 The $order param was added.
		 *
		 * @param array         $actions The available order actions for the order.
		 * @param WC_Order|null $order   The order object or null if no order is available.
		 */
		return apply_filters( 'woocommerce_order_actions', $actions, $order );
	}
}
PK     tS\F	~  ~  ,  meta-boxes/class-wc-meta-box-order-items.phpnu [        <?php
/**
 * Order Data
 *
 * Functions for displaying the order items meta box.
 *
 * @author      WooThemes
 * @category    Admin
 * @package     WooCommerce\Admin\Meta Boxes
 * @version     2.1.0
 */

use Automattic\WooCommerce\Utilities\OrderUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

/**
 * WC_Meta_Box_Order_Items Class.
 */
class WC_Meta_Box_Order_Items {

	/**
	 * Output the metabox.
	 *
	 * @param WP_Post|WC_Order $post Post or order object.
	 */
	public static function output( $post ) {
		global $post, $thepostid, $theorder;

		OrderUtil::init_theorder_object( $post );
		if ( ! is_int( $thepostid ) && ( $post instanceof WP_Post ) ) {
			$thepostid = $post->ID;
		}

		$order = $theorder;
		$data  = ( $post instanceof WP_Post ) ? get_post_meta( $post->ID ) : array();

		include __DIR__ . '/views/html-order-items.php';
	}

	/**
	 * Save meta box data.
	 *
	 * @param int $post_id
	 */
	public static function save( $post_id ) {
		/**
		 * This $_POST variable's data has been validated and escaped
		 * inside `wc_save_order_items()` function.
		 */
		wc_save_order_items( $post_id, $_POST );
	}
}
PK     tS\p>    0  meta-boxes/class-wc-meta-box-product-reviews.phpnu [        <?php
/**
 * Product Reviews
 *
 * Functions for displaying product reviews data meta box.
 *
 * @package WooCommerce\Admin\Meta Boxes
 */

defined( 'ABSPATH' ) || exit;

/**
 * WC_Meta_Box_Product_Reviews
 */
class WC_Meta_Box_Product_Reviews {

	/**
	 * Output the metabox.
	 *
	 * @param object $comment Comment being shown.
	 */
	public static function output( $comment ) {
		wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );

		$current = get_comment_meta( $comment->comment_ID, 'rating', true );
		?>
		<select name="rating" id="rating">
			<?php
			for ( $rating = 1; $rating <= 5; $rating ++ ) {
				printf( '<option value="%1$s"%2$s>%1$s</option>', $rating, selected( $current, $rating, false ) ); // WPCS: XSS ok.
			}
			?>
		</select>
		<?php
	}

	/**
	 * Save meta box data
	 *
	 * @param mixed $data Data to save.
	 * @return mixed
	 */
	public static function save( $data ) {
		// Not allowed, return regular value without updating meta.
		if ( ! isset( $_POST['woocommerce_meta_nonce'], $_POST['rating'] ) || ! wp_verify_nonce( wp_unslash( $_POST['woocommerce_meta_nonce'] ), 'woocommerce_save_data' ) ) { // WPCS: input var ok, sanitization ok.
			return $data;
		}

		if ( $_POST['rating'] > 5 || $_POST['rating'] < 0 ) { // WPCS: input var ok.
			return $data;
		}

		$comment_id = $data['comment_ID'];

		update_comment_meta( $comment_id, 'rating', intval( wp_unslash( $_POST['rating'] ) ) ); // WPCS: input var ok.

		// Return regular value after updating.
		return $data;
	}
}
PK     tS\/l  l  -  meta-boxes/class-wc-meta-box-product-data.phpnu [        <?php
/**
 * Product Data
 *
 * Displays the product data box, tabbed, with several panels covering price, stock etc.
 *
 * @package  WooCommerce\Admin\Meta Boxes
 * @version  3.0.0
 */

use Automattic\WooCommerce\Enums\ProductStatus;
use Automattic\WooCommerce\Enums\ProductType;
use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;
use Automattic\WooCommerce\Internal\ProductFeed\Integrations\POSCatalog\POSProductVisibilitySync;
use Automattic\WooCommerce\Utilities\FeaturesUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Meta_Box_Product_Data Class.
 */
class WC_Meta_Box_Product_Data {

	/**
	 * Output the metabox.
	 *
	 * @param WP_Post $post Post object.
	 */
	public static function output( $post ) {
		global $thepostid, $product_object;

		$thepostid      = $post->ID;
		$product_object = $thepostid ? wc_get_product( $thepostid ) : new WC_Product();

		wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );

		include __DIR__ . '/views/html-product-data-panel.php';
	}

	/**
	 * Show tab content/settings.
	 */
	private static function output_tabs() {
		global $post, $thepostid, $product_object;

		include __DIR__ . '/views/html-product-data-general.php';
		include __DIR__ . '/views/html-product-data-inventory.php';
		include __DIR__ . '/views/html-product-data-shipping.php';
		include __DIR__ . '/views/html-product-data-linked-products.php';
		include __DIR__ . '/views/html-product-data-attributes.php';
		include __DIR__ . '/views/html-product-data-advanced.php';
	}

	/**
	 * Return array of product type options.
	 *
	 * @return array
	 */
	private static function get_product_type_options() {
		/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
		return apply_filters(
			'product_type_options',
			wc_get_default_product_type_options(),
		);
		/* phpcs: enable */
	}

	/**
	 * Return array of tabs to show.
	 *
	 * @return array
	 */
	private static function get_product_data_tabs() {
		/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
		$tabs = apply_filters(
			'woocommerce_product_data_tabs',
			array(
				'general'        => array(
					'label'    => __( 'General', 'woocommerce' ),
					'target'   => 'general_product_data',
					'class'    => array( 'hide_if_grouped' ),
					'priority' => 10,
				),
				'inventory'      => array(
					'label'    => __( 'Inventory', 'woocommerce' ),
					'target'   => 'inventory_product_data',
					'class'    => array( 'show_if_simple', 'show_if_variable', 'show_if_grouped', 'show_if_external' ),
					'priority' => 20,
				),
				'shipping'       => array(
					'label'    => __( 'Shipping', 'woocommerce' ),
					'target'   => 'shipping_product_data',
					'class'    => array( 'hide_if_virtual', 'hide_if_grouped', 'hide_if_external' ),
					'priority' => 30,
				),
				'linked_product' => array(
					'label'    => __( 'Linked Products', 'woocommerce' ),
					'target'   => 'linked_product_data',
					'class'    => array(),
					'priority' => 40,
				),
				'attribute'      => array(
					'label'    => __( 'Attributes', 'woocommerce' ),
					'target'   => 'product_attributes',
					'class'    => array(),
					'priority' => 50,
				),
				'variations'     => array(
					'label'    => __( 'Variations', 'woocommerce' ),
					'target'   => 'variable_product_options',
					'class'    => array( 'show_if_variable' ),
					'priority' => 60,
				),
				'advanced'       => array(
					'label'    => __( 'Advanced', 'woocommerce' ),
					'target'   => 'advanced_product_data',
					'class'    => array(),
					'priority' => 70,
				),
			)
		);
		/* phpcs: enable */

		// Sort tabs based on priority.
		uasort( $tabs, array( __CLASS__, 'product_data_tabs_sort' ) );

		return $tabs;
	}

	/**
	 * Callback to sort product data tabs on priority.
	 *
	 * @since 3.1.0
	 * @param int $a First item.
	 * @param int $b Second item.
	 *
	 * @return bool
	 */
	private static function product_data_tabs_sort( $a, $b ) {
		if ( ! isset( $a['priority'], $b['priority'] ) ) {
			return -1;
		}

		if ( $a['priority'] === $b['priority'] ) {
			return 0;
		}

		return $a['priority'] < $b['priority'] ? -1 : 1;
	}

	/**
	 * Filter callback for finding variation attributes.
	 *
	 * @param  WC_Product_Attribute $attribute Product attribute.
	 * @return bool
	 */
	private static function filter_variation_attributes( $attribute ) {
		return true === $attribute->get_variation();
	}

	/**
	 * Filter callback for finding non-variation attributes.
	 *
	 * @param  WC_Product_Attribute $attribute Product attribute.
	 * @return bool
	 */
	private static function filter_non_variation_attributes( $attribute ) {
		return false === $attribute->get_variation();
	}

	/**
	 * Show options for the variable product type.
	 */
	public static function output_variations() {
		global $post, $wpdb, $product_object;

		/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
		$variation_attributes   = array_filter( $product_object->get_attributes(), array( __CLASS__, 'filter_variation_attributes' ) );
		$default_attributes     = $product_object->get_default_attributes();
		$variations_count       = absint( apply_filters( 'woocommerce_admin_meta_boxes_variations_count', $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(ID) FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'product_variation' AND post_status IN ('publish', 'private')", $post->ID ) ), $post->ID ) );
		$variations_per_page    = absint( apply_filters( 'woocommerce_admin_meta_boxes_variations_per_page', 15 ) );
		$variations_total_pages = ceil( $variations_count / $variations_per_page );
		$modal_title            = get_bloginfo( 'name' ) . __( ' says', 'woocommerce' );
		/* phpcs: enable */

		include __DIR__ . '/views/html-product-data-variations.php';
	}

	/**
	 * Prepare downloads for save.
	 *
	 * @param array $file_names File names.
	 * @param array $file_urls File urls.
	 * @param array $file_hashes File hashes.
	 *
	 * @return array
	 */
	private static function prepare_downloads( $file_names, $file_urls, $file_hashes ) {
		$downloads = array();

		if ( ! empty( $file_urls ) ) {
			$file_url_size = count( $file_urls );

			for ( $i = 0; $i < $file_url_size; $i++ ) {
				if ( ! empty( $file_urls[ $i ] ) ) {
					$downloads[] = array(
						'name'        => wc_clean( $file_names[ $i ] ),
						'file'        => wp_unslash( trim( $file_urls[ $i ] ) ),
						'download_id' => wc_clean( $file_hashes[ $i ] ),
					);
				}
			}
		}
		return $downloads;
	}

	/**
	 * Prepare children for save.
	 *
	 * @return array
	 */
	private static function prepare_children() {
		return isset( $_POST['grouped_products'] ) ? array_filter( array_map( 'intval', (array) $_POST['grouped_products'] ) ) : array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
	}

	/**
	 * Prepare attributes for save.
	 *
	 * @param array $data Attribute data.
	 *
	 * @return array
	 */
	public static function prepare_attributes( $data = false ) {
		$attributes = array();

		if ( ! $data ) {
			$data = stripslashes_deep( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
		}

		if ( isset( $data['attribute_names'], $data['attribute_values'] ) ) {
			$attribute_names         = $data['attribute_names'];
			$attribute_values        = $data['attribute_values'];
			$attribute_visibility    = isset( $data['attribute_visibility'] ) ? $data['attribute_visibility'] : array();
			$attribute_variation     = isset( $data['attribute_variation'] ) ? $data['attribute_variation'] : array();
			$attribute_position      = $data['attribute_position'];
			$attribute_names_max_key = max( array_keys( $attribute_names ) );

			for ( $i = 0; $i <= $attribute_names_max_key; $i++ ) {
				if ( empty( $attribute_names[ $i ] ) || ! isset( $attribute_values[ $i ] ) ) {
					continue;
				}
				$attribute_id   = 0;
				$attribute_name = wc_clean( esc_html( $attribute_names[ $i ] ) );

				if ( 'pa_' === substr( $attribute_name, 0, 3 ) ) {
					$attribute_id = wc_attribute_taxonomy_id_by_name( $attribute_name );
				}

				$options = isset( $attribute_values[ $i ] ) ? $attribute_values[ $i ] : '';

				if ( is_array( $options ) ) {
					// Term ids sent as array.
					$options = wp_parse_id_list( $options );
				} else {
					// Terms or text sent in textarea.
					$options = 0 < $attribute_id ? wc_sanitize_textarea( esc_html( wc_sanitize_term_text_based( $options ) ) ) : wc_sanitize_textarea( esc_html( $options ) );
					$options = wc_get_text_attributes( $options );
				}

				if ( empty( $options ) ) {
					continue;
				}

				$attribute = new WC_Product_Attribute();
				$attribute->set_id( $attribute_id );
				$attribute->set_name( $attribute_name );
				$attribute->set_options( $options );
				$attribute->set_position( $attribute_position[ $i ] );
				$attribute->set_visible( isset( $attribute_visibility[ $i ] ) );
				$attribute->set_variation( isset( $attribute_variation[ $i ] ) );
				/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
				$attributes[] = apply_filters( 'woocommerce_admin_meta_boxes_prepare_attribute', $attribute, $data, $i );
				/* phpcs: enable */
			}
		}
		return $attributes;
	}

	/**
	 * Prepare attributes for a specific variation or defaults.
	 *
	 * @param  array  $all_attributes List of attribute keys.
	 * @param  string $key_prefix Attribute key prefix.
	 * @param  int    $index Attribute array index.
	 * @return array
	 */
	private static function prepare_set_attributes( $all_attributes, $key_prefix = 'attribute_', $index = null ) {
		$attributes = array();

		if ( $all_attributes ) {
			foreach ( $all_attributes as $attribute ) {
				if ( $attribute->get_variation() ) {
					$attribute_key = sanitize_title( $attribute->get_name() );

					if ( ! is_null( $index ) ) {
						$value = isset( $_POST[ $key_prefix . $attribute_key ][ $index ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ][ $index ] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
					} else {
						$value = isset( $_POST[ $key_prefix . $attribute_key ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
					}

					if ( $attribute->is_taxonomy() ) {
						// Don't use wc_clean as it destroys sanitized characters.
						$value = sanitize_title( $value );
					} else {
						$value = html_entity_decode( wc_clean( $value ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // WPCS: sanitization ok.
					}

					$attributes[ $attribute_key ] = $value;
				}
			}
		}

		return $attributes;
	}

	/**
	 * Save meta box data.
	 *
	 * @param int     $post_id WP post id.
	 * @param WP_Post $post Post object.
	 */
	public static function save( $post_id, $post ) {
		// phpcs:disable WordPress.Security.NonceVerification.Missing
		// Process product type first so we have the correct class to run setters.
		$product_type = empty( $_POST['product-type'] ) ? WC_Product_Factory::get_product_type( $post_id ) : sanitize_title( wp_unslash( $_POST['product-type'] ) );
		$classname    = WC_Product_Factory::get_product_classname( $post_id, $product_type ? $product_type : ProductType::SIMPLE );
		$product      = new $classname( $post_id );
		$attributes   = self::prepare_attributes();
		$stock        = null;

		// Handle stock changes.
		if ( isset( $_POST['_stock'] ) ) {
			if ( isset( $_POST['_original_stock'] ) && wc_stock_amount( $product->get_stock_quantity( 'edit' ) ) !== wc_stock_amount( wp_unslash( $_POST['_original_stock'] ) ) ) {
				/* translators: 1: product ID 2: quantity in stock */
				WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The stock has not been updated because the value has changed since editing. Product %1$d has %2$d units in stock.', 'woocommerce' ), $product->get_id(), $product->get_stock_quantity( 'edit' ) ) );
			} else {
				$stock = wc_stock_amount( wp_unslash( $_POST['_stock'] ) );
			}
		}

		// Handle dates.
		$date_on_sale_from = '';
		$date_on_sale_to   = '';

		// Force date from to beginning of day.
		if ( isset( $_POST['_sale_price_dates_from'] ) ) {
			$date_on_sale_from = wc_clean( wp_unslash( $_POST['_sale_price_dates_from'] ) );

			if ( ! empty( $date_on_sale_from ) ) {
				$date_on_sale_from = date( 'Y-m-d 00:00:00', strtotime( $date_on_sale_from ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
			}
		}

		// Force date to to the end of the day.
		if ( isset( $_POST['_sale_price_dates_to'] ) ) {
			$date_on_sale_to = wc_clean( wp_unslash( $_POST['_sale_price_dates_to'] ) );

			if ( ! empty( $date_on_sale_to ) ) {
				$date_on_sale_to = date( 'Y-m-d 23:59:59', strtotime( $date_on_sale_to ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
			}
		}

		$errors = $product->set_props(
			array(
				'sku'                => isset( $_POST['_sku'] ) ? wc_clean( wp_unslash( $_POST['_sku'] ) ) : null,
				'global_unique_id'   => isset( $_POST['_global_unique_id'] ) ? wc_clean( wp_unslash( $_POST['_global_unique_id'] ) ) : null,
				'purchase_note'      => isset( $_POST['_purchase_note'] ) ? wp_kses_post( wp_unslash( $_POST['_purchase_note'] ) ) : '',
				'downloadable'       => isset( $_POST['_downloadable'] ),
				'virtual'            => isset( $_POST['_virtual'] ),
				'featured'           => isset( $_POST['_featured'] ),
				'catalog_visibility' => isset( $_POST['_visibility'] ) ? wc_clean( wp_unslash( $_POST['_visibility'] ) ) : null,
				'tax_status'         => isset( $_POST['_tax_status'] ) ? wc_clean( wp_unslash( $_POST['_tax_status'] ) ) : null,
				'tax_class'          => isset( $_POST['_tax_class'] ) ? sanitize_title( wp_unslash( $_POST['_tax_class'] ) ) : null,
				'weight'             => isset( $_POST['_weight'] ) ? wc_clean( wp_unslash( $_POST['_weight'] ) ) : null,
				'length'             => isset( $_POST['_length'] ) ? wc_clean( wp_unslash( $_POST['_length'] ) ) : null,
				'width'              => isset( $_POST['_width'] ) ? wc_clean( wp_unslash( $_POST['_width'] ) ) : null,
				'height'             => isset( $_POST['_height'] ) ? wc_clean( wp_unslash( $_POST['_height'] ) ) : null,
				'shipping_class_id'  => isset( $_POST['product_shipping_class'] ) ? absint( wp_unslash( $_POST['product_shipping_class'] ) ) : null,
				'sold_individually'  => ! empty( $_POST['_sold_individually'] ),
				'upsell_ids'         => isset( $_POST['upsell_ids'] ) ? array_map( 'intval', (array) wp_unslash( $_POST['upsell_ids'] ) ) : array(),
				'cross_sell_ids'     => isset( $_POST['crosssell_ids'] ) ? array_map( 'intval', (array) wp_unslash( $_POST['crosssell_ids'] ) ) : array(),
				'regular_price'      => isset( $_POST['_regular_price'] ) ? wc_clean( wp_unslash( $_POST['_regular_price'] ) ) : null,
				'sale_price'         => isset( $_POST['_sale_price'] ) ? wc_clean( wp_unslash( $_POST['_sale_price'] ) ) : null,
				'date_on_sale_from'  => $date_on_sale_from,
				'date_on_sale_to'    => $date_on_sale_to,
				'manage_stock'       => ! empty( $_POST['_manage_stock'] ),
				'backorders'         => isset( $_POST['_backorders'] ) ? wc_clean( wp_unslash( $_POST['_backorders'] ) ) : null,
				'stock_status'       => isset( $_POST['_stock_status'] ) ? wc_clean( wp_unslash( $_POST['_stock_status'] ) ) : null,
				'stock_quantity'     => $stock,
				'low_stock_amount'   => isset( $_POST['_low_stock_amount'] ) && '' !== $_POST['_low_stock_amount'] ? wc_stock_amount( wp_unslash( $_POST['_low_stock_amount'] ) ) : '',
				'download_limit'     => isset( $_POST['_download_limit'] ) && '' !== $_POST['_download_limit'] ? absint( wp_unslash( $_POST['_download_limit'] ) ) : '',
				'download_expiry'    => isset( $_POST['_download_expiry'] ) && '' !== $_POST['_download_expiry'] ? absint( wp_unslash( $_POST['_download_expiry'] ) ) : '',
				// Those are sanitized inside prepare_downloads.
				'downloads'          => self::prepare_downloads(
					isset( $_POST['_wc_file_names'] ) ? wp_unslash( $_POST['_wc_file_names'] ) : array(), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
					isset( $_POST['_wc_file_urls'] ) ? wp_unslash( $_POST['_wc_file_urls'] ) : array(), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
					isset( $_POST['_wc_file_hashes'] ) ? wp_unslash( $_POST['_wc_file_hashes'] ) : array() // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
				),
				'product_url'        => isset( $_POST['_product_url'] ) ? esc_url_raw( wp_unslash( $_POST['_product_url'] ) ) : '',
				'button_text'        => isset( $_POST['_button_text'] ) ? wc_clean( wp_unslash( $_POST['_button_text'] ) ) : '',
				'children'           => ProductType::GROUPED === $product_type ? self::prepare_children() : null,
				'reviews_allowed'    => ! empty( $_POST['comment_status'] ) && 'open' === $_POST['comment_status'],
				'attributes'         => $attributes,
				'default_attributes' => self::prepare_set_attributes( $attributes, 'default_attribute_' ),
			)
		);

		if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() ) {
			$cogs_value = wc_clean( wp_unslash( $_POST['_cogs_value'] ?? null ) );
			$product->set_cogs_value( is_null( $cogs_value ) ? null : (float) wc_format_decimal( $cogs_value ) );
		}

		if ( is_wp_error( $errors ) ) {
			WC_Admin_Meta_Boxes::add_error( $errors->get_error_message() );
		}

		// Remove _product_template_id for products that were created with the new product editor.
		$product->delete_meta_data( '_product_template_id' );

		if ( FeaturesUtil::feature_is_enabled( 'point_of_sale' ) ) {
			$visible_in_pos = isset( $_POST['_visible_in_pos'] ) && 'yes' === wc_clean( wp_unslash( $_POST['_visible_in_pos'] ) );
			wc_get_container()->get( POSProductVisibilitySync::class )->set_product_pos_visibility( $post_id, $visible_in_pos );
		}

		/**
		 * Set props before save.
		 *
		 * @since 3.0.0
		 */
		do_action( 'woocommerce_admin_process_product_object', $product );

		$product->save();

		if ( $product->is_type( ProductType::VARIABLE ) ) {
			$original_post_title = isset( $_POST['original_post_title'] ) ? wc_clean( wp_unslash( $_POST['original_post_title'] ) ) : '';
			$post_title          = isset( $_POST['post_title'] ) ? wc_clean( wp_unslash( $_POST['post_title'] ) ) : '';

			$product->get_data_store()->sync_variation_names( $product, $original_post_title, $post_title );
		}
		/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
		do_action( 'woocommerce_process_product_meta_' . $product_type, $post_id );
		/* phpcs:enable WordPress.Security.NonceVerification.Missing and WooCommerce.Commenting.CommentHooks.MissingHookComment */
	}

	/**
	 * Save variation meta box data.
	 *
	 * @param int     $post_id WP post id.
	 * @param WP_Post $post Post object.
	 */
	public static function save_variations( $post_id, $post ) {
		global $wpdb;

		// phpcs:disable WordPress.Security.NonceVerification.Missing
		if ( isset( $_POST['variable_post_id'] ) ) {
			$parent = wc_get_product( $post_id );
			$parent->set_default_attributes( self::prepare_set_attributes( $parent->get_attributes(), 'default_attribute_' ) );
			$parent->save();

			$max_loop   = max( array_keys( wp_unslash( $_POST['variable_post_id'] ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			$data_store = $parent->get_data_store();
			$data_store->sort_all_product_variations( $parent->get_id() );
			$new_variation_menu_order_id    = ! empty( $_POST['new_variation_menu_order_id'] ) ? wc_clean( wp_unslash( $_POST['new_variation_menu_order_id'] ) ) : false;
			$new_variation_menu_order_value = ! empty( $_POST['new_variation_menu_order_value'] ) ? wc_clean( wp_unslash( $_POST['new_variation_menu_order_value'] ) ) : false;

			// Only perform this operation if setting menu order via the prompt.
			if ( $new_variation_menu_order_id && $new_variation_menu_order_value ) {
				/*
				 * We need to gather all the variations with menu order that is
				 * equal or greater than the menu order that is newly set and
				 * increment them by one so that we can correctly insert the updated
				 * variation menu order.
				 */
				$wpdb->query(
					$wpdb->prepare(
						"UPDATE {$wpdb->posts} SET menu_order = menu_order + 1 WHERE post_type = 'product_variation' AND post_parent = %d AND post_status = 'publish' AND menu_order >= %d AND ID != %d",
						$post_id,
						$new_variation_menu_order_value,
						$new_variation_menu_order_id
					)
				);
			}

			$cogs_is_enabled = wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled();
			for ( $i = 0; $i <= $max_loop; $i++ ) {

				if ( ! isset( $_POST['variable_post_id'][ $i ] ) ) {
					continue;
				}
				$variation_id = absint( $_POST['variable_post_id'][ $i ] );
				$variation    = wc_get_product_object( ProductType::VARIATION, $variation_id );
				$stock        = null;

				// Handle stock changes.
				if ( isset( $_POST['variable_stock'], $_POST['variable_stock'][ $i ] ) ) {
					if ( isset( $_POST['variable_original_stock'], $_POST['variable_original_stock'][ $i ] ) && wc_stock_amount( $variation->get_stock_quantity( 'edit' ) ) !== wc_stock_amount( wp_unslash( $_POST['variable_original_stock'][ $i ] ) ) ) {
						/* translators: 1: product ID 2: quantity in stock */
						WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The stock has not been updated because the value has changed since editing. Product %1$d has %2$d units in stock.', 'woocommerce' ), $variation->get_id(), $variation->get_stock_quantity( 'edit' ) ) );
					} else {
						$stock = wc_stock_amount( wp_unslash( $_POST['variable_stock'][ $i ] ) );
					}
				}

				// Handle dates.
				$date_on_sale_from = '';
				$date_on_sale_to   = '';

				// Force date from to beginning of day.
				if ( isset( $_POST['variable_sale_price_dates_from'][ $i ] ) ) {
					$date_on_sale_from = wc_clean( wp_unslash( $_POST['variable_sale_price_dates_from'][ $i ] ) );

					if ( ! empty( $date_on_sale_from ) ) {
						$date_on_sale_from = date( 'Y-m-d 00:00:00', strtotime( $date_on_sale_from ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
					}
				}

				// Force date to to the end of the day.
				if ( isset( $_POST['variable_sale_price_dates_to'][ $i ] ) ) {
					$date_on_sale_to = wc_clean( wp_unslash( $_POST['variable_sale_price_dates_to'][ $i ] ) );

					if ( ! empty( $date_on_sale_to ) ) {
						$date_on_sale_to = date( 'Y-m-d 23:59:59', strtotime( $date_on_sale_to ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
					}
				}

				$errors = $variation->set_props(
					array(
						'status'            => isset( $_POST['variable_enabled'][ $i ] ) ? ProductStatus::PUBLISH : ProductStatus::PRIVATE,
						'menu_order'        => isset( $_POST['variation_menu_order'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variation_menu_order'][ $i ] ) ) : null,
						'regular_price'     => isset( $_POST['variable_regular_price'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_regular_price'][ $i ] ) ) : null,
						'sale_price'        => isset( $_POST['variable_sale_price'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_sale_price'][ $i ] ) ) : null,
						'virtual'           => isset( $_POST['variable_is_virtual'][ $i ] ),
						'downloadable'      => isset( $_POST['variable_is_downloadable'][ $i ] ),
						'date_on_sale_from' => $date_on_sale_from,
						'date_on_sale_to'   => $date_on_sale_to,
						'description'       => isset( $_POST['variable_description'][ $i ] ) ? wp_kses_post( wp_unslash( $_POST['variable_description'][ $i ] ) ) : null,
						'download_limit'    => isset( $_POST['variable_download_limit'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_download_limit'][ $i ] ) ) : null,
						'download_expiry'   => isset( $_POST['variable_download_expiry'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_download_expiry'][ $i ] ) ) : null,
						// Those are sanitized inside prepare_downloads.
						'downloads'         => self::prepare_downloads(
							isset( $_POST['_wc_variation_file_names'][ $variation_id ] ) ? wp_unslash( $_POST['_wc_variation_file_names'][ $variation_id ] ) : array(), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
							isset( $_POST['_wc_variation_file_urls'][ $variation_id ] ) ? wp_unslash( $_POST['_wc_variation_file_urls'][ $variation_id ] ) : array(), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
							isset( $_POST['_wc_variation_file_hashes'][ $variation_id ] ) ? wp_unslash( $_POST['_wc_variation_file_hashes'][ $variation_id ] ) : array() // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
						),
						'manage_stock'      => isset( $_POST['variable_manage_stock'][ $i ] ),
						'stock_quantity'    => $stock,
						'low_stock_amount'  => isset( $_POST['variable_low_stock_amount'][ $i ] ) && '' !== $_POST['variable_low_stock_amount'][ $i ] ? wc_stock_amount( wp_unslash( $_POST['variable_low_stock_amount'][ $i ] ) ) : '',
						'backorders'        => isset( $_POST['variable_backorders'], $_POST['variable_backorders'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_backorders'][ $i ] ) ) : null,
						'stock_status'      => isset( $_POST['variable_stock_status'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_stock_status'][ $i ] ) ) : null,
						'image_id'          => isset( $_POST['upload_image_id'][ $i ] ) ? wc_clean( wp_unslash( $_POST['upload_image_id'][ $i ] ) ) : null,
						'attributes'        => self::prepare_set_attributes( $parent->get_attributes(), 'attribute_', $i ),
						'sku'               => isset( $_POST['variable_sku'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_sku'][ $i ] ) ) : '',
						'global_unique_id'  => isset( $_POST['variable_global_unique_id'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_global_unique_id'][ $i ] ) ) : '',
						'weight'            => isset( $_POST['variable_weight'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_weight'][ $i ] ) ) : '',
						'length'            => isset( $_POST['variable_length'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_length'][ $i ] ) ) : '',
						'width'             => isset( $_POST['variable_width'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_width'][ $i ] ) ) : '',
						'height'            => isset( $_POST['variable_height'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_height'][ $i ] ) ) : '',
						'shipping_class_id' => isset( $_POST['variable_shipping_class'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_shipping_class'][ $i ] ) ) : null,
						'tax_class'         => isset( $_POST['variable_tax_class'][ $i ] ) ? sanitize_title( wp_unslash( $_POST['variable_tax_class'][ $i ] ) ) : null,
					)
				);

				if ( is_wp_error( $errors ) ) {
					WC_Admin_Meta_Boxes::add_error( $errors->get_error_message() );
				}

				if ( $cogs_is_enabled ) {
					$cogs_value = wc_clean( wp_unslash( $_POST['variable_cost_value'][ $i ] ?? '' ) );
					if ( '' === $cogs_value ) {
						$cogs_value = null;
					}
					$variation->set_cogs_value( is_null( $cogs_value ) ? null : (float) wc_format_decimal( $cogs_value ) );
				}

				/**
				 * Set variation props before save.
				 *
				 * @param object $variation WC_Product_Variation object.
				 * @param int $i
				 * @since 3.8.0
				 */
				do_action( 'woocommerce_admin_process_variation_object', $variation, $i );

				$variation->save();
				/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
				do_action( 'woocommerce_save_product_variation', $variation_id, $i );
				/* phpcs: enable */
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification.Missing
	}
}
PK     tS\8<    /  meta-boxes/class-wc-meta-box-product-images.phpnu [        <?php
/**
 * Product Images
 *
 * Display the product images meta box.
 *
 * @author      WooThemes
 * @category    Admin
 * @package     WooCommerce\Admin\Meta Boxes
 * @version     2.1.0
 */

use Automattic\WooCommerce\Enums\ProductType;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

/**
 * WC_Meta_Box_Product_Images Class.
 */
class WC_Meta_Box_Product_Images {

	/**
	 * Output the metabox.
	 *
	 * @param WP_Post $post
	 */
	public static function output( $post ) {
		global $thepostid, $product_object;

		$thepostid      = $post->ID;
		$product_object = $thepostid ? wc_get_product( $thepostid ) : new WC_Product();
		wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );
		?>
		<div id="product_images_container">
			<ul class="product_images">
				<?php
				$product_image_gallery = $product_object->get_gallery_image_ids( 'edit' );

				$attachments         = array_filter( $product_image_gallery );
				$update_meta         = false;
				$updated_gallery_ids = array();

				if ( ! empty( $attachments ) ) {
					foreach ( $attachments as $attachment_id ) {
						$attachment = wp_get_attachment_image( $attachment_id, 'thumbnail' );

						// if attachment is empty skip.
						if ( empty( $attachment ) ) {
							$update_meta = true;
							continue;
						}
						?>
						<li class="image" data-attachment_id="<?php echo esc_attr( $attachment_id ); ?>">
							<?php echo $attachment; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
							<ul class="actions">
								<li><a href="#" class="delete tips" data-tip="<?php esc_attr_e( 'Delete image', 'woocommerce' ); ?>"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a></li>
							</ul>
							<?php
							// Allow for extra info to be exposed or extra action to be executed for this attachment.
							do_action( 'woocommerce_admin_after_product_gallery_item', $thepostid, $attachment_id );
							?>
						</li>
						<?php

						// rebuild ids to be saved.
						$updated_gallery_ids[] = $attachment_id;
					}

					// need to update product meta to set new gallery ids
					if ( $update_meta ) {
						update_post_meta( $post->ID, '_product_image_gallery', implode( ',', $updated_gallery_ids ) );
					}
				}
				?>
			</ul>

			<input type="hidden" id="product_image_gallery" name="product_image_gallery" value="<?php echo esc_attr( implode( ',', $updated_gallery_ids ) ); ?>" />

		</div>
		<p class="add_product_images hide-if-no-js">
			<a href="#" data-choose="<?php esc_attr_e( 'Add images to product gallery', 'woocommerce' ); ?>" data-update="<?php esc_attr_e( 'Add to gallery', 'woocommerce' ); ?>" data-delete="<?php esc_attr_e( 'Delete image', 'woocommerce' ); ?>" data-text="<?php esc_attr_e( 'Delete', 'woocommerce' ); ?>"><?php esc_html_e( 'Add product gallery images', 'woocommerce' ); ?></a>
		</p>
		<?php
	}

	/**
	 * Save meta box data.
	 *
	 * @param int     $post_id
	 * @param WP_Post $post
	 */
	public static function save( $post_id, $post ) {
		$product_type   = empty( $_POST['product-type'] ) ? WC_Product_Factory::get_product_type( $post_id ) : sanitize_title( stripslashes( $_POST['product-type'] ) );
		$classname      = WC_Product_Factory::get_product_classname( $post_id, $product_type ? $product_type : ProductType::SIMPLE );
		$product        = new $classname( $post_id );
		$attachment_ids = isset( $_POST['product_image_gallery'] ) ? array_filter( explode( ',', wc_clean( $_POST['product_image_gallery'] ) ) ) : array();

		$product->set_gallery_image_ids( $attachment_ids );
		$product->save();
	}
}
PK     tS\.L  L  :  meta-boxes/class-wc-meta-box-product-short-description.phpnu [        <?php
/**
 * Product Short Description
 *
 * Replaces the standard excerpt box.
 *
 * @package     WooCommerce\Admin\Meta Boxes
 * @version     2.1.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * WC_Meta_Box_Product_Short_Description Class.
 */
class WC_Meta_Box_Product_Short_Description {

	/**
	 * Output the metabox.
	 *
	 * @param WP_Post $post Post object.
	 */
	public static function output( $post ) {

		$settings = array(
			'textarea_name' => 'excerpt',
			'quicktags'     => array( 'buttons' => 'em,strong,link' ),
			'tinymce'       => array(
				'theme_advanced_buttons1' => 'bold,italic,strikethrough,separator,bullist,numlist,separator,blockquote,separator,justifyleft,justifycenter,justifyright,separator,link,unlink,separator,undo,redo,separator',
				'theme_advanced_buttons2' => '',
			),
			'editor_css'    => '<style>#wp-excerpt-editor-container .wp-editor-area{height:175px; width:100%;}</style>',
		);

		wp_editor( htmlspecialchars_decode( $post->post_excerpt, ENT_QUOTES ), 'excerpt', apply_filters( 'woocommerce_product_short_description_editor_settings', $settings ) );
	}
}
PK     tS\T      ,  meta-boxes/class-wc-meta-box-order-notes.phpnu [        <?php
/**
 * Order Notes
 *
 * @package WooCommerce\Admin\Meta Boxes
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Meta_Box_Order_Notes Class.
 */
class WC_Meta_Box_Order_Notes {

	/**
	 * Output the metabox.
	 *
	 * @param WP_Post|WC_Order $post Post or order object.
	 */
	public static function output( $post ) {
		if ( $post instanceof WC_Order ) {
			$order_id = $post->get_id();
		} else {
			$order_id = $post->ID;
		}

		$args = array( 'order_id' => $order_id );

		if ( 0 !== $order_id ) {
			$notes = wc_get_order_notes( $args );
		} else {
			$notes = array();
		}
		?>
		<div class="add_note">
			<p>
				<label for="add_order_note"><?php esc_html_e( 'Add note', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'Add a note for your reference, or add a customer note (the user will be notified).', 'woocommerce' ) ); ?></label>
				<textarea type="text" name="order_note" id="add_order_note" class="input-text" cols="20" rows="5"></textarea>
			</p>
			<p>
				<label for="order_note_type" class="screen-reader-text"><?php esc_html_e( 'Note type', 'woocommerce' ); ?></label>
				<select name="order_note_type" id="order_note_type">
					<option value=""><?php esc_html_e( 'Private note', 'woocommerce' ); ?></option>
					<option value="customer"><?php esc_html_e( 'Note to customer', 'woocommerce' ); ?></option>
				</select>
				<button type="button" class="add_note button"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
			</p>
		</div>
		<?php
		include __DIR__ . '/views/html-order-notes.php';
	}
}
PK     tS\V^C  ^C  ,  meta-boxes/class-wc-meta-box-coupon-data.phpnu [        <?php
/**
 * Coupon Data
 *
 * Display the coupon data meta box.
 *
 * @author      WooThemes
 * @category    Admin
 * @package     WooCommerce\Admin\Meta Boxes
 * @version     x.x.x
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

/**
 * WC_Meta_Box_Coupon_Data Class.
 */
class WC_Meta_Box_Coupon_Data {

	/**
	 * Output the metabox.
	 *
	 * @param WP_Post $post
	 */
	public static function output( $post ) {
		wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );

		$coupon_id = absint( $post->ID );
		$coupon    = new WC_Coupon( $coupon_id );

		?>

		<style type="text/css">
			#edit-slug-box, #minor-publishing-actions { display:none }
		</style>
		<div id="coupon_options" class="panel-wrap coupon_data">

			<div class="wc-tabs-back"></div>

			<ul class="coupon_data_tabs wc-tabs" style="display:none;">
				<?php
				$coupon_data_tabs = apply_filters(
					'woocommerce_coupon_data_tabs',
					array(
						'general'           => array(
							'label'  => __( 'General', 'woocommerce' ),
							'target' => 'general_coupon_data',
							'class'  => 'general_coupon_data',
						),
						'usage_restriction' => array(
							'label'  => __( 'Usage restriction', 'woocommerce' ),
							'target' => 'usage_restriction_coupon_data',
							'class'  => '',
						),
						'usage_limit'       => array(
							'label'  => __( 'Usage limits', 'woocommerce' ),
							'target' => 'usage_limit_coupon_data',
							'class'  => '',
						),
					)
				);

				foreach ( $coupon_data_tabs as $key => $tab ) :
					?>
					<li class="<?php echo $key; ?>_options <?php echo $key; ?>_tab <?php echo implode( ' ', (array) $tab['class'] ); ?>">
						<a href="#<?php echo $tab['target']; ?>">
							<span><?php echo esc_html( $tab['label'] ); ?></span>
						</a>
					</li>
				<?php endforeach; ?>
			</ul>
			<div id="general_coupon_data" class="panel woocommerce_options_panel">
				<?php

				// Type.
				woocommerce_wp_select(
					array(
						'id'      => 'discount_type',
						'label'   => __( 'Discount type', 'woocommerce' ),
						'options' => wc_get_coupon_types(),
						'value'   => $coupon->get_discount_type( 'edit' ),
					)
				);

				// Amount.
				woocommerce_wp_text_input(
					array(
						'id'          => 'coupon_amount',
						'label'       => __( 'Coupon amount', 'woocommerce' ),
						'placeholder' => wc_format_localized_price( 0 ),
						'description' => __( 'Value of the coupon.', 'woocommerce' ),
						'data_type'   => 'percent' === $coupon->get_discount_type( 'edit' ) ? 'decimal' : 'price',
						'desc_tip'    => true,
						'value'       => $coupon->get_amount( 'edit' ),
					)
				);

				// Free Shipping.
				if ( wc_shipping_enabled() ) {
					woocommerce_wp_checkbox(
						array(
							'id'          => 'free_shipping',
							'label'       => __( 'Allow free shipping', 'woocommerce' ),
							// translators: %s: URL to free shipping document.
							'description' => sprintf( __( 'Check this box if the coupon grants free shipping. A <a href="%s" target="_blank">free shipping method</a> must be enabled in your shipping zone and be set to require "a valid free shipping coupon" (see the "Free Shipping Requires" setting).', 'woocommerce' ), 'https://woocommerce.com/document/free-shipping/' ),
							'value'       => wc_bool_to_string( $coupon->get_free_shipping( 'edit' ) ),
						)
					);
				}

				// Expiry date.
				$expiry_date = $coupon->get_date_expires( 'edit' ) ? $coupon->get_date_expires( 'edit' )->date( 'Y-m-d' ) : '';
				woocommerce_wp_text_input(
					array(
						'id'                => 'expiry_date',
						'value'             => esc_attr( $expiry_date ),
						'label'             => __( 'Coupon expiry date', 'woocommerce' ),
						'placeholder'       => _x( 'YYYY-MM-DD', 'coupon expiry date placeholder', 'woocommerce' ),
						'description'       => __( 'The coupon will expire at 00:00:00 of this date.', 'woocommerce' ),
						'desc_tip'          => true,
						'class'             => 'date-picker',
						'custom_attributes' => array(
							'pattern' => apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ),
						),
					)
				);

				do_action( 'woocommerce_coupon_options', $coupon->get_id(), $coupon );

				?>
			</div>
			<div id="usage_restriction_coupon_data" class="panel woocommerce_options_panel">
				<?php

				echo '<div class="options_group">';

				// minimum spend.
				woocommerce_wp_text_input(
					array(
						'id'          => 'minimum_amount',
						'label'       => __( 'Minimum spend', 'woocommerce' ),
						'placeholder' => __( 'No minimum', 'woocommerce' ),
						'description' => __( 'This field allows you to set the minimum spend (subtotal) allowed to use the coupon.', 'woocommerce' ),
						'data_type'   => 'price',
						'desc_tip'    => true,
						'value'       => $coupon->get_minimum_amount( 'edit' ),
					)
				);

				// maximum spend.
				woocommerce_wp_text_input(
					array(
						'id'          => 'maximum_amount',
						'label'       => __( 'Maximum spend', 'woocommerce' ),
						'placeholder' => __( 'No maximum', 'woocommerce' ),
						'description' => __( 'This field allows you to set the maximum spend (subtotal) allowed when using the coupon.', 'woocommerce' ),
						'data_type'   => 'price',
						'desc_tip'    => true,
						'value'       => $coupon->get_maximum_amount( 'edit' ),
					)
				);

				// Individual use.
				woocommerce_wp_checkbox(
					array(
						'id'          => 'individual_use',
						'label'       => __( 'Individual use only', 'woocommerce' ),
						'description' => __( 'Check this box if the coupon cannot be used in conjunction with other coupons.', 'woocommerce' ),
						'value'       => wc_bool_to_string( $coupon->get_individual_use( 'edit' ) ),
					)
				);

				// Exclude Sale Products.
				woocommerce_wp_checkbox(
					array(
						'id'          => 'exclude_sale_items',
						'label'       => __( 'Exclude sale items', 'woocommerce' ),
						'description' => __( 'Check this box if the coupon should not apply to items on sale. Per-item coupons will only work if the item is not on sale. Per-cart coupons will only work if there are items in the cart that are not on sale.', 'woocommerce' ),
						'value'       => wc_bool_to_string( $coupon->get_exclude_sale_items( 'edit' ) ),
					)
				);

				echo '</div><div class="options_group"><div class="hr-section hr-section-coupon_restrictions">' . esc_html__( 'And', 'woocommerce' ) . '</div>';

				// Product ids.
				?>
				<p class="form-field">
					<label><?php _e( 'Products', 'woocommerce' ); ?></label>
					<select class="wc-product-search" multiple="multiple" style="width: 50%;" name="product_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations">
						<?php
						$product_ids = $coupon->get_product_ids( 'edit' );

						foreach ( $product_ids as $product_id ) {
							$product = wc_get_product( $product_id );
							if ( is_object( $product ) ) {
								echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
							}
						}
						?>
					</select>
					<?php echo wc_help_tip( __( 'Products that the coupon will be applied to, or that need to be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
				</p>

				<?php // Exclude Product ids. ?>
				<p class="form-field">
					<label><?php _e( 'Exclude products', 'woocommerce' ); ?></label>
					<select class="wc-product-search" multiple="multiple" style="width: 50%;" name="exclude_product_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations">
						<?php
						$product_ids = $coupon->get_excluded_product_ids( 'edit' );

						foreach ( $product_ids as $product_id ) {
							$product = wc_get_product( $product_id );
							if ( is_object( $product ) ) {
								echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
							}
						}
						?>
					</select>
					<?php echo wc_help_tip( __( 'Products that the coupon will not be applied to, or that cannot be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
				</p>
				<?php

				echo '</div><div class="options_group"><div class="hr-section hr-section-coupon_restrictions">' . esc_html__( 'And', 'woocommerce' ) . '</div>';

				// Categories.
				?>
				<p class="form-field">
					<label for="product_categories"><?php _e( 'Product categories', 'woocommerce' ); ?></label>
					<select id="product_categories" name="product_categories[]" style="width: 50%;"  class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'Any category', 'woocommerce' ); ?>">
						<?php
						$category_ids = $coupon->get_product_categories( 'edit' );
						$categories   = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );

						if ( $categories ) {
							foreach ( $categories as $cat ) {
								echo '<option value="' . esc_attr( $cat->term_id ) . '"' . wc_selected( $cat->term_id, $category_ids ) . '>' . esc_html( $cat->name ) . '</option>';
							}
						}
						?>
					</select> <?php echo wc_help_tip( __( 'Product categories that the coupon will be applied to, or that need to be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
				</p>

				<?php // Exclude Categories. ?>
				<p class="form-field">
					<label for="exclude_product_categories"><?php _e( 'Exclude categories', 'woocommerce' ); ?></label>
					<select id="exclude_product_categories" name="exclude_product_categories[]" style="width: 50%;"  class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No categories', 'woocommerce' ); ?>">
						<?php
						$category_ids = $coupon->get_excluded_product_categories( 'edit' );
						$categories   = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );

						if ( $categories ) {
							foreach ( $categories as $cat ) {
								echo '<option value="' . esc_attr( $cat->term_id ) . '"' . wc_selected( $cat->term_id, $category_ids ) . '>' . esc_html( $cat->name ) . '</option>';
							}
						}
						?>
					</select>
					<?php echo wc_help_tip( __( 'Product categories that the coupon will not be applied to, or that cannot be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
				</p>
			</div>
			<div class="options_group"><div class="hr-section hr-section-coupon_restrictions"><?php echo esc_html__( 'And', 'woocommerce' ); ?></div>
				<?php
				// Customers.
				woocommerce_wp_text_input(
					array(
						'id'                => 'customer_email',
						'label'             => __( 'Allowed emails', 'woocommerce' ),
						'placeholder'       => __( 'No restrictions', 'woocommerce' ),
						'description'       => __( 'List of allowed billing emails to check against when an order is placed. Separate email addresses with commas. You can also use an asterisk (*) to match parts of an email. For example "*@gmail.com" would match all gmail addresses.', 'woocommerce' ),
						'value'             => implode( ', ', (array) $coupon->get_email_restrictions( 'edit' ) ),
						'desc_tip'          => true,
						'type'              => 'email',
						'class'             => '',
						'custom_attributes' => array(
							'multiple' => 'multiple',
						),
					)
				);
				?>
			</div>
			<?php do_action( 'woocommerce_coupon_options_usage_restriction', $coupon->get_id(), $coupon ); ?>
			</div>
			<div id="usage_limit_coupon_data" class="panel woocommerce_options_panel">
				<div class="options_group">
					<?php
					// Usage limit per coupons.
					woocommerce_wp_text_input(
						array(
							'id'                => 'usage_limit',
							'label'             => __( 'Usage limit per coupon', 'woocommerce' ),
							'placeholder'       => esc_attr__( 'Unlimited usage', 'woocommerce' ),
							'description'       => __( 'How many times this coupon can be used before it is void.', 'woocommerce' ),
							'type'              => 'number',
							'desc_tip'          => true,
							'class'             => 'short',
							'custom_attributes' => array(
								'step' => 1,
								'min'  => 0,
							),
							'value'             => $coupon->get_usage_limit( 'edit' ) ? $coupon->get_usage_limit( 'edit' ) : '',
						)
					);

					// Usage limit per product.
					woocommerce_wp_text_input(
						array(
							'id'                => 'limit_usage_to_x_items',
							'label'             => __( 'Limit usage to X items', 'woocommerce' ),
							'placeholder'       => esc_attr__( 'Apply to all qualifying items in cart', 'woocommerce' ),
							'description'       => __( 'The maximum number of individual items this coupon can apply to when using product discounts. Leave blank to apply to all qualifying items in cart.', 'woocommerce' ),
							'desc_tip'          => true,
							'class'             => 'short',
							'type'              => 'number',
							'custom_attributes' => array(
								'step' => 1,
								'min'  => 0,
							),
							'value'             => $coupon->get_limit_usage_to_x_items( 'edit' ) ? $coupon->get_limit_usage_to_x_items( 'edit' ) : '',
						)
					);

					// Usage limit per users.
					woocommerce_wp_text_input(
						array(
							'id'                => 'usage_limit_per_user',
							'label'             => __( 'Usage limit per user', 'woocommerce' ),
							'placeholder'       => esc_attr__( 'Unlimited usage', 'woocommerce' ),
							'description'       => __( 'How many times this coupon can be used by an individual user. Uses billing email for guests, and user ID for logged in users.', 'woocommerce' ),
							'desc_tip'          => true,
							'class'             => 'short',
							'type'              => 'number',
							'custom_attributes' => array(
								'step' => 1,
								'min'  => 0,
							),
							'value'             => $coupon->get_usage_limit_per_user( 'edit' ) ? $coupon->get_usage_limit_per_user( 'edit' ) : '',
						)
					);
					?>
				</div>
				<?php do_action( 'woocommerce_coupon_options_usage_limit', $coupon->get_id(), $coupon ); ?>
			</div>
			<?php do_action( 'woocommerce_coupon_data_panels', $coupon->get_id(), $coupon ); ?>
			<div class="clear"></div>
		</div>
		<?php
	}

	/**
	 * Save meta box data.
	 *
	 * @param int     $post_id
	 * @param WP_Post $post
	 */
	public static function save( $post_id, $post ) {
		// Check for dupe coupons.
		$coupon_code  = wc_format_coupon_code( $post->post_title );
		$id_from_code = wc_get_coupon_id_by_code( $coupon_code, $post_id );

		if ( $id_from_code ) {
			WC_Admin_Meta_Boxes::add_error( __( 'Coupon code already exists - customers will use the latest coupon with this code.', 'woocommerce' ) );
		}

		$product_categories         = isset( $_POST['product_categories'] ) ? (array) $_POST['product_categories'] : array();
		$exclude_product_categories = isset( $_POST['exclude_product_categories'] ) ? (array) $_POST['exclude_product_categories'] : array();

		$coupon = new WC_Coupon( $post_id );
		$errors = $coupon->set_props(
			array(
				'code'                        => $post->post_title,
				'discount_type'               => wc_clean( $_POST['discount_type'] ),
				'amount'                      => wc_format_decimal( $_POST['coupon_amount'] ),
				'date_expires'                => wc_clean( $_POST['expiry_date'] ),
				'individual_use'              => isset( $_POST['individual_use'] ),
				'product_ids'                 => isset( $_POST['product_ids'] ) ? array_filter( array_map( 'intval', (array) $_POST['product_ids'] ) ) : array(),
				'excluded_product_ids'        => isset( $_POST['exclude_product_ids'] ) ? array_filter( array_map( 'intval', (array) $_POST['exclude_product_ids'] ) ) : array(),
				'usage_limit'                 => absint( $_POST['usage_limit'] ),
				'usage_limit_per_user'        => absint( $_POST['usage_limit_per_user'] ),
				'limit_usage_to_x_items'      => absint( $_POST['limit_usage_to_x_items'] ),
				'free_shipping'               => isset( $_POST['free_shipping'] ),
				'product_categories'          => array_filter( array_map( 'intval', $product_categories ) ),
				'excluded_product_categories' => array_filter( array_map( 'intval', $exclude_product_categories ) ),
				'exclude_sale_items'          => isset( $_POST['exclude_sale_items'] ),
				'minimum_amount'              => wc_format_decimal( $_POST['minimum_amount'] ),
				'maximum_amount'              => wc_format_decimal( $_POST['maximum_amount'] ),
				'email_restrictions'          => array_filter( array_map( 'trim', explode( ',', wc_clean( $_POST['customer_email'] ) ) ) ),
			)
		);

		if ( is_wp_error( $errors ) ) {
			foreach ( $errors->get_error_messages() as $error_message ) {
				WC_Admin_Meta_Boxes::add_error( $error_message );
			}
		}

		$coupon->save();
		do_action( 'woocommerce_coupon_options_save', $post_id, $coupon );
	}
}
PK     tS\m:!  !    class-wc-admin-importers.phpnu [        <?php //phpcs:ignore Generic.PHP.RequireStrictTypes.MissingDeclaration
/**
 * Init WooCommerce data importers.
 *
 * @package WooCommerce\Admin
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Internal\Integrations\WPPostsImporter;

defined( 'ABSPATH' ) || exit;

/**
 * WC_Admin_Importers Class.
 */
class WC_Admin_Importers {

	/**
	 * Array of importer IDs.
	 *
	 * @var string[]
	 */
	protected $importers = array();

	/**
	 * Constructor.
	 */
	public function __construct() {
		if ( ! $this->import_allowed() ) {
			return;
		}

		add_action( 'admin_menu', array( $this, 'add_to_menus' ) );
		add_action( 'admin_init', array( $this, 'register_importers' ) );
		add_action( 'admin_head', array( $this, 'hide_from_menus' ) );
		add_action( 'admin_head', array( $this, 'menu_highlight_for_product_import' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
		add_action( 'wp_ajax_woocommerce_do_ajax_product_import', array( $this, 'do_ajax_product_import' ) );
		add_action( 'in_admin_footer', array( $this, 'track_importer_exporter_view' ) );

		/**
		 * Register the WP Posts importer.
		 */
		$wp_posts_importer = wc_get_container()->get( WPPostsImporter::class );
		$wp_posts_importer->register();

		// Register WooCommerce importers.
		$this->importers['product_importer'] = array(
			'menu'       => 'edit.php?post_type=product',
			'name'       => __( 'Product Import', 'woocommerce' ),
			'capability' => 'import',
			'callback'   => array( $this, 'product_importer' ),
		);
	}

	/**
	 * Return true if WooCommerce imports are allowed for current user, false otherwise.
	 *
	 * @return bool Whether current user can perform imports.
	 */
	protected function import_allowed() {
		return current_user_can( 'edit_products' ) && current_user_can( 'import' );
	}

	/**
	 * Add menu items for our custom importers.
	 */
	public function add_to_menus() {
		foreach ( $this->importers as $id => $importer ) {
			add_submenu_page( $importer['menu'], $importer['name'], $importer['name'], $importer['capability'], $id, $importer['callback'] );
		}
	}

	/**
	 * Hide menu items from view so the pages exist, but the menu items do not.
	 */
	public function hide_from_menus() {
		global $submenu;

		foreach ( $this->importers as $id => $importer ) {
			if ( isset( $submenu[ $importer['menu'] ] ) ) {
				foreach ( $submenu[ $importer['menu'] ] as $key => $menu ) {
					if ( $id === $menu[2] ) {
						unset( $submenu[ $importer['menu'] ][ $key ] );
					}
				}
			}
		}
	}

	/**
	 * Highlight Products > All Products submenu for Product Importer.
	 */
	public function menu_highlight_for_product_import() {
		global $submenu_file;

		$screen = get_current_screen();

		if ( $screen && 'product_page_product_importer' === $screen->id ) {
			$submenu_file = 'edit.php?post_type=product'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
		}
	}

	/**
	 * Register importer scripts.
	 */
	public function admin_scripts() {
		$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
		$version = Constants::get_constant( 'WC_VERSION' );
		wp_register_script( 'wc-product-import', WC()->plugin_url() . '/assets/js/admin/wc-product-import' . $suffix . '.js', array( 'jquery' ), $version, true );
	}

	/**
	 * The product importer.
	 *
	 * This has a custom screen - the Tools > Import item is a placeholder.
	 * If we're on that screen, redirect to the custom one.
	 */
	public function product_importer() {
		if ( Constants::is_defined( 'WP_LOAD_IMPORTERS' ) ) {
			wp_safe_redirect( admin_url( 'edit.php?post_type=product&page=product_importer&source=wordpress-importer' ) );
			exit;
		}

		// phpcs:ignore
		if ( isset( $_GET['source'] ) && 'wordpress-importer' === sanitize_text_field( wp_unslash( $_GET['source'] ) ) ) {
			wc_admin_record_tracks_event( 'product_importer_view_from_wp_importer' );
		}

		include_once WC_ABSPATH . 'includes/import/class-wc-product-csv-importer.php';
		include_once WC_ABSPATH . 'includes/admin/importers/class-wc-product-csv-importer-controller.php';

		$importer = new WC_Product_CSV_Importer_Controller();
		$importer->dispatch();
	}

	/**
	 * Register WordPress based importers.
	 */
	public function register_importers() {
		if ( Constants::is_defined( 'WP_LOAD_IMPORTERS' ) ) {
			register_importer( 'woocommerce_product_csv', __( 'WooCommerce products (CSV)', 'woocommerce' ), __( 'Import <strong>products</strong> to your store via a csv file.', 'woocommerce' ), array( $this, 'product_importer' ) );
			register_importer( 'woocommerce_tax_rate_csv', __( 'WooCommerce tax rates (CSV)', 'woocommerce' ), __( 'Import <strong>tax rates</strong> to your store via a csv file.', 'woocommerce' ), array( $this, 'tax_rates_importer' ) );
		}
	}

	/**
	 * The tax rate importer which extends WP_Importer.
	 */
	public function tax_rates_importer() {
		require_once ABSPATH . 'wp-admin/includes/import.php';

		if ( ! class_exists( 'WP_Importer' ) ) {
			$class_wp_importer = ABSPATH . 'wp-admin/includes/class-wp-importer.php';

			if ( file_exists( $class_wp_importer ) ) {
				require $class_wp_importer;
			}
		}

		wc_admin_record_tracks_event( 'tax_rates_importer_view_from_wp_importer' );

		require __DIR__ . '/importers/class-wc-tax-rate-importer.php';

		$importer = new WC_Tax_Rate_Importer();
		$importer->dispatch();
	}

	/**
	 * When running the WP XML importer, ensure attributes exist.
	 *
	 * WordPress import should work - however, it fails to import custom product attribute taxonomies.
	 * This code grabs the file before it is imported and ensures the taxonomies are created.
	 */
	public function post_importer_compatibility() {
		wc_deprecated_function( 'post_importer_compatibility', '10.1.0', 'A new integration with the WP WXR importer now filters the posts during import and registers the taxonomies, instead of initializing them at the start of the import and having to re-parse the file.' );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing
		if ( empty( $_POST['import_id'] ) || ! class_exists( 'WXR_Parser' ) ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Missing
		$id          = absint( $_POST['import_id'] );
		$file        = get_attached_file( $id );
		$parser      = new WXR_Parser();
		$import_data = $parser->parse( $file );

		if ( isset( $import_data['posts'] ) && ! empty( $import_data['posts'] ) ) {
			foreach ( $import_data['posts'] as $post ) {
				if ( 'product' === $post['post_type'] && ! empty( $post['terms'] ) ) {
					foreach ( $post['terms'] as $term ) {
						if ( strstr( $term['domain'], 'pa_' ) ) {
							if ( ! taxonomy_exists( $term['domain'] ) ) {
								$attribute_name = wc_attribute_taxonomy_slug( $term['domain'] );

								// Create the taxonomy.
								if ( ! in_array( $attribute_name, wc_get_attribute_taxonomies(), true ) ) {
									wc_create_attribute(
										array(
											'name'         => $attribute_name,
											'slug'         => $attribute_name,
											'type'         => 'select',
											'order_by'     => 'menu_order',
											'has_archives' => false,
										)
									);
								}

								// Register the taxonomy now so that the import works!
								register_taxonomy(
									$term['domain'],
									// phpcs:ignore
									apply_filters( 'woocommerce_taxonomy_objects_' . $term['domain'], array( 'product' ) ),
									// phpcs:ignore
									apply_filters(
										'woocommerce_taxonomy_args_' . $term['domain'],
										array(
											'hierarchical' => true,
											'show_ui'      => false,
											'query_var'    => true,
											'rewrite'      => false,
										)
									)
								);
							}
						}
					}
				}
			}
		}
	}

	/**
	 * Ajax callback for importing one batch of products from a CSV.
	 */
	public function do_ajax_product_import() {
		if ( ! $this->import_allowed() ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient privileges to import products.', 'woocommerce' ) ) );
		}

		include_once WC_ABSPATH . 'includes/admin/importers/class-wc-product-csv-importer-controller.php';
		WC_Product_CSV_Importer_Controller::dispatch_ajax();
	}

	/**
	 * Track importer/exporter view.
	 *
	 * @return void
	 */
	public function track_importer_exporter_view() {
		$screen = get_current_screen();

		if ( ! isset( $screen->id ) ) {
			return;
		}

		// Don't track if we're in a specific import screen.
		// phpcs:ignore
		if ( isset( $_GET['import'] ) ) {
			return;
		}

		if ( 'import' === $screen->id || 'export' === $screen->id ) {
			wc_admin_record_tracks_event( 'wordpress_' . $screen->id . '_view' );
		}
	}
}

new WC_Admin_Importers();
PK     tS\6cR  R    class-wc-admin-attributes.phpnu [        <?php
/**
 * Attributes Page
 *
 * The attributes section lets users add custom attributes to assign to products - they can also be used in the "Filter Products by Attribute" widget.
 *
 * @package WooCommerce\Admin
 * @version 2.3.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * WC_Admin_Attributes Class.
 */
class WC_Admin_Attributes {

	/**
	 * Edited attribute ID.
	 *
	 * @var int
	 */
	private static $edited_attribute_id;

	/**
	 * Handles output of the attributes page in admin.
	 *
	 * Shows the created attributes and lets you add new ones or edit existing ones.
	 * The added attributes are stored in the database and can be used for layered navigation.
	 */
	public static function output() {
		$result = '';
		$action = '';

		// Action to perform: add, edit, delete or none.
		if ( ! empty( $_POST['add_new_attribute'] ) ) { // WPCS: CSRF ok.
			$action = 'add';
		} elseif ( ! empty( $_POST['save_attribute'] ) && ! empty( $_GET['edit'] ) ) { // WPCS: CSRF ok.
			$action = 'edit';
		} elseif ( ! empty( $_GET['delete'] ) ) {
			$action = 'delete';
		}

		switch ( $action ) {
			case 'add':
				$result = self::process_add_attribute();
				break;
			case 'edit':
				$result = self::process_edit_attribute();
				break;
			case 'delete':
				$result = self::process_delete_attribute();
				break;
		}

		if ( is_wp_error( $result ) ) {
			echo '<div id="woocommerce_errors" class="error"><p>' . wp_kses_post( $result->get_error_message() ) . '</p></div>';
		}

		// Show admin interface.
		if ( ! empty( $_GET['edit'] ) ) {
			self::edit_attribute();
		} else {
			self::add_attribute();
		}
	}

	/**
	 * Get and sanitize posted attribute data.
	 *
	 * @return array
	 */
	private static function get_posted_attribute() {
		$attribute = array(
			'attribute_label'   => isset( $_POST['attribute_label'] ) ? wc_clean( wp_unslash( $_POST['attribute_label'] ) ) : '', // WPCS: input var ok, CSRF ok.
			'attribute_name'    => isset( $_POST['attribute_name'] ) ? wc_sanitize_taxonomy_name( wp_unslash( $_POST['attribute_name'] ) ) : '', // WPCS: input var ok, CSRF ok, sanitization ok.
			'attribute_type'    => isset( $_POST['attribute_type'] ) ? wc_clean( wp_unslash( $_POST['attribute_type'] ) ) : 'select', // WPCS: input var ok, CSRF ok.
			'attribute_orderby' => isset( $_POST['attribute_orderby'] ) ? wc_clean( wp_unslash( $_POST['attribute_orderby'] ) ) : '', // WPCS: input var ok, CSRF ok.
			'attribute_public'  => isset( $_POST['attribute_public'] ) ? 1 : 0, // WPCS: input var ok, CSRF ok.
		);

		if ( empty( $attribute['attribute_type'] ) ) {
			$attribute['attribute_type'] = 'select';
		}
		if ( empty( $attribute['attribute_label'] ) ) {
			$attribute['attribute_label'] = ucfirst( $attribute['attribute_name'] );
		}
		if ( empty( $attribute['attribute_name'] ) ) {
			$attribute['attribute_name'] = wc_sanitize_taxonomy_name( $attribute['attribute_label'] );
		}

		return $attribute;
	}

	/**
	 * Add an attribute.
	 *
	 * @return bool|WP_Error
	 */
	private static function process_add_attribute() {
		check_admin_referer( 'woocommerce-add-new_attribute' );

		$attribute = self::get_posted_attribute();
		$args      = array(
			'name'         => $attribute['attribute_label'],
			'slug'         => $attribute['attribute_name'],
			'type'         => $attribute['attribute_type'],
			'order_by'     => $attribute['attribute_orderby'],
			'has_archives' => $attribute['attribute_public'],
		);

		$id = wc_create_attribute( $args );

		if ( is_wp_error( $id ) ) {
			return $id;
		}

		return true;
	}

	/**
	 * Edit an attribute.
	 *
	 * @return bool|WP_Error
	 */
	private static function process_edit_attribute() {
		$attribute_id = isset( $_GET['edit'] ) ? absint( $_GET['edit'] ) : 0;
		check_admin_referer( 'woocommerce-save-attribute_' . $attribute_id );

		$attribute = self::get_posted_attribute();
		$args      = array(
			'name'         => $attribute['attribute_label'],
			'slug'         => $attribute['attribute_name'],
			'type'         => $attribute['attribute_type'],
			'order_by'     => $attribute['attribute_orderby'],
			'has_archives' => $attribute['attribute_public'],
		);

		$id = wc_update_attribute( $attribute_id, $args );

		if ( is_wp_error( $id ) ) {
			return $id;
		}

		self::$edited_attribute_id = $id;

		return true;
	}

	/**
	 * Delete an attribute.
	 *
	 * @return bool
	 */
	private static function process_delete_attribute() {
		$attribute_id = isset( $_GET['delete'] ) ? absint( $_GET['delete'] ) : 0;
		check_admin_referer( 'woocommerce-delete-attribute_' . $attribute_id );

		return wc_delete_attribute( $attribute_id );
	}

	/**
	 * Edit Attribute admin panel.
	 *
	 * Shows the interface for changing an attributes type between select and text.
	 */
	public static function edit_attribute() {
		global $wpdb;

		$edit = isset( $_GET['edit'] ) ? absint( $_GET['edit'] ) : 0;

		$attribute_to_edit = $wpdb->get_row(
			$wpdb->prepare(
				"
				SELECT attribute_type, attribute_label, attribute_name, attribute_orderby, attribute_public
				FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = %d
				",
				$edit
			)
		);

		?>
		<div class="wrap woocommerce">
			<h1><?php esc_html_e( 'Edit attribute', 'woocommerce' ); ?></h1>

			<?php
			if ( ! $attribute_to_edit ) {
				echo '<div id="woocommerce_errors" class="error"><p>' . esc_html__( 'Error: non-existing attribute ID.', 'woocommerce' ) . '</p></div>';
			} else {
				if ( self::$edited_attribute_id > 0 ) {
					echo '<div id="message" class="updated"><p>' . esc_html__( 'Attribute updated successfully', 'woocommerce' ) . '</p><p><a href="' . esc_url( admin_url( 'edit.php?post_type=product&amp;page=product_attributes' ) ) . '">' . esc_html__( 'Back to Attributes', 'woocommerce' ) . '</a></p></div>';
					self::$edited_attribute_id = null;
				}
				$att_type    = $attribute_to_edit->attribute_type;
				$att_label   = format_to_edit( $attribute_to_edit->attribute_label );
				$att_name    = $attribute_to_edit->attribute_name;
				$att_orderby = $attribute_to_edit->attribute_orderby;
				$att_public  = $attribute_to_edit->attribute_public;
				?>
				<form action="edit.php?post_type=product&amp;page=product_attributes&amp;edit=<?php echo absint( $edit ); ?>" method="post">
					<table class="form-table">
						<tbody>
							<?php do_action( 'woocommerce_before_edit_attribute_fields' ); ?>
							<tr class="form-field form-required">
								<th scope="row" valign="top">
									<label for="attribute_label"><?php esc_html_e( 'Name', 'woocommerce' ); ?></label>
								</th>
								<td>
									<input name="attribute_label" id="attribute_label" type="text" value="<?php echo esc_attr( $att_label ); ?>" />
									<p class="description"><?php esc_html_e( 'Name for the attribute (shown on the front-end).', 'woocommerce' ); ?></p>
								</td>
							</tr>
							<tr class="form-field form-required">
								<th scope="row" valign="top">
									<label for="attribute_name"><?php esc_html_e( 'Slug', 'woocommerce' ); ?></label>
								</th>
								<td>
									<input name="attribute_name" id="attribute_name" type="text" value="<?php echo esc_attr( $att_name ); ?>" maxlength="28" />
									<p class="description"><?php esc_html_e( 'Unique slug/reference for the attribute; must be no more than 28 characters.', 'woocommerce' ); ?></p>
								</td>
							</tr>
							<tr class="form-field form-required">
								<th scope="row" valign="top">
									<label for="attribute_public"><?php esc_html_e( 'Enable archives?', 'woocommerce' ); ?></label>
								</th>
								<td>
									<input name="attribute_public" id="attribute_public" type="checkbox" value="1" <?php checked( $att_public, 1 ); ?> />
									<p class="description"><?php esc_html_e( 'Enable this if you want this attribute to have product archives in your store.', 'woocommerce' ); ?></p>
								</td>
							</tr>
							<?php
							/**
							 * Attribute types can change the way attributes are displayed on the frontend and admin.
							 *
							 * By Default WooCommerce only includes the `select` type. Others can be added with the
							 * `product_attributes_type_selector` filter. If there is only the default type registered,
							 * this setting will be hidden.
							 */
							if ( wc_has_custom_attribute_types() ) {
								?>
								<tr class="form-field form-required">
									<th scope="row" valign="top">
										<label for="attribute_type"><?php esc_html_e( 'Type', 'woocommerce' ); ?></label>
									</th>
									<td>
										<select name="attribute_type" id="attribute_type">
											<?php foreach ( wc_get_attribute_types() as $key => $value ) : ?>
												<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $att_type, $key ); ?>><?php echo esc_html( $value ); ?></option>
											<?php endforeach; ?>
											<?php
												/**
												 * Deprecated action in favor of product_attributes_type_selector filter.
												 *
												 * @todo Remove in 4.0.0
												 * @deprecated 2.4.0
												 */
												do_action( 'woocommerce_admin_attribute_types' );
											?>
										</select>
										<p class="description"><?php esc_html_e( "Determines how this attribute's values are displayed.", 'woocommerce' ); ?></p>
									</td>
								</tr>
								<?php
							}
							?>
							<tr class="form-field form-required">
								<th scope="row" valign="top">
									<label for="attribute_orderby"><?php esc_html_e( 'Default sort order', 'woocommerce' ); ?></label>
								</th>
								<td>
									<select name="attribute_orderby" id="attribute_orderby">
										<option value="menu_order" <?php selected( $att_orderby, 'menu_order' ); ?>><?php esc_html_e( 'Custom ordering', 'woocommerce' ); ?></option>
										<option value="name" <?php selected( $att_orderby, 'name' ); ?>><?php esc_html_e( 'Name', 'woocommerce' ); ?></option>
										<option value="name_num" <?php selected( $att_orderby, 'name_num' ); ?>><?php esc_html_e( 'Name (numeric)', 'woocommerce' ); ?></option>
										<option value="id" <?php selected( $att_orderby, 'id' ); ?>><?php esc_html_e( 'Term ID', 'woocommerce' ); ?></option>
									</select>
									<p class="description"><?php esc_html_e( 'Determines the sort order of the terms on the frontend shop product pages. If using custom ordering, you can drag and drop the terms in this attribute.', 'woocommerce' ); ?></p>
								</td>
							</tr>
							<?php do_action( 'woocommerce_after_edit_attribute_fields' ); ?>
						</tbody>
					</table>
					<p class="submit"><button type="submit" name="save_attribute" id="submit" class="button-primary" value="<?php esc_attr_e( 'Update', 'woocommerce' ); ?>"><?php esc_html_e( 'Update', 'woocommerce' ); ?></button></p>
					<?php wp_nonce_field( 'woocommerce-save-attribute_' . $edit ); ?>
				</form>
			<?php } ?>
		</div>
		<?php
	}

	/**
	 * Add Attribute admin panel.
	 *
	 * Shows the interface for adding new attributes.
	 */
	public static function add_attribute() {
		?>
		<div class="wrap woocommerce">
			<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>

			<br class="clear" />
			<div id="col-container">
				<div id="col-right">
					<div class="col-wrap">
						<table class="widefat attributes-table wp-list-table ui-sortable" style="width:100%">
							<thead>
								<tr>
									<th scope="col"><?php esc_html_e( 'Name', 'woocommerce' ); ?></th>
									<th scope="col"><?php esc_html_e( 'Slug', 'woocommerce' ); ?></th>
									<?php if ( wc_has_custom_attribute_types() ) : ?>
										<th scope="col"><?php esc_html_e( 'Type', 'woocommerce' ); ?></th>
									<?php endif; ?>
									<th scope="col"><?php esc_html_e( 'Order by', 'woocommerce' ); ?></th>
									<th scope="col"><?php esc_html_e( 'Terms', 'woocommerce' ); ?></th>
								</tr>
							</thead>
							<tbody>
								<?php
								$attribute_taxonomies = wc_get_attribute_taxonomies();
								if ( $attribute_taxonomies ) {
									/**
									 * Filters the maximum number of terms that will be displayed for each taxonomy in the Attributes page.
									 *
									 * @param int @default_max_terms_to_display Default value.
									 * @returns int Actual value to use, may be zero.
									 *
									 * @since 6.9.0
									 */
									$max_terms_to_display = apply_filters( 'woocommerce_max_terms_displayed_in_attributes_page', 100 );
									foreach ( $attribute_taxonomies as $tax ) :
										?>
										<tr>
												<td>
													<strong><a href="edit-tags.php?taxonomy=<?php echo esc_attr( wc_attribute_taxonomy_name( $tax->attribute_name ) ); ?>&amp;post_type=product"><?php echo esc_html( $tax->attribute_label ); ?></a></strong>

													<div class="row-actions"><span class="edit"><a href="<?php echo esc_url( add_query_arg( 'edit', $tax->attribute_id, 'edit.php?post_type=product&amp;page=product_attributes' ) ); ?>"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a> | </span><span class="delete"><a class="delete" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'delete', $tax->attribute_id, 'edit.php?post_type=product&amp;page=product_attributes' ), 'woocommerce-delete-attribute_' . $tax->attribute_id ) ); ?>"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a></span></div>
												</td>
												<td><?php echo esc_html( $tax->attribute_name ); ?></td>
												<?php if ( wc_has_custom_attribute_types() ) : ?>
													<td><?php echo esc_html( wc_get_attribute_type_label( $tax->attribute_type ) ); ?> <?php echo $tax->attribute_public ? esc_html__( '(Public)', 'woocommerce' ) : ''; ?></td>
												<?php endif; ?>
												<td>
													<?php
													switch ( $tax->attribute_orderby ) {
														case 'name':
															esc_html_e( 'Name', 'woocommerce' );
															break;
														case 'name_num':
															esc_html_e( 'Name (numeric)', 'woocommerce' );
															break;
														case 'id':
															esc_html_e( 'Term ID', 'woocommerce' );
															break;
														default:
															esc_html_e( 'Custom ordering', 'woocommerce' );
															break;
													}
													?>
												</td>
												<td class="attribute-terms">
													<?php
													$taxonomy = wc_attribute_taxonomy_name( $tax->attribute_name );

													if ( taxonomy_exists( $taxonomy ) ) {
														$total_count = (int) get_terms(
															array(
																'taxonomy'   => $taxonomy,
																'fields'     => 'count',
																'hide_empty' => false,
															)
														);
														if ( 0 === $total_count ) {
															echo '<span class="na">&ndash;</span>';
														} elseif ( $max_terms_to_display > 0 ) {
															$terms        = get_terms(
																array(
																	'taxonomy'   => $taxonomy,
																	'number'     => $max_terms_to_display,
																	'fields'     => 'names',
																	'hide_empty' => false,
																)
															);
															$terms_string = implode( ', ', $terms );
															if ( $total_count > $max_terms_to_display ) {
																$remaining = $total_count - $max_terms_to_display;
																/* translators: 1: Comma-separated terms list, 2: how many terms are hidden */
																$terms_string = sprintf( __( '%1$s... (%2$s more)', 'woocommerce' ), $terms_string, $remaining );
															}
															echo esc_html( $terms_string );
														} elseif ( 1 === $total_count ) {
															echo esc_html( __( '1 term', 'woocommerce' ) );
														} else {
															/* translators: %s: Total count of terms available for the attribute */
															echo esc_html( sprintf( __( '%s terms', 'woocommerce' ), $total_count ) );
														}
													} else {
															echo '<span class="na">&ndash;</span><br />';
													}
													?>
													<br /><a href="edit-tags.php?taxonomy=<?php echo esc_attr( wc_attribute_taxonomy_name( $tax->attribute_name ) ); ?>&amp;post_type=product" class="configure-terms"><?php esc_html_e( 'Configure terms', 'woocommerce' ); ?></a>
												</td>
											</tr>
											<?php
										endforeach;
								} else {
									?>
										<tr>
											<td colspan="6"><?php esc_html_e( 'No attributes currently exist.', 'woocommerce' ); ?></td>
										</tr>
										<?php
								}
								?>
							</tbody>
						</table>
					</div>
				</div>
				<div id="col-left">
					<div class="col-wrap">
						<div class="form-wrap">
							<h2><?php esc_html_e( 'Add new attribute', 'woocommerce' ); ?></h2>
							<p><?php esc_html_e( 'Attributes let you define extra product data, such as size or color. You can use these attributes in the shop sidebar using the "layered nav" widgets.', 'woocommerce' ); ?></p>
							<form action="edit.php?post_type=product&amp;page=product_attributes" method="post">
								<?php do_action( 'woocommerce_before_add_attribute_fields' ); ?>

								<div class="form-field">
									<label for="attribute_label"><?php esc_html_e( 'Name', 'woocommerce' ); ?></label>
									<input name="attribute_label" id="attribute_label" type="text" value="" />
									<p class="description"><?php esc_html_e( 'Name for the attribute (shown on the front-end).', 'woocommerce' ); ?></p>
								</div>

								<div class="form-field">
									<label for="attribute_name"><?php esc_html_e( 'Slug', 'woocommerce' ); ?></label>
									<input name="attribute_name" id="attribute_name" type="text" value="" maxlength="28" />
									<p class="description"><?php esc_html_e( 'Unique slug/reference for the attribute; must be no more than 28 characters.', 'woocommerce' ); ?></p>
								</div>

								<div class="form-field">
									<label for="attribute_public"><input name="attribute_public" id="attribute_public" type="checkbox" value="1" /> <?php esc_html_e( 'Enable Archives?', 'woocommerce' ); ?></label>

									<p class="description"><?php esc_html_e( 'Enable this if you want this attribute to have product archives in your store.', 'woocommerce' ); ?></p>
								</div>

								<?php
								/**
								 * Attribute types can change the way attributes are displayed on the frontend and admin.
								 *
								 * By Default WooCommerce only includes the `select` type. Others can be added with the
								 * `product_attributes_type_selector` filter. If there is only the default type registered,
								 * this setting will be hidden.
								 */
								if ( wc_has_custom_attribute_types() ) {
									?>
									<div class="form-field">
										<label for="attribute_type"><?php esc_html_e( 'Type', 'woocommerce' ); ?></label>
										<select name="attribute_type" id="attribute_type">
											<?php foreach ( wc_get_attribute_types() as $key => $value ) : ?>
												<option value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $value ); ?></option>
											<?php endforeach; ?>
											<?php
												/**
												 * Deprecated action in favor of product_attributes_type_selector filter.
												 *
												 * @todo Remove in 4.0.0
												 * @deprecated 2.4.0
												 */
												do_action( 'woocommerce_admin_attribute_types' );
											?>
										</select>
										<p class="description"><?php esc_html_e( "Determines how this attribute's values are displayed.", 'woocommerce' ); ?></p>
									</div>
									<?php
								}
								?>

								<div class="form-field">
									<label for="attribute_orderby"><?php esc_html_e( 'Default sort order', 'woocommerce' ); ?></label>
									<select name="attribute_orderby" id="attribute_orderby">
										<option value="menu_order"><?php esc_html_e( 'Custom ordering', 'woocommerce' ); ?></option>
										<option value="name"><?php esc_html_e( 'Name', 'woocommerce' ); ?></option>
										<option value="name_num"><?php esc_html_e( 'Name (numeric)', 'woocommerce' ); ?></option>
										<option value="id"><?php esc_html_e( 'Term ID', 'woocommerce' ); ?></option>
									</select>
									<p class="description"><?php esc_html_e( 'Determines the sort order of the terms on the frontend shop product pages. If using custom ordering, you can drag and drop the terms in this attribute.', 'woocommerce' ); ?></p>
								</div>

								<?php do_action( 'woocommerce_after_add_attribute_fields' ); ?>

								<p class="submit"><button type="submit" name="add_new_attribute" id="submit" class="button button-primary" value="<?php esc_attr_e( 'Add attribute', 'woocommerce' ); ?>"><?php esc_html_e( 'Add attribute', 'woocommerce' ); ?></button></p>
								<?php wp_nonce_field( 'woocommerce-add-new_attribute' ); ?>
							</form>
						</div>
					</div>
				</div>
			</div>
			<script type="text/javascript">
			/* <![CDATA[ */

				jQuery( 'a.delete' ).on( 'click', function() {
					if ( window.confirm( '<?php esc_html_e( 'Are you sure you want to delete this attribute?', 'woocommerce' ); ?>' ) ) {
						return true;
					}
					return false;
				});

			/* ]]> */
			</script>
		</div>
		<?php
	}
}
PK     tS\ \    .  class-wc-admin-upload-downloadable-product.phpnu [        <?php
/**
 * Add hooks related to uploading downloadable products.
 *
 * @package     WooCommerce\Admin
 * @version     8.5.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Admin_Upload_Downloadable_Product', false ) ) {
	return new WC_Admin_Upload_Downloadable_Product();
}

/**
 * WC_Admin_Upload_Downloadable_Product Class.
 */
class WC_Admin_Upload_Downloadable_Product {
	/**
	 * Add hooks.
	 */
	public function __construct() {
		add_filter( 'upload_dir', array( $this, 'upload_dir' ) );
		add_filter( 'wp_unique_filename', array( $this, 'update_filename' ), 10, 3 );
		add_action( 'media_upload_downloadable_product', array( $this, 'media_upload_downloadable_product' ) );
	}
	/**
	 * Change upload dir for downloadable files.
	 *
	 * @param array $pathdata Array of paths.
	 * @return array
	 */
	public function upload_dir( $pathdata ) {
		// phpcs:disable WordPress.Security.NonceVerification.Missing
		if ( isset( $_POST['type'] ) && 'downloadable_product' === $_POST['type'] ) {

			if ( empty( $pathdata['subdir'] ) ) {
				$pathdata['path']   = $pathdata['path'] . '/woocommerce_uploads';
				$pathdata['url']    = $pathdata['url'] . '/woocommerce_uploads';
				$pathdata['subdir'] = '/woocommerce_uploads';
			} else {
				$new_subdir = '/woocommerce_uploads' . $pathdata['subdir'];

				$pathdata['path']   = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['path'] );
				$pathdata['url']    = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['url'] );
				$pathdata['subdir'] = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['subdir'] );
			}
		}
		return $pathdata;
		// phpcs:enable WordPress.Security.NonceVerification.Missing
	}

	/**
	 * Change filename for WooCommerce uploads and prepend unique chars for security.
	 *
	 * @param string $full_filename Original filename.
	 * @param string $ext           Extension of file.
	 * @param string $dir           Directory path.
	 *
	 * @return string New filename with unique hash.
	 * @since 4.0
	 */
	public function update_filename( $full_filename, $ext, $dir ) {
		// phpcs:disable WordPress.Security.NonceVerification.Missing
		if ( ! isset( $_POST['type'] ) || ! 'downloadable_product' === $_POST['type'] ) {
			return $full_filename;
		}

		if ( ! strpos( $dir, 'woocommerce_uploads' ) ) {
			return $full_filename;
		}

		if ( 'no' === get_option( 'woocommerce_downloads_add_hash_to_filename' ) ) {
			return $full_filename;
		}

		return $this->unique_filename( $full_filename, $ext );
		// phpcs:enable WordPress.Security.NonceVerification.Missing
	}

	/**
	 * Change filename to append random text.
	 *
	 * @param string $full_filename Original filename with extension.
	 * @param string $ext           Extension.
	 *
	 * @return string Modified filename.
	 */
	public function unique_filename( $full_filename, $ext ) {
		$ideal_random_char_length = 6;   // Not going with a larger length because then downloaded filename will not be pretty.
		$max_filename_length      = 255; // Max file name length for most file systems.
		$length_to_prepend        = min( $ideal_random_char_length, $max_filename_length - strlen( $full_filename ) - 1 );

		if ( 1 > $length_to_prepend ) {
			return $full_filename;
		}

		$suffix   = strtolower( wp_generate_password( $length_to_prepend, false, false ) );
		$filename = $full_filename;

		if ( strlen( $ext ) > 0 ) {
			$filename = substr( $filename, 0, strlen( $filename ) - strlen( $ext ) );
		}

		$full_filename = str_replace(
			$filename,
			"$filename-$suffix",
			$full_filename
		);

		return $full_filename;
	}

	/**
	 * Run a filter when uploading a downloadable product.
	 */
	public function woocommerce_media_upload_downloadable_product() {
		// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
		do_action( 'media_upload_file' );
	}
}
PK     tS\fDC  C  &  class-wc-admin-api-keys-table-list.phpnu [        <?php
/**
 * WooCommerce API Keys Table List
 *
 * @package WooCommerce\Admin
 * @version 2.4.0
 */

defined( 'ABSPATH' ) || exit;

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

/**
 * API Keys table list class.
 */
class WC_Admin_API_Keys_Table_List extends WP_List_Table {

	/**
	 * Initialize the API key table list.
	 */
	public function __construct() {
		parent::__construct(
			array(
				'singular' => 'key',
				'plural'   => 'keys',
				'ajax'     => false,
			)
		);
	}

	/**
	 * No items found text.
	 */
	public function no_items() {
		esc_html_e( 'No keys found.', 'woocommerce' );
	}

	/**
	 * Get list columns.
	 *
	 * @return array
	 */
	public function get_columns() {
		return array(
			'cb'            => '<input type="checkbox" />',
			'title'         => __( 'Description', 'woocommerce' ),
			'truncated_key' => __( 'Consumer key ending in', 'woocommerce' ),
			'user'          => __( 'User', 'woocommerce' ),
			'permissions'   => __( 'Permissions', 'woocommerce' ),
			'last_access'   => __( 'Last access', 'woocommerce' ),
		);
	}

	/**
	 * Column cb.
	 *
	 * @param  array $key Key data.
	 * @return string
	 */
	public function column_cb( $key ) {
		return sprintf( '<input type="checkbox" name="key[]" value="%1$s" />', $key['key_id'] );
	}

	/**
	 * Return title column.
	 *
	 * @param  array $key Key data.
	 * @return string
	 */
	public function column_title( $key ) {
		$url     = admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys&edit-key=' . $key['key_id'] );
		$user_id = intval( $key['user_id'] );

		// Check if current user can edit other users or if it's the same user.
		$can_edit = current_user_can( 'edit_user', $user_id ) || get_current_user_id() === $user_id;

		$output = '<strong>';
		if ( $can_edit ) {
			$output .= '<a href="' . esc_url( $url ) . '" class="row-title">';
		}
		if ( empty( $key['description'] ) ) {
			$output .= esc_html__( 'API key', 'woocommerce' );
		} else {
			$output .= esc_html( $key['description'] );
		}
		if ( $can_edit ) {
			$output .= '</a>';
		}
		$output .= '</strong>';

		// Get actions.
		$actions = array(
			/* translators: %s: API key ID. */
			'id' => sprintf( __( 'ID: %d', 'woocommerce' ), $key['key_id'] ),
		);

		if ( $can_edit ) {
			$actions['edit']  = '<a href="' . esc_url( $url ) . '">' . __( 'View/Edit', 'woocommerce' ) . '</a>';
			$actions['trash'] = '<a class="submitdelete" aria-label="' . esc_attr__( 'Revoke API key', 'woocommerce' ) . '" href="' . esc_url(
				wp_nonce_url(
					add_query_arg(
						array(
							'revoke-key' => $key['key_id'],
						),
						admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys' )
					),
					'revoke'
				)
			) . '">' . esc_html__( 'Revoke', 'woocommerce' ) . '</a>';
		}

		$row_actions = array();

		foreach ( $actions as $action => $link ) {
			$row_actions[] = '<span class="' . esc_attr( $action ) . '">' . $link . '</span>';
		}

		$output .= '<div class="row-actions">' . implode( ' | ', $row_actions ) . '</div>';

		return $output;
	}

	/**
	 * Return truncated consumer key column.
	 *
	 * @param  array $key Key data.
	 * @return string
	 */
	public function column_truncated_key( $key ) {
		return '<code>***' . esc_html( $key['truncated_key'] ) . '</code>';
	}

	/**
	 * Return user column.
	 *
	 * @param  array $key Key data.
	 * @return string
	 */
	public function column_user( $key ) {
		$user = get_user_by( 'id', $key['user_id'] );

		if ( ! $user ) {
			return '';
		}

		if ( current_user_can( 'edit_user', $user->ID ) ) {
			return '<a href="' . esc_url( add_query_arg( array( 'user_id' => $user->ID ), admin_url( 'user-edit.php' ) ) ) . '">' . esc_html( $user->display_name ) . '</a>';
		}

		return esc_html( $user->display_name );
	}

	/**
	 * Return permissions column.
	 *
	 * @param  array $key Key data.
	 * @return string
	 */
	public function column_permissions( $key ) {
		$permission_key = $key['permissions'];
		$permissions    = array(
			'read'       => __( 'Read', 'woocommerce' ),
			'write'      => __( 'Write', 'woocommerce' ),
			'read_write' => __( 'Read/Write', 'woocommerce' ),
		);

		if ( isset( $permissions[ $permission_key ] ) ) {
			return esc_html( $permissions[ $permission_key ] );
		} else {
			return '';
		}
	}

	/**
	 * Return last access column.
	 *
	 * @param  array $key Key data.
	 * @return string
	 */
	public function column_last_access( $key ) {
		if ( ! empty( $key['last_access'] ) ) {
			/* translators: 1: last access date 2: last access time */
			$date = sprintf( __( '%1$s at %2$s', 'woocommerce' ), date_i18n( wc_date_format(), strtotime( $key['last_access'] ) ), date_i18n( wc_time_format(), strtotime( $key['last_access'] ) ) );

			return apply_filters( 'woocommerce_api_key_last_access_datetime', $date, $key['last_access'] );
		}

		return __( 'Unknown', 'woocommerce' );
	}

	/**
	 * Get bulk actions.
	 *
	 * @return array
	 */
	protected function get_bulk_actions() {
		if ( ! current_user_can( 'remove_users' ) ) {
			return array();
		}

		return array(
			'revoke' => __( 'Revoke', 'woocommerce' ),
		);
	}

	/**
	 * Search box.
	 *
	 * @param  string $text     Button text.
	 * @param  string $input_id Input ID.
	 */
	public function search_box( $text, $input_id ) {
		if ( empty( $_REQUEST['s'] ) && ! $this->has_items() ) { // WPCS: input var okay, CSRF ok.
			return;
		}

		$input_id     = $input_id . '-search-input';
		$search_query = isset( $_REQUEST['s'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) : ''; // WPCS: input var okay, CSRF ok.

		echo '<p class="search-box">';
		echo '<label class="screen-reader-text" for="' . esc_attr( $input_id ) . '">' . esc_html( $text ) . ':</label>';
		echo '<input type="search" id="' . esc_attr( $input_id ) . '" name="s" value="' . esc_attr( $search_query ) . '" />';
		submit_button(
			$text,
			'',
			'',
			false,
			array(
				'id' => 'search-submit',
			)
		);
		echo '</p>';
	}

	/**
	 * Prepare table list items.
	 */
	public function prepare_items() {
		global $wpdb;

		$per_page     = $this->get_items_per_page( 'woocommerce_keys_per_page' );
		$current_page = $this->get_pagenum();

		if ( 1 < $current_page ) {
			$offset = $per_page * ( $current_page - 1 );
		} else {
			$offset = 0;
		}

		$search = '';

		if ( ! empty( $_REQUEST['s'] ) ) { // WPCS: input var okay, CSRF ok.
			$search = "AND description LIKE '%" . esc_sql( $wpdb->esc_like( wc_clean( wp_unslash( $_REQUEST['s'] ) ) ) ) . "%' "; // WPCS: input var okay, CSRF ok.
		}

		// Get the API keys.
		$keys = $wpdb->get_results(
			"SELECT key_id, user_id, description, permissions, truncated_key, last_access FROM {$wpdb->prefix}woocommerce_api_keys WHERE 1 = 1 {$search}" .
			$wpdb->prepare( 'ORDER BY key_id DESC LIMIT %d OFFSET %d;', $per_page, $offset ),
			ARRAY_A
		); // WPCS: unprepared SQL ok.

		$count = $wpdb->get_var( "SELECT COUNT(key_id) FROM {$wpdb->prefix}woocommerce_api_keys WHERE 1 = 1 {$search};" ); // WPCS: unprepared SQL ok.

		$this->items = $keys;

		// Set the pagination.
		$this->set_pagination_args(
			array(
				'total_items' => $count,
				'per_page'    => $per_page,
				'total_pages' => ceil( $count / $per_page ),
			)
		);
	}
}
PK     tS\HV    $  views/html-admin-dashboard-setup.phpnu [        <?php
/**
 * Admin View: Dashboard - Finish Setup
 *
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div class="dashboard-widget-finish-setup" data-current-step="<?php echo esc_html( $step_number - 1 ); ?>" data-total-steps="<?php echo esc_html( $tasks_count ); ?>">
	<span class='progress-wrapper'>
		<svg class="circle-progress" width="17" height="17" version="1.1" xmlns="http://www.w3.org/2000/svg">
		  <circle r="6.5" cx="10" cy="10" fill="transparent" stroke-dasharray="40.859" stroke-dashoffset="0"></circle>
		  <circle class="bar" r="6.5" cx="190" cy="10" fill="transparent" stroke-dasharray="40.859" stroke-dashoffset="<?php echo esc_attr( $circle_dashoffset ); ?>" transform='rotate(-90 100 100)'></circle>
		</svg>
		<span><?php esc_html_e( 'Step', 'woocommerce' ); ?> <?php echo esc_html( $step_number ); ?> <?php esc_html_e( 'of', 'woocommerce' ); ?> <?php echo esc_html( $tasks_count ); ?></span>
	</span>

	<div class="description">
		<div>
			<?php esc_html_e( 'You\'re almost there! Once you complete store setup you can start receiving orders.', 'woocommerce' ); ?>
			<div><a href='<?php echo esc_attr( $button_link ); ?>' class='button button-primary'><?php esc_html_e( 'Start selling', 'woocommerce' ); ?></a></div>
		</div>
		<img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/dashboard-widget-setup.png" />
	</div>
	<div class="clear"></div>
</div>

<script type="text/javascript">
	/*global jQuery */
	(function( $ ) {
		const widget = $( '.dashboard-widget-finish-setup' );
		const currentStep = widget.data( 'current-step' );
		const totalSteps = widget.data( 'total-steps' );

		$( function() {
			window.wcTracks.recordEvent( 'wcadmin_setup_widget_view', {
				completed_tasks: currentStep,
				total_tasks: totalSteps,
			} );
		});


		$( '.dashboard-widget-finish-setup a' ).on( 'click', function() {
			window.wcTracks.recordEvent( 'wcadmin_setup_widget_click', {
				completed_tasks: currentStep,
				total_tasks: totalSteps,
			} );
		});
	})( jQuery );
</script>
PK     tS\rB[      views/html-notice-updated.phpnu [        <?php
/**
 * Admin View: Notice - Updated.
 *
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

?>
<div id="message" class="updated woocommerce-message wc-connect woocommerce-message--success">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'update', remove_query_arg( 'do_update_woocommerce' ) ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>

	<p><?php esc_html_e( 'WooCommerce database update complete. Thank you for updating to the latest version!', 'woocommerce' ); ?></p>
</div>
PK     tS\iMP  P  '  views/html-notice-secure-connection.phpnu [        <?php
/**
 * Admin View: Notice - Secure connection.
 *
 * @package WooCommerce\Admin\Notices
 */

defined( 'ABSPATH' ) || exit;

?>
<div id="message" class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'no_secure_connection' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>

	<p>
	<?php
		echo wp_kses_post( sprintf(
			/* translators: %s: documentation URL */
			__( 'Your store does not appear to be using a secure connection. We highly recommend serving your entire website over an HTTPS connection to help keep customer data secure. <a href="%s">Learn more here.</a>', 'woocommerce' ),
			'https://woocommerce.com/document/ssl-and-https/'
		) );
	?>
	</p>
</div>
PK     tS\d%oI  I  (  views/html-notice-base-table-missing.phpnu [        <?php
/**
 * Admin View: Notice - Base table missing.
 *
 * @package WooCommerce\Admin
 */

defined( 'ABSPATH' ) || exit;

?>
<div class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'base_tables_missing' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>">
		<?php esc_html_e( 'Dismiss', 'woocommerce' ); ?>
	</a>

	<p>
		<strong><?php esc_html_e( 'Database tables missing', 'woocommerce' ); ?></strong>
	</p>
	<p>
		<?php
		$verify_db_tool_available = array_key_exists( 'verify_db_tables', WC_Admin_Status::get_tools() );
		$missing_tables           = get_option( 'woocommerce_schema_missing_tables' );
		if ( $verify_db_tool_available ) {
			echo wp_kses_post(
				sprintf(
				/* translators: %1%s: Missing tables (separated by ",") %2$s: Link to check again */
					__( 'One or more tables required for WooCommerce to function are missing, some features may not work as expected. Missing tables: %1$s. <a href="%2$s">Check again.</a>', 'woocommerce' ),
					esc_html( implode( ', ', $missing_tables ) ),
					wp_nonce_url( admin_url( 'admin.php?page=wc-status&tab=tools&action=verify_db_tables' ), 'debug_action' )
				)
			);
		} else {
			echo wp_kses_post(
				sprintf(
				/* translators: %1%s: Missing tables (separated by ",") */
					__( 'One or more tables required for WooCommerce to function are missing, some features may not work as expected. Missing tables: %1$s.', 'woocommerce' ),
					esc_html( implode( ', ', $missing_tables ) )
				)
			);
		}
		?>
	</p>
</div>
PK     tS\VՕ5  5     views/html-bulk-edit-product.phpnu [        <?php
/**
 * Admin View: Bulk Edit Products
 */

use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;
use Automattic\WooCommerce\Enums\CatalogVisibility;
use Automattic\WooCommerce\Enums\ProductTaxStatus;
use Automattic\WooCommerce\Utilities\I18nUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

?>

<fieldset class="inline-edit-col-right">
	<div id="woocommerce-fields-bulk" class="inline-edit-col">

		<h4><?php _e( 'Product data', 'woocommerce' ); ?></h4>

		<?php do_action( 'woocommerce_product_bulk_edit_start' ); ?>

		<div class="inline-edit-group">
			<label class="alignleft">
				<span class="title"><?php _e( 'Price', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<select class="change_regular_price change_to" name="change_regular_price">
						<?php
						$options = array(
							''  => __( '— No change —', 'woocommerce' ),
							'1' => __( 'Change to:', 'woocommerce' ),
							'2' => __( 'Increase existing price by (fixed amount or %):', 'woocommerce' ),
							'3' => __( 'Decrease existing price by (fixed amount or %):', 'woocommerce' ),
						);
						foreach ( $options as $key => $value ) {
							echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
						}
						?>
					</select>
				</span>
			</label>
			<label class="change-input">
				<input type="text" name="_regular_price" class="text regular_price" placeholder="<?php printf( esc_attr__( 'Enter price (%s)', 'woocommerce' ), get_woocommerce_currency_symbol() ); ?>" value="" />
			</label>
		</div>

		<div class="inline-edit-group">
			<label class="alignleft">
				<span class="title"><?php _e( 'Sale', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<select class="change_sale_price change_to" name="change_sale_price">
						<?php
						$options = array(
							''  => __( '— No change —', 'woocommerce' ),
							'1' => __( 'Change to:', 'woocommerce' ),
							'2' => __( 'Increase existing sale price by (fixed amount or %):', 'woocommerce' ),
							'3' => __( 'Decrease existing sale price by (fixed amount or %):', 'woocommerce' ),
							'4' => __( 'Set to regular price decreased by (fixed amount or %):', 'woocommerce' ),
						);
						foreach ( $options as $key => $value ) {
							echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
						}
						?>
					</select>
				</span>
			</label>
			<label class="change-input">
				<input type="text" name="_sale_price" class="text sale_price" placeholder="<?php printf( esc_attr__( 'Enter sale price (%s)', 'woocommerce' ), get_woocommerce_currency_symbol() ); ?>" value="" />
			</label>
		</div>

		<?php if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() ) : ?>
			<div class="inline-edit-group">
				<label class="alignleft">
					<span class="title"><?php esc_html_e( 'Cost', 'woocommerce' ); ?></span>
					<span class="input-text-wrap">
						<select class="change_cogs_value change_to" name="change_cogs_value">
							<?php
							$options = array(
								''  => __( '— No change —', 'woocommerce' ),
								'1' => __( 'Change to:', 'woocommerce' ),
							);
							foreach ( $options as $key => $value ) {
								echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
							}
							?>
						</select>
					</span>
				</label>
				<label class="change-input">
					<?php /* phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- the esc_attr is somehow not detected */ ?>
					<?php /* translators: %s = cost value (formatted as currency) */ ?>
					<input type="text" name="_cogs_value" class="text cogs_value" placeholder="<?php esc_attr( printf( __( 'Enter cost value (%s)', 'woocommerce' ), get_woocommerce_currency_symbol() ) ); ?>" value="" />
					<?php /* phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped */ ?>
				</label>
			<div class="inline-edit-group">
		<?php endif; ?>

		<?php if ( wc_tax_enabled() ) : ?>
			<label>
				<span class="title"><?php _e( 'Tax status', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<select class="tax_status" name="_tax_status">
						<?php
						$options = array(
							''                         => __( '— No change —', 'woocommerce' ),
							ProductTaxStatus::TAXABLE  => __( 'Taxable', 'woocommerce' ),
							ProductTaxStatus::SHIPPING => __( 'Shipping only', 'woocommerce' ),
							ProductTaxStatus::NONE     => _x( 'None', 'Tax status', 'woocommerce' ),
						);
						foreach ( $options as $key => $value ) {
							echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
						}
						?>
					</select>
				</span>
			</label>

			<label>
				<span class="title"><?php _e( 'Tax class', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<select class="tax_class" name="_tax_class">
						<?php
						$options = array(
							''         => __( '— No change —', 'woocommerce' ),
							'standard' => __( 'Standard', 'woocommerce' ),
						);

						$tax_classes = WC_Tax::get_tax_classes();

						if ( ! empty( $tax_classes ) ) {
							foreach ( $tax_classes as $class ) {
								$options[ sanitize_title( $class ) ] = esc_html( $class );
							}
						}

						foreach ( $options as $key => $value ) {
							echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
						}
						?>
					</select>
				</span>
			</label>
		<?php endif; ?>

		<?php if ( wc_product_weight_enabled() ) : ?>
			<div class="inline-edit-group">
				<label class="alignleft">
					<span class="title"><?php _e( 'Weight', 'woocommerce' ); ?></span>
					<span class="input-text-wrap">
						<select class="change_weight change_to" name="change_weight">
							<?php
								$options = array(
									''  => __( '— No change —', 'woocommerce' ),
									'1' => __( 'Change to:', 'woocommerce' ),
								);
								foreach ( $options as $key => $value ) {
									echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
								}
								?>
						</select>
					</span>
				</label>
				<label class="change-input">
					<?php
					$placeholder = sprintf(
						/* translators: 1. Weight number; 2. Weight unit; E.g. 2 kg */
						__( '%1$s (%2$s)', 'woocommerce' ),
						wc_format_localized_decimal( 0 ),
						I18nUtil::get_weight_unit_label( get_option( 'woocommerce_weight_unit', 'kg' ) )
					);
					?>
					<input
						type="text"
						name="_weight"
						class="text weight"
						placeholder="<?php echo esc_attr( $placeholder ); ?>"
						value=""
					>
				</label>
			</div>
		<?php endif; ?>

		<?php if ( wc_product_dimensions_enabled() ) : ?>
			<div class="inline-edit-group dimensions">
				<label class="alignleft">
					<span class="title"><?php _e( 'L/W/H', 'woocommerce' ); ?></span>
					<span class="input-text-wrap">
						<select class="change_dimensions change_to" name="change_dimensions">
							<?php
							$options = array(
								''  => __( '— No change —', 'woocommerce' ),
								'1' => __( 'Change to:', 'woocommerce' ),
							);
							foreach ( $options as $key => $value ) {
								echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
							}
							?>
						</select>
					</span>
				</label>
				<label class="change-input">
					<?php
					$dimension_unit_label = I18nUtil::get_dimensions_unit_label( get_option( 'woocommerce_dimension_unit', 'cm' ) );
					?>
					<input
						type="text"
						name="_length"
						class="text length"
						<?php /* translators: %s is dimension unit label */ ?>
						placeholder="<?php printf( esc_attr__( 'Length (%s)', 'woocommerce' ), esc_html( $dimension_unit_label ) ); ?>"
						value=""
					>
					<input
						type="text"
						name="_width"
						class="text width"
						<?php /* translators: %s is dimension unit label */ ?>
						placeholder="<?php printf( esc_attr__( 'Width (%s)', 'woocommerce' ), esc_html( $dimension_unit_label ) ); ?>"
						value=""
					>
					<input
						type="text"
						name="_height"
						class="text height"
						<?php /* translators: %s is dimension unit label */ ?>
						placeholder="<?php printf( esc_attr__( 'Height (%s)', 'woocommerce' ), esc_html( $dimension_unit_label ) ); ?>"
						value=""
					>
				</label>
			</div>
		<?php endif; ?>

		<label>
			<span class="title"><?php _e( 'Shipping class', 'woocommerce' ); ?></span>
			<span class="input-text-wrap">
				<select class="shipping_class" name="_shipping_class">
					<option value=""><?php _e( '— No change —', 'woocommerce' ); ?></option>
					<option value="_no_shipping_class"><?php _e( 'No shipping class', 'woocommerce' ); ?></option>
					<?php
					foreach ( $shipping_class as $key => $value ) {
						echo '<option value="' . esc_attr( $value->slug ) . '">' . esc_html( $value->name ) . '</option>';
					}
					?>
				</select>
			</span>
		</label>

		<label>
			<span class="title"><?php _e( 'Visibility', 'woocommerce' ); ?></span>
			<span class="input-text-wrap">
				<select class="visibility" name="_visibility">
					<?php
					$options = array(
						''                         => __( '— No change —', 'woocommerce' ),
						CatalogVisibility::VISIBLE => __( 'Catalog &amp; search', 'woocommerce' ),
						CatalogVisibility::CATALOG => __( 'Catalog', 'woocommerce' ),
						CatalogVisibility::SEARCH  => __( 'Search', 'woocommerce' ),
						CatalogVisibility::HIDDEN  => __( 'Hidden', 'woocommerce' ),
					);
					foreach ( $options as $key => $value ) {
						echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
					}
					?>
				</select>
			</span>
		</label>
		<label>
			<span class="title"><?php _e( 'Featured', 'woocommerce' ); ?></span>
			<span class="input-text-wrap">
				<select class="featured" name="_featured">
					<?php
					$options = array(
						''    => __( '— No change —', 'woocommerce' ),
						'yes' => __( 'Yes', 'woocommerce' ),
						'no'  => __( 'No', 'woocommerce' ),
					);
					foreach ( $options as $key => $value ) {
						echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
					}
					?>
				</select>
			</span>
		</label>

		<label>
			<span class="title"><?php _e( 'In stock?', 'woocommerce' ); ?></span>
			<span class="input-text-wrap">
				<select class="stock_status" name="_stock_status">
					<?php
					echo '<option value="">' . esc_html__( '— No Change —', 'woocommerce' ) . '</option>';

					foreach ( wc_get_product_stock_status_options() as $key => $value ) {
						echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
					}
					?>
				</select>
			</span>
		</label>
		<?php if ( 'yes' == get_option( 'woocommerce_manage_stock' ) ) : ?>

			<label>
				<span class="title"><?php _e( 'Manage stock?', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<select class="manage_stock" name="_manage_stock">
						<?php
						$options = array(
							''    => __( '— No change —', 'woocommerce' ),
							'yes' => __( 'Yes', 'woocommerce' ),
							'no'  => __( 'No', 'woocommerce' ),
						);
						foreach ( $options as $key => $value ) {
							echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
						}
						?>
					</select>
				</span>
			</label>

			<div class="inline-edit-group">
				<label class="alignleft stock_qty_field">
					<span class="title"><?php _e( 'Stock qty', 'woocommerce' ); ?></span>
					<span class="input-text-wrap">
						<select class="change_stock change_to" name="change_stock">
							<?php
							$options = array(
								''  => __( '— No change —', 'woocommerce' ),
								'1' => __( 'Change to:', 'woocommerce' ),
								'2' => __( 'Increase existing stock by:', 'woocommerce' ),
								'3' => __( 'Decrease existing stock by:', 'woocommerce' ),
							);
							foreach ( $options as $key => $value ) {
								echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
							}
							?>
						</select>
					</span>
				</label>
				<label class="change-input">
					<input type="text" name="_stock" class="text stock" placeholder="<?php esc_attr_e( 'Stock qty', 'woocommerce' ); ?>" step="any" value="">
				</label>
			</div>

			<label>
				<span class="title"><?php _e( 'Backorders?', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<select class="backorders" name="_backorders">
						<?php
						echo '<option value="">' . esc_html__( '— No Change —', 'woocommerce' ) . '</option>';

						foreach ( wc_get_product_backorder_options() as $key => $value ) {
							echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
						}
						?>
					</select>
				</span>
			</label>

		<?php endif; ?>

		<label>
			<span class="title"><?php esc_html_e( 'Sold individually?', 'woocommerce' ); ?></span>
			<span class="input-text-wrap">
				<select class="sold_individually" name="_sold_individually">
					<?php
					$options = array(
						''    => __( '— No change —', 'woocommerce' ),
						'yes' => __( 'Yes', 'woocommerce' ),
						'no'  => __( 'No', 'woocommerce' ),
					);
					foreach ( $options as $key => $value ) {
						echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
					}
					?>
				</select>
			</span>
		</label>

		<?php do_action( 'woocommerce_product_bulk_edit_end' ); ?>

		<input type="hidden" name="woocommerce_bulk_edit" value="1" />
		<input type="hidden" name="woocommerce_quick_edit_nonce" value="<?php echo wp_create_nonce( 'woocommerce_quick_edit_nonce' ); ?>" />
	</div>
</fieldset>
PK     tS\c#	  	  !  views/html-admin-page-reports.phpnu [        <?php
/**
 * Admin View: Page - Reports
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

?>
<div class="wrap woocommerce">
	<?php if ( WC()->is_wc_admin_active() ) { ?>
	<div id="message" class="error inline" style="margin-top:30px">
		<p>
			<strong>
			<?php
			/* translators: 1: Link URL */
			echo wp_kses_post( sprintf( __( 'With the release of WooCommerce 4.0, these reports are being replaced. There is a new and better Analytics section available for users running WordPress 5.3+. Head on over to the <a href="%1$s">WooCommerce Analytics</a> or learn more about the new experience in the <a href="https://woocommerce.com/document/woocommerce-analytics/" target="_blank">WooCommerce Analytics documentation</a>.', 'woocommerce' ), esc_url( wc_admin_url( '&path=/analytics/overview' ) ) ) );
			?>
			</strong>
		</p>
	</div>
	<?php } ?>
	<nav class="nav-tab-wrapper woo-nav-tab-wrapper">
		<?php
		foreach ( $reports as $key => $report_group ) {
			echo '<a href="' . admin_url( 'admin.php?page=wc-reports&tab=' . urlencode( $key ) ) . '" class="nav-tab ';
			if ( $current_tab == $key ) {
				echo 'nav-tab-active';
			}
			echo '">' . esc_html( $report_group['title'] ) . '</a>';
		}

		do_action( 'wc_reports_tabs' );
		?>
	</nav>
	<?php
	if ( count( $reports[ $current_tab ]['reports'] ) > 1 ) {
		?>
		<ul class="subsubsub">
			<li>
			<?php

			$links = array();

			foreach ( $reports[ $current_tab ]['reports'] as $key => $report ) {
				$link = '<a href="admin.php?page=wc-reports&tab=' . urlencode( $current_tab ) . '&amp;report=' . urlencode( $key ) . '" class="';

				if ( $key == $current_report ) {
					$link .= 'current';
				}

				$link .= '">' . $report['title'] . '</a>';

				$links[] = $link;
			}

			echo implode( ' | </li><li>', $links );

			?>
			</li>
		</ul>
		<br class="clear" />
		<?php
	}

	if ( isset( $reports[ $current_tab ]['reports'][ $current_report ] ) ) {
		$report = $reports[ $current_tab ]['reports'][ $current_report ];

		if ( ! isset( $report['hide_title'] ) || true != $report['hide_title'] ) {
			echo '<h1>' . esc_html( $report['title'] ) . '</h1>';
		} else {
			echo '<h1 class="screen-reader-text">' . esc_html( $report['title'] ) . '</h1>';
		}

		if ( $report['description'] ) {
			echo '<p>' . $report['description'] . '</p>';
		}

		if ( $report['callback'] && ( is_callable( $report['callback'] ) ) ) {
			call_user_func( $report['callback'], $current_report );
		}
	}
	?>
</div>
PK     tS\:h    ,  views/html-notice-redirect-only-download.phpnu [        <?php
/**
 * Admin View: Notice - Redirect only download method is selected.
 *
 * @package WooCommerce\Admin\Notices
 */

defined( 'ABSPATH' ) || exit;

?>
<div class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'redirect_download_method' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>
	<p>
		<?php
		echo wp_kses_post(
			sprintf(
				/* translators: %s: Link to settings page. */
				__( 'Your store is configured to serve digital products using "Redirect only" method. This method is deprecated, <a href="%s">please switch to a different method instead.</a><br><em>If you use a remote server for downloadable files (such as Google Drive, Dropbox, Amazon S3), you may optionally wish to "allow using redirects as a last resort". Enabling that and/or selecting any of the other options will make this notice go away.</em>', 'woocommerce' ),
				add_query_arg(
					array(
						'page'    => 'wc-settings',
						'tab'     => 'products',
						'section' => 'downloadable',
					),
					admin_url( 'admin.php' )
				)
			)
		);
		?>
	</p>
</div>
PK     tS\:9]j  j  (  views/html-admin-page-status-logs-db.phpnu [        <?php
/**
 * Admin View: Page - Status Database Logs
 *
 * @package WooCommerce\Admin\Logs
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$delete_confirmation_js = sprintf(
	"return window.confirm( '%s' )",
	esc_js( __( 'Are you sure you want to clear all logs from the database?', 'woocommerce' ) )
);
?>
<form method="get" id="mainform">
	<input type="hidden" name="page" value="wc-status" />
	<input type="hidden" name="tab" value="logs" />

	<?php $log_table_list->search_box( __( 'Search logs', 'woocommerce' ), 'log' ); ?>
	<?php $log_table_list->display(); ?>

	<?php
	submit_button(
		__( 'Flush all logs', 'woocommerce' ),
		'delete',
		'flush-logs',
		true,
		array(
			'onclick' => esc_attr( $delete_confirmation_js ),
		)
	);
	?>
</form>
<script>
	document.addEventListener( 'DOMContentLoaded', function() {
		var contextToggles = Array.from( document.getElementsByClassName( 'log-toggle' ) );
		contextToggles.forEach( ( element ) => {
			element.addEventListener( 'click', ( event ) => {
				event.preventDefault();
				const button = event.currentTarget;
				const buttonLabel = button.querySelector( '.log-toggle-label' );
				const buttonIcon = button.querySelector( '.dashicons' );
				const context = document.getElementById( 'log-context-' + button.dataset.logId );

				switch ( button.dataset.toggleStatus ) {
					case 'off':
						context.style.display = 'table-row';
						buttonLabel.textContent = button.dataset.labelHide;
						buttonIcon.classList.replace( 'dashicons-arrow-down-alt2', 'dashicons-arrow-up-alt2' );
						button.dataset.toggleStatus = 'on';
						break;
					case 'on':
						context.style.display = 'none';
						buttonLabel.textContent = button.dataset.labelShow;
						buttonIcon.classList.replace( 'dashicons-arrow-up-alt2', 'dashicons-arrow-down-alt2' );
						button.dataset.toggleStatus = 'off';
						break;
				}
			} );
		} );
	} );
</script>
PK     tS\bЩ    +  views/html-notice-sync-on-read-disabled.phpnu [        <?php
/**
 * Admin View: Notice - HPOS sync-on-read disabled.
 *
 * @package WooCommerce\Admin\Notices
 */

defined( 'ABSPATH' ) || exit;

?>
<div id="message" class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'hpos_sync_on_read_disabled' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>

	<p>
		<strong><?php esc_html_e( 'HPOS order "sync on read" has been disabled', 'woocommerce' ); ?></strong><br />
		<?php
			echo wp_kses_post(
				sprintf(
					/* translators: %s: URL to blog post about this change. */
					__( 'Compatibility mode for HPOS no longer pulls order changes made to the posts database back into your orders automatically. If your site uses custom code or plugins that modify orders outside of WooCommerce, this may affect how order data is handled. <a href="%s">Learn more about this change and what to do</a>.', 'woocommerce' ),
					'https://developer.woocommerce.com/2026/02/16/hpos-sync-on-read-to-be-disabled-by-default-in-woocommerce-10-7/'
				)
			);
			?>
	</p>
</div>
PK     tS\`&    /  views/html-notice-regenerating-lookup-table.phpnu [        <?php
/**
 * Admin View: Notice - Regenerating product lookup table.
 *
 * @package WooCommerce\Admin
 */

use Automattic\Jetpack\Constants;

defined( 'ABSPATH' ) || exit;

$pending_actions_url = admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=wc_update_product_lookup_tables&status=pending' );
$cron_disabled       = Constants::is_true( 'DISABLE_WP_CRON' );
$cron_cta            = $cron_disabled ? __( 'You can manually run queued updates here.', 'woocommerce' ) : __( 'View progress &rarr;', 'woocommerce' );
?>
<div id="message" class="updated woocommerce-message">
	<p>
		<strong><?php esc_html_e( 'WooCommerce is updating product data in the background', 'woocommerce' ); ?></strong><br>
		<?php
		esc_html_e( 'Product display, sorting, and reports may not be accurate until this finishes. It will take a few minutes and this notice will disappear when complete.', 'woocommerce' );

		if ( $cron_disabled ) {
			echo '<br>' . esc_html__( 'Note: WP CRON has been disabled on your install which may prevent this update from completing.', 'woocommerce' );
		}
		?>
		&nbsp;<a href="<?php echo esc_url( $pending_actions_url ); ?>"><?php echo esc_html( $cron_cta ); ?></a>
	</p>
</div>
PK     tS\_Jhy  y    views/html-notice-updating.phpnu [        <?php
/**
 * Admin View: Notice - Updating
 *
 * @package WooCommerce\Admin
 */

use Automattic\Jetpack\Constants;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$pending_actions_url = admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=woocommerce_run_update&status=pending' );
$cron_disabled       = Constants::is_true( 'DISABLE_WP_CRON' );
$cron_cta            = $cron_disabled ? __( 'You can manually run queued updates here.', 'woocommerce' ) : __( 'View progress &rarr;', 'woocommerce' );
?>
<div id="message" class="updated woocommerce-message wc-connect">
	<p>
		<strong><?php esc_html_e( 'WooCommerce database update', 'woocommerce' ); ?></strong><br>
		<?php esc_html_e( 'WooCommerce is updating the database in the background. The database update process may take a little while, so please be patient.', 'woocommerce' ); ?>
		<?php
		if ( $cron_disabled ) {
			echo '<br>' . esc_html__( 'Note: WP CRON has been disabled on your install which may prevent this update from completing.', 'woocommerce' );
		}
		?>
		&nbsp;<a href="<?php echo esc_url( $pending_actions_url ); ?>"><?php echo esc_html( $cron_cta ); ?></a>
	</p>
</div>
PK     tS\t;z  z    views/html-notice-update.phpnu [        <?php
/**
 * Admin View: Notice - Update
 *
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$update_url = wp_nonce_url(
	add_query_arg( 'do_update_woocommerce', 'true', admin_url( 'admin.php?page=wc-settings' ) ),
	'wc_db_update',
	'wc_db_update_nonce'
);

?>
<div id="message" class="updated woocommerce-message wc-connect">
	<p>
		<strong><?php esc_html_e( 'WooCommerce database update required', 'woocommerce' ); ?></strong>
	</p>
	<p>
		<?php
			esc_html_e( 'WooCommerce has been updated! To keep things running smoothly, we have to update your database to the newest version.', 'woocommerce' );

			/* translators: 1: Link to docs 2: Close link. */
			printf( ' ' . esc_html__( 'The database update process runs in the background and may take a little while, so please be patient. Advanced users can alternatively update via %1$sWP CLI%2$s.', 'woocommerce' ), '<a href="https://developer.woocommerce.com/docs/wc-cli/wc-cli-examples/#upgrading-the-database-using-wp-cli">', '</a>' );
		?>
	</p>
	<p class="submit">
		<a href="<?php echo esc_url( $update_url ); ?>" class="wc-update-now button-primary">
			<?php esc_html_e( 'Update WooCommerce Database', 'woocommerce' ); ?>
		</a>
		<a href="https://woocommerce.com/document/how-to-update-woocommerce/" class="button-secondary">
			<?php esc_html_e( 'Learn more about updates', 'woocommerce' ); ?>
		</a>
	</p>
</div>
PK     tS\2  2  (  views/html-admin-page-product-export.phpnu [        <?php
/**
 * Admin View: Product Export
 *
 * @package WooCommerce\Admin\Export
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

wp_enqueue_script( 'wc-product-export' );

$exporter = new WC_Product_CSV_Exporter();

$product_ids_to_export    = array();
$is_exporting_product_ids = false;

if ( ! empty( $_GET['product_ids'] ) ) {
	check_admin_referer( 'export-selected-products' );

	$ids_raw                  = explode( ',', sanitize_text_field( wp_unslash( $_GET['product_ids'] ) ) );
	$product_ids_to_export    = array_filter( array_map( 'absint', $ids_raw ) );
	$is_exporting_product_ids = ! empty( $product_ids_to_export ) ? true : false;
}
?>
<div class="wrap woocommerce">
	<h1><?php esc_html_e( 'Export Products', 'woocommerce' ); ?></h1>

	<?php
	if ( $is_exporting_product_ids ) {
		$clear_url = remove_query_arg( 'product_ids' );
		$count     = count( $product_ids_to_export );
		$notice    = sprintf(
			// translators: %1$d: Number of products, %2$s: URL to clear selection.
			_n(
				'You are about to export %1$d product. To export all products, <a href="%2$s">clear your selection</a>.',
				'You are about to export %1$d products. To export all products, <a href="%2$s">clear your selection</a>.',
				$count,
				'woocommerce'
			),
			$count,
			esc_url( $clear_url )
		);
		?>
		<div id="selected-product-export-notice" class="notice notice-info inline">
			<p><?php echo wp_kses_post( $notice ); ?></p>
		</div>
		<?php
	}
	?>

	<div class="woocommerce-exporter-wrapper">
		<form class="woocommerce-exporter">
			<?php
			// Add hidden input if exporting product IDs, so JS can potentially pick it up.
			if ( $is_exporting_product_ids ) {
				echo '<input type="hidden" name="product_ids" value="' . esc_attr( implode( ',', $product_ids_to_export ) ) . '" />';
			}
			?>
			<header>
				<span class="spinner is-active"></span>
				<h2><?php esc_html_e( 'Export products to a CSV file', 'woocommerce' ); ?></h2>
				<p>
					<?php
					if ( $is_exporting_product_ids ) {
						esc_html_e( 'This tool allows you to generate and download a CSV file containing the selected products.', 'woocommerce' );
					} else {
						esc_html_e( 'This tool allows you to generate and download a CSV file containing a list of all products.', 'woocommerce' );
					}
					?>
				</p>
			</header>
			<section>
				<table class="form-table woocommerce-exporter-options">
					<tbody>
						<tr>
							<th scope="row">
								<label for="woocommerce-exporter-columns"><?php esc_html_e( 'Which columns should be exported?', 'woocommerce' ); ?></label>
							</th>
							<td>
								<select id="woocommerce-exporter-columns" class="woocommerce-exporter-columns wc-enhanced-select" style="width:100%;" multiple data-placeholder="<?php esc_attr_e( 'Export all columns', 'woocommerce' ); ?>">
									<?php
									foreach ( $exporter->get_default_column_names() as $column_id => $column_name ) {
										echo '<option value="' . esc_attr( $column_id ) . '">' . esc_html( $column_name ) . '</option>';
									}
									?>
									<option value="downloads"><?php esc_html_e( 'Downloads', 'woocommerce' ); ?></option>
									<option value="attributes"><?php esc_html_e( 'Attributes', 'woocommerce' ); ?></option>
								</select>
							</td>
						</tr>
						<?php if ( ! $is_exporting_product_ids ) : ?>
						<tr>
							<th scope="row">
								<label for="woocommerce-exporter-types"><?php esc_html_e( 'Which product types should be exported?', 'woocommerce' ); ?></label>
							</th>
							<td>
								<select id="woocommerce-exporter-types" class="woocommerce-exporter-types wc-enhanced-select" style="width:100%;" multiple data-placeholder="<?php esc_attr_e( 'Export all products', 'woocommerce' ); ?>">
									<?php
									foreach ( WC_Admin_Exporters::get_product_types() as $value => $label ) {
										echo '<option value="' . esc_attr( $value ) . '">' . esc_html( $label ) . '</option>';
									}
									?>
								</select>
							</td>
						</tr>
						<tr>
							<th scope="row">
								<label for="woocommerce-exporter-category"><?php esc_html_e( 'Which product category should be exported?', 'woocommerce' ); ?></label>
							</th>
							<td>
								<select id="woocommerce-exporter-category" class="woocommerce-exporter-category wc-enhanced-select" style="width:100%;" multiple data-placeholder="<?php esc_attr_e( 'Export all categories', 'woocommerce' ); ?>">
								<?php
								$categories = get_categories(
									array(
										'taxonomy'   => 'product_cat',
										'hide_empty' => false,
									)
								);
								foreach ( $categories as $category ) {
									echo '<option value="' . esc_attr( $category->slug ) . '">' . esc_html( $category->name ) . '</option>';
								}
								?>
								</select>
							</td>
						</tr>
						<?php endif; ?>
						<tr>
							<th scope="row">
								<label for="woocommerce-exporter-meta"><?php esc_html_e( 'Export custom meta?', 'woocommerce' ); ?></label>
							</th>
							<td>
								<input type="checkbox" id="woocommerce-exporter-meta" value="1" />
								<label for="woocommerce-exporter-meta"><?php esc_html_e( 'Yes, export all custom meta', 'woocommerce' ); ?></label>
							</td>
						</tr>
						<?php do_action( 'woocommerce_product_export_row' ); ?>
					</tbody>
				</table>
				<progress class="woocommerce-exporter-progress" max="100" value="0"></progress>
			</section>
			<div class="wc-actions">
				<button type="submit" class="woocommerce-exporter-button button button-primary" value="<?php esc_attr_e( 'Generate CSV', 'woocommerce' ); ?>"><?php esc_html_e( 'Generate CSV', 'woocommerce' ); ?></button>
			</div>
		</form>
	</div>
</div>
PK     tS\x    '  views/html-admin-page-status-report.phpnu [        <?php
/**
 * Admin View: Page - Status Report.
 *
 * @package WooCommerce
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils;
use Automattic\WooCommerce\Utilities\RestApiUtil;

defined( 'ABSPATH' ) || exit;

global $wpdb;

$report             = wc_get_container()->get( RestApiUtil::class )->get_endpoint_data( '/wc/v3/system_status' );
$environment        = $report['environment'];
$database           = $report['database'];
$post_type_counts   = isset( $report['post_type_counts'] ) ? $report['post_type_counts'] : array();
$active_plugins     = $report['active_plugins'];
$inactive_plugins   = $report['inactive_plugins'];
$dropins_mu_plugins = $report['dropins_mu_plugins'];
$theme              = $report['theme'];
$security           = $report['security'];
$settings           = $report['settings'];
$logging            = $report['logging'];
$wp_pages           = $report['pages'];
$plugin_updates     = new WC_Plugin_Updates();
$untested_plugins   = $plugin_updates->get_untested_plugins( WC()->version, Constants::get_constant( 'WC_SSR_PLUGIN_UPDATE_RELEASE_VERSION_TYPE' ) );

$active_plugins_count   = is_countable( $active_plugins ) ? count( $active_plugins ) : 0;
$inactive_plugins_count = is_countable( $inactive_plugins ) ? count( $inactive_plugins ) : 0;

// Include necessary WordPress file to use get_plugin_data().
if ( ! function_exists( 'get_plugin_data' ) ) {
	require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
// Define the path to the main WooCommerce plugin file using the correct constant.
$plugin_path = WP_PLUGIN_DIR . '/woocommerce/woocommerce.php';
// Initialize the WooCommerce version variable.
$wc_version = '';
// Check if the plugin file exists before trying to access it.
if ( file_exists( $plugin_path ) ) {
	$plugin_data = get_plugin_data( $plugin_path );
	$wc_version  = $plugin_data['Version'] ?? ''; // Use null coalescing operator to handle undefined index.
}

?>
<div class="updated woocommerce-message inline">
	<p>
		<?php esc_html_e( 'Please copy and paste this information in your ticket when contacting support:', 'woocommerce' ); ?>
	</p>
	<p class="submit">
		<a href="#" class="button-primary debug-report"><?php esc_html_e( 'Get system report', 'woocommerce' ); ?></a>
		<a class="button-secondary docs" href="https://woocommerce.com/document/understanding-the-woocommerce-system-status-report/" target="_blank">
			<?php esc_html_e( 'Understanding the status report', 'woocommerce' ); ?>
		</a>
	</p>
	<div id="debug-report">
		<textarea readonly="readonly"></textarea>
		<p class="submit">
			<button id="download-for-support" class="button-primary" href="#">
				<?php esc_html_e( 'Download for support', 'woocommerce' ); ?>
			</button>
			<button id="copy-for-support" class="button" href="#" data-tip="<?php esc_attr_e( 'Copied!', 'woocommerce' ); ?>">
				<?php esc_html_e( 'Copy for support', 'woocommerce' ); ?>
			</button>
			<button id="copy-for-github" class="button" href="#" data-tip="<?php esc_attr_e( 'Copied!', 'woocommerce' ); ?>">
				<?php esc_html_e( 'Copy for GitHub', 'woocommerce' ); ?>
			</button>
		</p>
		<p class="copy-error hidden">
			<?php esc_html_e( 'Copying to clipboard failed. Please press Ctrl/Cmd+C to copy.', 'woocommerce' ); ?>
		</p>
	</div>
</div>
<table class="wc_status_table widefat" cellspacing="0" id="status">
	<thead>
		<tr>
			<th colspan="3" data-export-label="WordPress Environment"><h2><?php esc_html_e( 'WordPress environment', 'woocommerce' ); ?></h2></th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td data-export-label="WordPress address (URL)"><?php esc_html_e( 'WordPress address (URL)', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The root URL of your site.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $environment['site_url'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="Site address (URL)"><?php esc_html_e( 'Site address (URL)', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The homepage URL of your site.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $environment['home_url'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="WC Version"><?php esc_html_e( 'WooCommerce version', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The version of WooCommerce installed on your site.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( ! empty( $wc_version ) ? $wc_version : $environment['version'] ); ?></td>

		</tr>
		<tr>
			<td data-export-label="Legacy REST API Package Version"><?php esc_html_e( 'WooCommerce Legacy REST API package', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The WooCommerce Legacy REST API plugin running on this site.', 'woocommerce' ) ); ?></td>
			<td>
				<?php
				if ( WC()->legacy_rest_api_is_available() ) {
					$plugin_path = wc_get_container()->get( \Automattic\WooCommerce\Utilities\PluginUtil::class )->get_wp_plugin_id( 'woocommerce-legacy-rest-api' );
					$version     = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_path )['Version'] ?? '';
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span> ' . esc_html( $version ) . ' <code class="private">' . esc_html( wc()->api->get_rest_api_package_path() ) . '</code></mark> ';
				} else {
					echo '<mark class="info-icon"><span class="dashicons dashicons-info"></span> ' . esc_html__( 'The Legacy REST API plugin is not installed on this site.', 'woocommerce' ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="Action Scheduler Version"><?php esc_html_e( 'Action Scheduler package', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Action Scheduler package running on your site.', 'woocommerce' ) ); ?></td>
			<td>
				<?php
				if ( class_exists( 'ActionScheduler_Versions' ) && class_exists( 'ActionScheduler' ) ) {
					$version = ActionScheduler_Versions::instance()->latest_version();
					$path    = ActionScheduler::plugin_path( '' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
				} else {
					$version = null;
				}

				if ( ! is_null( $version ) ) {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span> ' . esc_html( $version ) . ' <code class="private">' . esc_html( $path ) . '</code></mark> ';
				} else {
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . esc_html__( 'Unable to detect the Action Scheduler package.', 'woocommerce' ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="Log Directory Writable"><?php esc_html_e( 'Log directory writable', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Several WooCommerce extensions can write logs which makes debugging problems easier. The directory must be writable for this to happen.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $environment['log_directory_writable'] ) {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span> <code class="private">' . esc_html( $environment['log_directory'] ) . '</code></mark> ';
				} else {
					printf(
						'<mark class="error"><span class="dashicons dashicons-warning"></span> %s</mark>',
						sprintf(
							// Translators: %s: Log directory path.
							esc_html__( 'To allow logging, make %s writable.', 'woocommerce' ),
							'<code>' . esc_html( $environment['log_directory'] ) . '</code>'
						)
					);
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="WP Version"><?php esc_html_e( 'WordPress version', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The version of WordPress installed on your site.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				$latest_version = get_transient( 'woocommerce_system_status_wp_version_check' );

				if ( false === $latest_version ) {
					$version_check = wp_remote_get( 'https://api.wordpress.org/core/version-check/1.7/' );
					$api_response  = json_decode( wp_remote_retrieve_body( $version_check ), true );

					if ( $api_response && isset( $api_response['offers'], $api_response['offers'][0], $api_response['offers'][0]['version'] ) ) {
						$latest_version = $api_response['offers'][0]['version'];
					} else {
						$latest_version = $environment['wp_version'];
					}
					set_transient( 'woocommerce_system_status_wp_version_check', $latest_version, DAY_IN_SECONDS );
				}

				if ( version_compare( $environment['wp_version'], $latest_version, '<' ) ) {
					/* Translators: %1$s: Current version, %2$s: New version */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( '%1$s - There is a newer version of WordPress available (%2$s)', 'woocommerce' ), esc_html( $environment['wp_version'] ), esc_html( $latest_version ) ) . '</mark>';
				} else {
					echo '<mark class="yes">' . esc_html( $environment['wp_version'] ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="WP Multisite"><?php esc_html_e( 'WordPress multisite', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Whether or not you have WordPress Multisite enabled.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo ( $environment['wp_multisite'] ) ? '<span class="dashicons dashicons-yes"></span>' : '&ndash;'; ?></td>
		</tr>
		<tr>
			<td data-export-label="WP Memory Limit"><?php esc_html_e( 'WordPress memory limit', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The maximum amount of memory (RAM) that your site can use at one time.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $environment['wp_memory_limit'] < 67108864 ) {
					/* Translators: %1$s: Memory limit, %2$s: Docs link. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( '%1$s - We recommend setting memory to at least 64MB. See: %2$s', 'woocommerce' ), esc_html( size_format( $environment['wp_memory_limit'] ) ), '<a href="https://wordpress.org/support/article/editing-wp-config-php/#increasing-memory-allocated-to-php" target="_blank">' . esc_html__( 'Increasing memory allocated to PHP', 'woocommerce' ) . '</a>' ) . '</mark>';
				} else {
					echo '<mark class="yes">' . esc_html( size_format( $environment['wp_memory_limit'] ) ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="WP Debug Mode"><?php esc_html_e( 'WordPress debug mode', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Displays whether or not WordPress is in Debug Mode.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php if ( $environment['wp_debug_mode'] ) : ?>
					<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>
				<?php else : ?>
					<mark class="no">&ndash;</mark>
				<?php endif; ?>
			</td>
		</tr>
		<tr>
			<td data-export-label="WP Cron"><?php esc_html_e( 'WordPress cron', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Displays whether or not WP Cron Jobs are enabled.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php if ( $environment['wp_cron'] ) : ?>
					<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>
				<?php else : ?>
					<mark class="no">&ndash;</mark>
				<?php endif; ?>
			</td>
		</tr>
		<tr>
			<td data-export-label="WP Environment Type"><?php esc_html_e( 'Environment type', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The current environment type set for this site.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $environment['wp_environment_type'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="Language"><?php esc_html_e( 'Language', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The current language used by WordPress. Default = English', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $environment['language'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="External object cache"><?php esc_html_e( 'External object cache', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Displays whether or not WordPress is using an external object cache.', 'woocommerce' ) ); ?></td>
			<td>
				<?php if ( $environment['external_object_cache'] ) : ?>
					<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>
				<?php else : ?>
					<mark class="no">&ndash;</mark>
				<?php endif; ?>
			</td>
		</tr>
	</tbody>
</table>
<table class="wc_status_table widefat" cellspacing="0">
	<thead>
		<tr>
			<th colspan="3" data-export-label="Server Environment"><h2><?php esc_html_e( 'Server environment', 'woocommerce' ); ?></h2></th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td data-export-label="Server Info"><?php esc_html_e( 'Server info', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Information about the web server that is currently hosting your site.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $environment['server_info'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="Server Architecture"><?php esc_html_e( 'Server architecture', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Information about the operating system your server is running.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo ! empty( $environment['server_architecture'] ) ? esc_html( $environment['server_architecture'] ) : esc_html__( 'Unable to determine server architecture.  Please ask your hosting provider for this information.', 'woocommerce' ); ?></td>
		</tr>
		<tr>
			<td data-export-label="PHP Version"><?php esc_html_e( 'PHP version', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The version of PHP installed on your hosting server.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php echo '<mark class="yes">' . esc_html( $environment['php_version'] ) . '</mark>'; ?>
			</td>
		</tr>
		<?php if ( function_exists( 'ini_get' ) ) : ?>
			<tr>
				<td data-export-label="PHP Post Max Size"><?php esc_html_e( 'PHP post max size', 'woocommerce' ); ?>:</td>
				<td class="help"><?php echo wc_help_tip( esc_html__( 'The largest filesize that can be contained in one post.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
				<td><?php echo esc_html( size_format( $environment['php_post_max_size'] ) ); ?></td>
			</tr>
			<tr>
				<td data-export-label="PHP Time Limit"><?php esc_html_e( 'PHP time limit', 'woocommerce' ); ?>:</td>
				<td class="help"><?php echo wc_help_tip( esc_html__( 'The amount of time (in seconds) that your site will spend on a single operation before timing out (to avoid server lockups)', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
				<td><?php echo esc_html( $environment['php_max_execution_time'] ); ?></td>
			</tr>
			<tr>
				<td data-export-label="PHP Max Input Vars"><?php esc_html_e( 'PHP max input vars', 'woocommerce' ); ?>:</td>
				<td class="help"><?php echo wc_help_tip( esc_html__( 'The maximum number of variables your server can use for a single function to avoid overloads.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
				<td><?php echo esc_html( $environment['php_max_input_vars'] ); ?></td>
			</tr>
			<tr>
				<td data-export-label="cURL Version"><?php esc_html_e( 'cURL version', 'woocommerce' ); ?>:</td>
				<td class="help"><?php echo wc_help_tip( esc_html__( 'The version of cURL installed on your server.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
				<td><?php echo esc_html( $environment['curl_version'] ); ?></td>
			</tr>
			<tr>
				<td data-export-label="SUHOSIN Installed"><?php esc_html_e( 'SUHOSIN installed', 'woocommerce' ); ?>:</td>
				<td class="help"><?php echo wc_help_tip( esc_html__( 'Suhosin is an advanced protection system for PHP installations. It was designed to protect your servers on the one hand against a number of well known problems in PHP applications and on the other hand against potential unknown vulnerabilities within these applications or the PHP core itself. If enabled on your server, Suhosin may need to be configured to increase its data submission limits.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
				<td><?php echo $environment['suhosin_installed'] ? '<span class="dashicons dashicons-yes"></span>' : '&ndash;'; ?></td>
			</tr>
		<?php endif; ?>

		<?php

		if ( $environment['mysql_version'] ) :
			?>
			<tr>
				<td data-export-label="MySQL Version"><?php esc_html_e( 'MySQL version', 'woocommerce' ); ?>:</td>
				<td class="help"><?php echo wc_help_tip( esc_html__( 'The version of MySQL installed on your hosting server.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
				<td>
					<?php
					if ( version_compare( $environment['mysql_version'], '5.6', '<' ) && ! strstr( $environment['mysql_version_string'], 'MariaDB' ) ) {
						/* Translators: %1$s: MySQL version, %2$s: Recommended MySQL version. */
						echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( '%1$s - We recommend a minimum MySQL version of 5.6. See: %2$s', 'woocommerce' ), esc_html( $environment['mysql_version_string'] ), '<a href="https://wordpress.org/about/requirements/" target="_blank">' . esc_html__( 'WordPress requirements', 'woocommerce' ) . '</a>' ) . '</mark>';
					} else {
						echo '<mark class="yes">' . esc_html( $environment['mysql_version_string'] ) . '</mark>';
					}
					?>
				</td>
			</tr>
		<?php endif; ?>
		<tr>
			<td data-export-label="Max Upload Size"><?php esc_html_e( 'Max upload size', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The largest filesize that can be uploaded to your WordPress installation.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( size_format( $environment['max_upload_size'] ) ); ?></td>
		</tr>
		<tr>
			<td data-export-label="Default Timezone is UTC"><?php esc_html_e( 'Default timezone is UTC', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The default timezone for your server.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( 'UTC' !== $environment['default_timezone'] ) {
					/* Translators: %s: default timezone.. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( 'Default timezone is %s - it should be UTC', 'woocommerce' ), esc_html( $environment['default_timezone'] ) ) . '</mark>';
				} else {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="fsockopen/cURL"><?php esc_html_e( 'fsockopen/cURL', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Payment gateways can use cURL to communicate with remote servers to authorize payments, other plugins may also use it when communicating with remote services.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $environment['fsockopen_or_curl_enabled'] ) {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>';
				} else {
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . esc_html__( 'Your server does not have fsockopen or cURL enabled - PayPal IPN and other scripts which communicate with other servers will not work. Contact your hosting provider.', 'woocommerce' ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="SoapClient"><?php esc_html_e( 'SoapClient', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Some webservices like shipping use SOAP to get information from remote servers, for example, live shipping quotes from FedEx require SOAP to be installed.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $environment['soapclient_enabled'] ) {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>';
				} else {
					/* Translators: %s classname and link. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( 'Your server does not have the %s class enabled - some gateway plugins which use SOAP may not work as expected.', 'woocommerce' ), '<a href="https://php.net/manual/en/class.soapclient.php">SoapClient</a>' ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="DOMDocument"><?php esc_html_e( 'DOMDocument', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'HTML/Multipart emails use DOMDocument to generate inline CSS in templates.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $environment['domdocument_enabled'] ) {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>';
				} else {
					/* Translators: %s: classname and link. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( 'Your server does not have the %s class enabled - HTML/Multipart emails, and also some extensions, will not work without DOMDocument.', 'woocommerce' ), '<a href="https://php.net/manual/en/class.domdocument.php">DOMDocument</a>' ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="GZip"><?php esc_html_e( 'GZip', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'GZip (gzopen) is used to open the GEOIP database from MaxMind.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $environment['gzip_enabled'] ) {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>';
				} else {
					/* Translators: %s: classname and link. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( 'Your server does not support the %s function - this is required to use the GeoIP database from MaxMind.', 'woocommerce' ), '<a href="https://php.net/manual/en/zlib.installation.php">gzopen</a>' ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="Multibyte String"><?php esc_html_e( 'Multibyte string', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Multibyte String (mbstring) is used to convert character encoding, like for emails or converting characters to lowercase.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $environment['mbstring_enabled'] ) {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>';
				} else {
					/* Translators: %s: classname and link. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( 'Your server does not support the %s functions - this is required for better character encoding. Some fallbacks will be used instead for it.', 'woocommerce' ), '<a href="https://php.net/manual/en/mbstring.installation.php">mbstring</a>' ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="Remote Post"><?php esc_html_e( 'Remote post', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'PayPal uses this method of communicating when sending back transaction information.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $environment['remote_post_successful'] ) {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>';
				} else {
					/* Translators: %s: function name. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( '%s failed. Contact your hosting provider.', 'woocommerce' ), 'wp_remote_post()' ) . ' ' . esc_html( $environment['remote_post_response'] ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="Remote Get"><?php esc_html_e( 'Remote get', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'WooCommerce plugins may use this method of communication when checking for plugin updates.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $environment['remote_get_successful'] ) {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>';
				} else {
					/* Translators: %s: function name. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( '%s failed. Contact your hosting provider.', 'woocommerce' ), 'wp_remote_get()' ) . ' ' . esc_html( $environment['remote_get_response'] ) . '</mark>';
				}
				?>
			</td>
		</tr>
		<?php
		// phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment
		/**
		 * Filters the environment rows to show in the WooCommerce status report.
		 */
		$rows = apply_filters( 'woocommerce_system_status_environment_rows', array() );
		// phpcs:enable WooCommerce.Commenting.CommentHooks.MissingSinceVersionComment
		foreach ( $rows as $row ) {
			if ( ! empty( $row['success'] ) ) {
				$css_class = 'yes';
				$icon      = '<span class="dashicons dashicons-yes"></span>';
			} else {
				$css_class = 'error';
				$icon      = '<span class="dashicons dashicons-no-alt"></span>';
			}
			?>
			<tr>
				<td data-export-label="<?php echo esc_attr( $row['name'] ); ?>"><?php echo esc_html( $row['name'] ); ?>:</td>
				<td class="help"><?php echo esc_html( isset( $row['help'] ) ? $row['help'] : '' ); ?></td>
				<td>
					<mark class="<?php echo esc_attr( $css_class ); ?>">
						<?php echo wp_kses_post( $icon ); ?> <?php echo wp_kses_data( ! empty( $row['note'] ) ? $row['note'] : '' ); ?>
					</mark>
				</td>
			</tr>
			<?php
		}
		?>
	</tbody>
</table>
<table id="status-database" class="wc_status_table widefat" cellspacing="0">
	<thead>
	<tr>
		<th colspan="3" data-export-label="Database">
			<h2>
				<?php
					esc_html_e( 'Database', 'woocommerce' );
					self::output_tables_info();
				?>
			</h2>
		</th>
	</tr>
	</thead>
	<tbody>
		<tr>
			<td data-export-label="WC Database Version"><?php esc_html_e( 'WooCommerce database version', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The database version for WooCommerce. This should be the same as your WooCommerce version.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $database['wc_database_version'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="WC Database Prefix"><?php esc_html_e( 'Database prefix', 'woocommerce' ); ?></td>
			<td class="help">&nbsp;</td>
			<td>
				<?php
				if ( strlen( $database['database_prefix'] ) > 20 ) {
					/* Translators: %1$s: Database prefix, %2$s: Docs link. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( '%1$s - We recommend using a prefix with less than 20 characters. See: %2$s', 'woocommerce' ), esc_html( $database['database_prefix'] ), '<a href="https://woocommerce.com/document/completed-order-email-doesnt-contain-download-links/#section-2" target="_blank">' . esc_html__( 'How to update your database table prefix', 'woocommerce' ) . '</a>' ) . '</mark>';
				} else {
					echo '<mark class="yes">' . esc_html( $database['database_prefix'] ) . '</mark>';
				}
				?>
			</td>
		</tr>

		<?php if ( ! empty( $database['database_size'] ) && ! empty( $database['database_tables'] ) ) : ?>
			<tr>
				<td><?php esc_html_e( 'Total Database Size', 'woocommerce' ); ?></td>
				<td class="help">&nbsp;</td>
				<td><?php printf( '%.2fMB', esc_html( $database['database_size']['data'] + $database['database_size']['index'] ) ); ?></td>
			</tr>

			<tr>
				<td><?php esc_html_e( 'Database Data Size', 'woocommerce' ); ?></td>
				<td class="help">&nbsp;</td>
				<td><?php printf( '%.2fMB', esc_html( $database['database_size']['data'] ) ); ?></td>
			</tr>

			<tr>
				<td><?php esc_html_e( 'Database Index Size', 'woocommerce' ); ?></td>
				<td class="help">&nbsp;</td>
				<td><?php printf( '%.2fMB', esc_html( $database['database_size']['index'] ) ); ?></td>
			</tr>

			<?php foreach ( $database['database_tables']['woocommerce'] as $table => $table_data ) { ?>
				<tr>
					<td><?php echo esc_html( $table ); ?></td>
					<td class="help">&nbsp;</td>
					<td>
						<?php
						if ( ! $table_data ) {
							echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . esc_html__( 'Table does not exist', 'woocommerce' ) . '</mark>';
						} else {
							/* Translators: %1$f: Table size, %2$f: Index size, %3$s Engine. */
							printf( esc_html__( 'Data: %1$.2fMB + Index: %2$.2fMB + Engine %3$s', 'woocommerce' ), esc_html( wc_format_decimal( $table_data['data'], 2 ) ), esc_html( wc_format_decimal( $table_data['index'], 2 ) ), esc_html( $table_data['engine'] ) );
						}
						?>
					</td>
				</tr>
			<?php } ?>

			<?php foreach ( $database['database_tables']['other'] as $table => $table_data ) { ?>
				<tr>
					<td><?php echo esc_html( $table ); ?></td>
					<td class="help">&nbsp;</td>
					<td>
						<?php
							/* Translators: %1$f: Table size, %2$f: Index size, %3$s Engine. */
							printf( esc_html__( 'Data: %1$.2fMB + Index: %2$.2fMB + Engine %3$s', 'woocommerce' ), esc_html( wc_format_decimal( $table_data['data'], 2 ) ), esc_html( wc_format_decimal( $table_data['index'], 2 ) ), esc_html( $table_data['engine'] ) );
						?>
					</td>
				</tr>
			<?php } ?>
		<?php else : ?>
			<tr>
				<td><?php esc_html_e( 'Database information:', 'woocommerce' ); ?></td>
				<td class="help">&nbsp;</td>
				<td>
					<?php
					esc_html_e(
						'Unable to retrieve database information. Usually, this is not a problem, and it only means that your install is using a class that replaces the WordPress database class (e.g., HyperDB) and WooCommerce is unable to get database information.',
						'woocommerce'
					);
					?>
				</td>
			</tr>
		<?php endif; ?>
	</tbody>
</table>
<?php if ( $post_type_counts ) : ?>
	<table class="wc_status_table widefat" cellspacing="0">
		<thead>
		<tr>
			<th colspan="3" data-export-label="Post Type Counts"><h2><?php esc_html_e( 'Post Type Counts', 'woocommerce' ); ?></h2></th>
		</tr>
		</thead>
		<tbody>
			<?php
			foreach ( $post_type_counts as $ptype ) {
				?>
				<tr>
					<td><?php echo esc_html( $ptype['type'] ); ?></td>
					<td class="help">&nbsp;</td>
					<td><?php echo absint( $ptype['count'] ); ?></td>
				</tr>
				<?php
			}
			?>
		</tbody>
	</table>
<?php endif; ?>
<table class="wc_status_table widefat" cellspacing="0">
	<thead>
		<tr>
			<th colspan="3" data-export-label="Security"><h2><?php esc_html_e( 'Security', 'woocommerce' ); ?></h2></th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td data-export-label="Secure connection (HTTPS)"><?php esc_html_e( 'Secure connection (HTTPS)', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Is the connection to your store secure?', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php if ( $security['secure_connection'] ) : ?>
					<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>
				<?php else : ?>
					<mark class="error"><span class="dashicons dashicons-warning"></span>
					<?php
					/* Translators: %s: docs link. */
					echo wp_kses_post( sprintf( __( 'Your store is not using HTTPS. <a href="%s" target="_blank">Learn more about HTTPS and SSL Certificates</a>.', 'woocommerce' ), 'https://woocommerce.com/document/ssl-and-https/' ) );
					?>
					</mark>
				<?php endif; ?>
			</td>
		</tr>
		<tr>
			<td data-export-label="Hide errors from visitors"><?php esc_html_e( 'Hide errors from visitors', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Error messages can contain sensitive information about your store environment. These should be hidden from untrusted visitors.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php if ( $security['hide_errors'] ) : ?>
					<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>
				<?php else : ?>
					<mark class="error"><span class="dashicons dashicons-warning"></span><?php esc_html_e( 'Error messages should not be shown to visitors.', 'woocommerce' ); ?></mark>
				<?php endif; ?>
			</td>
		</tr>
	</tbody>
</table>
<table class="wc_status_table widefat" cellspacing="0">
	<thead>
		<tr>
			<th colspan="3" data-export-label="Active Plugins (<?php echo esc_attr( $active_plugins_count ); ?>)"><h2><?php esc_html_e( 'Active plugins', 'woocommerce' ); ?> (<?php echo esc_attr( $active_plugins_count ); ?>)</h2></th>
		</tr>
	</thead>
	<tbody>
		<?php self::output_plugins_info( $active_plugins, $untested_plugins ); ?>
	</tbody>
</table>
<table class="wc_status_table widefat" cellspacing="0">
	<thead>
		<tr>
			<th colspan="3" data-export-label="Inactive Plugins (<?php echo esc_attr( $inactive_plugins_count ); ?>)"><h2><?php esc_html_e( 'Inactive plugins', 'woocommerce' ); ?> (<?php echo esc_attr( $inactive_plugins_count ); ?>)</h2></th>
		</tr>
	</thead>
	<tbody>
		<?php self::output_plugins_info( $inactive_plugins, $untested_plugins ); ?>
	</tbody>
</table>
<?php
$dropins_count = is_countable( $dropins_mu_plugins['dropins'] ) ? count( $dropins_mu_plugins['dropins'] ) : 0;
if ( 0 < $dropins_count ) :
	?>
	<table class="wc_status_table widefat" cellspacing="0">
		<thead>
			<tr>
				<th colspan="3" data-export-label="Dropin Plugins (<?php $dropins_count; ?>)"><h2><?php esc_html_e( 'Dropin Plugins', 'woocommerce' ); ?> (<?php $dropins_count; ?>)</h2></th>
			</tr>
		</thead>
		<tbody>
			<?php
			foreach ( $dropins_mu_plugins['dropins'] as $dropin ) {
				?>
				<tr>
					<td><?php echo wp_kses_post( $dropin['plugin'] ); ?></td>
					<td class="help">&nbsp;</td>
					<td><?php echo wp_kses_post( $dropin['name'] ); ?>
				</tr>
				<?php
			}
			?>
		</tbody>
	</table>
	<?php
endif;

$mu_plugins_count = is_countable( $dropins_mu_plugins['mu_plugins'] ) ? count( $dropins_mu_plugins['mu_plugins'] ) : 0;
if ( 0 < $mu_plugins_count ) :
	?>
	<table class="wc_status_table widefat" cellspacing="0">
		<thead>
			<tr>
				<th colspan="3" data-export-label="Must Use Plugins (<?php echo esc_attr( $mu_plugins_count ); ?>)"><h2><?php esc_html_e( 'Must Use Plugins', 'woocommerce' ); ?> (<?php echo esc_attr( $mu_plugins_count ); ?>)</h2></th>
			</tr>
		</thead>
		<tbody>
			<?php
			foreach ( $dropins_mu_plugins['mu_plugins'] as $mu_plugin ) { // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
				$plugin_name = esc_html( $mu_plugin['name'] );
				if ( ! empty( $mu_plugin['url'] ) ) {
					$plugin_name = '<a href="' . esc_url( $mu_plugin['url'] ) . '" aria-label="' . esc_attr__( 'Visit plugin homepage', 'woocommerce' ) . '" target="_blank">' . $plugin_name . '</a>';
				}
				?>
				<tr>
					<td><?php echo wp_kses_post( $plugin_name ); ?></td>
					<td class="help">&nbsp;</td>
					<td>
					<?php
						/* translators: %s: plugin author */
						printf( esc_html__( 'by %s', 'woocommerce' ), esc_html( $mu_plugin['author_name'] ) );
						echo ' &ndash; ' . esc_html( $mu_plugin['version'] );
					?>
				</tr>
				<?php
			}
			?>
		</tbody>
	</table>
<?php endif; ?>
<table class="wc_status_table widefat" cellspacing="0">
	<thead>
		<tr>
			<th colspan="3" data-export-label="Settings"><h2><?php esc_html_e( 'Settings', 'woocommerce' ); ?></h2></th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td data-export-label="Legacy API Enabled"><?php esc_html_e( 'Legacy API enabled', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Does your site have the Legacy REST API enabled?', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo $settings['api_enabled'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">&ndash;</mark>'; ?></td>
		</tr>
		<tr>
			<td data-export-label="Force SSL"><?php esc_html_e( 'Force SSL', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Does your site force a SSL Certificate for transactions?', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo $settings['force_ssl'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">&ndash;</mark>'; ?></td>
		</tr>
		<tr>
			<td data-export-label="Currency"><?php esc_html_e( 'Currency', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'What currency prices are listed at in the catalog and which currency gateways will take payments in.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $settings['currency'] ); ?> (<?php echo esc_html( $settings['currency_symbol'] ); ?>)</td>
		</tr>
		<tr>
			<td data-export-label="Currency Position"><?php esc_html_e( 'Currency position', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The position of the currency symbol.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $settings['currency_position'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="Thousand Separator"><?php esc_html_e( 'Thousand separator', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The thousand separator of displayed prices.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $settings['thousand_separator'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="Decimal Separator"><?php esc_html_e( 'Decimal separator', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The decimal separator of displayed prices.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $settings['decimal_separator'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="Number of Decimals"><?php esc_html_e( 'Number of decimals', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The number of decimal points shown in displayed prices.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $settings['number_of_decimals'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="Taxonomies: Product Types"><?php esc_html_e( 'Taxonomies: Product types', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'A list of taxonomy terms that can be used in regard to order/product statuses.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				$display_terms = array();
				foreach ( $settings['taxonomies'] as $slug => $name ) {
					$display_terms[] = strtolower( $name ) . ' (' . $slug . ')';
				}
				echo implode( ', ', array_map( 'esc_html', $display_terms ) );
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="Taxonomies: Product Visibility"><?php esc_html_e( 'Taxonomies: Product visibility', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'A list of taxonomy terms used for product visibility.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				$display_terms = array();
				foreach ( $settings['product_visibility_terms'] as $slug => $name ) {
					$display_terms[] = strtolower( $name ) . ' (' . $slug . ')';
				}
				echo implode( ', ', array_map( 'esc_html', $display_terms ) );
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="Connected to WooCommerce.com"><?php esc_html_e( 'Connected to WooCommerce.com', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Is your site connected to WooCommerce.com?', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo 'yes' === $settings['woocommerce_com_connected'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">&ndash;</mark>'; ?></td>
		</tr>
		<tr>
			<td data-export-label="Enforce Approved Product Download Directories"><?php esc_html_e( 'Enforce Approved Product Download Directories', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Is your site enforcing the use of Approved Product Download Directories?', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo $settings['enforce_approved_download_dirs'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">&ndash;</mark>'; ?></td>
		</tr>

		<tr>
			<td data-export-label="HPOS feature enabled"><?php esc_html_e( 'HPOS enabled:', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Is HPOS enabled?', 'woocommerce' ) ); ?></td>
			<td><?php echo $settings['HPOS_enabled'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">&ndash;</mark>'; ?></td>
		</tr>
		<tr>
			<td data-export-label="Order datastore"><?php esc_html_e( 'Order datastore:', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Datastore currently in use for orders.', 'woocommerce' ) ); ?></td>
			<td><?php echo esc_html( $settings['order_datastore'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="HPOS data sync enabled"><?php esc_html_e( 'HPOS data sync enabled:', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Is data sync enabled for HPOS?', 'woocommerce' ) ); ?></td>
			<td><?php echo $settings['HPOS_sync_enabled'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">&ndash;</mark>'; ?></td>
		</tr>

		<tr>
			<td data-export-label="Enabled Features"><?php esc_html_e( 'Enabled features:', 'woocommerce' ); ?></td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Features that are currently enabled.', 'woocommerce' ) ); ?></td>
			<td><?php echo esc_html( implode( ', ', $settings['enabled_features'] ) ); ?></td>
		</tr>

	</tbody>
</table>
<table class="wc_status_table widefat" cellspacing="0">
	<thead>
	<tr>
		<th colspan="3" data-export-label="Logging"><h2><?php esc_html_e( 'Logging', 'woocommerce' ); ?></h2></th>
	</tr>
	</thead>
	<tbody>
	<tr>
		<td data-export-label="Enabled"><?php esc_html_e( 'Enabled', 'woocommerce' ); ?></td>
		<td class="help"><?php echo wc_help_tip( esc_html__( 'Is logging enabled?', 'woocommerce' ) ); ?></td>
		<td><?php echo $logging['logging_enabled'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">&ndash;</mark>'; ?></td>
	</tr>
	<tr>
		<td data-export-label="Handler"><?php esc_html_e( 'Handler', 'woocommerce' ); ?></td>
		<td class="help"><?php echo wc_help_tip( esc_html__( 'How log entries are being stored.', 'woocommerce' ) ); ?></td>
		<td><?php echo esc_html( $logging['default_handler'] ); ?></td>
	</tr>
	<tr>
		<td data-export-label="Retention period"><?php esc_html_e( 'Retention period', 'woocommerce' ); ?></td>
		<td class="help"><?php echo wc_help_tip( esc_html__( 'How many days log entries will be kept before being auto-deleted.', 'woocommerce' ) ); ?></td>
		<td>
			<?php
			printf(
				esc_html(
					// translators: %s is a number of days.
					_n(
						'%s day',
						'%s days',
						$logging['retention_period_days'],
						'woocommerce'
					)
				),
				esc_html( number_format_i18n( $logging['retention_period_days'] ) )
			);
			?>
		</td>
	</tr>
	<tr>
		<td data-export-label="Level threshold"><?php esc_html_e( 'Level threshold', 'woocommerce' ); ?></td>
		<td class="help"><?php echo wc_help_tip( esc_html__( 'The minimum severity level of logs that will be stored.', 'woocommerce' ) ); ?></td>
		<td><?php echo $logging['level_threshold'] ? esc_html( $logging['level_threshold'] ) : '<mark class="no">&ndash;</mark>'; ?></td>
	</tr>
	<tr>
		<td data-export-label="Log directory size"><?php esc_html_e( 'Log directory size', 'woocommerce' ); ?></td>
		<td class="help"><?php echo wc_help_tip( esc_html__( 'The total size of the files in the log directory.', 'woocommerce' ) ); ?></td>
		<td><?php echo esc_html( $logging['log_directory_size'] ); ?></td>
	</tr>
	</tbody>
</table>
<table class="wc_status_table widefat" cellspacing="0">
	<thead>
		<tr>
			<th colspan="3" data-export-label="WC Pages"><h2><?php esc_html_e( 'WooCommerce pages', 'woocommerce' ); ?></h2></th>
		</tr>
	</thead>
	<tbody>
		<?php
		$alt = 1;
		foreach ( $wp_pages as $_page ) {
			$found_error = false;

			if ( $_page['page_id'] ) {
				/* Translators: %s: page name. */
				$page_name = '<a href="' . get_edit_post_link( $_page['page_id'] ) . '" aria-label="' . sprintf( esc_html__( 'Edit %s page', 'woocommerce' ), esc_html( $_page['page_name'] ) ) . '">' . esc_html( $_page['page_name'] ) . '</a>';
			} else {
				$page_name = esc_html( $_page['page_name'] );
			}

			echo '<tr><td data-export-label="' . esc_attr( $page_name ) . '">' . wp_kses_post( $page_name ) . ':</td>';
			/* Translators: %s: page name. */
			echo '<td class="help">' . wc_help_tip( sprintf( esc_html__( 'The URL of your %s page (along with the Page ID).', 'woocommerce' ), $page_name ) ) . '</td><td>';

			// Page ID check.
			if ( ! $_page['page_set'] ) {
				echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . esc_html__( 'Page not set', 'woocommerce' ) . '</mark>';
				$found_error = true;
			} elseif ( ! $_page['page_exists'] ) {
				echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . esc_html__( 'Page ID is set, but the page does not exist', 'woocommerce' ) . '</mark>';
				$found_error = true;
			} elseif ( ! $_page['page_visible'] ) {
				/* Translators: %s: docs link. */
				echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . wp_kses_post( sprintf( __( 'Page visibility should be <a href="%s" target="_blank">public</a>', 'woocommerce' ), 'https://wordpress.org/support/article/content-visibility/' ) ) . '</mark>';
				$found_error = true;
			} elseif ( $_page['shortcode_required'] || $_page['block_required'] ) {
				// Shortcode and block check.
				if ( ! $_page['shortcode_present'] && ! $_page['block_present'] ) {
					/* Translators: %1$s: shortcode text, %2$s: block slug. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . ( $_page['block_required'] ? sprintf( esc_html__( 'Page does not contain the %1$s shortcode or the %2$s block.', 'woocommerce' ), esc_html( $_page['shortcode'] ), esc_html( $_page['block'] ) ) : sprintf( esc_html__( 'Page does not contain the %s shortcode.', 'woocommerce' ), esc_html( $_page['shortcode'] ) ) ) . '</mark>'; /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */
					$found_error = true;
				}

				// Warn merchants if both the shortcode and block are present, which will be a confusing shopper experience.
				if ( $_page['shortcode_present'] && $_page['block_present'] ) {
					/* Translators: %1$s: shortcode text, %2$s: block slug. */
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . sprintf( esc_html__( 'Page contains both the %1$s shortcode and the %2$s block.', 'woocommerce' ), esc_html( $_page['shortcode'] ), esc_html( $_page['block'] ) ) . '</mark>'; /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */
					$found_error = true;
				}
			}

			if ( ! $found_error ) {

				$additional_info = '';

				if ( ! empty( $_page['shortcode'] ) || ! empty( $_page['block'] ) ) {
					// We check first if, in a blocks theme, the template content does not load the page content.
					if ( CartCheckoutUtils::is_overriden_by_custom_template_content( $_page['block'] ) ) {
						$additional_info = __( "This page's content is overridden by custom template content", 'woocommerce' );
					} elseif ( $_page['shortcode_present'] ) {
						// Always display the shortcode with square brackets for consistency.
						$shortcode_display = $_page['shortcode'];
						if ( $shortcode_display && '[' !== $shortcode_display[0] ) {
							$shortcode_display = '[' . $shortcode_display . ']';
						}
						/* translators: %1$s: shortcode text. */
						$additional_info = sprintf( __( 'Contains the <strong>%1$s</strong> shortcode', 'woocommerce' ), esc_html( $shortcode_display ) );
					} elseif ( $_page['block_present'] ) {
						/* Translators: %1$s: block slug. */
						$additional_info = sprintf( __( 'Contains the <strong>%1$s</strong> block', 'woocommerce' ), esc_html( $_page['block'] ) );
					}

					if ( ! empty( $additional_info ) ) {
						$additional_info = '<mark class="no"> - <span class="dashicons dashicons-info"></span> ' . $additional_info . '</mark>';
					}
				}

				echo '<mark class="yes">#' . absint( $_page['page_id'] ) . ' - ' . esc_html( str_replace( home_url(), '', get_permalink( $_page['page_id'] ) ) ) . '</mark>' . $additional_info; /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */
			}

			echo '</td></tr>';
		}
		?>
	</tbody>
</table>
<table class="wc_status_table widefat" cellspacing="0">
	<thead>
		<tr>
			<th colspan="3" data-export-label="Theme"><h2><?php esc_html_e( 'Theme', 'woocommerce' ); ?></h2></th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td data-export-label="Name"><?php esc_html_e( 'Name', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The name of the current active theme.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $theme['name'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="Version"><?php esc_html_e( 'Version', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The installed version of the current active theme.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( version_compare( $theme['version'], $theme['version_latest'], '<' ) ) {
					/* translators: 1: current version. 2: latest version */
					echo esc_html( sprintf( __( '%1$s (update to version %2$s is available)', 'woocommerce' ), $theme['version'], $theme['version_latest'] ) );
				} else {
					echo esc_html( $theme['version'] );
				}
				?>
			</td>
		</tr>
		<tr>
			<td data-export-label="Author URL"><?php esc_html_e( 'Author URL', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'The theme developers URL.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td><?php echo esc_html( $theme['author_url'] ); ?></td>
		</tr>
		<tr>
			<td data-export-label="Child Theme"><?php esc_html_e( 'Child theme', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Displays whether or not the current theme is a child theme.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $theme['is_child_theme'] ) {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>';
				} else {
					/* Translators: %s docs link. */
					echo '<span class="dashicons dashicons-no-alt"></span> &ndash; ' . wp_kses_post( sprintf( __( 'If you are modifying WooCommerce on a parent theme that you did not build personally we recommend using a child theme. See: <a href="%s" target="_blank">How to create a child theme</a>', 'woocommerce' ), 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ) );
				}
				?>
				</td>
		</tr>
		<?php if ( $theme['is_child_theme'] ) : ?>
			<tr>
				<td data-export-label="Parent Theme Name"><?php esc_html_e( 'Parent theme name', 'woocommerce' ); ?>:</td>
				<td class="help"><?php echo wc_help_tip( esc_html__( 'The name of the parent theme.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
				<td><?php echo esc_html( $theme['parent_name'] ); ?></td>
			</tr>
			<tr>
				<td data-export-label="Parent Theme Version"><?php esc_html_e( 'Parent theme version', 'woocommerce' ); ?>:</td>
				<td class="help"><?php echo wc_help_tip( esc_html__( 'The installed version of the parent theme.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
				<td>
					<?php
					echo esc_html( $theme['parent_version'] );
					if ( version_compare( $theme['parent_version'], $theme['parent_version_latest'], '<' ) ) {
						/* translators: %s: parent theme latest version */
						echo ' &ndash; <strong style="color:red;">' . sprintf( esc_html__( '%s is available', 'woocommerce' ), esc_html( $theme['parent_version_latest'] ) ) . '</strong>';
					}
					?>
				</td>
			</tr>
			<tr>
				<td data-export-label="Parent Theme Author URL"><?php esc_html_e( 'Parent theme author URL', 'woocommerce' ); ?>:</td>
				<td class="help"><?php echo wc_help_tip( esc_html__( 'The parent theme developers URL.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
				<td><?php echo esc_html( $theme['parent_author_url'] ); ?></td>
			</tr>
		<?php endif ?>
		<?php if ( isset( $theme['is_block_theme'] ) ) : ?>
		<tr>
			<td data-export-label="Theme type"><?php esc_html_e( 'Theme type', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Displays whether the current active theme is a block theme or a classic theme.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( $theme['is_block_theme'] ) {
					esc_html_e( 'Block theme', 'woocommerce' );
				} else {
					esc_html_e( 'Classic theme', 'woocommerce' );
				}
				?>
			</td>
		</tr>
		<?php endif ?>
		<tr>
			<td data-export-label="WooCommerce Support"><?php esc_html_e( 'WooCommerce support', 'woocommerce' ); ?>:</td>
			<td class="help"><?php echo wc_help_tip( esc_html__( 'Displays whether or not the current active theme declares WooCommerce support.', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
			<td>
				<?php
				if ( ! $theme['has_woocommerce_support'] ) {
					echo '<mark class="error"><span class="dashicons dashicons-warning"></span> ' . esc_html__( 'Not declared', 'woocommerce' ) . '</mark>';
				} else {
					echo '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>';
				}
				?>
			</td>
		</tr>
	</tbody>
</table>
<table class="wc_status_table widefat" id="status-table-templates" cellspacing="0">
	<thead>
		<tr>
			<th colspan="3" data-export-label="Templates"><h2><?php esc_html_e( 'Templates', 'woocommerce' ); ?><?php echo wc_help_tip( esc_html__( 'This section shows any files that are overriding the default WooCommerce template pages.', 'woocommerce' ) ); ?></h2></th>
		</tr>
	</thead>
	<tbody>
		<?php if ( $theme['has_woocommerce_file'] ) : ?>
		<tr>
			<td data-export-label="Archive Template"><?php esc_html_e( 'Archive template', 'woocommerce' ); ?>:</td>
			<td class="help">&nbsp;</td>
			<td><?php esc_html_e( 'Your theme has a woocommerce.php file, you will not be able to override the woocommerce/archive-product.php custom template since woocommerce.php has priority over archive-product.php. This is intended to prevent display issues.', 'woocommerce' ); ?></td>
		</tr>
		<?php endif ?>
		<?php if ( ! empty( $theme['overrides'] ) ) : ?>
			<?php foreach ( $theme['overrides'] as $i => $override ) : ?>
			<tr>
				<td data-export-label="Override">
					<?php if ( 0 === $i ) : ?>
						<?php esc_html_e( 'Overrides', 'woocommerce' ); ?>:
					<?php endif; ?>
				</td>
				<td class="help">&nbsp;</td>
				<?php
				echo '<td>';
				echo '<code>' . esc_html( $override['file'] ) . '</code>';
				if ( $override['core_version'] && '' === $override['version'] ) {
					echo ' <br><mark class="error"><span class="dashicons dashicons-warning"></span> ';
					printf(
						/* Translators: %s: Core version. */
						esc_html__( 'Version header is missing. The core version is %s', 'woocommerce' ),
						'<strong>' . esc_html( $override['core_version'] ) . '</strong>'
					);
					echo '</mark>';
				} elseif ( $override['core_version'] && version_compare( $override['version'], $override['core_version'], '<' ) ) {
					echo ' <br><mark class="error"><span class="dashicons dashicons-warning"></span> ';
					printf(
						/* Translators: %1$s: Template version, %2$s: Core version. */
						esc_html__( 'Version %1$s is out of date. The core version is %2$s', 'woocommerce' ),
						'<strong>' . esc_html( $override['version'] ) . '</strong>',
						'<strong>' . esc_html( $override['core_version'] ) . '</strong>'
					);
					echo '</mark>';
				}
				echo '</td>';
				?>
			</tr>
			<?php endforeach; ?>
		<?php else : ?>
			<tr>
				<td data-export-label="Overrides"><?php esc_html_e( 'Overrides', 'woocommerce' ); ?>:</td>
				<td class="help">&nbsp;</td>
				<td>&ndash;</td>
			</tr>
		<?php endif; ?>
	</tbody>
	<?php if ( true === $theme['has_outdated_templates'] ) : ?>
	<tfoot>
		<tr>
			<td><?php esc_html_e( 'Outdated templates', 'woocommerce' ); ?>:</td>
			<td class="help">&nbsp;</td>
			<td>
				<mark class="error">
					<span class="dashicons dashicons-warning"></span>
				</mark>
				<span class="private">
					<a href="https://developer.woocommerce.com/docs/theming/theme-development/fixing-outdated-woocommerce-templates/" target="_blank">
						<?php esc_html_e( 'Learn how to update', 'woocommerce' ); ?>
					</a> |
					<mark class="info">
						<span class="dashicons dashicons-info"></span>
					</mark>
					<a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-status&tab=tools' ) ); ?>">
						<?php esc_html_e( 'Clear system status theme info cache', 'woocommerce' ); ?>
					</a>
				</span>
			</td>
		</tr>
	</tfoot>
	<?php endif; ?>
</table>

<?php
	/**
	 * Action fired when the WooCommerce system status report is rendered.
	 *
	 * @since 2.4.0 Introduced hook.
	 * @since 9.8.0 Made SSR report data available to callbacks.
	 *
	 * @param array|WP_Error $report Report data.
	 */
	do_action( 'woocommerce_system_status_report', $report );
?>

<table class="wc_status_table widefat" cellspacing="0">
	<thead>
	<tr>
		<th colspan="3" data-export-label="Status report information"><h2><?php esc_html_e( 'Status report information', 'woocommerce' ); ?><?php echo wc_help_tip( esc_html__( 'This section shows information about this status report.', 'woocommerce' ) ); ?></h2></th>
	</tr>
	</thead>
	<tbody>
	<tr>
		<td data-export-label="Generated at"><?php esc_html_e( 'Generated at', 'woocommerce' ); ?>:</td>
		<td class="help">&nbsp;</td>
		<td><?php echo esc_html( current_time( 'Y-m-d H:i:s P' ) ); ?></td>

	</tr>
	</tbody>
</table>
PK     tS\ C~    6  views/html-notice-uploads-directory-is-unprotected.phpnu [        <?php
/**
 * Admin View: Notice - Uploads directory is unprotected.
 *
 * @package WooCommerce\Admin\Notices
 * @since   4.2.0
 */

defined( 'ABSPATH' ) || exit;

$uploads = wp_get_upload_dir();

?>
<div id="message" class="error woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'uploads_directory_is_unprotected' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>

	<p>
	<?php
		echo wp_kses_post(
			sprintf(
				/* translators: 1: uploads directory URL 2: documentation URL */
				__( 'Your store\'s uploads directory is <a href="%1$s">browsable via the web</a>. We strongly recommend <a href="%2$s">configuring your web server to prevent directory indexing</a>.', 'woocommerce' ),
				esc_url( $uploads['baseurl'] . '/woocommerce_uploads' ),
				'https://woocommerce.com/document/digital-downloadable-product-handling/#protecting-your-uploads-directory'
			)
		);
		?>
	</p>
</div>
PK     tS\#r    %  views/html-notice-legacy-shipping.phpnu [        <?php
/**
 * Admin View: Notice - Legacy Shipping.
 *
 * @package WooCommerce\Admin\Notices
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div id="message" class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'legacy_shipping' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>">
		<?php esc_html_e( 'Dismiss', 'woocommerce' ); ?>
	</a>

	<p class="main">
		<strong><?php esc_html_e( 'New:', 'woocommerce' ); ?> <?php esc_html_e( 'Shipping zones', 'woocommerce' ); ?></strong> &#8211; <?php esc_html_e( 'a group of regions that can be assigned different shipping methods and rates.', 'woocommerce' ); ?>
	</p>
	<p>
		<?php esc_html_e( 'Legacy shipping methods (flat rate, international flat rate, local pickup and delivery, and free shipping) are deprecated but will continue to work as normal for now. <b><em>They will be removed in future versions of WooCommerce</em></b>. We recommend disabling these and setting up new rates within shipping zones as soon as possible.', 'woocommerce' ); ?>
	</p>

	<p class="submit">
		<?php if ( ! is_wc_admin_settings_page() || empty( $_GET['tab'] ) || 'shipping' !== $_GET['tab'] ) : // phpcs:ignore WordPress.Security.NonceVerification.Recommended ?>
			<a class="button-primary" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ); ?>">
				<?php esc_html_e( 'Setup shipping zones', 'woocommerce' ); ?>
			</a>
		<?php endif; ?>
		<a class="button-secondary" href="https://woocommerce.com/document/setting-up-shipping-zones/">
			<?php esc_html_e( 'Learn more about shipping zones', 'woocommerce' ); ?>
		</a>
	</p>
</div>
PK     tS\XM#  #  )  views/html-notice-no-shipping-methods.phpnu [        <?php
/**
 * Admin View: Notice - No Shipping methods.
 *
 * @package WooCommerce\Admin\Notices
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div id="message" class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'no_shipping_methods' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>">
		<?php esc_html_e( 'Dismiss', 'woocommerce' ); ?>
	</a>

	<p class="main">
		<strong>
			<?php esc_html_e( 'Add shipping methods &amp; zones', 'woocommerce' ); ?>
		</strong>
	</p>
	<p>
		<?php esc_html_e( 'Shipping is currently enabled, but you have not added any shipping methods to your shipping zones.', 'woocommerce' ); ?>
	</p>
	<p>
		<?php esc_html_e( 'Customers will not be able to purchase physical goods from your store until a shipping method is available.', 'woocommerce' ); ?>
	</p>

	<p class="submit">
		<a class="button-primary" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ); ?>">
			<?php esc_html_e( 'Setup shipping zones', 'woocommerce' ); ?>
		</a>
		<a class="button-secondary" href="https://woocommerce.com/document/setting-up-shipping-zones/">
			<?php esc_html_e( 'Learn more about shipping zones', 'woocommerce' ); ?>
		</a>
	</p>
</div>
PK     tS\v14  4  %  views/html-email-template-preview.phpnu [        <?php
/**
 * Admin View: Email Template Preview
 *
 * @deprecated 9.8.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

?>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed aliquet diam a facilisis eleifend. Cras ac justo felis. Mauris faucibus, orci eu blandit fermentum, lorem nibh sollicitudin mi, sit amet interdum metus urna ut lacus.</p>

<p><a class="link" href="#">Sed sit amet sapien odio</a></p>

<p>Phasellus quis varius augue. Fusce eu euismod leo, a accumsan tellus. Quisque vitae dolor eu justo cursus egestas. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed sit amet sapien odio. Sed pellentesque arcu mi, quis malesuada lectus lacinia et. Cras a tempor leo.</p>

<h2>Lorem ipsum dolor</h2>

<p>Fusce eu euismod leo, a accumsan tellus. Quisque vitae dolor eu justo cursus egestas. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed sit amet sapien odio. Sed pellentesque arcu mi, quis malesuada lectus lacinia et. Cras a tempor leo.</p>
PK     tS\v    0  views/html-notice-download-dir-sync-complete.phpnu [        <?php
/**
 * Admin View: Notice - Product downloads directories sync complete.
 */

defined( 'ABSPATH' ) || exit;

?>
<div id="message" class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'download_directories_sync_complete' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php _e( 'Dismiss', 'woocommerce' ); ?></a>

	<p>
		<?php
		$settings_screen_link = '<a href="' . esc_url( get_admin_url( null, 'admin.php?page=wc-settings&tab=products&section=download_urls' ) ) . '">';
		$documentation_link   = '<a href="https://woocommerce.com/document/approved-download-directories">';
		$closing_link         = '</a>';

		printf(
			/* translators: %1$s and %3$s are HTML (opening link tags). %2$s is also HTML (closing link tag). */
			esc_html__( 'The %1$sApproved Product Download Directories list%2$s has been updated. To protect your site, please review the list and make any changes that might be required. For more information, please refer to %3$sthis guide%2$s.', 'woocommerce' ),
			$settings_screen_link,
			$closing_link,
			$documentation_link
		);
		?>
	</p>
</div>
PK     tS\J c  c    views/html-report-by-date.phpnu [        <?php
/**
 * Admin View: Report by Date (with date filters)
 *
 * @package WooCommerce\Admin\Reporting
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}
?>
<div id="poststuff" class="woocommerce-reports-wide">
	<div class="postbox">

	<?php if ( 'custom' === $current_range && isset( $_GET['start_date'], $_GET['end_date'] ) ) : ?>
		<h3 class="screen-reader-text">
			<?php
			/* translators: 1: start date 2: end date */
			printf(
				esc_html__( 'From %1$s to %2$s', 'woocommerce' ),
				esc_html( wc_clean( wp_unslash( $_GET['start_date'] ) ) ),
				esc_html( wc_clean( wp_unslash( $_GET['end_date'] ) ) )
			);
			?>
		</h3>
	<?php else : ?>
		<h3 class="screen-reader-text"><?php echo esc_html( $ranges[ $current_range ] ); ?></h3>
	<?php endif; ?>

		<div class="stats_range">
			<?php $this->get_export_button(); ?>
			<ul>
				<?php
				foreach ( $ranges as $range => $name ) {
					echo '<li class="' . ( $current_range == $range ? 'active' : '' ) . '"><a href="' . esc_url( remove_query_arg( array( 'start_date', 'end_date' ), add_query_arg( 'range', $range ) ) ) . '">' . esc_html( $name ) . '</a></li>';
				}
				?>
				<li class="custom <?php echo ( 'custom' === $current_range ) ? 'active' : ''; ?>">
					<?php esc_html_e( 'Custom:', 'woocommerce' ); ?>
					<form method="GET">
						<div>
							<?php
							// Maintain query string.
							foreach ( $_GET as $key => $value ) {
								if ( is_array( $value ) ) {
									foreach ( $value as $v ) {
										echo '<input type="hidden" name="' . esc_attr( sanitize_text_field( $key ) ) . '[]" value="' . esc_attr( sanitize_text_field( $v ) ) . '" />';
									}
								} else {
									echo '<input type="hidden" name="' . esc_attr( sanitize_text_field( $key ) ) . '" value="' . esc_attr( sanitize_text_field( $value ) ) . '" />';
								}
							}
							?>
							<input type="hidden" name="range" value="custom" />
							<input type="text" size="11" placeholder="yyyy-mm-dd" value="<?php echo ( ! empty( $_GET['start_date'] ) ) ? esc_attr( wp_unslash( $_GET['start_date'] ) ) : ''; ?>" name="start_date" class="range_datepicker from" autocomplete="off" /><?php //@codingStandardsIgnoreLine ?>
							<span>&ndash;</span>
							<input type="text" size="11" placeholder="yyyy-mm-dd" value="<?php echo ( ! empty( $_GET['end_date'] ) ) ? esc_attr( wp_unslash( $_GET['end_date'] ) ) : ''; ?>" name="end_date" class="range_datepicker to" autocomplete="off" /><?php //@codingStandardsIgnoreLine ?>
							<button type="submit" class="button" value="<?php esc_attr_e( 'Go', 'woocommerce' ); ?>"><?php esc_html_e( 'Go', 'woocommerce' ); ?></button>
							<?php wp_nonce_field( 'custom_range', 'wc_reports_nonce', false ); ?>
						</div>
					</form>
				</li>
			</ul>
		</div>
		<?php if ( empty( $hide_sidebar ) ) : ?>
			<div class="inside chart-with-sidebar">
				<div class="chart-sidebar">
					<?php if ( $legends = $this->get_chart_legend() ) : ?>
						<ul class="chart-legend">
							<?php foreach ( $legends as $legend ) : ?>
								<?php // @codingStandardsIgnoreStart ?>
								<li style="border-color: <?php echo $legend['color']; ?>" <?php if ( isset( $legend['highlight_series'] ) ) echo 'class="highlight_series ' . ( isset( $legend['placeholder'] ) ? 'tips' : '' ) . '" data-series="' . esc_attr( $legend['highlight_series'] ) . '"'; ?> data-tip="<?php echo isset( $legend['placeholder'] ) ? $legend['placeholder'] : ''; ?>">
									<?php echo $legend['title']; ?>
								</li>
								<?php // @codingStandardsIgnoreEnd ?>
							<?php endforeach; ?>
						</ul>
					<?php endif; ?>
					<ul class="chart-widgets">
						<?php foreach ( $this->get_chart_widgets() as $widget ) : ?>
							<li class="chart-widget">
								<?php if ( $widget['title'] ) : ?>
									<h4><?php echo esc_html( $widget['title'] ); ?></h4>
								<?php endif; ?>
								<?php call_user_func( $widget['callback'] ); ?>
							</li>
						<?php endforeach; ?>
					</ul>
				</div>
				<div class="main">
					<?php $this->get_main_chart(); ?>
				</div>
			</div>
		<?php else : ?>
			<div class="inside">
				<?php $this->get_main_chart(); ?>
			</div>
		<?php endif; ?>
	</div>
</div>
PK     tS\DjN  N  -  views/html-admin-page-addons-category-nav.phpnu [        <?php
/**
 * Admin View: Page - Addons - category navigation
 *
 * @package WooCommerce\Admin
 * @var array  $sections
 * @var string $current_section
 * @var string $current_section_name
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div id="marketplace-current-section-dropdown" class="current-section-dropdown">
	<h2 class="current-section-dropdown__title"><?php esc_html_e( 'Browse categories', 'woocommerce' ); ?></h2>
	<ul>
		<?php foreach ( $sections as $section ) : ?>
			<?php
			if ( $current_section === $section->slug && '_featured' !== $section->slug ) {
				$current_section_name = $section->label;
			}
			?>
			<?php if ( $current_section === $section->slug ) : ?>
				<li class="current">
			<?php else: ?>
				<li>
			<?php endif; ?>
			<a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-addons&section=' . esc_attr( $section->slug ) ) ); ?>">
				<?php echo esc_html( $section->label ); ?>
			</a>
			</li>
		<?php endforeach; ?>
	</ul>
	<div id="marketplace-current-section-name" class="current-section-name"><?php echo esc_html( $current_section_name ); ?></div>
</div>
PK     tS\lS    1  views/html-notice-wp-php-minimum-requirements.phpnu [        <?php
/**
 * Admin View: Notice - PHP & WP minimum requirements.
 *
 * @package WooCommerce\Admin\Notices
 */

defined( 'ABSPATH' ) || exit;
?>
<div id="message" class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', WC_PHP_MIN_REQUIREMENTS_NOTICE ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>

	<p>
		<?php
		echo wp_kses_post(
			sprintf(
				$msg . '<p><a href="%s" class="button button-primary">' . __( 'Learn how to upgrade', 'woocommerce' ) . '</a></p>',
				add_query_arg(
					array(
						'utm_source'   => 'wpphpupdatebanner',
						'utm_medium'   => 'product',
						'utm_campaign' => 'woocommerceplugin',
						'utm_content'  => 'docs',
					),
					'https://woocommerce.com/document/update-php-wordpress/'
				)
			)
		);
		?>
	</p>
</div>
PK     tS\וh    $  views/html-notice-template-check.phpnu [        <?php
/**
 * Admin View: Notice - Template Check
 *
 * @package WooCommerce\Views
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$theme = wp_get_theme();
?>
<div id="message" class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'template_files' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>

	<p>
		<?php /* translators: %s: theme name */ ?>
		<?php printf( __( '<strong>Your theme (%s) contains outdated copies of some WooCommerce template files.</strong> These files may need updating to ensure they are compatible with the current version of WooCommerce. Suggestions to fix this:', 'woocommerce' ), esc_html( $theme['Name'] ) ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?>
		<ol>
			<li><?php esc_html_e( 'Update your theme to the latest version. If no update is available contact your theme author asking about compatibility with the current WooCommerce version.', 'woocommerce' ); ?></li>
			<li><?php esc_html_e( 'If you copied over a template file to change something, then you will need to copy the new version of the template and apply your changes again.', 'woocommerce' ); ?></li>
		</ol>
	</p>
	<p class="submit">
		<a class="button-primary" href="https://woocommerce.com/document/template-structure/" target="_blank"><?php esc_html_e( 'Learn more about templates', 'woocommerce' ); ?></a>
		<a class="button-primary" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-status#status-table-templates' ) ); ?>" target="_blank"><?php esc_html_e( 'View affected templates', 'woocommerce' ); ?></a>
	</p>
</div>
PK     tS\V    %  views/html-admin-page-status-logs.phpnu [        <?php
/**
 * Admin View: Page - Status Logs
 *
 * @package WooCommerce\Admin\Logs
 */

use Automattic\WooCommerce\Utilities\LoggingUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$log_directory = LoggingUtil::get_log_directory();

?>
<?php if ( $logs ) : ?>
	<div id="log-viewer-select">
		<div class="alignleft">
			<h2>
				<?php echo esc_html( $viewed_log ); ?>
				<?php if ( ! empty( $viewed_log ) ) : ?>
					<a class="page-title-action" href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'handle' => sanitize_title( $viewed_log ) ), admin_url( 'admin.php?page=wc-status&tab=logs' ) ), 'remove_log' ) ); ?>" class="button"><?php esc_html_e( 'Delete log', 'woocommerce' ); ?></a>
				<?php endif; ?>
			</h2>
		</div>
		<div class="alignright">
			<form action="<?php echo esc_url( admin_url( 'admin.php?page=wc-status&tab=logs' ) ); ?>" method="post">
				<select class="wc-enhanced-select" name="log_file">
					<?php foreach ( $logs as $log_key => $log_file ) : ?>
						<?php
							$timestamp = filemtime( $log_directory . $log_file );
							$date      = sprintf(
								/* translators: 1: last access date 2: last access time 3: last access timezone abbreviation */
								__( '%1$s at %2$s %3$s', 'woocommerce' ),
								wp_date( wc_date_format(), $timestamp ),
								wp_date( wc_time_format(), $timestamp ),
								wp_date( 'T', $timestamp )
							);
						?>
						<option value="<?php echo esc_attr( $log_key ); ?>" <?php selected( sanitize_title( $viewed_log ), $log_key ); ?>><?php echo esc_html( $log_file ); ?> (<?php echo esc_html( $date ); ?>)</option>
					<?php endforeach; ?>
				</select>
				<button type="submit" class="button" value="<?php esc_attr_e( 'View', 'woocommerce' ); ?>"><?php esc_html_e( 'View', 'woocommerce' ); ?></button>
			</form>
		</div>
		<div class="clear"></div>
	</div>
	<div id="log-viewer">
		<pre><?php echo esc_html( file_get_contents( $log_directory . $viewed_log ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents ?></pre>
	</div>
<?php else : ?>
	<div class="updated woocommerce-message inline"><p><?php esc_html_e( 'There are currently no logs to view.', 'woocommerce' ); ?></p></div>
<?php endif; ?>
PK     tS\w       views/html-admin-page-status.phpnu [        <?php
/**
 * Admin View: Page - Status
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$current_tab = ! empty( $_REQUEST['tab'] ) ? sanitize_title( $_REQUEST['tab'] ) : 'status';
$tabs        = array(
	'status' => __( 'System status', 'woocommerce' ),
	'tools'  => __( 'Tools', 'woocommerce' ),
	'logs'   => __( 'Logs', 'woocommerce' ),
);
$tabs        = apply_filters( 'woocommerce_admin_status_tabs', $tabs );
?>
<div class="wrap woocommerce">
	<nav class="nav-tab-wrapper woo-nav-tab-wrapper">
		<?php
		foreach ( $tabs as $name => $label ) {
			echo '<a href="' . admin_url( 'admin.php?page=wc-status&tab=' . $name ) . '" class="nav-tab ';
			if ( $current_tab == $name ) {
				echo 'nav-tab-active';
			}
			echo '">' . $label . '</a>';
		}
		?>
	</nav>
	<h1 class="screen-reader-text"><?php echo esc_html( $tabs[ $current_tab ] ); ?></h1>
	<?php
	switch ( $current_tab ) {
		case 'tools':
			WC_Admin_Status::status_tools();
			break;
		case 'logs':
			WC_Admin_Status::status_logs();
			break;
		default:
			if ( array_key_exists( $current_tab, $tabs ) && has_action( 'woocommerce_admin_status_content_' . $current_tab ) ) {
				do_action( 'woocommerce_admin_status_content_' . $current_tab );
			} else {
				WC_Admin_Status::status_report();
			}
			break;
	}
	?>
</div>
PK     tS\!  !  !  views/html-quick-edit-product.phpnu [        <?php
/**
 * Admin View: Quick Edit Product
 *
 * @package WooCommerce\Admin\Notices
 */

use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;
use Automattic\WooCommerce\Enums\CatalogVisibility;
use Automattic\WooCommerce\Enums\ProductTaxStatus;

defined( 'ABSPATH' ) || exit;
?>

<fieldset class="inline-edit-col-left">
	<div id="woocommerce-fields" class="inline-edit-col">

		<h4><?php esc_html_e( 'Product data', 'woocommerce' ); ?></h4>

		<?php do_action( 'woocommerce_product_quick_edit_start' ); ?>

		<?php if ( wc_product_sku_enabled() ) : ?>

			<label>
				<span class="title"><?php esc_html_e( 'SKU', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<input type="text" name="_sku" class="text sku" value="">
				</span>
			</label>
			<br class="clear" />

		<?php endif; ?>

		<div class="price_fields">
			<label>
				<span class="title"><?php esc_html_e( 'Price', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<input type="text" name="_regular_price" class="text wc_input_price regular_price" placeholder="<?php esc_attr_e( 'Regular price', 'woocommerce' ); ?>" value="">
				</span>
			</label>
			<br class="clear" />
			<label>
				<span class="title"><?php esc_html_e( 'Sale', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<input type="text" name="_sale_price" class="text wc_input_price sale_price" placeholder="<?php esc_attr_e( 'Sale price', 'woocommerce' ); ?>" value="">
				</span>
			</label>
			<br class="clear" />
		</div>

		<?php if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() ) : ?>
			<div class="cost_fields">
				<label>
					<span class="title"><?php esc_html_e( 'Cost', 'woocommerce' ); ?></span>
					<span class="input-text-wrap">
						<input type="text" name="_cogs_value" class="text wc_input_price cogs_value" placeholder="<?php esc_attr_e( 'Cost value', 'woocommerce' ); ?>" value="">
					</span>
				</label>
				<br class="clear" />
			</div>
		<?php endif; ?>

		<?php if ( wc_tax_enabled() ) : ?>
			<label class="alignleft">
				<span class="title"><?php esc_html_e( 'Tax status', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<select class="tax_status" name="_tax_status">
						<?php
						$options = array(
							ProductTaxStatus::TAXABLE  => __( 'Taxable', 'woocommerce' ),
							ProductTaxStatus::SHIPPING => __( 'Shipping only', 'woocommerce' ),
							ProductTaxStatus::NONE     => _x( 'None', 'Tax status', 'woocommerce' ),
						);
						foreach ( $options as $key => $value ) {
							echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
						}
						?>
					</select>
				</span>
			</label>
			<br class="clear" />
			<label class="alignleft">
				<span class="title"><?php esc_html_e( 'Tax class', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<select class="tax_class" name="_tax_class">
						<?php
						$options = array(
							'' => __( 'Standard', 'woocommerce' ),
						);

						$tax_classes = WC_Tax::get_tax_classes();

						if ( ! empty( $tax_classes ) ) {
							foreach ( $tax_classes as $class ) {
								$options[ sanitize_title( $class ) ] = esc_html( $class );
							}
						}

						foreach ( $options as $key => $value ) {
							echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
						}
						?>
					</select>
				</span>
			</label>
			<br class="clear" />
		<?php endif; ?>

		<?php if ( wc_product_weight_enabled() || wc_product_dimensions_enabled() ) : ?>
		<div class="dimension_fields">

			<?php if ( wc_product_weight_enabled() ) : ?>
				<label>
					<span class="title"><?php esc_html_e( 'Weight', 'woocommerce' ); ?></span>
					<span class="input-text-wrap">
						<input type="text" name="_weight" class="text weight" placeholder="<?php echo esc_attr( wc_format_localized_decimal( 0 ) ); ?>" value="">
					</span>
				</label>
				<br class="clear" />
			<?php endif; ?>

			<?php if ( wc_product_dimensions_enabled() ) : ?>
				<div class="inline-edit-group dimensions">
					<div>
						<span class="title"><?php esc_html_e( 'L/W/H', 'woocommerce' ); ?></span>
						<span class="input-text-wrap">
							<input type="text" name="_length" class="text wc_input_decimal length" placeholder="<?php esc_attr_e( 'Length', 'woocommerce' ); ?>" value="">
							<input type="text" name="_width" class="text wc_input_decimal width" placeholder="<?php esc_attr_e( 'Width', 'woocommerce' ); ?>" value="">
							<input type="text" name="_height" class="text wc_input_decimal height" placeholder="<?php esc_attr_e( 'Height', 'woocommerce' ); ?>" value="">
						</span>
					</div>
				</div>
			<?php endif; ?>

		</div>
		<?php endif; ?>

		<div class="inline-edit-group">
			<span class="title"><?php esc_html_e( 'Shipping class', 'woocommerce' ); ?></span>
			<span class="input-text-wrap">
				<select class="shipping_class" name="_shipping_class">
					<option value="_no_shipping_class"><?php esc_html_e( 'No shipping class', 'woocommerce' ); ?></option>
					<?php
					foreach ( $shipping_class as $key => $value ) {
						echo '<option value="' . esc_attr( $value->slug ) . '">' . esc_html( $value->name ) . '</option>';
					}
					?>
				</select>
			</span>
		</div>

		<div class="inline-edit-group">
			<label class="alignleft">
				<span class="title"><?php esc_html_e( 'Visibility', 'woocommerce' ); ?></span>
				<span class="input-text-wrap">
					<select class="visibility" name="_visibility">
						<?php
						$options = apply_filters(
							'woocommerce_product_visibility_options',
							array(
								CatalogVisibility::VISIBLE => __( 'Catalog &amp; search', 'woocommerce' ),
								CatalogVisibility::CATALOG => __( 'Catalog', 'woocommerce' ),
								CatalogVisibility::SEARCH  => __( 'Search', 'woocommerce' ),
								CatalogVisibility::HIDDEN  => __( 'Hidden', 'woocommerce' ),
							)
						);
						foreach ( $options as $key => $value ) {
							echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
						}
						?>
					</select>
				</span>
			</label>
			<label class="alignleft featured">
				<input type="checkbox" name="_featured" value="1">
				<span class="checkbox-title"><?php esc_html_e( 'Featured', 'woocommerce' ); ?></span>
			</label>
		</div>

		<?php if ( get_option( 'woocommerce_manage_stock' ) === 'yes' ) : ?>
			<div class="inline-edit-group manage_stock_field">
				<label class="manage_stock">
					<input type="checkbox" name="_manage_stock" value="1">
					<span class="checkbox-title"><?php esc_html_e( 'Manage stock?', 'woocommerce' ); ?></span>
				</label>
			</div>
		<?php endif; ?>

		<label class="stock_status_field">
			<span class="title"><?php esc_html_e( 'In stock?', 'woocommerce' ); ?></span>
			<span class="input-text-wrap">
				<select class="stock_status" name="_stock_status">
					<?php
					echo '<option value="" id="stock_status_no_change">' . esc_html__( '— No Change —', 'woocommerce' ) . '</option>';
					foreach ( wc_get_product_stock_status_options() as $key => $value ) {
						echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
					}
					?>
				</select>
				<div class="wc-quick-edit-warning" style="display:none">
					<?php echo esc_html__( 'This will change the stock status of all variations.', 'woocommerce' ); ?></p>
				</div>
			</span>
		</label>

		<div class="stock_fields">
			<?php if ( get_option( 'woocommerce_manage_stock' ) === 'yes' ) : ?>
				<label class="stock_qty_field">
					<span class="title"><?php esc_html_e( 'Stock qty', 'woocommerce' ); ?></span>
					<span class="input-text-wrap">
						<input type="number" name="_stock" class="text stock" step="any" value="">
					</span>
				</label>
			<?php endif; ?>
		</div>

		<label class="alignleft backorder_field">
			<span class="title"><?php esc_html_e( 'Backorders?', 'woocommerce' ); ?></span>
			<span class="input-text-wrap">
				<select class="backorders" name="_backorders">
					<?php
					foreach ( wc_get_product_backorder_options() as $key => $value ) {
						echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
					}
					?>
				</select>
			</span>
		</label>

		<?php do_action( 'woocommerce_product_quick_edit_end' ); ?>

		<input type="hidden" name="woocommerce_quick_edit" value="1" />
		<input type="hidden" name="woocommerce_quick_edit_nonce" value="<?php echo esc_attr( wp_create_nonce( 'woocommerce_quick_edit_nonce' ) ); ?>" />
	</div>
</fieldset>
PK     tS\3CQ      views/html-admin-settings.phpnu [        <?php
/**
 * Admin View: Settings
 *
 * This file is included in WC_Admin_Settings::output().
 *
 * @package WooCommerce
 */

// phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Utilities\FeaturesUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * The current WC admin settings tab ID.
 *
 * @var string $current_tab
 */

/**
 * The current WC admin settings section ID.
 *
 * @var string $current_section
 */

$tab_exists        = isset( $tabs[ $current_tab ] ) || has_action( 'woocommerce_sections_' . $current_tab ) || has_action( 'woocommerce_settings_' . $current_tab ) || has_action( 'woocommerce_settings_tabs_' . $current_tab );
$current_tab_label = isset( $tabs[ $current_tab ] ) ? $tabs[ $current_tab ] : '';

if ( ! $tab_exists ) {
	wp_safe_redirect( admin_url( 'admin.php?page=wc-settings' ) );
	exit;
}

$hide_nav = 'checkout' === $current_tab && in_array( $current_section, array( 'offline', 'bacs', 'cheque', 'cod' ), true );

// Move 'Advanced' to the last.
if ( array_key_exists( 'advanced', $tabs ) ) {
	$advanced = $tabs['advanced'];
	unset( $tabs['advanced'] );
	// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
	$tabs['advanced'] = $advanced;
}

$marketplace_base_url = trailingslashit(
	esc_url_raw( apply_filters( 'woo_com_base_url', 'https://woocommerce.com/' ) )
) . 'product-category/woocommerce-extensions/';

$marketplace_links = array(
	'products' => array(
		'url'         => $marketplace_base_url . 'merchandising/',
		'is_external' => true,
		/* translators: %1$s: opening link tag, %2$s: closing link tag */
		'message'     => __( '%1$sExplore solutions%2$s that help highlight products and drive more sales.', 'woocommerce' ),
	),
	'tax'      => array(
		'url'         => $marketplace_base_url . 'operations/sales-tax-and-duties/',
		'is_external' => true,
		/* translators: %1$s: opening link tag, %2$s: closing link tag */
		'message'     => __( '%1$sExplore solutions%2$s that help with tax calculations, compliance, and regional requirements.', 'woocommerce' ),
	),
	'shipping' => array(
		'url'         => $marketplace_base_url . 'shipping-delivery-and-fulfillment/',
		'is_external' => true,
		/* translators: %1$s: opening link tag, %2$s: closing link tag */
		'message'     => __( '%1$sExplore solutions%2$s that enhance shipping, delivery, and fulfillment workflows.', 'woocommerce' ),
	),
	'account'  => array(
		'url'         => $marketplace_base_url . 'store-content-and-customizations/cart-and-checkout-features/',
		'is_external' => true,
		/* translators: %1$s: opening link tag, %2$s: closing link tag */
		'message'     => __( '%1$sExplore solutions%2$s that help customize cart and checkout flows.', 'woocommerce' ),
	),
	'email'    => array(
		'url'         => $marketplace_base_url . 'marketing-extensions/email-marketing-extensions/',
		'is_external' => true,
		/* translators: %1$s: opening link tag, %2$s: closing link tag */
		'message'     => __( '%1$sExplore solutions%2$s that help automate and improve customer email communication.', 'woocommerce' ),
	),
	'general'  => array(
		'url'         => admin_url( 'admin.php?page=wc-admin&path=%2Fextensions' ),
		'is_external' => false,
		/* translators: %1$s: opening link tag, %2$s: closing link tag */
		'message'     => __( '%1$sDiscover additional solutions%2$s to boost your business and expand what your store can do.', 'woocommerce' ),
	),
);

?>

<div class="wrap woocommerce">
	<?php do_action( 'woocommerce_before_settings_' . $current_tab ); ?>
	<form method="<?php echo esc_attr( apply_filters( 'woocommerce_settings_form_method_tab_' . $current_tab, 'post' ) ); ?>" id="mainform" action="" enctype="multipart/form-data">
		<?php if ( ! $hide_nav ) : ?>
			<nav class="nav-tab-wrapper woo-nav-tab-wrapper">
				<?php

				foreach ( $tabs as $slug => $label ) {
					echo '<a href="' . esc_html( admin_url( 'admin.php?page=wc-settings&tab=' . esc_attr( $slug ) ) ) . '" class="nav-tab ' . ( $current_tab === $slug ? 'nav-tab-active' : '' ) . '">' . esc_html( $label ) . '</a>';
				}

				/**
				 * Hook for adding additional settings tabs.
				 *
				 * @since 1.0.0
				 */
				do_action( 'woocommerce_settings_tabs' );

				?>
			</nav>
		<?php endif; ?>
			<h1 class="screen-reader-text"><?php echo esc_html( $current_tab_label ); ?></h1>
			<?php
				do_action( 'woocommerce_sections_' . $current_tab );

				WC_Admin_Settings::show_messages();

				do_action( 'woocommerce_settings_' . $current_tab );
				do_action( 'woocommerce_settings_tabs_' . $current_tab ); // @deprecated 3.4.0 hook.
			?>
			<p class="submit">
				<?php if ( empty( $GLOBALS['hide_save_button'] ) ) : ?>
					<button name="save" disabled class="woocommerce-save-button components-button is-primary" type="submit" value="<?php esc_attr_e( 'Save changes', 'woocommerce' ); ?>"><?php esc_html_e( 'Save changes', 'woocommerce' ); ?></button>
				<?php endif; ?>
				<?php wp_nonce_field( 'woocommerce-settings' ); ?>
			</p>
			<?php if ( isset( $marketplace_links[ $current_tab ] ) ) : ?>
				<?php
				$link_config = $marketplace_links[ $current_tab ];

				if ( $link_config['is_external'] ) {
					$utm_source    = 'settings_' . $current_tab . ( $current_section ? '_' . $current_section : '' );
					$link_url      = add_query_arg( 'utm_source', $utm_source, $link_config['url'] );
					$icon_url      = WC()->plugin_url() . '/assets/images/icons/external-link.svg';
					$external_icon = '<img src="' . esc_url( $icon_url ) . '" alt="" />';
					$screen_reader = '<span class="screen-reader-text">' . esc_html__( '(opens in a new tab)', 'woocommerce' ) . '</span>';
					$link_open     = '<a href="' . esc_url( $link_url ) . '" target="_blank" rel="noopener noreferrer">' . $external_icon;
					$link_close    = $screen_reader . '</a>';
				} else {
					$link_open  = '<a href="' . esc_url( $link_config['url'] ) . '">';
					$link_close = '</a>';
				}
				?>
			<p class="wc-settings-marketplace-link" data-settings-tab="<?php echo esc_attr( $current_tab ); ?>"<?php echo $current_section ? ' data-settings-section="' . esc_attr( $current_section ) . '"' : ''; ?>>
				<?php
				echo wp_kses(
					sprintf( $link_config['message'], $link_open, $link_close ),
					array(
						'a'    => array(
							'href'   => array(),
							'target' => array(),
							'rel'    => array(),
						),
						'img'  => array(
							'src' => array(),
							'alt' => array(),
						),
						'span' => array(
							'class' => array(),
						),
					)
				);
				?>
			</p>
			<?php endif; ?>
	</form>
	<?php do_action( 'woocommerce_after_settings_' . $current_tab ); ?>
</div>
PK     tS\Q      views/html-notice-install.phpnu [        <?php
/**
 * Admin View: Notice - Install
 *
 * @deprecated 4.6.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

?>
<div id="message" class="updated woocommerce-message wc-connect">
	<p><?php _e( '<strong>Welcome to WooCommerce</strong> &#8211; You&lsquo;re almost ready to start selling :)', 'woocommerce' ); ?></p>
	<p class="submit"><a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-setup' ) ); ?>" class="button-primary"><?php _e( 'Run the Setup Wizard', 'woocommerce' ); ?></a> <a class="button-secondary skip" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'install' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php _e( 'Skip setup', 'woocommerce' ); ?></a></p>
</div>
PK     tS\:hj  j  -  views/html-notice-regenerating-thumbnails.phpnu [        <?php
/**
 * Admin View: Notice - Regenerating thumbnails.
 */

defined( 'ABSPATH' ) || exit;

?>
<div id="message" class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'regenerating_thumbnails' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php _e( 'Cancel thumbnail regeneration', 'woocommerce' ); ?></a>

	<p><?php esc_html_e( 'Thumbnail regeneration is running in the background. Depending on the amount of images in your store this may take a while.', 'woocommerce' ); ?></p>
</div>
PK     tS\Y48      views/html-notice-custom.phpnu [        <?php
/**
 * Admin View: Custom Notices
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

?>
<div id="message" class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', $notice ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php _e( 'Dismiss', 'woocommerce' ); ?></a>
	<?php echo wp_kses_post( wpautop( $notice_html ) ); ?>
</div>
PK     tS\G    &  views/html-admin-page-status-tools.phpnu [        <?php
/**
 * Admin View: Page - Status Tools
 *
 * @package WooCommerce
 */

use Automattic\WooCommerce\Utilities\ArrayUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

foreach ( $tools as $action_name => $tool ) {
	?>
	<form id="<?php echo esc_attr( 'form_' . $action_name ); ?>" method="GET" action="<?php echo esc_attr( esc_url( admin_url( 'admin.php?foo=bar' ) ) ); ?>">
		<?php wp_nonce_field( 'debug_action', '_wpnonce', false ); ?>
		<input type="hidden" name="page" value="wc-status"/>
		<input type="hidden" name="tab" value="tools"/>
		<input type="hidden" name="action" value="<?php echo esc_attr( $action_name ); ?>"/>
	</form>
	<?php
}
?>

<table class="wc_status_table wc_status_table--tools widefat" cellspacing="0">
	<tbody class="tools">
		<?php foreach ( $tools as $action_name => $tool ) : ?>
			<tr class="<?php echo sanitize_html_class( $action_name ); ?>">
				<th>
					<strong class="name"><?php echo esc_html( $tool['name'] ); ?></strong>
					<p class="description">
						<?php
						echo wp_kses_post( $tool['desc'] );
						if ( ! is_null( ArrayUtil::get_value_or_default( $tool, 'selector' ) ) ) {
							$selector = $tool['selector'];
							if ( isset( $selector['description'] ) ) {
								echo '</p><p class="description">';
								echo wp_kses_post( $selector['description'] );
							}
							// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
							echo "&nbsp;&nbsp;<select style='width: 300px;' form='form_$action_name' id='selector_$action_name' data-allow_clear='true' class='{$selector['class']}' name='{$selector['name']}' data-placeholder='{$selector['placeholder']}' data-action='{$selector['search_action']}'></select>";
						}
						?>
					</p>
				</th>
				<td class="run-tool">
					<?php if ( ! empty( $tool['status_text'] ) ) : ?>
					<span class="run-tool-status"><?php echo wp_kses_post( $tool['status_text'] ); ?></span>
					<?php endif; ?>

					<?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
					<input <?php echo ArrayUtil::is_truthy( $tool, 'disabled' ) ? 'disabled' : ''; ?> type="submit" form="<?php echo 'form_' . $action_name; ?>" class="button button-large" value="<?php echo esc_attr( $tool['button'] ); ?>" />
				</td>
			</tr>
		<?php endforeach; ?>
	</tbody>
</table>
PK     tS\cW    )  views/html-notice-maxmind-license-key.phpnu [        <?php
/**
 * Admin View: Notice - Missing MaxMind license key
 *
 * @package WooCommerce\Admin
 */

defined( 'ABSPATH' ) || exit;

?>

<div id="message" class="updated woocommerce-message">
	<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'maxmind_license_key' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>

	<p>
		<strong><?php esc_html_e( 'Geolocation has not been configured.', 'woocommerce' ); ?></strong>
	</p>

	<p>
		<?php
		echo wp_kses_post(
			sprintf(
				/* translators: %1%s: integration page %2$s: general settings page */
				__( 'You must enter a valid license key on the <a href="%1$s">MaxMind integration settings page</a> in order to use the geolocation service. If you do not need geolocation for shipping or taxes, you should change the default customer location on the <a href="%2$s">general settings page</a>.', 'woocommerce' ),
				admin_url( 'admin.php?page=wc-settings&tab=integration&section=maxmind_geolocation' ),
				admin_url( 'admin.php?page=wc-settings&tab=general' )
			)
		);
		?>
	</p>
</div>
PK     tS\wLj      class-wc-admin-exporters.phpnu [        <?php
/**
 * Init WooCommerce data exporters.
 *
 * @package     WooCommerce\Admin
 * @version     x.x.x
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Enums\ProductType;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Admin_Exporters Class.
 */
class WC_Admin_Exporters {

	/**
	 * Array of exporter IDs.
	 *
	 * @var string[]
	 */
	protected $exporters = array();

	/**
	 * Constructor.
	 */
	public function __construct() {
		if ( ! $this->export_allowed() ) {
			return;
		}

		add_action( 'admin_menu', array( $this, 'add_to_menus' ) );
		add_action( 'admin_head', array( $this, 'hide_from_menus' ) );
		add_action( 'admin_head', array( $this, 'menu_highlight_for_product_export' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
		add_action( 'admin_init', array( $this, 'download_export_file' ) );
		add_action( 'wp_ajax_woocommerce_do_ajax_product_export', array( $this, 'do_ajax_product_export' ) );

		// Register WooCommerce exporters.
		$this->exporters['product_exporter'] = array(
			'menu'       => 'edit.php?post_type=product',
			'name'       => __( 'Product Export', 'woocommerce' ),
			'capability' => 'export',
			'callback'   => array( $this, 'product_exporter' ),
		);
	}

	/**
	 * Return true if WooCommerce export is allowed for current user, false otherwise.
	 *
	 * @return bool Whether current user can perform export.
	 */
	protected function export_allowed() {
		return current_user_can( 'edit_products' ) && current_user_can( 'export' );
	}

	/**
	 * Add menu items for our custom exporters.
	 */
	public function add_to_menus() {
		foreach ( $this->exporters as $id => $exporter ) {
			add_submenu_page( $exporter['menu'], $exporter['name'], $exporter['name'], $exporter['capability'], $id, $exporter['callback'] );
		}
	}

	/**
	 * Hide menu items from view so the pages exist, but the menu items do not.
	 */
	public function hide_from_menus() {
		global $submenu;

		foreach ( $this->exporters as $id => $exporter ) {
			if ( isset( $submenu[ $exporter['menu'] ] ) ) {
				foreach ( $submenu[ $exporter['menu'] ] as $key => $menu ) {
					if ( $id === $menu[2] ) {
						unset( $submenu[ $exporter['menu'] ][ $key ] );
					}
				}
			}
		}
	}

	/**
	 * Highlight Products > All Products submenu for Product Exporter.
	 */
	public function menu_highlight_for_product_export() {
		global $submenu_file;

		$screen = get_current_screen();

		if ( $screen && 'product_page_product_exporter' === $screen->id ) {
			$submenu_file = 'edit.php?post_type=product'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
		}
	}

	/**
	 * Enqueue scripts.
	 */
	public function admin_scripts() {
		$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
		$version = Constants::get_constant( 'WC_VERSION' );
		wp_register_script( 'wc-product-export', WC()->plugin_url() . '/assets/js/admin/wc-product-export' . $suffix . '.js', array( 'jquery' ), $version );
		wp_localize_script(
			'wc-product-export',
			'wc_product_export_params',
			array(
				'export_nonce' => wp_create_nonce( 'wc-product-export' ),
			)
		);
	}

	/**
	 * Export page UI.
	 */
	public function product_exporter() {
		include_once WC_ABSPATH . 'includes/export/class-wc-product-csv-exporter.php';
		include_once dirname( __FILE__ ) . '/views/html-admin-page-product-export.php';
	}

	/**
	 * Serve the generated file.
	 */
	public function download_export_file() {
		if ( isset( $_GET['action'], $_GET['nonce'] ) && wp_verify_nonce( wp_unslash( $_GET['nonce'] ), 'product-csv' ) && 'download_product_csv' === wp_unslash( $_GET['action'] ) ) { // WPCS: input var ok, sanitization ok.
			include_once WC_ABSPATH . 'includes/export/class-wc-product-csv-exporter.php';
			$exporter = new WC_Product_CSV_Exporter();

			if ( ! empty( $_GET['filename'] ) ) { // WPCS: input var ok.
				$exporter->set_filename( wp_unslash( $_GET['filename'] ) ); // WPCS: input var ok, sanitization ok.
			}

			$exporter->export();
		}
	}

	/**
	 * AJAX callback for doing the actual export to the CSV file.
	 */
	public function do_ajax_product_export() {
		check_ajax_referer( 'wc-product-export', 'security' );

		if ( ! $this->export_allowed() ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient privileges to export products.', 'woocommerce' ) ) );
		}

		include_once WC_ABSPATH . 'includes/export/class-wc-product-csv-exporter.php';

		$step     = isset( $_POST['step'] ) ? absint( $_POST['step'] ) : 1; // WPCS: input var ok, sanitization ok.
		$exporter = new WC_Product_CSV_Exporter();

		if ( ! empty( $_POST['columns'] ) ) { // WPCS: input var ok.
			$exporter->set_column_names( wp_unslash( $_POST['columns'] ) ); // WPCS: input var ok, sanitization ok.
		}

		if ( ! empty( $_POST['selected_columns'] ) ) { // WPCS: input var ok.
			$exporter->set_columns_to_export( wp_unslash( $_POST['selected_columns'] ) ); // WPCS: input var ok, sanitization ok.
		}

		if ( ! empty( $_POST['export_meta'] ) ) { // WPCS: input var ok.
			$exporter->enable_meta_export( true );
		}

		if ( ! empty( $_POST['export_types'] ) ) { // WPCS: input var ok.
			$exporter->set_product_types_to_export( wp_unslash( $_POST['export_types'] ) ); // WPCS: input var ok, sanitization ok.
		}

		if ( ! empty( $_POST['export_category'] ) && is_array( $_POST['export_category'] ) ) {// WPCS: input var ok.
			$exporter->set_product_category_to_export( wp_unslash( array_values( $_POST['export_category'] ) ) ); // WPCS: input var ok, sanitization ok.
		}

		// Set specific product IDs if provided.
		if ( ! empty( $_POST['export_product_ids'] ) ) { // WPCS: input var ok.
			$ids_raw = explode( ',', sanitize_text_field( wp_unslash( $_POST['export_product_ids'] ) ) ); // WPCS: input var ok, sanitization ok.

			if ( ! empty( $ids_raw ) ) {
				$exporter->set_product_ids_to_export( $ids_raw );
			}
		}

		if ( ! empty( $_POST['filename'] ) ) { // WPCS: input var ok.
			$exporter->set_filename( wp_unslash( $_POST['filename'] ) ); // WPCS: input var ok, sanitization ok.
		}

		$exporter->set_page( $step );
		$exporter->generate_file();

		$query_args = apply_filters(
			'woocommerce_export_get_ajax_query_args',
			array(
				'nonce'    => wp_create_nonce( 'product-csv' ),
				'action'   => 'download_product_csv',
				'filename' => $exporter->get_filename(),
			)
		);

		if ( 100 === $exporter->get_percent_complete() ) {
			wp_send_json_success(
				array(
					'step'       => 'done',
					'percentage' => 100,
					'url'        => add_query_arg( $query_args, admin_url( 'edit.php?post_type=product&page=product_exporter' ) ),
				)
			);
		} else {
			wp_send_json_success(
				array(
					'step'       => ++$step,
					'percentage' => $exporter->get_percent_complete(),
					'columns'    => $exporter->get_column_names(),
				)
			);
		}
	}

	/**
	 * Gets the product types that can be exported.
	 *
	 * @since 5.1.0
	 * @return array The product types keys and labels.
	 */
	public static function get_product_types() {
		$product_types                           = wc_get_product_types();
		$product_types[ ProductType::VARIATION ] = __( 'Product variations', 'woocommerce' );

		/**
		 * Allow third-parties to filter the exportable product types.
		 *
		 * @since 5.1.0
		 * @param array $product_types {
		 *     The product type key and label.
		 *
		 *     @type string Product type key - eg 'variable', 'simple' etc.
		 *     @type string A translated product label which appears in the export product type dropdown.
		 * }
		 */
		return apply_filters( 'woocommerce_exporter_product_types', $product_types );
	}
}

new WC_Admin_Exporters();
PK     tS\#p  p    class-wc-admin-dashboard.phpnu [        <?php
/**
 * Admin Dashboard
 *
 * @package     WooCommerce\Admin
 * @version     2.1.0
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Enums\OrderInternalStatus;
use Automattic\WooCommerce\Utilities\OrderUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :

	/**
	 * WC_Admin_Dashboard Class.
	 */
	class WC_Admin_Dashboard {

		/**
		 * Hook in tabs.
		 */
		public function __construct() {
			// Only hook in admin parts if the user has admin access.
			if ( $this->should_display_widget() ) {
				// If on network admin, only load the widget that works in that context and skip the rest.
				if ( is_multisite() && is_network_admin() ) {
					add_action( 'wp_network_dashboard_setup', array( $this, 'register_network_order_widget' ) );
				} else {
					add_action( 'wp_dashboard_setup', array( $this, 'init' ) );
				}
			}
		}

		/**
		 * Init dashboard widgets.
		 */
		public function init() {
			// Reviews Widget.
			if ( current_user_can( 'publish_shop_orders' ) && post_type_supports( 'product', 'comments' ) ) {
				wp_add_dashboard_widget( 'woocommerce_dashboard_recent_reviews', __( 'WooCommerce Recent Reviews', 'woocommerce' ), array( $this, 'recent_reviews' ) );
			}
			wp_add_dashboard_widget( 'woocommerce_dashboard_status', __( 'WooCommerce Status', 'woocommerce' ), array( $this, 'status_widget' ) );

			// Network Order Widget.
			if ( is_multisite() && is_main_site() ) {
				$this->register_network_order_widget();
			}
		}

		/**
		 * Register the network order dashboard widget.
		 */
		public function register_network_order_widget() {
			wp_add_dashboard_widget( 'woocommerce_network_orders', __( 'WooCommerce Network Orders', 'woocommerce' ), array( $this, 'network_orders' ) );
		}

		/**
		 * Check to see if we should display the widget.
		 *
		 * @return bool
		 */
		private function should_display_widget() {
			if ( ! WC()->is_wc_admin_active() ) {
				return false;
			}

			$has_permission           = current_user_can( 'view_woocommerce_reports' ) || current_user_can( 'manage_woocommerce' ) || current_user_can( 'publish_shop_orders' );
			$task_completed_or_hidden = 'yes' === get_option( 'woocommerce_task_list_complete' ) || 'yes' === get_option( 'woocommerce_task_list_hidden' );
			return $task_completed_or_hidden && $has_permission;
		}

		/**
		 * Get top seller from DB.
		 *
		 * @return object
		 */
		private function get_top_seller() {
			global $wpdb;

			$hpos_enabled         = OrderUtil::custom_orders_table_usage_is_enabled();
			$orders_table         = OrderUtil::get_table_for_orders();
			$orders_column_id     = $hpos_enabled ? 'id' : 'ID';
			$orders_column_type   = $hpos_enabled ? 'type' : 'post_type';
			$orders_column_status = $hpos_enabled ? 'status' : 'post_status';
			$orders_column_date   = $hpos_enabled ? 'date_created_gmt' : 'post_date_gmt';

			$query           = array();
			$query['fields'] = "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id FROM {$orders_table} AS orders";
			$query['join']   = "INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON orders.{$orders_column_id} = order_id ";
			$query['join']  .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id ";
			$query['join']  .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id ";
			$query['where']  = "WHERE orders.{$orders_column_type} IN ( '" . implode( "','", wc_get_order_types( 'order-count' ) ) . "' ) ";

			/**
			 * Allows modifying the order statuses used in the top seller query inside the dashboard status widget.
			 *
			 * @since 2.2.0
			 *
			 * @param string[] $order_statuses Order statuses.
			 */
			$order_statuses  = apply_filters( 'woocommerce_reports_order_statuses', array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD ) );
			$query['where'] .= "AND orders.{$orders_column_status} IN ( 'wc-" . implode( "','wc-", $order_statuses ) . "' ) ";

			$query['where']  .= "AND order_item_meta.meta_key = '_qty' ";
			$query['where']  .= "AND order_item_meta_2.meta_key = '_product_id' ";
			$query['where']  .= "AND orders.{$orders_column_date} >= '" . gmdate( 'Y-m-01', current_time( 'timestamp' ) ) . "' "; // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
			$query['where']  .= "AND orders.{$orders_column_date} <= '" . gmdate( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) . "' "; // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
			$query['groupby'] = 'GROUP BY product_id';
			$query['orderby'] = 'ORDER BY qty DESC';
			$query['limits']  = 'LIMIT 1';

			/**
			 * Allows modification of the query to determine the top seller product in the dashboard status widget.
			 *
			 * @since 2.2.0
			 *
			 * @param array $query SQL query parts.
			 */
			$query = apply_filters( 'woocommerce_dashboard_status_widget_top_seller_query', $query );

			$sql = implode( ' ', $query );
			return $wpdb->get_row( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
		}

		/**
		 * Show status widget.
		 */
		public function status_widget() {
			$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
			$version = Constants::get_constant( 'WC_VERSION' );

			wp_enqueue_script( 'wc-status-widget', WC()->plugin_url() . '/assets/js/admin/wc-status-widget' . $suffix . '.js', array( 'jquery', 'wc-flot' ), $version, true );
			wp_enqueue_script( 'wc-status-widget-async', WC()->plugin_url() . '/assets/js/admin/wc-status-widget-async' . $suffix . '.js', array( 'jquery' ), $version, true );

			wp_localize_script(
				'wc-status-widget-async',
				'wc_status_widget_params',
				array(
					'ajax_url'      => admin_url( 'admin-ajax.php' ),
					'security'      => wp_create_nonce( 'wc-status-widget' ),
					'error_message' => esc_html__( 'Error loading widget', 'woocommerce' ),
				)
			);

			// Display loading placeholder.
			echo '<div id="wc-status-widget-loading" class="wc-status-widget-loading">';
			echo '<p>' . esc_html__( 'Loading status data...', 'woocommerce' ) . ' <span class="spinner is-active"></span></p>';
			echo '</div>';
			echo '<div id="wc-status-widget-content" style="display:none;"></div>';
		}

		/**
		 * Generate the actual status widget content.
		 * This contains the original content of the status_widget() method.
		 */
		public function status_widget_content() {
			//phpcs:ignore
			$is_wc_admin_disabled = apply_filters( 'woocommerce_admin_disabled', false ) || ! Features::is_enabled( 'analytics' );

			$status_widget_reports = array(
				'net_sales_link'      => 'admin.php?page=wc-admin&path=%2Fanalytics%2Frevenue&chart=net_revenue&orderby=net_revenue&period=month&compare=previous_period',
				'top_seller_link'     => 'admin.php?page=wc-admin&filter=single_product&path=%2Fanalytics%2Fproducts&products=',
				'lowstock_link'       => 'admin.php?page=wc-admin&type=lowstock&path=%2Fanalytics%2Fstock',
				'outofstock_link'     => 'admin.php?page=wc-admin&type=outofstock&path=%2Fanalytics%2Fstock',
				'report_data'         => null,
				'get_sales_sparkline' => array( $this, 'get_sales_sparkline' ),
			);

			if ( $is_wc_admin_disabled ) {
				/**
				 * Filter to change the reports of the status widget on the Dashboard page.
				 *
				 * Please note that this filter is mainly for backward compatibility with the legacy reports.
				 * It's not recommended to use this filter to change the data of this widget.
				 *
				 * @since 9.5.0
				 */
				$status_widget_reports = apply_filters( 'woocommerce_dashboard_status_widget_reports', $status_widget_reports );
			} else {
				$status_widget_reports['report_data'] = $this->get_wc_admin_performance_data();
			}

			echo '<ul class="wc_status_list">';

			if ( current_user_can( 'view_woocommerce_reports' ) ) {
				$report_data         = $status_widget_reports['report_data'];
				$get_sales_sparkline = $status_widget_reports['get_sales_sparkline'];
				$net_sales_link      = $status_widget_reports['net_sales_link'];
				$top_seller_link     = $status_widget_reports['top_seller_link'];

				$days = max( 7, (int) gmdate( 'd', current_time( 'timestamp' ) ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested

				$sparkline_allowed_html = array(
					'span' => array(
						'class'          => array(),
						'data-color'     => array(),
						'data-tip'       => array(),
						'data-barwidth'  => array(),
						'data-sparkline' => array(),
					),
				);

				if ( $report_data && is_callable( $get_sales_sparkline ) ) {
					$sparkline = call_user_func_array( $get_sales_sparkline, array( '', $days ) );
					$sparkline = $this->sales_sparkline_markup( 'sales', $days, $sparkline['total'], $sparkline['data'] );
					?>
				<li class="sales-this-month">
				<a href="<?php echo esc_url( admin_url( $net_sales_link ) ); ?>">
					<?php echo wp_kses( $sparkline, $sparkline_allowed_html ); ?>
					<?php
						printf(
							/* translators: %s: net sales */
							esc_html__( '%s net sales this month', 'woocommerce' ),
							'<strong>' . wc_price( $report_data->net_sales ) . '</strong>'
						); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
					?>
					</a>
				</li>
					<?php
				}

				$top_seller = $this->get_top_seller();
				if ( $top_seller && $top_seller->qty && is_callable( $get_sales_sparkline ) ) {
					$sparkline = call_user_func_array( $get_sales_sparkline, array( $top_seller->product_id, $days, 'count' ) );
					$sparkline = $this->sales_sparkline_markup( 'count', $days, $sparkline['total'], $sparkline['data'] );
					?>
				<li class="best-seller-this-month">
				<a href="<?php echo esc_url( admin_url( $top_seller_link . $top_seller->product_id ) ); ?>">
					<?php echo wp_kses( $sparkline, $sparkline_allowed_html ); ?>
					<?php
						printf(
							/* translators: 1: top seller product title 2: top seller quantity */
							esc_html__( '%1$s top seller this month (sold %2$d)', 'woocommerce' ),
							'<strong>' . get_the_title( $top_seller->product_id ) . '</strong>',
							$top_seller->qty
						); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
					?>
					</a>
				</li>
					<?php
				}
			}

			$this->status_widget_order_rows();
			if ( get_option( 'woocommerce_manage_stock' ) === 'yes' ) {
				$this->status_widget_stock_rows( $status_widget_reports['lowstock_link'], $status_widget_reports['outofstock_link'] );
			}

			/**
			 * Filter to change the first argument passed to the `woocommerce_after_dashboard_status_widget` action.
			 *
			 * Please note that this filter is mainly for backward compatibility with the legacy reports.
			 * It's not recommended to use this filter as it will soon be deprecated along with the retiring of the legacy reports.
			 *
			 * @since 9.5.0
			 */
			$reports = apply_filters( 'woocommerce_after_dashboard_status_widget_parameter', null );
			do_action( 'woocommerce_after_dashboard_status_widget', $reports );
			echo '</ul>';
		}

		/**
		 * Show order data is status widget.
		 */
		private function status_widget_order_rows() {
			if ( ! current_user_can( 'edit_shop_orders' ) ) {
				return;
			}
			$on_hold_count    = 0;
			$processing_count = 0;

			foreach ( wc_get_order_types( 'order-count' ) as $type ) {
				$counts            = OrderUtil::get_count_for_type( $type );
				$on_hold_count    += $counts[ OrderInternalStatus::ON_HOLD ];
				$processing_count += $counts[ OrderInternalStatus::PROCESSING ];
			}
			?>
			<li class="processing-orders">
			<a href="<?php echo esc_url( admin_url( 'edit.php?post_status=wc-processing&post_type=shop_order' ) ); ?>">
				<?php
					printf(
						/* translators: %s: order count */
						_n( '<strong>%s order</strong> awaiting processing', '<strong>%s orders</strong> awaiting processing', $processing_count, 'woocommerce' ),
						$processing_count
					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
				?>
				</a>
			</li>
			<li class="on-hold-orders">
				<a href="<?php echo esc_url( admin_url( 'edit.php?post_status=wc-on-hold&post_type=shop_order' ) ); ?>">
				<?php
					printf(
						/* translators: %s: order count */
						_n( '<strong>%s order</strong> on-hold', '<strong>%s orders</strong> on-hold', $on_hold_count, 'woocommerce' ),
						$on_hold_count
					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
				?>
				</a>
			</li>
			<?php
		}

		/**
		 * Show stock data is status widget.
		 *
		 * @param string $lowstock_link Low stock link.
		 * @param string $outofstock_link Out of stock link.
		 */
		private function status_widget_stock_rows( $lowstock_link, $outofstock_link ) {
			global $wpdb;

			// Requires lookup table added in 3.6.
			if ( version_compare( get_option( 'woocommerce_db_version', null ), '3.6', '<' ) ) {
				return;
			}

			$stock   = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
			$nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );

			$transient_name   = 'wc_low_stock_count';
			$lowinstock_count = get_transient( $transient_name );

			if ( false === $lowinstock_count ) {
				/**
				 * Status widget low in stock count pre query.
				 *
				 * @since 4.3.0
				 * @param null|string $low_in_stock_count Low in stock count, by default null.
				 * @param int         $stock              Low stock amount.
				 * @param int         $nostock            No stock amount
				 */
				$lowinstock_count = apply_filters( 'woocommerce_status_widget_low_in_stock_count_pre_query', null, $stock, $nostock );

				if ( is_null( $lowinstock_count ) ) {
					$lowinstock_count = $wpdb->get_var(
						$wpdb->prepare(
							"SELECT COUNT( product_id )
							FROM {$wpdb->wc_product_meta_lookup} AS lookup
							INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID
							WHERE stock_quantity <= %d
							AND stock_quantity > %d
							AND posts.post_status = 'publish'",
							$stock,
							$nostock
						)
					);
				}

				set_transient( $transient_name, (int) $lowinstock_count, DAY_IN_SECONDS * 30 );
			}

			$transient_name   = 'wc_outofstock_count';
			$outofstock_count = get_transient( $transient_name );
			$lowstock_url     = $lowstock_link ? admin_url( $lowstock_link ) : '#';
			$outofstock_url   = $outofstock_link ? admin_url( $outofstock_link ) : '#';

			if ( false === $outofstock_count ) {
				/**
				 * Status widget out of stock count pre query.
				 *
				 * @since 4.3.0
				 * @param null|string $outofstock_count Out of stock count, by default null.
				 * @param int         $nostock          No stock amount
				 */
				$outofstock_count = apply_filters( 'woocommerce_status_widget_out_of_stock_count_pre_query', null, $nostock );

				if ( is_null( $outofstock_count ) ) {
					$outofstock_count = (int) $wpdb->get_var(
						$wpdb->prepare(
							"SELECT COUNT( product_id )
							FROM {$wpdb->wc_product_meta_lookup} AS lookup
							INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID
							WHERE stock_quantity <= %d
							AND posts.post_status = 'publish'",
							$nostock
						)
					);
				}

				set_transient( $transient_name, (int) $outofstock_count, DAY_IN_SECONDS * 30 );
			}
			?>
			<li class="low-in-stock">
				<a href="<?php echo esc_url( $lowstock_url ); ?>">
				<?php
					printf(
						/* translators: %s: order count */
						_n( '<strong>%s product</strong> low in stock', '<strong>%s products</strong> low in stock', $lowinstock_count, 'woocommerce' ),
						$lowinstock_count
					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
				?>
				</a>
			</li>
			<li class="out-of-stock">
				<a href="<?php echo esc_url( $outofstock_url ); ?>">
				<?php
					printf(
						/* translators: %s: order count */
						_n( '<strong>%s product</strong> out of stock', '<strong>%s products</strong> out of stock', $outofstock_count, 'woocommerce' ),
						$outofstock_count
					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
				?>
				</a>
			</li>
			<?php
		}

		/**
		 * Recent reviews widget: legacy implementation.
		 */
		private function legacy_recent_reviews(): void {
			global $wpdb;

			/**
			 * Filters the from-clause used for fetching latest product reviews.
			 *
			 * @since 3.1.0
			 *
			 * @param string $clause The from-clause.
			 */
			$query_from = apply_filters(
				'woocommerce_report_recent_reviews_query_from',
				"FROM {$wpdb->comments} comments
				LEFT JOIN {$wpdb->posts} posts ON (comments.comment_post_ID = posts.ID)
				WHERE comments.comment_approved = '1'
				AND comments.comment_type = 'review'
				AND posts.post_password = ''
				AND posts.post_type = 'product'
				AND comments.comment_parent = 0
				ORDER BY comments.comment_date_gmt DESC
				LIMIT 5"
			);

			$comments = $wpdb->get_results(
				"SELECT posts.ID, posts.post_title, comments.comment_author, comments.comment_author_email, comments.comment_ID, comments.comment_content {$query_from};" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			);

			if ( $comments ) {
				echo '<ul>';
				foreach ( $comments as $comment ) {

					echo '<li>';

					echo get_avatar( $comment->comment_author_email, '32' );

					/**
					 * Filters the product name for display in the latest reviews.
					 *
					 * @param string    $product_title The product name.
					 * @param \stdClass $comment      The comment.
					 * @since 2.1.0
					 */
					$product_title = apply_filters( 'woocommerce_admin_dashboard_recent_reviews', $comment->post_title, $comment );
					$rating        = intval( get_comment_meta( $comment->comment_ID, 'rating', true ) );

					/* translators: %s: rating */
					echo '<div class="star-rating"><span style="width:' . esc_attr( $rating * 20 ) . '%">' . sprintf( esc_html__( '%s out of 5', 'woocommerce' ), esc_html( $rating ) ) . '</span></div>';

					/* translators: %s: review author */
					echo '<h4 class="meta"><a href="' . esc_url( get_permalink( $comment->ID ) ) . '#comment-' . esc_attr( absint( $comment->comment_ID ) ) . '">' . esc_html( $product_title ) . '</a> ' . sprintf( esc_html__( 'reviewed by %s', 'woocommerce' ), esc_html( $comment->comment_author ) ) . '</h4>';
					echo '<blockquote>' . wp_kses_data( $comment->comment_content ) . '</blockquote></li>';

				}
				echo '</ul>';
			} else {
				echo '<p>' . esc_html__( 'There are no product reviews yet.', 'woocommerce' ) . '</p>';
			}
		}

		/**
		 * Recent reviews widget: placeholder.
		 */
		public function recent_reviews() {
			$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
			$version = Constants::get_constant( 'WC_VERSION' );

			wp_enqueue_script( 'wc-recent-reviews-widget-async', WC()->plugin_url() . '/assets/js/admin/wc-recent-reviews-widget-async' . $suffix . '.js', array( 'jquery' ), $version, true );
			wp_localize_script(
				'wc-recent-reviews-widget-async',
				'wc_recent_reviews_widget_params',
				array(
					'ajax_url'      => admin_url( 'admin-ajax.php' ),
					'security'      => wp_create_nonce( 'wc-recent-reviews-widget' ),
					'error_message' => esc_html__( 'Error loading widget', 'woocommerce' ),
				)
			);

			// Display loading placeholder.
			echo '<div id="wc-recent-reviews-widget-loading" class="wc-recent-reviews-widget-loading">';
			echo '<p>' . esc_html__( 'Loading reviews data...', 'woocommerce' ) . ' <span class="spinner is-active"></span></p>';
			echo '</div>';
			echo '<div id="wc-recent-reviews-widget-content" style="display:none;"></div>';
		}

		/**
		 * Recent reviews widget: content.
		 */
		public function recent_reviews_content(): void {
			// Backward compatibility mode: if any of the checked below hooks are in use, use the legacy implementation.
			$has_legacy_query_filter         = has_filter( 'woocommerce_report_recent_reviews_query_from' );
			$has_legacy_product_title_filter = has_filter( 'woocommerce_admin_dashboard_recent_reviews' );
			$use_legacy_implementation       = $has_legacy_query_filter || $has_legacy_product_title_filter;
			if ( $use_legacy_implementation ) {
				if ( $has_legacy_query_filter ) {
					wc_deprecated_hook( 'woocommerce_report_recent_reviews_query_from', '10.5.0' );
				}
				if ( $has_legacy_product_title_filter ) {
					wc_deprecated_hook( 'woocommerce_admin_dashboard_recent_reviews', '10.5.0', 'dashboard-widget-reviews.php template' );
				}
				$this->legacy_recent_reviews();

				return;
			}

			// Optimized version of the widget: faster SQL queries and templates-based rendering for customization.
			/** @var \WP_Comment[] $comments */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort
			$comments = get_comments(
				array(
					'type'                      => 'review',
					'status'                    => 'approve',
					'parent'                    => 0,
					'number'                    => 25,
					'update_comment_post_cache' => true,
				)
			);
			$comments = array_filter(
				$comments,
				static fn( \WP_Comment $comment ) => current_user_can( 'read_product', $comment->comment_post_ID ) && ! post_password_required( (int) $comment->comment_post_ID )
			);
			if ( $comments ) {
				echo '<ul>';
				$count_rendered = 0;
				foreach ( $comments as $comment ) {
					$product = wc_get_product( $comment->comment_post_ID );
					if ( $product ) {
						wc_get_template(
							'dashboard-widget-reviews.php',
							array(
								'product' => $product,
								'comment' => $comment,
							)
						);
						if ( 5 === ++$count_rendered ) {
							break;
						}
					}
				}
				echo '</ul>';
			} else {
				echo '<p>' . esc_html__( 'There are no product reviews yet.', 'woocommerce' ) . '</p>';
			}
		}

		/**
		 * Network orders widget.
		 */
		public function network_orders() {
			$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
			$version = Constants::get_constant( 'WC_VERSION' );

			wp_enqueue_style( 'wc-network-orders', WC()->plugin_url() . '/assets/css/network-order-widget.css', array(), $version );

			wp_enqueue_script( 'wc-network-orders', WC()->plugin_url() . '/assets/js/admin/network-orders' . $suffix . '.js', array( 'jquery', 'underscore' ), $version, true );

			$user     = wp_get_current_user();
			$blogs    = get_blogs_of_user( $user->ID );
			$blog_ids = wp_list_pluck( $blogs, 'userblog_id' );

			wp_localize_script(
				'wc-network-orders',
				'woocommerce_network_orders',
				array(
					'nonce'          => wp_create_nonce( 'wp_rest' ),
					'sites'          => array_values( $blog_ids ),
					'order_endpoint' => get_rest_url( null, 'wc/v3/orders/network' ),
				)
			);
			?>
			<div class="post-type-shop_order">
			<div id="woocommerce-network-order-table-loading" class="woocommerce-network-order-table-loading is-active">
				<p>
					<span class="spinner is-active"></span> <?php esc_html_e( 'Loading network orders', 'woocommerce' ); ?>
				</p>

			</div>
			<table id="woocommerce-network-order-table" class="woocommerce-network-order-table">
				<thead>
					<tr>
						<td><?php esc_html_e( 'Order', 'woocommerce' ); ?></td>
						<td><?php esc_html_e( 'Status', 'woocommerce' ); ?></td>
						<td><?php esc_html_e( 'Total', 'woocommerce' ); ?></td>
					</tr>
				</thead>
				<tbody id="network-orders-tbody">

				</tbody>
			</table>
			<div id="woocommerce-network-orders-no-orders" class="woocommerce-network-orders-no-orders">
				<p>
					<?php esc_html_e( 'No orders found', 'woocommerce' ); ?>
				</p>
			</div>
			<?php // @codingStandardsIgnoreStart ?>
			<script type="text/template" id="network-orders-row-template">
				<tr>
					<td>
						<a href="<%- edit_url %>" class="order-view"><strong>#<%- number %> <%- customer %></strong></a>
						<br>
						<em>
							<%- blog.blogname %>
						</em>
					</td>
					<td>
						<mark class="order-status status-<%- status %>"><span><%- status_name %></span></mark>
					</td>
					<td>
						<%= formatted_total %>
					</td>
				</tr>
			</script>
			<?php // @codingStandardsIgnoreEnd ?>
		</div>
			<?php
		}

		/**
		 * Gets the sales performance data from the new WooAdmin store.
		 *
		 * @return stdClass|WP_Error|WP_REST_Response
		 */
		private function get_wc_admin_performance_data() {
			$request    = new \WP_REST_Request( 'GET', '/wc-analytics/reports/performance-indicators' );
			$start_date = gmdate( 'Y-m-01 00:00:00', current_time( 'timestamp' ) );
			$end_date   = gmdate( 'Y-m-d 23:59:59', current_time( 'timestamp' ) );
			$request->set_query_params(
				array(
					'before' => $end_date,
					'after'  => $start_date,
					'stats'  => 'revenue/total_sales,revenue/net_revenue,orders/orders_count,products/items_sold,variations/items_sold',
				)
			);
			$response = rest_do_request( $request );

			if ( is_wp_error( $response ) ) {
				return $response;
			}

			if ( 200 !== $response->get_status() ) {
				return new \WP_Error( 'woocommerce_analytics_performance_indicators_result_failed', __( 'Sorry, fetching performance indicators failed.', 'woocommerce' ) );
			}
			$report_keys      = array(
				'net_revenue' => 'net_sales',
			);
			$performance_data = new stdClass();
			foreach ( $response->get_data() as $indicator ) {
				if ( isset( $indicator['chart'] ) && isset( $indicator['value'] ) ) {
					$key                    = isset( $report_keys[ $indicator['chart'] ] ) ? $report_keys[ $indicator['chart'] ] : $indicator['chart'];
					$performance_data->$key = $indicator['value'];
				}
			}
			return $performance_data;
		}

		/**
		 * Prepares the data for a sparkline to show sales in the last X days.
		 *
		 * @param  int    $id ID of the product to show. Blank to get all orders.
		 * @param  int    $days Days of stats to get. Default to 7 days.
		 * @param  string $type Type of sparkline to get. Ignored if ID is not set.
		 * @return array
		 */
		private function get_sales_sparkline( $id = '', $days = 7, $type = 'sales' ) {
			$sales_endpoint = '/wc-analytics/reports/revenue/stats';
			$start_date     = gmdate( 'Y-m-d 00:00:00', current_time( 'timestamp' ) - ( ( $days - 1 ) * DAY_IN_SECONDS ) );
			$end_date       = gmdate( 'Y-m-d 23:59:59', current_time( 'timestamp' ) );
			$meta_key       = 'net_revenue';
			$params         = array(
				'order'    => 'asc',
				'interval' => 'day',
				'per_page' => 100,
				'before'   => $end_date,
				'after'    => $start_date,
			);
			if ( $id ) {
				$sales_endpoint     = '/wc-analytics/reports/products/stats';
				$meta_key           = ( 'sales' === $type ) ? 'net_revenue' : 'items_sold';
				$params['products'] = $id;
			}
			$request          = new \WP_REST_Request( 'GET', $sales_endpoint );
			$params['fields'] = array( $meta_key );
			$request->set_query_params( $params );

			$response = rest_do_request( $request );

			if ( is_wp_error( $response ) ) {
				return $response;
			}

			$resp_data = $response->get_data();
			$data      = $resp_data['intervals'];

			$sparkline_data = array();
			$total          = 0;
			foreach ( $data as $d ) {
				$total += $d['subtotals']->$meta_key;
				array_push( $sparkline_data, array( strval( strtotime( $d['interval'] ) * 1000 ), $d['subtotals']->$meta_key ) );
			}

			return array(
				'total' => $total,
				'data'  => $sparkline_data,
			);
		}

		/**
		 * Prepares the markup for a sparkline to show sales in the last X days with the given data.
		 *
		 * @param  string $type Type of sparkline to form the markup.
		 * @param  int    $days Days of stats to form the markup.
		 * @param  int    $total Total income or items sold to form the markup.
		 * @param  array  $sparkline_data Sparkline data to form the markup.
		 * @return string
		 */
		private function sales_sparkline_markup( $type, $days, $total, $sparkline_data ) {
			if ( 'sales' === $type ) {
				/* translators: 1: total income 2: days */
				$tooltip = sprintf( __( 'Sold %1$s worth in the last %2$d days', 'woocommerce' ), strip_tags( wc_price( $total ) ), $days );
			} else {
				/* translators: 1: total items sold 2: days */
				$tooltip = sprintf( _n( 'Sold %1$d item in the last %2$d days', 'Sold %1$d items in the last %2$d days', $total, 'woocommerce' ), $total, $days );
			}

			return '<span class="wc_sparkline ' . ( ( 'sales' === $type ) ? 'lines' : 'bars' ) . ' tips" data-color="#777" data-tip="' . esc_attr( $tooltip ) . '" data-barwidth="' . 60 * 60 * 16 * 1000 . '" data-sparkline="' . wc_esc_json( wp_json_encode( $sparkline_data ) ) . '"></span>';
		}
	}

endif;

return new WC_Admin_Dashboard();
PK     tS\]#4  #4  $  class-wc-admin-duplicate-product.phpnu [        <?php
/**
 * Duplicate product functionality
 *
 * @package     WooCommerce\Admin
 * @version     3.0.0
 */

use Automattic\WooCommerce\Enums\ProductStatus;
use Automattic\WooCommerce\Enums\ProductType;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Admin_Duplicate_Product', false ) ) {
	return new WC_Admin_Duplicate_Product();
}

/**
 * WC_Admin_Duplicate_Product Class.
 */
class WC_Admin_Duplicate_Product {

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'admin_action_duplicate_product', array( $this, 'duplicate_product_action' ) );
		add_filter( 'post_row_actions', array( $this, 'dupe_link' ), 10, 2 );
		add_action( 'post_submitbox_start', array( $this, 'dupe_button' ) );
	}

	/**
	 * Show the "Duplicate" link in admin products list.
	 *
	 * @param array   $actions Array of actions.
	 * @param WP_Post $post Post object.
	 * @return array
	 */
	public function dupe_link( $actions, $post ) {
		global $the_product;

		if ( ! current_user_can( apply_filters( 'woocommerce_duplicate_product_capability', 'manage_woocommerce' ) ) ) {
			return $actions;
		}

		if ( 'product' !== $post->post_type ) {
			return $actions;
		}

		// Add Class to Delete Permanently link in row actions.
		if ( empty( $the_product ) || $the_product->get_id() !== $post->ID ) {
			$the_product = wc_get_product( $post );
		}

		if ( $the_product && ProductStatus::PUBLISH === $the_product->get_status() && 0 < $the_product->get_total_sales() ) {
			$actions['trash'] = sprintf(
				'<a href="%s" class="submitdelete trash-product" aria-label="%s">%s</a>',
				get_delete_post_link( $the_product->get_id(), '', false ),
				/* translators: %s: post title */
				esc_attr( sprintf( __( 'Move &#8220;%s&#8221; to the Trash', 'woocommerce' ), $the_product->get_name() ) ),
				esc_html__( 'Trash', 'woocommerce' )
			);
		}

		$actions['duplicate'] = '<a href="' . wp_nonce_url( admin_url( 'edit.php?post_type=product&action=duplicate_product&amp;post=' . $post->ID ), 'woocommerce-duplicate-product_' . $post->ID ) . '" aria-label="' . esc_attr__( 'Make a duplicate from this product', 'woocommerce' )
			. '" rel="permalink">' . esc_html__( 'Duplicate', 'woocommerce' ) . '</a>';

		return $actions;
	}

	/**
	 * Show the dupe product link in admin.
	 */
	public function dupe_button() {
		global $post;

		if ( ! current_user_can( apply_filters( 'woocommerce_duplicate_product_capability', 'manage_woocommerce' ) ) ) {
			return;
		}

		if ( ! is_object( $post ) ) {
			return;
		}

		if ( 'product' !== $post->post_type ) {
			return;
		}

		$notify_url = wp_nonce_url( admin_url( 'edit.php?post_type=product&action=duplicate_product&post=' . absint( $post->ID ) ), 'woocommerce-duplicate-product_' . $post->ID );
		?>
		<div id="duplicate-action"><a class="submitduplicate duplication" href="<?php echo esc_url( $notify_url ); ?>"><?php esc_html_e( 'Copy to a new draft', 'woocommerce' ); ?></a></div>
		<?php
	}

	/**
	 * Duplicate a product action.
	 */
	public function duplicate_product_action() {
		if ( empty( $_REQUEST['post'] ) ) {
			wp_die( esc_html__( 'No product to duplicate has been supplied!', 'woocommerce' ) );
		}

		$product_id = isset( $_REQUEST['post'] ) ? absint( $_REQUEST['post'] ) : '';

		check_admin_referer( 'woocommerce-duplicate-product_' . $product_id );

		$product = wc_get_product( $product_id );

		if ( false === $product ) {
			/* translators: %s: product id */
			wp_die( sprintf( esc_html__( 'Product creation failed, could not find original product: %s', 'woocommerce' ), esc_html( $product_id ) ) );
		}

		$duplicate = $this->product_duplicate( $product );

		// Hook rename to match other woocommerce_product_* hooks, and to move away from depending on a response from the wp_posts table.
		do_action( 'woocommerce_product_duplicate', $duplicate, $product );
		wc_do_deprecated_action( 'woocommerce_duplicate_product', array( $duplicate->get_id(), $this->get_product_to_duplicate( $product_id ) ), '3.0', 'Use woocommerce_product_duplicate action instead.' );

		// Redirect to the edit screen for the new draft page.
		wp_redirect( admin_url( 'post.php?action=edit&post=' . $duplicate->get_id() ) );
		exit;
	}

	/**
	 * Function to create the duplicate of the product.
	 *
	 * @param WC_Product $product The product to duplicate.
	 * @return WC_Product The duplicate.
	 */
	public function product_duplicate( $product ) {
		if ( ! $product instanceof WC_Product ) {
			wc_doing_it_wrong( __METHOD__, 'product_duplicate() expects a WC_Product instance', '10.5.0' );
			return new WC_Product();
		}

		/**
		 * Filter to allow us to exclude meta keys from product duplication..
		 *
		 * @param array $exclude_meta The keys to exclude from the duplicate.
		 * @param array $existing_meta_keys The meta keys that the product already has.
		 * @since 2.6
		 */
		$meta_to_exclude = array_filter(
			apply_filters(
				'woocommerce_duplicate_product_exclude_meta',
				array(),
				array_map(
					function ( $datum ) {
						return $datum->key;
					},
					$product->get_meta_data()
				)
			)
		);

		$duplicate = clone $product;
		$duplicate->set_id( 0 );
		/* translators: %s contains the name of the original product. */
		$duplicate->set_name( sprintf( esc_html__( '%s (Copy)', 'woocommerce' ), $duplicate->get_name() ) );
		$duplicate->set_total_sales( 0 );
		if ( '' !== $product->get_sku( 'edit' ) ) {
			$this->generate_unique_sku( $duplicate );
		}
		if ( '' !== $product->get_global_unique_id( 'edit' ) ) {
			$duplicate->set_global_unique_id( '' );
		}
		$duplicate->set_status( ProductStatus::DRAFT );
		$duplicate->set_date_created( null );
		$duplicate->set_slug( '' );
		$duplicate->set_rating_counts( 0 );
		$duplicate->set_average_rating( 0 );
		$duplicate->set_review_count( 0 );

		foreach ( $meta_to_exclude as $meta_key ) {
			$duplicate->delete_meta_data( $meta_key );
		}

		/**
		 * This action can be used to modify the object further before it is created - it will be passed by reference.
		 *
		 * @since 3.0
		 */
		do_action( 'woocommerce_product_duplicate_before_save', $duplicate, $product );

		// Save parent product.
		$duplicate->save();

		/**
		 * Duplicate children of a variable product.
		 *
		 * @since 2.7
		 */
		if ( ! apply_filters( 'woocommerce_duplicate_product_exclude_children', false, $product ) && $product->is_type( ProductType::VARIABLE ) ) {
			foreach ( $product->get_children() as $child_id ) {
				$child = wc_get_product( $child_id );

				if ( ! $child instanceof WC_Product ) {
					wc_doing_it_wrong( __METHOD__, 'product_duplicate() expects product children to be WC_Product instances', '10.5.0' );
					continue;
				}

				$child->read_meta_data();
				$child_duplicate = clone $child;
				$child_duplicate->set_parent_id( $duplicate->get_id() );
				$child_duplicate->set_id( 0 );
				$child_duplicate->set_date_created( null );

				// If we wait and let the insertion generate the slug, we will see extreme performance degradation
				// in the case where a product is used as a template. Every time the template is duplicated, each
				// variation will query every consecutive slug until it finds an empty one. To avoid this, we can
				// optimize the generation ourselves, avoiding the issue altogether.
				$this->generate_unique_slug( $child_duplicate );

				if ( '' !== $child->get_sku( 'edit' ) ) {
					$this->generate_unique_sku( $child_duplicate );
				}
				if ( '' !== $child->get_global_unique_id( 'edit' ) ) {
					$child_duplicate->set_global_unique_id( '' );
				}

				foreach ( $meta_to_exclude as $meta_key ) {
					$child_duplicate->delete_meta_data( $meta_key );
				}

				/**
				 * This action can be used to modify the object further before it is created - it will be passed by reference.
				 *
				 * @since 3.0
				 */
				do_action( 'woocommerce_product_duplicate_before_save', $child_duplicate, $child );

				$child_duplicate->save();
			}

			// Get new object to reflect new children.
			$duplicate = wc_get_product( $duplicate->get_id() );
		}

		return $duplicate;
	}

	/**
	 * Get a product from the database to duplicate.
	 *
	 * @deprecated 3.0.0
	 * @param mixed $id The ID of the product to duplicate.
	 * @return object|bool
	 * @see duplicate_product
	 */
	private function get_product_to_duplicate( $id ) {
		global $wpdb;

		$id = absint( $id );

		if ( ! $id ) {
			return false;
		}

		$post = $wpdb->get_row( $wpdb->prepare( "SELECT {$wpdb->posts}.* FROM {$wpdb->posts} WHERE ID = %d", $id ) );

		if ( isset( $post->post_type ) && 'revision' === $post->post_type ) {
			$id   = $post->post_parent;
			$post = $wpdb->get_row( $wpdb->prepare( "SELECT {$wpdb->posts}.* FROM {$wpdb->posts} WHERE ID = %d", $id ) );
		}

		return $post;
	}

	/**
	 * Generates a unique slug for a given product. We do this so that we can override the
	 * behavior of wp_unique_post_slug(). The normal slug generation will run single
	 * select queries on every non-unique slug, resulting in very bad performance.
	 *
	 * @param WC_Product $product The product to generate a slug for.
	 * @since 3.9.0
	 */
	private function generate_unique_slug( $product ) {
		global $wpdb;

		// We want to remove the suffix from the slug so that we can find the maximum suffix using this root slug.
		// This will allow us to find the next-highest suffix that is unique. While this does not support gap
		// filling, this shouldn't matter for our use-case.
		$root_slug = preg_replace( '/-[0-9]+$/', '', $product->get_slug() );

		$results = $wpdb->get_results(
			$wpdb->prepare( "SELECT post_name FROM $wpdb->posts WHERE post_name LIKE %s AND post_type IN ( 'product', 'product_variation' )", $root_slug . '%' )
		);

		// The slug is already unique!
		if ( empty( $results ) ) {
			return;
		}

		// Find the maximum suffix so we can ensure uniqueness.
		$max_suffix = 1;
		foreach ( $results as $result ) {
			// Pull a numerical suffix off the slug after the last hyphen.
			$suffix = intval( substr( $result->post_name, strrpos( $result->post_name, '-' ) + 1 ) );
			if ( $suffix > $max_suffix ) {
				$max_suffix = $suffix;
			}
		}

		$product->set_slug( $root_slug . '-' . ( $max_suffix + 1 ) );
	}

	/**
	 * Generates a unique sku for a given product.
	 *
	 * @param WC_Product $product The product to generate a sku for.
	 * @return void
	 * @since 10.5.0
	 *
	 * @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
	 */
	private function generate_unique_sku( $product ) {
		global $wpdb;

		// We want to remove the suffix from the sku so that we can find the maximum suffix using this root sku.
		// This will allow us to find the next-highest suffix that is unique. While this does not support gap
		// filling, this shouldn't matter for our use-case.
		$root_sku = preg_replace( '/-[0-9]+$/', '', $product->get_sku() );

		// If the parent product has no SKU, don't do anything.
		if ( ! $root_sku ) {
			return;
		}

		$existing_skus = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT lookup.sku
					FROM {$wpdb->posts} as posts
					INNER JOIN {$wpdb->wc_product_meta_lookup} AS lookup ON posts.ID = lookup.product_id
					WHERE posts.post_type IN ( 'product', 'product_variation' )
					AND lookup.sku LIKE %s",
				$wpdb->esc_like( $root_sku ) . '%'
			)
		);

		// The sku is already unique!
		if ( empty( $existing_skus ) ) {
			$product->set_sku( $root_sku );
			return;
		}

		// Find the maximum suffix so we can ensure uniqueness.
		$max_suffix = 0;
		foreach ( $existing_skus as $existing_sku ) {
			// Pull a numerical suffix off the sku after the last hyphen.
			$suffix = intval( substr( $existing_sku, strrpos( $existing_sku, '-', -1 ) + 1 ) );
			if ( $suffix > $max_suffix ) {
				$max_suffix = $suffix;
			}
		}

		// We set a limit of SKUs to try in order to avoid infinite loops.
		$limit      = $max_suffix + 100;
		$product_id = $product->get_id();

		while ( $max_suffix < $limit ) {
			$new_sku = $root_sku . '-' . ( $max_suffix + 1 );

			/**
			 * Gives plugins an opportunity to verify SKU uniqueness themselves. Filter added to keep backwards
			 * compatibility with `wc_product_has_unique_sku()`.
			 * See: https://github.com/woocommerce/woocommerce/pull/62628
			 *
			 * @since 10.5.0
			 *
			 * @param bool|null $has_unique_sku Set to a boolean value to short-circuit the default SKU check.
			 * @param int $product_id The ID of the current product.
			 * @param string $sku The SKU to check for uniqueness.
			 */
			$pre_has_unique_sku = apply_filters( 'wc_product_pre_has_unique_sku', true, $product_id, $new_sku );

			if ( $pre_has_unique_sku ) {
				/**
				 * Gives plugins an opportunity to verify SKU uniqueness themselves. Filter added to keep backwards
				 * compatibility with `wc_product_has_unique_sku()`.
				 * See: https://github.com/woocommerce/woocommerce/pull/62628
				 *
				 * @since 10.5.0
				 *
				 * @param bool|null $sku_found Set to a boolean value to short-circuit the default SKU check.
				 * @param int $product_id The ID of the current product.
				 * @param string $sku The SKU to check for uniqueness.
				 */
				$sku_found = apply_filters( 'wc_product_has_unique_sku', false, $product_id, $new_sku );

				if ( ! $sku_found ) {
					$product->set_sku( $new_sku );
					return;
				}
			}
			++$max_suffix;
		}
	}
}

return new WC_Admin_Duplicate_Product();
PK     tS\<F      class-wc-admin-assets.phpnu [        <?php
/**
 * Load assets
 *
 * @package WooCommerce\Admin
 * @version 3.7.0
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Enums\ProductType;
use Automattic\WooCommerce\Internal\Admin\Analytics;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;
use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'WC_Admin_Assets', false ) ) :

	/**
	 * WC_Admin_Assets Class.
	 *
	 * These scripts are enqueued in the admin of the store.  The registered script handles in this class
	 * can be used to enqueue the scripts in the admin by third party plugins and the handles will follow
	 * WooCommerce's L-1 support policy.  Scripts registered outside of this class do not guarantee support
	 * and can be removed in future versions of WooCommerce.
	 */
	class WC_Admin_Assets {

		/**
		 * Hook in tabs.
		 */
		public function __construct() {
			add_action( 'admin_init', array( $this, 'register_scripts' ) );
			add_action( 'admin_enqueue_scripts', array( $this, 'admin_styles' ) );
			add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
			add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ) );
		}

		/**
		 * Enqueue styles.
		 */
		public function admin_styles() {
			$version   = Constants::get_constant( 'WC_VERSION' );
			$screen    = get_current_screen();
			$screen_id = $screen ? $screen->id : '';

			// Register admin styles.
			wp_register_style( 'woocommerce_admin_menu_styles', WC()->plugin_url() . '/assets/css/menu.css', array(), $version );
			wp_register_style( 'woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css', array(), $version );
			wp_register_style( 'jquery-ui-style', WC()->plugin_url() . '/assets/css/jquery-ui/jquery-ui.min.css', array(), $version );
			wp_register_style( 'woocommerce_admin_dashboard_styles', WC()->plugin_url() . '/assets/css/dashboard.css', array(), $version );
			wp_register_style( 'woocommerce_admin_print_reports_styles', WC()->plugin_url() . '/assets/css/reports-print.css', array(), $version, 'print' );
			wp_register_style( 'woocommerce_admin_marketplace_styles', WC()->plugin_url() . '/assets/css/marketplace-suggestions.css', array(), $version );
			wp_register_style( 'woocommerce_admin_privacy_styles', WC()->plugin_url() . '/assets/css/privacy.css', array(), $version );

			// Add RTL support for admin styles.
			wp_style_add_data( 'woocommerce_admin_menu_styles', 'rtl', 'replace' );
			wp_style_add_data( 'woocommerce_admin_styles', 'rtl', 'replace' );
			wp_style_add_data( 'woocommerce_admin_dashboard_styles', 'rtl', 'replace' );
			wp_style_add_data( 'woocommerce_admin_print_reports_styles', 'rtl', 'replace' );
			wp_style_add_data( 'woocommerce_admin_marketplace_styles', 'rtl', 'replace' );
			wp_style_add_data( 'woocommerce_admin_privacy_styles', 'rtl', 'replace' );

			if ( $screen && $screen->is_block_editor() ) {
				if ( ! wp_is_block_theme() ) {
					wp_register_style( 'woocommerce-classictheme-editor-fonts', WC()->plugin_url() . '/assets/css/woocommerce-classictheme-editor-fonts.css', array(), $version );
					wp_enqueue_style( 'woocommerce-classictheme-editor-fonts' );
				}

				$styles = WC_Frontend_Scripts::get_styles();

				if ( $styles ) {
					foreach ( $styles as $handle => $args ) {
						wp_register_style(
							$handle,
							$args['src'],
							$args['deps'],
							$args['version'],
							$args['media']
						);

						if ( ! isset( $args['has_rtl'] ) ) {
							wp_style_add_data( $handle, 'rtl', 'replace' );
						}

						wp_enqueue_style( $handle );
					}
				}
			}

			// Sitewide menu CSS.
			wp_enqueue_style( 'woocommerce_admin_menu_styles' );

			// Admin styles for WC pages only.
			if ( in_array( $screen_id, wc_get_screen_ids() ) ) {
				wp_enqueue_style( 'woocommerce_admin_styles' );
				wp_enqueue_style( 'jquery-ui-style' );
				wp_enqueue_style( 'wp-color-picker' );
			}

			if ( in_array( $screen_id, array( 'dashboard' ) ) ) {
				wp_enqueue_style( 'woocommerce_admin_dashboard_styles' );
			}

			if ( in_array( $screen_id, array( 'woocommerce_page_wc-reports', 'toplevel_page_wc-reports' ) ) ) {
				wp_enqueue_style( 'woocommerce_admin_print_reports_styles' );
			}

			// Privacy Policy Guide css for back-compat.
			if ( isset( $_GET['wp-privacy-policy-guide'] ) || in_array( $screen_id, array( 'privacy-policy-guide' ) ) ) {
				wp_enqueue_style( 'woocommerce_admin_privacy_styles' );
			}

			// @deprecated 2.3.
			if ( has_action( 'woocommerce_admin_css' ) ) {
				/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
				do_action( 'woocommerce_admin_css' );
				/* phpcs: enable */
				wc_deprecated_function( 'The woocommerce_admin_css action', '2.3', 'admin_enqueue_scripts' );
			}

			if ( WC_Marketplace_Suggestions::show_suggestions_for_screen( $screen_id ) ) {
				wp_enqueue_style( 'woocommerce_admin_marketplace_styles' );
			}
		}

		/**
		 * Get the scripts used for registration.
		 *
		 * @return array
		 */
		private function get_scripts(): array {
			$suffix     = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
			$version    = Constants::get_constant( 'WC_VERSION' );
			$plugin_url = WC()->plugin_url();

			return array(
				array(
					'handle'       => 'woocommerce_admin',
					'path'         => $plugin_url . '/assets/js/admin/woocommerce_admin' . $suffix . '.js',
					'dependencies' => array( 'jquery', 'wc-jquery-blockui', 'jquery-ui-sortable', 'jquery-ui-widget', 'jquery-ui-core', 'wc-jquery-tiptip' ),
					'version'      => $version,
				),
				array(
					'legacy_handle' => 'jquery-blockui',
					'handle'        => 'wc-jquery-blockui',
					'path'          => $plugin_url . '/assets/js/jquery-blockui/jquery.blockUI' . $suffix . '.js',
					'dependencies'  => array( 'jquery' ),
					'version'       => '2.70',
					'args'          => array(
						'in_footer' => true,
					),
				),
				array(
					'legacy_handle' => 'jquery-tiptip',
					'handle'        => 'wc-jquery-tiptip',
					'path'          => $plugin_url . '/assets/js/jquery-tiptip/jquery.tipTip' . $suffix . '.js',
					'dependencies'  => array( 'jquery', 'wc-dompurify' ),
					'version'       => $version,
					'args'          => array(
						'in_footer' => true,
					),
				),
				array(
					'legacy_handle' => 'round',
					'handle'        => 'wc-round',
					'path'          => $plugin_url . '/assets/js/round/round' . $suffix . '.js',
					'dependencies'  => array( 'jquery' ),
					'version'       => $version,
				),
				array(
					'handle'       => 'wc-admin-meta-boxes',
					'path'         => $plugin_url . '/assets/js/admin/meta-boxes' . $suffix . '.js',
					'dependencies' => array( 'jquery', 'jquery-ui-datepicker', 'jquery-ui-sortable', 'wc-accounting', 'wc-round', 'wc-enhanced-select', 'plupload-all', 'wc-stupidtable', 'wc-jquery-tiptip', 'wc-jquery-blockui' ),
					'version'      => $version,
				),
				array(
					'legacy_handle' => 'qrcode',
					'handle'        => 'wc-qrcode',
					'path'          => $plugin_url . '/assets/js/jquery-qrcode/jquery.qrcode' . $suffix . '.js',
					'dependencies'  => array( 'jquery' ),
					'version'       => $version,
				),
				array(
					'legacy_handle' => 'stupidtable',
					'handle'        => 'wc-stupidtable',
					'path'          => $plugin_url . '/assets/js/stupidtable/stupidtable' . $suffix . '.js',
					'dependencies'  => array( 'jquery' ),
					'version'       => $version,
				),
				array(
					'legacy_handle' => 'serializejson',
					'handle'        => 'wc-serializejson',
					'path'          => $plugin_url . '/assets/js/jquery-serializejson/jquery.serializejson' . $suffix . '.js',
					'dependencies'  => array( 'jquery' ),
					'version'       => '2.8.1',
				),
				array(
					'legacy_handle' => 'flot',
					'handle'        => 'wc-flot',
					'path'          => $plugin_url . '/assets/js/jquery-flot/jquery.flot' . $suffix . '.js',
					'dependencies'  => array( 'jquery' ),
					'version'       => $version,
				),
				array(
					'legacy_handle' => 'flot-resize',
					'handle'        => 'wc-flot-resize',
					'path'          => $plugin_url . '/assets/js/jquery-flot/jquery.flot.resize' . $suffix . '.js',
					'dependencies'  => array( 'jquery', 'wc-flot' ),
					'version'       => $version,
				),
				array(
					'legacy_handle' => 'flot-time',
					'handle'        => 'wc-flot-time',
					'path'          => $plugin_url . '/assets/js/jquery-flot/jquery.flot.time' . $suffix . '.js',
					'dependencies'  => array( 'jquery', 'wc-flot' ),
					'version'       => $version,
				),
				array(
					'legacy_handle' => 'flot-pie',
					'handle'        => 'wc-flot-pie',
					'path'          => $plugin_url . '/assets/js/jquery-flot/jquery.flot.pie' . $suffix . '.js',
					'dependencies'  => array( 'jquery', 'wc-flot' ),
					'version'       => $version,
				),
				array(
					'legacy_handle' => 'flot-stack',
					'handle'        => 'wc-flot-stack',
					'path'          => $plugin_url . '/assets/js/jquery-flot/jquery.flot.stack' . $suffix . '.js',
					'dependencies'  => array( 'jquery', 'wc-flot' ),
					'version'       => $version,
				),
				array(
					'handle'       => 'wc-settings-tax',
					'path'         => $plugin_url . '/assets/js/admin/settings-views-html-settings-tax' . $suffix . '.js',
					'dependencies' => array( 'jquery', 'wp-util', 'underscore', 'backbone', 'wc-jquery-blockui' ),
					'version'      => $version,
				),
				array(
					'handle'       => 'wc-backbone-modal',
					'path'         => $plugin_url . '/assets/js/admin/backbone-modal' . $suffix . '.js',
					'dependencies' => array( 'underscore', 'backbone', 'wp-util' ),
					'version'      => $version,
				),
				array(
					'handle'       => 'wc-shipping-zones',
					'path'         => $plugin_url . '/assets/js/admin/wc-shipping-zones' . $suffix . '.js',
					'dependencies' => array( 'jquery', 'wp-util', 'underscore', 'backbone', 'jquery-ui-sortable', 'wc-enhanced-select', 'wc-backbone-modal' ),
					'version'      => $version,
				),
				array(
					'handle'       => 'wc-shipping-zone-methods',
					'path'         => $plugin_url . '/assets/js/admin/wc-shipping-zone-methods' . $suffix . '.js',
					'dependencies' => array( 'jquery', 'wp-util', 'underscore', 'backbone', 'jquery-ui-sortable', 'wc-backbone-modal' ),
					'version'      => $version,
				),
				array(
					'handle'       => 'wc-shipping-classes',
					'path'         => $plugin_url . '/assets/js/admin/wc-shipping-classes' . $suffix . '.js',
					'dependencies' => array( 'jquery', 'wp-util', 'underscore', 'backbone', 'wc-backbone-modal' ),
					'version'      => $version,
				),
				array(
					'handle'       => 'wc-shipping-providers',
					'path'         => $plugin_url . '/assets/js/admin/wc-shipping-providers' . $suffix . '.js',
					'dependencies' => array( 'jquery', 'wp-util', 'underscore', 'backbone', 'wc-backbone-modal' ),
					'version'      => $version,
				),
				array(
					'handle'       => 'wc-clipboard',
					'path'         => $plugin_url . '/assets/js/admin/wc-clipboard' . $suffix . '.js',
					'dependencies' => array( 'jquery' ),
					'version'      => $version,
				),
				array(
					'legacy_handle' => 'select2',
					'handle'        => 'wc-select2',
					'path'          => $plugin_url . '/assets/js/select2/select2.full' . $suffix . '.js',
					'dependencies'  => array( 'jquery' ),
					'version'       => '4.0.3',
				),
				array(
					'handle'       => 'selectWoo',
					'path'         => $plugin_url . '/assets/js/selectWoo/selectWoo.full' . $suffix . '.js',
					'dependencies' => array( 'jquery' ),
					'version'      => '1.0.6',
				),
				array(
					'handle'       => 'wc-enhanced-select',
					'path'         => $plugin_url . '/assets/js/admin/wc-enhanced-select' . $suffix . '.js',
					'dependencies' => array( 'jquery', 'selectWoo' ),
					'version'      => $version,
				),
				array(
					'legacy_handle' => 'js-cookie',
					'handle'        => 'wc-js-cookie',
					'path'          => $plugin_url . '/assets/js/js-cookie/js.cookie' . $suffix . '.js',
					'dependencies'  => array(),
					'version'       => '2.1.4',
					'args'          => array(
						'in_footer' => true,
					),
				),
				array(
					'legacy_handle' => 'dompurify',
					'handle'        => 'wc-dompurify',
					'path'          => $plugin_url . '/assets/js/dompurify/purify' . $suffix . '.js',
					'dependencies'  => array(),
					'version'       => $version,
				),
				array(
					'legacy_handle' => 'accounting',
					'handle'        => 'wc-accounting',
					'path'          => $plugin_url . '/assets/js/accounting/accounting' . $suffix . '.js',
					'dependencies'  => array( 'jquery' ),
					'version'       => '0.4.2',
				),
			);
		}

		/**
		 * Register the scripts.
		 *
		 * These scripts are registered early to allow other
		 * plugins to take advantage of them by handle.
		 */
		public function register_scripts() {
			$scripts = $this->get_scripts();

			foreach ( $scripts as $script ) {
				wp_register_script(
					$script['handle'],
					$script['path'],
					$script['dependencies'] ?? array(),
					$script['version'] ?? null,
					$script['args'] ?? array( 'in_footer' => false )
				);

				if ( isset( $script['legacy_handle'] ) ) {
					wp_register_script(
						$script['legacy_handle'],
						false,
						array( $script['handle'] ),
						$script['version'] ?? null,
						true
					);
				}
			}

			wp_localize_script(
				'wc-enhanced-select',
				'wc_enhanced_select_params',
				array(
					'i18n_no_matches'                 => _x( 'No matches found', 'enhanced select', 'woocommerce' ),
					'i18n_ajax_error'                 => _x( 'Loading failed', 'enhanced select', 'woocommerce' ),
					'i18n_input_too_short_1'          => _x( 'Please enter 1 or more characters', 'enhanced select', 'woocommerce' ),
					'i18n_input_too_short_n'          => _x( 'Please enter %qty% or more characters', 'enhanced select', 'woocommerce' ),
					'i18n_input_too_long_1'           => _x( 'Please delete 1 character', 'enhanced select', 'woocommerce' ),
					'i18n_input_too_long_n'           => _x( 'Please delete %qty% characters', 'enhanced select', 'woocommerce' ),
					'i18n_selection_too_long_1'       => _x( 'You can only select 1 item', 'enhanced select', 'woocommerce' ),
					'i18n_selection_too_long_n'       => _x( 'You can only select %qty% items', 'enhanced select', 'woocommerce' ),
					'i18n_load_more'                  => _x( 'Loading more results&hellip;', 'enhanced select', 'woocommerce' ),
					'i18n_searching'                  => _x( 'Searching&hellip;', 'enhanced select', 'woocommerce' ),
					'ajax_url'                        => admin_url( 'admin-ajax.php' ),
					'search_products_nonce'           => wp_create_nonce( 'search-products' ),
					'search_customers_nonce'          => wp_create_nonce( 'search-customers' ),
					'search_categories_nonce'         => wp_create_nonce( 'search-categories' ),
					'search_taxonomy_terms_nonce'     => wp_create_nonce( 'search-taxonomy-terms' ),
					'search_product_attributes_nonce' => wp_create_nonce( 'search-product-attributes' ),
					'search_pages_nonce'              => wp_create_nonce( 'search-pages' ),
					'search_order_metakeys_nonce'     => wp_create_nonce( 'search-order-metakeys' ),
				)
			);

			wp_localize_script(
				'wc-accounting',
				'accounting_params',
				array(
					'mon_decimal_point' => wc_get_price_decimal_separator(),
				)
			);
		}


		/**
		 * Enqueue scripts.
		 */
		public function admin_scripts() {
			global $wp_query, $post, $theorder;

			$screen       = get_current_screen();
			$screen_id    = $screen ? $screen->id : '';
			$wc_screen_id = 'woocommerce';
			$suffix       = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
			$version      = Constants::get_constant( 'WC_VERSION' );

			wp_register_script( 'wc-orders', WC()->plugin_url() . '/assets/js/admin/wc-orders' . $suffix . '.js', array( 'jquery', 'wp-util', 'underscore', 'backbone', 'wc-jquery-blockui' ), $version, array( 'in_footer' => false ) );
			wp_localize_script(
				'wc-orders',
				'wc_orders_params',
				array(
					'ajax_url'      => admin_url( 'admin-ajax.php' ),
					'preview_nonce' => wp_create_nonce( 'woocommerce-preview-order' ),
				)
			);

			// WooCommerce admin pages.
			if ( in_array( $screen_id, wc_get_screen_ids() ) ) {
				wp_enqueue_script( 'iris' );
				wp_enqueue_script( 'woocommerce_admin' );
				wp_enqueue_script( 'wc-enhanced-select' );

				wp_enqueue_script( 'jquery-ui-sortable' );
				wp_enqueue_script( 'jquery-ui-autocomplete' );

				$locale        = localeconv();
				$decimal_point = isset( $locale['decimal_point'] ) ? $locale['decimal_point'] : '.';
				$decimal       = ( ! empty( wc_get_price_decimal_separator() ) ) ? wc_get_price_decimal_separator() : $decimal_point;

				$params = array(
					/* translators: %s: decimal */
					'i18n_decimal_error'                => sprintf( __( 'Please enter a value with one decimal point (%s) without thousand separators.', 'woocommerce' ), $decimal ),
					/* translators: %s: price decimal separator */
					'i18n_mon_decimal_error'            => sprintf( __( 'Please enter a value with one monetary decimal point (%s) without thousand separators and currency symbols.', 'woocommerce' ), wc_get_price_decimal_separator() ),
					'i18n_country_iso_error'            => __( 'Please enter in country code with two capital letters.', 'woocommerce' ),
					'i18n_sale_less_than_regular_error' => __( 'Please enter in a value less than the regular price.', 'woocommerce' ),
					'i18n_delete_product_notice'        => __( 'This product has produced sales and may be linked to existing orders. Are you sure you want to delete it?', 'woocommerce' ),
					'i18n_remove_personal_data_notice'  => __( 'This action cannot be reversed. Are you sure you wish to erase personal data from the selected orders?', 'woocommerce' ),
					'i18n_confirm_delete'               => __( 'Are you sure you wish to delete this item?', 'woocommerce' ),
					'i18n_global_unique_id_error'       => __( 'Please enter only numbers and hyphens (-).', 'woocommerce' ),
					'decimal_point'                     => $decimal,
					'mon_decimal_point'                 => wc_get_price_decimal_separator(),
					'ajax_url'                          => admin_url( 'admin-ajax.php' ),
					'strings'                           => array(
						'import_products'          => __( 'Import', 'woocommerce' ),
						'export_products'          => __( 'Export', 'woocommerce' ),
						// translators: %d: number of selected products.
						'export_selected_products' => __( 'Export %d selected', 'woocommerce' ),
					),
					'nonces'                            => array(
						'gateway_toggle'                 => current_user_can( 'manage_woocommerce' ) ? wp_create_nonce( 'woocommerce-toggle-payment-gateway-enabled' ) : null,
						'export_selected_products_nonce' => current_user_can( 'export' ) ? wp_create_nonce( 'export-selected-products' ) : null,
					),
					'urls'                              => array(
						'add_product'     => \Automattic\WooCommerce\Utilities\FeaturesUtil::feature_is_enabled( 'product_block_editor' ) ? esc_url_raw( admin_url( 'admin.php?page=wc-admin&path=/add-product' ) ) : null,
						'import_products' => current_user_can( 'import' ) ? esc_url_raw( admin_url( 'edit.php?post_type=product&page=product_importer' ) ) : null,
						'export_products' => current_user_can( 'export' ) ? esc_url_raw( admin_url( 'edit.php?post_type=product&page=product_exporter' ) ) : null,
					),
				);

				wp_localize_script( 'woocommerce_admin', 'woocommerce_admin', $params );
			}

			// Edit product category pages.
			if ( in_array( $screen_id, array( 'edit-product_cat' ) ) ) {
				wp_enqueue_media();
			}

			// Products.
			if ( in_array( $screen_id, array( 'edit-product' ) ) ) {
				wp_enqueue_script( 'woocommerce_quick-edit', WC()->plugin_url() . '/assets/js/admin/quick-edit' . $suffix . '.js', array( 'jquery', 'woocommerce_admin' ), $version );

				$params = array(
					'strings' => array(
						'allow_reviews' => esc_js( __( 'Enable reviews', 'woocommerce' ) ),
					),
				);

				wp_localize_script( 'woocommerce_quick-edit', 'woocommerce_quick_edit', $params );
			}

			// Product description.
			if ( in_array( $screen_id, array( 'product' ), true ) ) {
				wp_enqueue_script( 'wc-admin-product-editor', WC()->plugin_url() . '/assets/js/admin/product-editor' . $suffix . '.js', array( 'jquery' ), $version, false );

				wp_localize_script(
					'wc-admin-product-editor',
					'woocommerce_admin_product_editor',
					array(
						'i18n_description' => esc_js( __( 'Product description', 'woocommerce' ) ),
					)
				);
			}

			// Meta boxes.
			/* phpcs:disable */
			if ( in_array( $screen_id, array( 'product', 'edit-product' ) ) ) {
				wp_enqueue_media();
				wp_register_script( 'wc-admin-product-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes-product' . $suffix . '.js', array( 'wc-admin-meta-boxes', 'media-models' ), $version );
				wp_register_script( 'wc-admin-variation-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes-product-variation' . $suffix . '.js', array( 'wc-admin-meta-boxes', 'wc-serializejson', 'media-models', 'backbone', 'jquery-ui-sortable', 'wc-backbone-modal', 'wp-data', 'wp-notices' ), $version );

				wp_enqueue_script( 'wc-admin-product-meta-boxes' );
				wp_enqueue_script( 'wc-admin-variation-meta-boxes' );

				$params = array(
					'post_id'                             => isset( $post->ID ) ? $post->ID : '',
					'plugin_url'                          => WC()->plugin_url(),
					'ajax_url'                            => admin_url( 'admin-ajax.php' ),
					'woocommerce_placeholder_img_src'     => wc_placeholder_img_src(),
					'add_variation_nonce'                 => wp_create_nonce( 'add-variation' ),
					'link_variation_nonce'                => wp_create_nonce( 'link-variations' ),
					'delete_variations_nonce'             => wp_create_nonce( 'delete-variations' ),
					'load_variations_nonce'               => wp_create_nonce( 'load-variations' ),
					'save_variations_nonce'               => wp_create_nonce( 'save-variations' ),
					'bulk_edit_variations_nonce'          => wp_create_nonce( 'bulk-edit-variations' ),
					/* translators: %d: Number of variations */
					'i18n_link_all_variations'            => esc_js( sprintf( __( 'Do you want to generate all variations? This will create a new variation for each and every possible combination of variation attributes (max %d per run).', 'woocommerce' ), Constants::is_defined( 'WC_MAX_LINKED_VARIATIONS' ) ? Constants::get_constant( 'WC_MAX_LINKED_VARIATIONS' ) : 50 ) ),
					'i18n_enter_a_value'                  => esc_js( __( 'Enter a value', 'woocommerce' ) ),
					'i18n_enter_menu_order'               => esc_js( __( 'Variation menu order (determines position in the list of variations)', 'woocommerce' ) ),
					'i18n_enter_a_value_fixed_or_percent' => esc_js( __( 'Enter a value (fixed or %)', 'woocommerce' ) ),
					'i18n_sale_price_warning'            => esc_js( __( 'Warning: Sale prices will be removed if they are not lower than regular prices.', 'woocommerce' ) ),
					'i18n_delete_all_variations'          => esc_js( __( 'Are you sure you want to delete all variations? This cannot be undone.', 'woocommerce' ) ),
					'i18n_last_warning'                   => esc_js( __( 'Last warning, are you sure?', 'woocommerce' ) ),
					'i18n_choose_image'                   => esc_js( __( 'Choose an image', 'woocommerce' ) ),
					'i18n_set_image'                      => esc_js( __( 'Set variation image', 'woocommerce' ) ),
					'i18n_variation_added'                => esc_js( __( '1 variation added', 'woocommerce' ) ),
					'i18n_variations_added'               => esc_js( __( '%qty% variations added', 'woocommerce' ) ),
					'i18n_remove_variation'               => esc_js( __( 'Are you sure you want to remove this variation?', 'woocommerce' ) ),
					'i18n_scheduled_sale_start'           => esc_js( __( 'Sale start date (YYYY-MM-DD format or leave blank)', 'woocommerce' ) ),
					'i18n_scheduled_sale_end'             => esc_js( __( 'Sale end date (YYYY-MM-DD format or leave blank)', 'woocommerce' ) ),
					'i18n_edited_variations'              => esc_js( __( 'Save changes before changing page?', 'woocommerce' ) ),
					'i18n_variation_count_single'         => esc_js( __( '1 variation', 'woocommerce' ) ),
					'i18n_variation_count_plural'         => esc_js( __( '%qty% variations', 'woocommerce' ) ),
					'i18n_variation_cost_remove_warning'  => esc_js( __( 'The custom cost of goods sold values will revert back to their defaults for all the variations. Would you like to continue?', 'woocommerce' ) ),
					'variations_per_page'                 => absint( apply_filters( 'woocommerce_admin_meta_boxes_variations_per_page', 15 ) ),
				);

				wp_localize_script( 'wc-admin-variation-meta-boxes', 'woocommerce_admin_meta_boxes_variations', $params );
			}
			/* phpcs: enable */
			if ( $this->is_order_meta_box_screen( $screen_id ) ) {
				$default_location = wc_get_customer_default_location();

				wp_enqueue_script( 'wc-admin-order-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes-order' . $suffix . '.js', array( 'wc-admin-meta-boxes', 'wc-backbone-modal', 'selectWoo', 'wc-clipboard' ), $version );
				wp_localize_script(
					'wc-admin-order-meta-boxes',
					'woocommerce_admin_meta_boxes_order',
					array(
						'countries'              => wp_json_encode(
							array_merge( WC()->countries->get_allowed_country_states(), WC()->countries->get_shipping_country_states() ),
							JSON_HEX_TAG | JSON_UNESCAPED_SLASHES
						),
						'i18n_select_state_text' => esc_attr__( 'Select an option&hellip;', 'woocommerce' ),
						'default_country'        => isset( $default_location['country'] ) ? $default_location['country'] : '',
						'default_state'          => isset( $default_location['state'] ) ? $default_location['state'] : '',
						'placeholder_name'       => esc_attr__( 'Name (required)', 'woocommerce' ),
						'placeholder_value'      => esc_attr__( 'Value (required)', 'woocommerce' ),
					)
				);
			}
			/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
			if ( in_array( $screen_id, array( 'shop_coupon', 'edit-shop_coupon' ) ) ) {
				wp_enqueue_script( 'wc-admin-coupon-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes-coupon' . $suffix . '.js', array( 'wc-admin-meta-boxes' ), $version );
				wp_localize_script(
					'wc-admin-coupon-meta-boxes',
					'woocommerce_admin_meta_boxes_coupon',
					array(
						'generate_button_text' => esc_html__( 'Generate coupon code', 'woocommerce' ),
						'characters'           => apply_filters( 'woocommerce_coupon_code_generator_characters', 'ABCDEFGHJKMNPQRSTUVWXYZ23456789' ),
						'char_length'          => apply_filters( 'woocommerce_coupon_code_generator_character_length', 8 ),
						'prefix'               => apply_filters( 'woocommerce_coupon_code_generator_prefix', '' ),
						'suffix'               => apply_filters( 'woocommerce_coupon_code_generator_suffix', '' ),
					)
				);
			}
			/* phpcs: enable */
			if ( in_array( str_replace( 'edit-', '', $screen_id ), array( 'shop_coupon', 'product' ), true ) || $this->is_order_meta_box_screen( $screen_id ) ) {
				$post_id                = isset( $post->ID ) ? $post->ID : '';
				$currency               = '';
				$remove_item_notice     = __( 'Are you sure you want to remove the selected items?', 'woocommerce' );
				$remove_fee_notice      = __( 'Are you sure you want to remove the selected fees?', 'woocommerce' );
				$remove_shipping_notice = __( 'Are you sure you want to remove the selected shipping?', 'woocommerce' );

				// Eventually this will become wc_data_or_post object as we implement more custom tables.
				$order_or_post_object = $post;
				if ( ( $theorder instanceof WC_Order ) && $this->is_order_meta_box_screen( $screen_id ) ) {
					$order_or_post_object = $theorder;
					if ( $order_or_post_object ) {
						$currency = $order_or_post_object->get_currency();

						if ( ! $order_or_post_object->has_status( array( OrderStatus::PENDING, OrderStatus::FAILED, OrderStatus::CANCELLED ) ) ) {
							$remove_item_notice = $remove_item_notice . ' ' . __( "You may need to manually restore the item's stock.", 'woocommerce' );
						}
					}
				}

				$params = array(
					'remove_item_notice'                              => $remove_item_notice,
					'remove_fee_notice'                               => $remove_fee_notice,
					'remove_shipping_notice'                          => $remove_shipping_notice,
					'i18n_select_items'                               => __( 'Please select some items.', 'woocommerce' ),
					'i18n_do_refund'                                  => __( 'Are you sure you wish to process this refund? This action cannot be undone.', 'woocommerce' ),
					'i18n_delete_refund'                              => __( 'Are you sure you wish to delete this refund? This action cannot be undone.', 'woocommerce' ),
					'i18n_delete_tax'                                 => __( 'Are you sure you wish to delete this tax column? This action cannot be undone.', 'woocommerce' ),
					'remove_item_meta'                                => __( 'Remove this item meta?', 'woocommerce' ),
					'name_label'                                      => __( 'Name', 'woocommerce' ),
					'remove_label'                                    => __( 'Remove', 'woocommerce' ),
					'click_to_toggle'                                 => __( 'Click to toggle', 'woocommerce' ),
					'values_label'                                    => __( 'Value(s)', 'woocommerce' ),
					'text_attribute_tip'                              => __( 'Enter some text, or some attributes by pipe (|) separating values.', 'woocommerce' ),
					'visible_label'                                   => __( 'Visible on the product page', 'woocommerce' ),
					'used_for_variations_label'                       => __( 'Used for variations', 'woocommerce' ),
					'new_attribute_prompt'                            => __( 'Enter a name for the new attribute term:', 'woocommerce' ),
					'calc_totals'                                     => __( 'Recalculate totals? This will calculate taxes based on the customers country (or the store base country) and update totals.', 'woocommerce' ),
					'copy_billing'                                    => __( 'Copy billing information to shipping information? This will remove any currently entered shipping information.', 'woocommerce' ),
					'load_billing'                                    => __( "Load the customer's billing information? This will remove any currently entered billing information.", 'woocommerce' ),
					'load_shipping'                                   => __( "Load the customer's shipping information? This will remove any currently entered shipping information.", 'woocommerce' ),
					'featured_label'                                  => __( 'Featured', 'woocommerce' ),
					'prices_include_tax'                              => esc_attr( get_option( 'woocommerce_prices_include_tax' ) ),
					'tax_based_on'                                    => esc_attr( get_option( 'woocommerce_tax_based_on' ) ),
					'round_at_subtotal'                               => esc_attr( get_option( 'woocommerce_tax_round_at_subtotal' ) ),
					'no_customer_selected'                            => __( 'No customer selected', 'woocommerce' ),
					'plugin_url'                                      => WC()->plugin_url(),
					'ajax_url'                                        => admin_url( 'admin-ajax.php' ),
					'order_item_nonce'                                => wp_create_nonce( 'order-item' ),
					'add_attribute_nonce'                             => wp_create_nonce( 'add-attribute' ),
					'save_attributes_nonce'                           => wp_create_nonce( 'save-attributes' ),
					'add_attributes_and_variations'                   => wp_create_nonce( 'add-attributes-and-variations' ),
					'calc_totals_nonce'                               => wp_create_nonce( 'calc-totals' ),
					'get_customer_details_nonce'                      => wp_create_nonce( 'get-customer-details' ),
					'search_products_nonce'                           => wp_create_nonce( 'search-products' ),
					'grant_access_nonce'                              => wp_create_nonce( 'grant-access' ),
					'revoke_access_nonce'                             => wp_create_nonce( 'revoke-access' ),
					'add_order_note_nonce'                            => wp_create_nonce( 'add-order-note' ),
					'delete_order_note_nonce'                         => wp_create_nonce( 'delete-order-note' ),
					'calendar_image'                                  => WC()->plugin_url() . '/assets/images/calendar.png',
					'post_id'                                         => $this->is_order_meta_box_screen( $screen_id ) && isset( $order_or_post_object ) ? \Automattic\WooCommerce\Utilities\OrderUtil::get_post_or_order_id( $order_or_post_object ) : $post_id,
					'base_country'                                    => WC()->countries->get_base_country(),
					'currency_format_num_decimals'                    => wc_get_price_decimals(),
					'currency_format_symbol'                          => get_woocommerce_currency_symbol( $currency ),
					'currency_format_decimal_sep'                     => esc_attr( wc_get_price_decimal_separator() ),
					'currency_format_thousand_sep'                    => esc_attr( wc_get_price_thousand_separator() ),
					'currency_format'                                 => esc_attr( str_replace( array( '%1$s', '%2$s' ), array( '%s', '%v' ), get_woocommerce_price_format() ) ), // For accounting JS.
					'rounding_precision'                              => wc_get_rounding_precision(),
					'tax_rounding_mode'                               => wc_get_tax_rounding_mode(),
					'product_types'                                   => array_unique( array_merge( array( ProductType::SIMPLE, ProductType::GROUPED, ProductType::VARIABLE, ProductType::EXTERNAL ), array_keys( wc_get_product_types() ) ) ),
					'i18n_download_permission_fail'                   => __( 'Could not grant access - the user may already have permission for this file or billing email is not set. Ensure the billing email is set, and the order has been saved.', 'woocommerce' ),
					'i18n_permission_revoke'                          => __( 'Are you sure you want to revoke access to this download?', 'woocommerce' ),
					'i18n_tax_rate_already_exists'                    => __( 'You cannot add the same tax rate twice!', 'woocommerce' ),
					'i18n_delete_note'                                => __( 'Are you sure you wish to delete this note? This action cannot be undone.', 'woocommerce' ),
					'i18n_apply_coupon'                               => __( 'Enter a coupon code to apply. Discounts are applied to line totals, before taxes.', 'woocommerce' ),
					'i18n_add_fee'                                    => __( 'Enter a fixed amount or percentage to apply as a fee.', 'woocommerce' ),
					'i18n_attribute_name_placeholder'                 => __( 'New attribute', 'woocommerce' ),
					'i18n_product_simple_tip'                         => __( '<b>Simple –</b> covers the vast majority of any products you may sell. Simple products are shipped and have no options. For example, a book.', 'woocommerce' ),
					'i18n_product_grouped_tip'                        => __( '<b>Grouped –</b> a collection of related products that can be purchased individually and only consist of simple products. For example, a set of six drinking glasses.', 'woocommerce' ),
					'i18n_product_external_tip'                       => __( '<b>External or Affiliate –</b> one that you list and describe on your website but is sold elsewhere.', 'woocommerce' ),
					'i18n_product_variable_tip'                       => __( '<b>Variable –</b> a product with variations, each of which may have a different SKU, price, stock option, etc. For example, a t-shirt available in different colors and/or sizes.', 'woocommerce' ),
					'i18n_product_other_tip'                          => __( 'Product types define available product details and attributes, such as downloadable files and variations. They’re also used for analytics and inventory management.', 'woocommerce' ),
					'i18n_product_description_tip'                    => __( 'Describe this product. What makes it unique? What are its most important features?', 'woocommerce' ),
					'i18n_product_short_description_tip'              => __( 'Summarize this product in 1-2 short sentences. We’ll show it at the top of the page.', 'woocommerce' ),
					'i18n_save_attribute_variation_tip'               => __( 'Make sure you enter the name and values for each attribute.', 'woocommerce' ),
					/* translators: %1$s: maximum file size */
					'i18n_product_image_tip'                          => sprintf( __( 'For best results, upload JPEG or PNG files that are 1000 by 1000 pixels or larger. Maximum upload file size: %1$s.', 'woocommerce' ), size_format( wp_max_upload_size() ) ),
					'i18n_remove_used_attribute_confirmation_message' => __( 'If you remove this attribute, customers will no longer be able to purchase some variations of this product.', 'woocommerce' ),
					'i18n_add_attribute_error_notice'                 => __( 'Adding new attribute failed.', 'woocommerce' ),
					/* translators: %s: WC_DELIMITER */
					'i18n_attributes_default_placeholder'             => sprintf( esc_attr__( 'Enter some descriptive text. Use “%s” to separate different values.', 'woocommerce' ), esc_attr( WC_DELIMITER ) ),
					'i18n_attributes_used_for_variations_placeholder' => sprintf( esc_attr__( 'Enter options for customers to choose from, f.e. “Blue” or “Large”. Use “%s” to separate different options.', 'woocommerce' ), esc_attr( WC_DELIMITER ) )
				);

				$cogs_controller = wc_get_container()->get( CostOfGoodsSoldController::class );
				if( $cogs_controller->feature_is_enabled() ) {
					$params['cogs_value_tooltip_simple_products'] = esc_attr( $cogs_controller->get_general_cost_edit_field_tooltip( false ) );
					$params['cogs_value_tooltip_variable_products'] = esc_attr( $cogs_controller->get_general_cost_edit_field_tooltip( true ) );
				}
				wp_localize_script( 'wc-admin-meta-boxes', 'woocommerce_admin_meta_boxes', $params );
			}

			// Term ordering - only when sorting by term_order.
			/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
			if ( ( strstr( $screen_id, 'edit-pa_' ) || ( ! empty( $_GET['taxonomy'] ) && in_array( wp_unslash( $_GET['taxonomy'] ), apply_filters( 'woocommerce_sortable_taxonomies', array( 'product_cat' ) ) ) ) ) && ! isset( $_GET['orderby'] ) ) {

				wp_register_script( 'woocommerce_term_ordering', WC()->plugin_url() . '/assets/js/admin/term-ordering' . $suffix . '.js', array( 'jquery-ui-sortable' ), $version );
				wp_enqueue_script( 'woocommerce_term_ordering' );

				$taxonomy = isset( $_GET['taxonomy'] ) ? wc_clean( wp_unslash( $_GET['taxonomy'] ) ) : '';

				$woocommerce_term_order_params = array(
					'taxonomy' => $taxonomy,
					'nonce'    => wp_create_nonce( 'term-ordering' ),
				);

				wp_localize_script( 'woocommerce_term_ordering', 'woocommerce_term_ordering_params', $woocommerce_term_order_params );
			}
			/* phpcs: enable */

			// Product sorting - only when sorting by menu order on the products page.
			if ( current_user_can( 'edit_others_pages' ) && 'edit-product' === $screen_id && isset( $wp_query->query['orderby'] ) && 'menu_order title' === $wp_query->query['orderby'] ) {
				wp_register_script( 'woocommerce_product_ordering', WC()->plugin_url() . '/assets/js/admin/product-ordering' . $suffix . '.js', array( 'jquery-ui-sortable' ), $version, true );
				wp_enqueue_script( 'woocommerce_product_ordering' );

				wp_localize_script(
					'woocommerce_product_ordering',
					'woocommerce_product_ordering_params',
					array( 'nonce' => wp_create_nonce( 'product-ordering' ) )
				);
			}

			// Reports Pages.
			/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
			if ( in_array( $screen_id, apply_filters( 'woocommerce_reports_screen_ids', array( $wc_screen_id . '_page_wc-reports', 'toplevel_page_wc-reports' ) ) ) ) {
				wp_register_script( 'wc-reports', WC()->plugin_url() . '/assets/js/admin/reports' . $suffix . '.js', array( 'jquery', 'jquery-ui-datepicker' ), $version );

				wp_enqueue_script( 'wc-reports' );
				wp_enqueue_script( 'wc-flot' );
				wp_enqueue_script( 'wc-flot-resize' );
				wp_enqueue_script( 'wc-flot-time' );
				wp_enqueue_script( 'wc-flot-pie' );
				wp_enqueue_script( 'wc-flot-stack' );
			}
			/* phpcs: enable */

			// API settings.
			if ( $wc_screen_id . '_page_wc-settings' === $screen_id && isset( $_GET['section'] ) && 'keys' == $_GET['section'] ) {
				wp_register_script( 'wc-api-keys', WC()->plugin_url() . '/assets/js/admin/api-keys' . $suffix . '.js', array( 'jquery', 'woocommerce_admin', 'underscore', 'backbone', 'wp-util', 'wc-qrcode', 'wc-clipboard' ), $version, true );
				wp_enqueue_script( 'wc-api-keys' );
				wp_localize_script(
					'wc-api-keys',
					'woocommerce_admin_api_keys',
					array(
						'ajax_url'         => admin_url( 'admin-ajax.php' ),
						'update_api_nonce' => wp_create_nonce( 'update-api-key' ),
						'clipboard_failed' => esc_html__( 'Copying to clipboard failed. Please press Ctrl/Cmd+C to copy.', 'woocommerce' ),
					)
				);
			}

			// Email settings.
			if ( $wc_screen_id . '_page_wc-settings' === $screen_id && isset( $_GET['tab'] ) && 'email' === $_GET['tab'] ) {
				wp_enqueue_media();
			}

			// System status.
			if ( $wc_screen_id . '_page_wc-status' === $screen_id ) {
				wp_register_script( 'wc-admin-system-status', WC()->plugin_url() . '/assets/js/admin/system-status' . $suffix . '.js', array( 'wc-clipboard' ), $version );
				wp_enqueue_script( 'wc-admin-system-status' );
				wp_localize_script(
					'wc-admin-system-status',
					'woocommerce_admin_system_status',
					array(
						'delete_log_confirmation' => esc_js( __( 'Are you sure you want to delete this log?', 'woocommerce' ) ),
						'run_tool_confirmation'   => esc_js( __( 'Are you sure you want to run this tool?', 'woocommerce' ) ),
					)
				);
			}

			if ( in_array( $screen_id, array( 'user-edit', 'profile' ) ) ) {
				wp_register_script( 'wc-users', WC()->plugin_url() . '/assets/js/admin/users' . $suffix . '.js', array( 'jquery', 'wc-enhanced-select', 'selectWoo' ), $version, true );
				wp_enqueue_script( 'wc-users' );
				wp_localize_script(
					'wc-users',
					'wc_users_params',
					array(
						'countries'              => wp_json_encode(
							array_merge( WC()->countries->get_allowed_country_states(), WC()->countries->get_shipping_country_states() ),
							JSON_HEX_TAG | JSON_UNESCAPED_SLASHES
						),
						'i18n_select_state_text' => esc_attr__( 'Select an option&hellip;', 'woocommerce' ),
					)
				);
			}

			if ( WC_Marketplace_Suggestions::show_suggestions_for_screen( $screen_id ) ) {
				$active_plugin_slugs = array_map( 'dirname', get_option( 'active_plugins' ) );
				wp_register_script(
					'marketplace-suggestions',
					WC()->plugin_url() . '/assets/js/admin/marketplace-suggestions' . $suffix . '.js',
					array( 'jquery', 'underscore', 'wc-js-cookie' ),
					$version,
					true
				);
				wp_localize_script(
					'marketplace-suggestions',
					'marketplace_suggestions',
					array(
						'dismiss_suggestion_nonce' => wp_create_nonce( 'add_dismissed_marketplace_suggestion' ),
						'active_plugins'           => $active_plugin_slugs,
						'dismissed_suggestions'    => WC_Marketplace_Suggestions::get_dismissed_suggestions(),
						'suggestions_data'         => WC_Marketplace_Suggestions::get_suggestions_api_data(),
						'manage_suggestions_url'   => admin_url( 'admin.php?page=wc-settings&tab=advanced&section=woocommerce_com' ),
						'in_app_purchase_params'   => WC_Admin_Addons::get_in_app_purchase_url_params(),
						'admin_base_url'           => admin_url(),
						'i18n_marketplace_suggestions_default_cta'
							=> esc_html__( 'Learn More', 'woocommerce' ),
						'i18n_marketplace_suggestions_dismiss_tooltip'
							=> esc_attr__( 'Dismiss this suggestion', 'woocommerce' ),
						'i18n_marketplace_suggestions_manage_suggestions'
							=> esc_html__( 'Manage suggestions', 'woocommerce' ),
					)
				);
				wp_enqueue_script( 'marketplace-suggestions' );
			}

			// Marketplace promotions.
			if ( in_array( $screen_id, array( 'edit-shop_coupon', 'woocommerce_page_wc-admin' ), true ) ) {

				$promotions = WC_Admin_Marketplace_Promotions::get_active_promotions();

				if ( false === $promotions ) {
					return;
				}

				wp_add_inline_script(
					'wc-admin-app',
					'window.wcMarketplace = ' . wp_json_encode( array( 'promotions' => $promotions ), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
					'before'
				);
			}
		}

		/**
		 * Enqueue a script in the block editor.
		 * Similar to `WCAdminAssets::register_script()` but without enqueuing unnecessary dependencies.
		 *
		 * @return void
		 */
		private function enqueue_block_editor_script( $script_path_name, $script_name ) {
			$script_assets_filename = WCAdminAssets::get_script_asset_filename( $script_path_name, $script_name );
			$script_assets          = require WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER .  $script_path_name . '/' . $script_assets_filename;

			wp_enqueue_script(
				'wc-admin-' . $script_name,
				WCAdminAssets::get_url( $script_path_name . '/' . $script_name, 'js' ),
				$script_assets['dependencies'],
				WCAdminAssets::get_file_version( 'js', $script_assets['version'] ),
				true
			);
		}

		/**
		 * Enqueue block editor assets.
		 *
		 * @return void
		 */
		public function enqueue_block_editor_assets() {
			$settings_tabs = apply_filters('woocommerce_settings_tabs_array', []);

			if ( is_array( $settings_tabs ) && count( $settings_tabs ) > 0  ) {
				$formatted_settings_tabs = array();
				foreach ($settings_tabs as $key => $label) {
					if (
						is_string( $key ) && $key !== "" &&
						is_string( $label ) && $label !== ""
					) {
						$formatted_settings_tabs[] = array(
							'key'   => $key,
							'label' => wp_strip_all_tags( $label ),
						);
					}
				}

				self::enqueue_block_editor_script( 'wp-admin-scripts', 'command-palette' );
				wp_localize_script(
					'wc-admin-command-palette',
					'wcCommandPaletteSettings',
					array(
						'settingsTabs'    => $formatted_settings_tabs,
					)
				);
			}

			$admin_features_disabled = apply_filters( 'woocommerce_admin_disabled', false );
			if ( ! $admin_features_disabled ) {
				$analytics_reports = Analytics::get_report_pages();
				if ( is_array( $analytics_reports ) && count( $analytics_reports ) > 0 ) {
					$formatted_analytics_reports = array_map( function( $report ) {
						if ( ! is_array( $report ) ) {
							return null;
						}
						$title = array_key_exists( 'title', $report ) ? $report['title'] : '';
						$path = array_key_exists( 'path', $report ) ? $report['path'] : '';
						if (
							is_string( $title ) && $title !== "" &&
							is_string( $path ) && $path !== ""
						) {
							return array(
								'title' => wp_strip_all_tags( $title ),
								'path' => $path,
							);
						}
						return null;
					}, $analytics_reports );
					$formatted_analytics_reports = array_filter( $formatted_analytics_reports, 'is_array' );

					self::enqueue_block_editor_script( 'wp-admin-scripts', 'command-palette-analytics' );
					wp_localize_script(
						'wc-admin-command-palette-analytics',
						'wcCommandPaletteAnalytics',
						array(
							'reports'    => $formatted_analytics_reports,
						)
					);
				}
			}
		}

		/**
		 * Helper function to determine whether the current screen is an order edit screen.
		 *
		 * @param string $screen_id Screen ID.
		 *
		 * @return bool Whether the current screen is an order edit screen.
		 */
		private function is_order_meta_box_screen( $screen_id ) {
			$screen_id = str_replace( 'edit-', '', $screen_id );

			$types_with_metaboxes_screen_ids = array_filter(
				array_map(
					'wc_get_page_screen_id',
					wc_get_order_types( 'order-meta-boxes' )
				)
			);

			return in_array( $screen_id, $types_with_metaboxes_screen_ids, true );
		}

	}

endif;

return new WC_Admin_Assets();
PK     tS\'6  6    wc-meta-box-functions.phpnu [        <?php
/**
 * WooCommerce Meta Box Functions
 *
 * @author      WooThemes
 * @category    Core
 * @package     WooCommerce\Admin\Functions
 * @version     2.3.0
 */

use Automattic\WooCommerce\Utilities\OrderUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

/**
 * Output a text input box.
 *
 * @param array        $field Field data.
 * @param WC_Data|null $data  WC_Data object, will be preferred over post object when passed.
 */
function woocommerce_wp_text_input( $field, ?WC_Data $data = null ) {
	global $post;

	$field['placeholder']   = isset( $field['placeholder'] ) ? $field['placeholder'] : '';
	$field['class']         = isset( $field['class'] ) ? $field['class'] : 'short';
	$field['style']         = isset( $field['style'] ) ? $field['style'] : '';
	$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
	$field['value']         = $field['value'] ?? OrderUtil::get_post_or_object_meta( $post, $data, $field['id'], true );
	$field['name']          = isset( $field['name'] ) ? $field['name'] : $field['id'];
	$field['type']          = isset( $field['type'] ) ? $field['type'] : 'text';
	$field['desc_tip']      = isset( $field['desc_tip'] ) ? $field['desc_tip'] : false;
	$data_type              = empty( $field['data_type'] ) ? '' : $field['data_type'];

	switch ( $data_type ) {
		case 'price':
			$field['class'] .= ' wc_input_price';
			$field['value']  = wc_format_localized_price( $field['value'] );
			break;
		case 'decimal':
			$field['class'] .= ' wc_input_decimal';
			$field['value']  = wc_format_localized_decimal( $field['value'] );
			break;
		case 'stock':
			$field['class'] .= ' wc_input_stock';
			$field['value']  = wc_stock_amount( $field['value'] );
			break;
		case 'url':
			$field['class'] .= ' wc_input_url';
			$field['value']  = esc_url( $field['value'] );
			break;

		default:
			break;
	}

	// Custom attribute handling
	$custom_attributes = array();

	if ( ! empty( $field['custom_attributes'] ) && is_array( $field['custom_attributes'] ) ) {

		foreach ( $field['custom_attributes'] as $attribute => $value ) {
			$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $value ) . '"';
		}
	}

	echo '<p class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '">
		<label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label>';

	$help_tip    = null;
	$description = null;
	if ( ! empty( $field['description'] ) ) {
		if ( is_array( $field['description'] ) ) {
			$help_tip    = reset( $field['description'] );
			$description = end( $field['description'] );
		} elseif ( false !== $field['desc_tip'] ) {
			$help_tip = $field['description'];
		} else {
			$description = $field['description'];
		}
	}

	if ( ! is_null( $help_tip ) ) {
		echo wc_help_tip( $help_tip );
	}

	echo '<input type="' . esc_attr( $field['type'] ) . '" class="' . esc_attr( $field['class'] ) . '" style="' . esc_attr( $field['style'] ) . '" name="' . esc_attr( $field['name'] ) . '" id="' . esc_attr( $field['id'] ) . '" value="' . esc_attr( $field['value'] ) . '" placeholder="' . esc_attr( $field['placeholder'] ) . '" ' . implode( ' ', $custom_attributes ) . ' /> ';

	if ( ! is_null( $description ) ) {
		$hidden_class = true === ( $field['description_hidden'] ?? false ) ? ' hidden' : '';
		//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo '<span class="description' . $hidden_class . '">' . wp_kses_post( $description ) . '</span>';
	}

	echo '</p>';
}

/**
 * Output a hidden input box.
 *
 * @param array        $field Field data.
 * @param WC_Data|null $data  WC_Data object, will be preferred over post object when passed.
 */
function woocommerce_wp_hidden_input( $field, ?WC_Data $data = null ) {
	global $post;

	$field['value'] = isset( $field['value'] ) ? $field['value'] : OrderUtil::get_post_or_object_meta( $post, $data, $field['id'], true );
	$field['class'] = isset( $field['class'] ) ? $field['class'] : '';

	echo '<input type="hidden" class="' . esc_attr( $field['class'] ) . '" name="' . esc_attr( $field['id'] ) . '" id="' . esc_attr( $field['id'] ) . '" value="' . esc_attr( $field['value'] ) . '" /> ';
}

/**
 * Output a textarea input box.
 *
 * @param array        $field Field data.
 * @param WC_Data|null $data  WC_Data object, will be preferred over post object when passed.
 */
function woocommerce_wp_textarea_input( $field, ?WC_Data $data = null ) {
	global $post;

	$field['placeholder']   = isset( $field['placeholder'] ) ? $field['placeholder'] : '';
	$field['class']         = isset( $field['class'] ) ? $field['class'] : 'short';
	$field['style']         = isset( $field['style'] ) ? $field['style'] : '';
	$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
	$field['value']         = $field['value'] ?? OrderUtil::get_post_or_object_meta( $post, $data, $field['id'], true );
	$field['desc_tip']      = isset( $field['desc_tip'] ) ? $field['desc_tip'] : false;
	$field['name']          = isset( $field['name'] ) ? $field['name'] : $field['id'];
	$field['rows']          = isset( $field['rows'] ) ? $field['rows'] : 2;
	$field['cols']          = isset( $field['cols'] ) ? $field['cols'] : 20;

	// Custom attribute handling
	$custom_attributes = array();

	if ( ! empty( $field['custom_attributes'] ) && is_array( $field['custom_attributes'] ) ) {

		foreach ( $field['custom_attributes'] as $attribute => $value ) {
			$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $value ) . '"';
		}
	}

	echo '<p class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '">
		<label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label>';

	if ( ! empty( $field['description'] ) && false !== $field['desc_tip'] ) {
		echo wc_help_tip( $field['description'] );
	}

	echo '<textarea class="' . esc_attr( $field['class'] ) . '" style="' . esc_attr( $field['style'] ) . '"  name="' . esc_attr( $field['name'] ) . '" id="' . esc_attr( $field['id'] ) . '" placeholder="' . esc_attr( $field['placeholder'] ) . '" rows="' . esc_attr( $field['rows'] ) . '" cols="' . esc_attr( $field['cols'] ) . '" ' . implode( ' ', $custom_attributes ) . '>' . esc_textarea( $field['value'] ) . '</textarea> ';

	if ( ! empty( $field['description'] ) && false === $field['desc_tip'] ) {
		echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
	}

	echo '</p>';
}

/**
 * Output a checkbox input box.
 *
 * @param array        $field Field data.
 * @param WC_Data|null $data  WC_Data object, will be preferred over post object when passed.
 */
function woocommerce_wp_checkbox( $field, ?WC_Data $data = null ) {
	global $post;

	$field['class']         = isset( $field['class'] ) ? $field['class'] : 'checkbox';
	$field['style']         = isset( $field['style'] ) ? $field['style'] : '';
	$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
	$field['value']         = $field['value'] ?? OrderUtil::get_post_or_object_meta( $post, $data, $field['id'], true );
	$field['cbvalue']       = isset( $field['cbvalue'] ) ? $field['cbvalue'] : 'yes';
	$field['name']          = isset( $field['name'] ) ? $field['name'] : $field['id'];
	$field['desc_tip']      = isset( $field['desc_tip'] ) ? $field['desc_tip'] : false;

	/**
	 * These values are what get passed vis $_POST depending on if the field is checked or not. If no unchecked_value is
	 * provided, the $_POST will not be set. This maintains backwards compatibility where consumers would use `isset`.
	 */
	$field['checked_value']   = isset( $field['checked_value'] ) ? $field['checked_value'] : $field['cbvalue'];
	$field['unchecked_value'] = isset( $field['unchecked_value'] ) ? $field['unchecked_value'] : null;

	// Custom attribute handling.
	$custom_attributes = array();

	if ( ! empty( $field['custom_attributes'] ) && is_array( $field['custom_attributes'] ) ) {

		foreach ( $field['custom_attributes'] as $attribute => $value ) {
			$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $value ) . '"';
		}
	}

	if ( ! empty( $field['style'] ) ) {
		$custom_attributes[] = 'style="' . esc_attr( $field['style'] ) . '"';
	}

	if ( ! empty( $field['class'] ) ) {
		$custom_attributes[] = 'class="' . esc_attr( $field['class'] ) . '"';
	}

	echo '<p class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '">
		<label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label>';

	if ( ! empty( $field['description'] ) && false !== $field['desc_tip'] ) {
		echo wc_help_tip( $field['description'] );
	}

	// Output a hidden field so a value is POSTed if the box is not checked.
	if ( ! is_null( $field['unchecked_value'] ) ) {
		printf( '<input type="hidden" name="%1$s" value="%2$s" />', esc_attr( $field['name'] ), esc_attr( $field['unchecked_value'] ) );
	}

	printf(
		'<input type="checkbox" name="%1$s" id="%2$s" value="%3$s" %4$s %5$s />',
		esc_attr( $field['name'] ),
		esc_attr( $field['id'] ),
		esc_attr( $field['checked_value'] ),
		checked( $field['value'], $field['checked_value'], false ),
		implode( ' ', $custom_attributes ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	);

	if ( ! empty( $field['description'] ) && false === $field['desc_tip'] ) {
		echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
	}

	echo '</p>';
}

/**
 * Output a select input box.
 *
 * @param array        $field Field data.
 * @param WC_Data|null $data  WC_Data object, will be preferred over post object when passed.
 */
function woocommerce_wp_select( $field, ?WC_Data $data = null ) {
	global $post;

	$field = wp_parse_args(
		$field,
		array(
			'class'             => 'select short',
			'style'             => '',
			'wrapper_class'     => '',
			'value'             => OrderUtil::get_post_or_object_meta( $post, $data, $field['id'], true ),
			'name'              => $field['id'],
			'desc_tip'          => false,
			'custom_attributes' => array(),
		)
	);

	$wrapper_attributes = array(
		'class' => $field['wrapper_class'] . " form-field {$field['id']}_field",
	);

	$label_attributes = array(
		'for' => $field['id'],
	);

	$field_attributes          = (array) $field['custom_attributes'];
	$field_attributes['style'] = $field['style'];
	$field_attributes['id']    = $field['id'];
	$field_attributes['name']  = $field['name'];
	$field_attributes['class'] = $field['class'];

	$tooltip     = ! empty( $field['description'] ) && false !== $field['desc_tip'] ? $field['description'] : '';
	$description = ! empty( $field['description'] ) && false === $field['desc_tip'] ? $field['description'] : '';
	?>
	<p <?php echo wc_implode_html_attributes( $wrapper_attributes ); // WPCS: XSS ok. ?>>
		<label <?php echo wc_implode_html_attributes( $label_attributes ); // WPCS: XSS ok. ?>><?php echo wp_kses_post( $field['label'] ); ?></label>
		<?php if ( $tooltip ) : ?>
			<?php echo wc_help_tip( $tooltip ); // WPCS: XSS ok. ?>
		<?php endif; ?>
		<select <?php echo wc_implode_html_attributes( $field_attributes ); // WPCS: XSS ok. ?>>
			<?php
			foreach ( $field['options'] as $key => $value ) {
				echo '<option value="' . esc_attr( $key ) . '"' . wc_selected( $key, $field['value'] ) . '>' . esc_html( $value ) . '</option>';
			}
			?>
		</select>
		<?php if ( $description ) : ?>
			<span class="description"><?php echo wp_kses_post( $description ); ?></span>
		<?php endif; ?>
	</p>
	<?php
}

/**
 * Output a radio input box.
 *
 * @param array        $field Field data.
 * @param WC_Data|null $data  WC_Data object, will be preferred over post object when passed.
 */
function woocommerce_wp_radio( $field, ?WC_Data $data = null ) {
	global $post;

	$field['class']         = isset( $field['class'] ) ? $field['class'] : 'select short';
	$field['style']         = isset( $field['style'] ) ? $field['style'] : '';
	$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
	$field['value']         = $field['value'] ?? OrderUtil::get_post_or_object_meta( $post, $data, $field['id'], true );
	$field['name']          = isset( $field['name'] ) ? $field['name'] : $field['id'];
	$field['desc_tip']      = isset( $field['desc_tip'] ) ? $field['desc_tip'] : false;

	echo '<fieldset class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '"><legend>' . wp_kses_post( $field['label'] ) . '</legend>';

	if ( ! empty( $field['description'] ) && false !== $field['desc_tip'] ) {
		echo wc_help_tip( $field['description'] );
	}

	echo '<ul class="wc-radios">';

	foreach ( $field['options'] as $key => $value ) {

		echo '<li><label><input
				name="' . esc_attr( $field['name'] ) . '"
				value="' . esc_attr( $key ) . '"
				type="radio"
				class="' . esc_attr( $field['class'] ) . '"
				style="' . esc_attr( $field['style'] ) . '"
				' . checked( esc_attr( $field['value'] ), esc_attr( $key ), false ) . '
				/> ' . esc_html( $value ) . '</label>
		</li>';
	}
	echo '</ul>';

	if ( ! empty( $field['description'] ) && false === $field['desc_tip'] ) {
		echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
	}

	echo '</fieldset>';
}

/**
 * Output a note.
 *
 * @param array $field Field data.
 */
function woocommerce_wp_note( $field ) {
	$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';

	echo '<p class="form-field ' . esc_attr( $field['wrapper_class'] ) . '">';
	echo '<label for="' . esc_attr( $field['id'] ) . '" ';

	if ( ! empty( $field['label-aria-label'] ) ) {
		echo 'aria-label="' . esc_attr( $field['label-aria-label'] ) . '"';
	}

	echo '>' . esc_attr( $field['label'] ) . '</label>';
	echo '<output name="' . esc_attr( $field['id'] ) . '" id="' . esc_attr( $field['id'] ) . '" aria-live="off">' . wp_kses_post( $field['message'] ) . '</output>';
	echo '</p>';
}
PK     tS\w.  .  )  class-wc-admin-marketplace-promotions.phpnu [        <?php
/**
 * Addons Page
 *
 * @package  WooCommerce\Admin
 * @version  2.5.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Admin_Marketplace_Promotions class.
 */
class WC_Admin_Marketplace_Promotions {

	const CRON_NAME           = 'woocommerce_marketplace_cron_fetch_promotions';
	const TRANSIENT_NAME      = 'woocommerce_marketplace_promotions_v2';
	const TRANSIENT_LIFE_SPAN = DAY_IN_SECONDS;
	const PROMOTIONS_API_URL  = 'https://woocommerce.com/wp-json/wccom-extensions/3.0/promotions';

	/**
	 * The user's locale, for example en_US.
	 *
	 * @var string
	 */
	public static string $locale;

	/**
	 * On all admin pages, try go get Marketplace promotions every day.
	 * Shows notice and adds menu badge to WooCommerce Extensions item
	 * if the promotions API requests them.
	 *
	 * WC_Admin calls this method when it is instantiated during
	 * is_admin requests.
	 *
	 * @return void
	 */
	public static function init() {
		// A legacy hook that can be triggered by action scheduler.
		add_action( 'woocommerce_marketplace_fetch_promotions', array( __CLASS__, 'clear_deprecated_action' ) );
		add_action(
			'woocommerce_marketplace_fetch_promotions_clear',
			array(
				__CLASS__,
				'clear_deprecated_scheduled_event',
			)
		);

		// Fetch promotions from the API and store them in a transient.
		add_action( self::CRON_NAME, array( __CLASS__, 'update_promotions' ) );

		if (
			defined( 'DOING_AJAX' ) && DOING_AJAX
			|| defined( 'DOING_CRON' ) && DOING_CRON
			|| defined( 'WP_CLI' ) && WP_CLI
		) {
			return;
		}

		if ( ! is_admin() ) {
			return;
		}

		self::schedule_cron_event();

		register_deactivation_hook( WC_PLUGIN_FILE, array( __CLASS__, 'clear_cron_event' ) );

		self::$locale = ( self::$locale ?? get_user_locale() ) ?? 'en_US';
		self::maybe_show_bubble_promotions();
	}

	/**
	 * Schedule a daily cron event to fetch promotions.
	 *
	 * @version 9.5.0
	 *
	 * @return void
	 */
	private static function schedule_cron_event() {
		if ( ! wp_next_scheduled( self::CRON_NAME ) ) {
			wp_schedule_event( time(), 'twicedaily', self::CRON_NAME );
		}
	}

	/**
	 * Fetch promotions from the API and store them in a transient.
	 *
	 * @return void
	 */
	public static function update_promotions() {
		// Fetch promotions from the API.
		$promotions = self::fetch_marketplace_promotions();
		set_transient( self::TRANSIENT_NAME, $promotions, self::TRANSIENT_LIFE_SPAN );
	}

	/**
	 * Get active Marketplace promotions from the transient.
	 * Use `woocommerce_marketplace_suppress_promotions` filter to suppress promotions.
	 *
	 * @since 9.0
	 */
	public static function get_active_promotions() {
		/**
		 * Filter to suppress the requests for and showing of marketplace promotions.
		 *
		 * @since 8.8
		 */
		if ( apply_filters( 'woocommerce_marketplace_suppress_promotions', false ) ) {
			return array();
		}

		$promotions = get_transient( self::TRANSIENT_NAME );
		if ( ! $promotions ) {
			return array();
		}

		$promotions = self::merge_promos( $promotions );

		return self::filter_out_inactive_promotions( $promotions );
	}

	/**
	 * Get promotions to show in the Woo in-app marketplace and load them into a transient
	 * with a 12-hour life. Run as a recurring scheduled action.
	 *
	 * @return array
	 */
	private static function fetch_marketplace_promotions() {
		/**
		 * Filter to suppress the requests for and showing of marketplace promotions.
		 *
		 * @since 8.8
		 */
		if ( apply_filters( 'woocommerce_marketplace_suppress_promotions', false ) ) {
			return array();
		}

		// Fetch promotions from the API.
		$fetch_options  = array(
			'auth'    => true,
			'country' => true,
		);
		$raw_promotions = WC_Admin_Addons::fetch( self::PROMOTIONS_API_URL, $fetch_options );

		// phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores
		if ( is_wp_error( $raw_promotions ) ) {
			/**
			 * Allows connection error to be handled.
			 *
			 * @since 8.7
			 */
			do_action( 'woocommerce_page_wc-addons_connection_error', $raw_promotions->get_error_message() );
		}

		$response_code = (int) wp_remote_retrieve_response_code( $raw_promotions );
		if ( 200 !== $response_code ) {
			/**
			 * Allows connection error to be handled.
			 *
			 * @since 8.7
			 */
			do_action( 'woocommerce_page_wc-addons_connection_error', $response_code );
		}

		$promotions = json_decode( wp_remote_retrieve_body( $raw_promotions ), true );

		if ( ! is_array( $promotions ) ) {
			$promotions = array();

			/**
			 * Allows connection error to be handled.
			 *
			 * @since 8.7
			 */
			do_action( 'woocommerce_page_wc-addons_connection_error', 'Malformed response' );
		}
		// phpcs:enable WordPress.NamingConventions.ValidHookName.UseUnderscores

		return $promotions;
	}

	/**
	 * If there's an active promotion of the format `menu_bubble`,
	 * add a filter to show a bubble on the Extensions item in the
	 * WooCommerce menu.
	 *
	 * Use `woocommerce_marketplace_suppress_promotions` filter to suppress the bubble.
	 *
	 * @return void
	 * @throws Exception  If we are unable to create a DateTime from the date_to_gmt.
	 */
	private static function maybe_show_bubble_promotions() {
		/**
		 * Filter to suppress the requests for and showing of marketplace promotions.
		 *
		 * @since 8.8
		 */
		if ( apply_filters( 'woocommerce_marketplace_suppress_promotions', false ) ) {
			return;
		}

		$promotions = get_transient( self::TRANSIENT_NAME );
		if ( ! $promotions ) {
			return;
		}

		$bubble_promotions = self::get_promotions_of_format( $promotions, 'menu_bubble' );
		if ( empty( $bubble_promotions ) ) {
			return;
		}

		$now_date_time = new DateTime( 'now', new DateTimeZone( 'UTC' ) );

		// Let's make absolutely sure the promotion is still active.
		foreach ( $bubble_promotions as $promotion ) {
			if ( ! isset( $promotion['date_to_gmt'] ) ) {
				continue;
			}

			try {
				$date_to_gmt = new DateTime( $promotion['date_to_gmt'], new DateTimeZone( 'UTC' ) );
			} catch ( \Exception $ex ) {
				continue;
			}

			if ( $now_date_time < $date_to_gmt ) {
				add_filter(
					'woocommerce_marketplace_menu_items',
					function ( $marketplace_pages ) use ( $promotion ) {
						return self::filter_marketplace_menu_items( $marketplace_pages, $promotion );
					}
				);

				break;
			}
		}
	}

	/**
	 * From the array of promotions, select those of a given format.
	 *
	 * @param ?array  $promotions  Array of data about promotions of all formats.
	 * @param ?string $format      Format we want to filter for.
	 *
	 * @return array
	 */
	private static function get_promotions_of_format( $promotions = array(), $format = '' ): array {
		if ( empty( $promotions ) || empty( $format ) ) {
			return array();
		}

		return array_filter(
			$promotions,
			function( $promotion ) use ( $format ) {
				return isset( $promotion['format'] ) && $format === $promotion['format'];
			}
		);
	}

	/**
	 * Find promotions that are still active – they have a date range that
	 * includes the current date.
	 *
	 * @param ?array $promotions  Data about current promotions.
	 *
	 * @return array
	 */
	private static function filter_out_inactive_promotions( $promotions = array() ) {
		$now_date_time     = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
		$active_promotions = array();

		foreach ( $promotions as $promotion ) {
			if ( ! isset( $promotion['date_from_gmt'] ) || ! isset( $promotion['date_to_gmt'] ) ) {
				continue;
			}

			try {
				$date_from_gmt = new DateTime( $promotion['date_from_gmt'], new DateTimeZone( 'UTC' ) );
				$date_to_gmt   = new DateTime( $promotion['date_to_gmt'], new DateTimeZone( 'UTC' ) );
			} catch ( \Exception $ex ) {
				continue;
			}

			if ( $now_date_time >= $date_from_gmt && $now_date_time <= $date_to_gmt ) {
				$active_promotions[] = $promotion;
			}
		}

		// Sort promotions so the ones starting more recently are at the top.
		usort(
			$active_promotions,
			function ( $a, $b ) {
				return $b['date_from_gmt'] <=> $a['date_from_gmt'];
			}
		);

		return $active_promotions;
	}

	/**
	 * Promos arrive in the array of promotions as an array of arrays with the key 'promos'.
	 * We merge them into the main array.
	 *
	 * @param ?array $promotions  Promotions data received from WCCOM.
	 *                            May have an element with the key 'promos', which contains an array.
	 *
	 * @return array
	 * */
	private static function merge_promos( ?array $promotions = array() ): array {
		if (
			! empty( $promotions['promos'] )
			&& is_array( $promotions['promos'] )
		) {
			$promotions = array_merge( $promotions, $promotions['promos'] );
			unset( $promotions['promos'] );
		}

		return $promotions;
	}

	/**
	 * Callback for the `woocommerce_marketplace_menu_items` filter
	 * in `Automattic\WooCommerce\Internal\Admin\Marketplace::get_marketplace_pages`.
	 * At the moment, the Extensions page is the only page in `$menu_items`.
	 * Adds a bubble to the menu item.
	 *
	 * @param array  $menu_items  Arrays representing items in nav menu.
	 * @param ?array $promotion   Data about a promotion from the WooCommerce.com API.
	 *
	 * @return array
	 */
	public static function filter_marketplace_menu_items( $menu_items, $promotion = array() ): array {
		if ( ! isset( $promotion['menu_item_id'] ) || ! isset( $promotion['content'] ) ) {
			return $menu_items;
		}
		foreach ( $menu_items as $index => $menu_item ) {
			if (
				'woocommerce' === $menu_item['parent']
				&& $promotion['menu_item_id'] === $menu_item['id']
			) {
				$bubble_text                   = $promotion['content'][ self::$locale ] ?? ( $promotion['content']['en_US'] ?? __( 'Sale', 'woocommerce' ) );
				$menu_items[ $index ]['title'] = self::append_bubble( $menu_item['title'], $bubble_text );

				break;
			}
		}

		return $menu_items;
	}

	/**
	 * Return the markup for a menu item bubble with a given text.
	 *
	 * @param string $menu_item_text Text of menu item we want to change.
	 * @param string $bubble_text    Text of bubble.
	 *
	 * @return string
	 */
	private static function append_bubble( string $menu_item_text, string $bubble_text ): string {
		// Strip out update count bubble added by Marketplace::get_marketplace_update_count_html.
		$menu_item_text = preg_replace( '|<span class="update-plugins count-[\d]+">[A-z0-9 <>="-]+</span>|', '', $menu_item_text );

		return $menu_item_text
			. '<span class="update-plugins remaining-tasks-badge woocommerce-task-list-remaining-tasks-badge">'
			. esc_html( $bubble_text )
			. '</span>';
	}

	/**
	 * When WooCommerce is disabled, clear the WP Cron event we use to fetch promotions.
	 *
	 * @version 9.5.0
	 *
	 * @return void
	 */
	public static function clear_cron_event() {
		$timestamp = wp_next_scheduled( self::CRON_NAME );
		wp_unschedule_event( $timestamp, self::CRON_NAME );
	}

	/**
	 * Clear deprecated scheduled action that was used to fetch promotions in WooCommerce 8.8.
	 * Replaced with a transient in WooCommerce 9.0.
	 *
	 * @return void
	 */
	public static function clear_deprecated_scheduled_event() {
		if ( function_exists( 'as_unschedule_all_actions' ) ) {
			as_unschedule_all_actions( 'woocommerce_marketplace_fetch_promotions' );
		}
	}

	/**
	 * We can't clear deprecated action from AS when it's running,
	 * so we schedule a new single action to clear the deprecated
	 * `woocommerce_marketplace_fetch_promotions` action.
	 */
	public static function clear_deprecated_action() {
		if ( function_exists( 'as_schedule_single_action' ) ) {
			as_schedule_single_action( time(), 'woocommerce_marketplace_fetch_promotions_clear' );
		}
	}
}

// Fetch list of promotions from WooCommerce.com for WooCommerce admin UI.
if ( ! has_action( 'init', array( 'WC_Admin_Marketplace_Promotions', 'init' ) ) ) {
	add_action( 'init', array( 'WC_Admin_Marketplace_Promotions', 'init' ), 11 );
}
PK     tS\'jG  G    class-wc-admin-api-keys.phpnu [        <?php
/**
 * WooCommerce Admin API Keys Class
 *
 * @package WooCommerce\Admin
 * @version 2.4.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * WC_Admin_API_Keys.
 */
class WC_Admin_API_Keys {

	/**
	 * Initialize the API Keys admin actions.
	 */
	public function __construct() {
		add_action( 'admin_init', array( $this, 'actions' ) );
		add_action( 'woocommerce_settings_page_init', array( $this, 'screen_option' ) );
		add_filter( 'woocommerce_save_settings_advanced_keys', array( $this, 'allow_save_settings' ) );
	}

	/**
	 * Check if should allow save settings.
	 * This prevents "Your settings have been saved." notices on the table list.
	 *
	 * @param  bool $allow If allow save settings.
	 * @return bool
	 */
	public function allow_save_settings( $allow ) {
		if ( ! isset( $_GET['create-key'], $_GET['edit-key'] ) ) { // WPCS: input var okay, CSRF ok.
			return false;
		}

		return $allow;
	}

	/**
	 * Check if is API Keys settings page.
	 *
	 * @return bool
	 */
	private function is_api_keys_settings_page() {
		return is_wc_admin_settings_page() && isset( $_GET['tab'], $_GET['section'] ) && 'advanced' === $_GET['tab'] && 'keys' === $_GET['section']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
	}

	/**
	 * Page output.
	 */
	public static function page_output() {
		// Hide the save button.
		$GLOBALS['hide_save_button'] = true;

		if ( isset( $_GET['create-key'] ) || isset( $_GET['edit-key'] ) ) {
			$key_id   = isset( $_GET['edit-key'] ) ? absint( $_GET['edit-key'] ) : 0; // WPCS: input var okay, CSRF ok.
			$key_data = self::get_key_data( $key_id );
			$user_id  = (int) $key_data['user_id'];

			if ( $key_id && $user_id && ! current_user_can( 'edit_user', $user_id ) ) {
				if ( get_current_user_id() !== $user_id ) {
					wp_die( esc_html__( 'You do not have permission to edit this API Key', 'woocommerce' ) );
				}
			}

			include dirname( __FILE__ ) . '/settings/views/html-keys-edit.php';
		} else {
			self::table_list_output();
		}
	}

	/**
	 * Add screen option.
	 */
	public function screen_option() {
		global $keys_table_list;

		if ( ! isset( $_GET['create-key'] ) && ! isset( $_GET['edit-key'] ) && $this->is_api_keys_settings_page() ) { // WPCS: input var okay, CSRF ok.
			$keys_table_list = new WC_Admin_API_Keys_Table_List();

			// Add screen option.
			add_screen_option(
				'per_page',
				array(
					'default' => 10,
					'option'  => 'woocommerce_keys_per_page',
				)
			);
		}
	}

	/**
	 * Table list output.
	 */
	private static function table_list_output() {
		global $wpdb, $keys_table_list;

		echo '<h2 class="wc-table-list-header">' . esc_html__( 'REST API', 'woocommerce' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys&create-key=1' ) ) . '" class="page-title-action">' . esc_html__( 'Add key', 'woocommerce' ) . '</a></h2>';

		// Get the API keys count.
		$count = $wpdb->get_var( "SELECT COUNT(key_id) FROM {$wpdb->prefix}woocommerce_api_keys WHERE 1 = 1;" );

		if ( absint( $count ) && $count > 0 ) {
			$keys_table_list->prepare_items();

			echo '<input type="hidden" name="page" value="wc-settings" />';
			echo '<input type="hidden" name="tab" value="advanced" />';
			echo '<input type="hidden" name="section" value="keys" />';

			$keys_table_list->views();
			$keys_table_list->search_box( __( 'Search key', 'woocommerce' ), 'key' );
			$keys_table_list->display();
		} else {
			echo '<div class="woocommerce-BlankState woocommerce-BlankState--api">';
			?>
			<h2 class="woocommerce-BlankState-message"><?php esc_html_e( 'The WooCommerce REST API allows external apps to view and manage store data. Access is granted only to those with valid API keys.', 'woocommerce' ); ?></h2>
			<a class="woocommerce-BlankState-cta button-primary button" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys&create-key=1' ) ); ?>"><?php esc_html_e( 'Create an API key', 'woocommerce' ); ?></a>
			<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions { display: none; }</style>
			<?php
		}
	}

	/**
	 * Get key data.
	 *
	 * @param  int $key_id API Key ID.
	 * @return array
	 */
	private static function get_key_data( $key_id ) {
		global $wpdb;

		$empty = array(
			'key_id'        => 0,
			'user_id'       => '',
			'description'   => '',
			'permissions'   => '',
			'truncated_key' => '',
			'last_access'   => '',
		);

		if ( 0 === $key_id ) {
			return $empty;
		}

		$key = $wpdb->get_row(
			$wpdb->prepare(
				"SELECT key_id, user_id, description, permissions, truncated_key, last_access
				FROM {$wpdb->prefix}woocommerce_api_keys
				WHERE key_id = %d",
				$key_id
			),
			ARRAY_A
		);

		if ( is_null( $key ) ) {
			return $empty;
		}

		return $key;
	}

	/**
	 * API Keys admin actions.
	 */
	public function actions() {
		if ( $this->is_api_keys_settings_page() ) {
			// Revoke key.
			if ( isset( $_REQUEST['revoke-key'] ) ) { // WPCS: input var okay, CSRF ok.
				$this->revoke_key();
			}

			// Bulk actions.
			if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['key'] ) ) { // WPCS: input var okay, CSRF ok.
				$this->bulk_actions();
			}
		}
	}

	/**
	 * Notices.
	 */
	public static function notices() {
		if ( isset( $_GET['revoked'] ) ) { // WPCS: input var okay, CSRF ok.
			$revoked = absint( $_GET['revoked'] ); // WPCS: input var okay, CSRF ok.

			/* translators: %d: count */
			WC_Admin_Settings::add_message( sprintf( _n( '%d API key permanently revoked.', '%d API keys permanently revoked.', $revoked, 'woocommerce' ), $revoked ) );
		}
	}

	/**
	 * Revoke key.
	 */
	private function revoke_key() {
		global $wpdb;

		check_admin_referer( 'revoke' );

		if ( isset( $_REQUEST['revoke-key'] ) ) { // WPCS: input var okay, CSRF ok.
			$key_id  = absint( $_REQUEST['revoke-key'] ); // WPCS: input var okay, CSRF ok.
			$user_id = (int) $wpdb->get_var( $wpdb->prepare( "SELECT user_id FROM {$wpdb->prefix}woocommerce_api_keys WHERE key_id = %d", $key_id ) );

			if ( $key_id && $user_id && ( current_user_can( 'edit_user', $user_id ) || get_current_user_id() === $user_id ) ) {
				$this->remove_key( $key_id );
			} else {
				wp_die( esc_html__( 'You do not have permission to revoke this API Key', 'woocommerce' ) );
			}
		}

		wp_safe_redirect( esc_url_raw( add_query_arg( array( 'revoked' => 1 ), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys' ) ) ) );
		exit();
	}

	/**
	 * Bulk actions.
	 */
	private function bulk_actions() {
		check_admin_referer( 'woocommerce-settings' );

		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_die( esc_html__( 'You do not have permission to edit API Keys', 'woocommerce' ) );
		}

		if ( isset( $_REQUEST['action'] ) ) { // WPCS: input var okay, CSRF ok.
			$action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ); // WPCS: input var okay, CSRF ok.
			$keys   = isset( $_REQUEST['key'] ) ? array_map( 'absint', (array) $_REQUEST['key'] ) : array(); // WPCS: input var okay, CSRF ok.

			if ( 'revoke' === $action ) {
				$this->bulk_revoke_key( $keys );
			}
		}
	}

	/**
	 * Bulk revoke key.
	 *
	 * @param array $keys API Keys.
	 */
	private function bulk_revoke_key( $keys ) {
		if ( ! current_user_can( 'remove_users' ) ) {
			wp_die( esc_html__( 'You do not have permission to revoke API Keys', 'woocommerce' ) );
		}

		$qty = 0;
		foreach ( $keys as $key_id ) {
			$result = $this->remove_key( $key_id );

			if ( $result ) {
				$qty++;
			}
		}

		// Redirect to webhooks page.
		wp_safe_redirect( esc_url_raw( add_query_arg( array( 'revoked' => $qty ), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys' ) ) ) );
		exit();
	}

	/**
	 * Remove key.
	 *
	 * @param  int $key_id API Key ID.
	 * @return bool
	 */
	private function remove_key( $key_id ) {
		global $wpdb;

		$delete = $wpdb->delete( $wpdb->prefix . 'woocommerce_api_keys', array( 'key_id' => $key_id ), array( '%d' ) );

		return $delete;
	}
}

new WC_Admin_API_Keys();
PK     tS\\[4  4    class-wc-admin-addons.phpnu [        <?php
/**
 * Addons Page
 *
 * @package  WooCommerce\Admin
 * @version  2.5.0
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\RemoteInboxNotifications as PromotionRuleEngine;
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\RuleEvaluator;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Admin_Addons Class.
 */
class WC_Admin_Addons {

	/**
	 * Fetch featured products from WCCOM's the Featured 3.0 Endpoint and cache the data for a day.
	 *
	 * @return array|WP_Error
	 */
	public static function fetch_featured() {
		$transient_name = 'wc_addons_featured';
		// Important: WCCOM Extensions API v4.0 is used.
		$url      = 'https://woocommerce.com/wp-json/wccom-extensions/4.0/featured';
		$locale   = get_user_locale();
		$featured = self::get_locale_data_from_transient( $transient_name, $locale );

		if ( false === $featured ) {
			$fetch_options = array(
				'auth'    => true,
				'locale'  => true,
				'country' => true,
			);
			$raw_featured  = self::fetch( $url, $fetch_options );

			$featured = self::process_api_response( $raw_featured, 'featured' );

			if ( ! is_wp_error( $featured ) && $featured ) {
				self::set_locale_data_in_transient( $transient_name, $featured, $locale, DAY_IN_SECONDS );
			}
		}

		return $featured;
	}

	/**
	 * Fetch markup and other info for the preview of a product.
	 *
	 * @param int $product_id The ID of the product to fetch preview for.
	 * @return array|WP_Error Preview data or error object.
	 */
	public static function fetch_product_preview( int $product_id ) {
		$url = 'https://woocommerce.com/wp-json/wccom-extensions/1.0/product-previews?product_id=' . $product_id;

		$fetch_options = array(
			'locale' => true,
		);

		$raw_preview = self::fetch( $url, $fetch_options );

		return self::process_api_response( $raw_preview, 'product preview', true );
	}

	/**
	 * Check if the error is due to an SSL error
	 *
	 * @param string $error_message Error message.
	 *
	 * @return bool True if SSL error, false otherwise
	 */
	public static function is_ssl_error( $error_message ) {
		return false !== stripos( $error_message, 'cURL error 35' );
	}

	/**
	 * Get sections for the addons screen
	 *
	 * @return array of objects
	 */
	public static function get_sections() {
		$locale         = get_user_locale();
		$addon_sections = self::get_locale_data_from_transient( 'wc_addons_sections', $locale );
		if ( false === ( $addon_sections ) ) {
			$parameter_string = '?' . http_build_query( array( 'locale' => get_user_locale() ) );
			$raw_sections     = wp_safe_remote_get(
				'https://woocommerce.com/wp-json/wccom-extensions/1.0/categories' . $parameter_string,
				array(
					'user-agent' => 'WooCommerce/' . WC()->version . '; ' . get_bloginfo( 'url' ),
				)
			);
			if ( ! is_wp_error( $raw_sections ) ) {
				$addon_sections = json_decode( wp_remote_retrieve_body( $raw_sections ) );
				if ( $addon_sections ) {
					self::set_locale_data_in_transient( 'wc_addons_sections', $addon_sections, $locale, WEEK_IN_SECONDS );
				}
			}
		}
		return apply_filters( 'woocommerce_addons_sections', $addon_sections );
	}

	/**
	 * Get section for the addons screen.
	 *
	 * @param  string $section_id Required section ID.
	 *
	 * @return object|bool
	 */
	public static function get_section( $section_id ) {
		$sections = self::get_sections();
		if ( isset( $sections[ $section_id ] ) ) {
			return $sections[ $section_id ];
		}
		return false;
	}

	/**
	 * Returns in-app-purchase URL params.
	 */
	public static function get_in_app_purchase_url_params() {
		// Get url (from path onward) for the current page,
		// so WCCOM "back" link returns user to where they were.
		$back_admin_path = add_query_arg( array() );
		return array(
			'wccom-site'          => site_url(),
			'wccom-back'          => rawurlencode( $back_admin_path ),
			'wccom-woo-version'   => WC()->stable_version(),
			'wccom-connect-nonce' => wp_create_nonce( 'connect' ),
		);
	}

	/**
	 * Add in-app-purchase URL params to link.
	 *
	 * Adds various url parameters to a url to support a streamlined
	 * flow for obtaining and setting up WooCommerce extensons.
	 *
	 * @param string $url    Destination URL.
	 */
	public static function add_in_app_purchase_url_params( $url ) {
		return add_query_arg(
			self::get_in_app_purchase_url_params(),
			$url
		);
	}

	/**
	 * Outputs a button.
	 *
	 * @param string $url    Destination URL.
	 * @param string $text   Button label text.
	 * @param string $style  Button style class.
	 * @param string $plugin The plugin the button is promoting.
	 */
	public static function output_button( $url, $text, $style, $plugin = '' ) {
		$style = __( 'Free', 'woocommerce' ) === $text ? 'addons-button-outline-purple' : $style;
		$style = is_plugin_active( $plugin ) ? 'addons-button-installed' : $style;
		$text  = is_plugin_active( $plugin ) ? __( 'Installed', 'woocommerce' ) : $text;
		$url   = self::add_in_app_purchase_url_params( $url );
		?>
		<a
			class="addons-button <?php echo esc_attr( $style ); ?>"
			href="<?php echo esc_url( $url ); ?>">
			<?php echo esc_html( $text ); ?>
		</a>
		<?php
	}

	/**
	 * Process requests to legacy marketplace menu and redirect to correct in-app pages.
	 *
	 * @return void
	 */
	public static function handle_legacy_marketplace_redirects() {
		$section = isset( $_GET['section'] ) ? sanitize_text_field( wp_unslash( $_GET['section'] ) ) : '_featured';
		$search  = isset( $_GET['search'] ) ? sanitize_text_field( wp_unslash( $_GET['search'] ) ) : '';

		if ( 'helper' === $section ) {
			$url = admin_url( 'admin.php?page=wc-admin&tab=my-subscriptions&path=%2Fextensions' );

			if ( isset( $_GET['connect'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
				$url .= '&connect';
			}

			wp_safe_redirect( $url );
			exit();
		}

		if ( 'search' === $section || ! empty( $search ) ) {
			wp_safe_redirect( admin_url( 'admin.php?page=wc-admin&term=' . $search . '&tab=search&path=%2Fextensions' ) );
			exit();
		}

		$sections         = self::get_sections();
		$allowed_sections = array_map( fn( $section_object ) => $section_object->slug, $sections );
		// Validate if the category is supported.
		$section = in_array( $section, $allowed_sections, true ) ? $section : '_featured';

		if ( '_featured' === $section ) {
			wp_safe_redirect( admin_url( 'admin.php?page=wc-admin&path=%2Fextensions' ) );
			exit();
		}

		wp_safe_redirect( admin_url( 'admin.php?page=wc-admin&tab=extensions&path=%2Fextensions&category=' . $section ) );
		exit();
	}

	/**
	 * We're displaying page=wc-addons and page=wc-addons&section=helper as two separate pages.
	 * When we're on those pages, add body classes to distinguishe them.
	 *
	 * @param string $admin_body_class Unfiltered body class.
	 *
	 * @return string Body class with added class for Marketplace or My Subscriptions page.
	 */
	public static function filter_admin_body_classes( string $admin_body_class = '' ): string {
		if ( isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) {
			return " $admin_body_class woocommerce-page-wc-subscriptions ";
		}

		return " $admin_body_class woocommerce-page-wc-marketplace ";
	}

	/**
	 * Take an action object and return the URL based on properties of the action.
	 *
	 * @param object $action Action object.
	 * @return string URL.
	 */
	public static function get_action_url( $action ): string {
		if ( ! isset( $action->url ) ) {
			return '';
		}

		if ( isset( $action->url_is_admin_query ) && $action->url_is_admin_query ) {
			return wc_admin_url( $action->url );
		}

		if ( isset( $action->url_is_admin_nonce_query ) && $action->url_is_admin_nonce_query ) {
			if ( empty( $action->nonce ) ) {
				return '';
			}
			return wp_nonce_url(
				admin_url( $action->url ),
				$action->nonce
			);
		}

		return $action->url;
	}

	/**
	 * Retrieves the locale data from a transient.
	 *
	 * Transient value is an array of locale data in the following format:
	 * array(
	 *    'en_US' => ...,
	 *    'fr_FR' => ...,
	 * )
	 *
	 * If the transient does not exist, does not have a value, or has expired,
	 * then the return value will be false.
	 *
	 * @param string $transient Transient name. Expected to not be SQL-escaped.
	 * @param string $locale  Locale to retrieve.
	 * @return mixed Value of transient.
	 */
	private static function get_locale_data_from_transient( $transient, $locale ) {
		$transient_value = get_transient( $transient );
		$transient_value = is_array( $transient_value ) ? $transient_value : array();
		return $transient_value[ $locale ] ?? false;
	}

	/**
	 * Sets the locale data in a transient.
	 *
	 * Transient value is an array of locale data in the following format:
	 * array(
	 *    'en_US' => ...,
	 *    'fr_FR' => ...,
	 * )
	 *
	 * @param string $transient  Transient name. Expected to not be SQL-escaped.
	 *                           Must be 172 characters or fewer in length.
	 * @param mixed  $value      Transient value. Must be serializable if non-scalar.
	 *                           Expected to not be SQL-escaped.
	 * @param string $locale  Locale to set.
	 * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
	 * @return bool True if the value was set, false otherwise.
	 */
	private static function set_locale_data_in_transient( $transient, $value, $locale, $expiration = 0 ) {
		$transient_value            = get_transient( $transient );
		$transient_value            = is_array( $transient_value ) ? $transient_value : array();
		$transient_value[ $locale ] = $value;
		return set_transient( $transient, $transient_value, $expiration );
	}

	/**
	 * Process API response from WooCommerce.com endpoints.
	 *
	 * @param array|WP_Error $response    The response from the API request.
	 * @param string         $context     Context for error messages (e.g. 'featured', 'product-preview').
	 * @param bool           $associative Whether to decode the JSON as an associative array.
	 *
	 * @return array|WP_Error Processed API data or WP_Error on failure.
	 */
	private static function process_api_response( $response, $context = 'api', $associative = false ) {
		if ( is_wp_error( $response ) ) {
			/**
			 * Hook fired when there is a connection error with WooCommerce.com.
			 *
			 * @since 6.1.0
			 * @param string $error_message The error message.
			 */
			do_action( 'woocommerce_page_wc_addons_connection_error', $response->get_error_message() );

			$message = self::is_ssl_error( $response->get_error_message() )
				? __(
					'We encountered an SSL error. Please ensure your site supports TLS version 1.2 or above.',
					'woocommerce'
				)
				: $response->get_error_message();

			return new WP_Error( 'wc-addons-connection-error', $message );
		}

		$response_code = (int) wp_remote_retrieve_response_code( $response );
		if ( 200 !== $response_code ) {
			/**
			 * Hook fired when there is a connection error with WooCommerce.com.
			 *
			 * @since 6.1.0
			 * @param int $response_code The HTTP response code.
			 */
			do_action( 'woocommerce_page_wc_addons_connection_error', $response_code );

			$message = sprintf(
				/* translators: 1: Context (e.g. 'featured', 'product-preview') 2: HTTP error code */
				__( 'Our request to the %1$s API got error code %2$d.', 'woocommerce' ),
				$context,
				$response_code
			);

			return new WP_Error( 'wc-addons-connection-error', $message );
		}

		$data = json_decode( wp_remote_retrieve_body( $response ), $associative );
		if ( empty( $data ) || ! is_array( $data ) ) {
			/**
			 * Hook fired when there is a connection error with WooCommerce.com.
			 *
			 * @since 6.1.0
			 * @param string $error_message The error message.
			 */
			do_action( 'woocommerce_page_wc_addons_connection_error', 'Empty or malformed response' );

			$message = sprintf(
				/* translators: %s: Context (e.g. 'featured', 'product-preview') */
				__( 'Our request to the %s API got a malformed response.', 'woocommerce' ),
				$context
			);

			return new WP_Error( 'wc-addons-connection-error', $message );
		}

		return $data;
	}

	/**
	 * Make wp_safe_remote_get request to WooCommerce.com endpoint.
	 * Optionally pass user auth token, locale or country.
	 *
	 * @param string $url     URL to request.
	 * @param ?array $options Options for the request. For example, to pass auth token, locale and country,
	 *                        pass array( 'auth' => true, 'locale' => true, 'country' => true, ).
	 *
	 * @return array|WP_Error
	 */
	public static function fetch( $url, $options = array() ) {
		$headers = array();

		if ( isset( $options['auth'] ) && $options['auth'] ) {
			$auth = WC_Helper_Options::get( 'auth' );

			if ( isset( $auth['access_token'] ) && ! empty( $auth['access_token'] ) ) {
				$headers['Authorization'] = 'Bearer ' . $auth['access_token'];
			}
		}

		$parameters = array();

		if ( isset( $options['locale'] ) && $options['locale'] ) {
			$parameters['locale'] = get_user_locale();
		}

		if ( isset( $options['country'] ) && $options['country'] ) {
			$country = WC()->countries->get_base_country();
			if ( ! empty( $country ) ) {
				$parameters['country'] = $country;
			}
		}

		// Check if URL already has query parameters.
		$connector    = strpos( $url, '?' ) !== false ? '&' : '?';
		$query_string = ! empty( $parameters ) ? $connector . http_build_query( $parameters ) : '';

		return wp_safe_remote_get(
			$url . $query_string,
			array(
				'headers'    => $headers,
				'user-agent' => 'WooCommerce/' . WC()->version . '; ' . get_bloginfo( 'url' ),
			)
		);
	}
}
PK     tS\uG      class-wc-admin-help.phpnu [        <?php
/**
 * Add some content to the help tab
 *
 * @package     WooCommerce\Admin
 * @version     2.1.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Admin_Help', false ) ) {
	return new WC_Admin_Help();
}

/**
 * WC_Admin_Help Class.
 */
class WC_Admin_Help {

	/**
	 * Hook in tabs.
	 */
	public function __construct() {
		add_action( 'current_screen', array( $this, 'add_tabs' ), 50 );
	}

	/**
	 * Add help tabs.
	 */
	public function add_tabs() {
		$screen = get_current_screen();

		if ( ! $screen || ! in_array( $screen->id, wc_get_screen_ids() ) ) {
			return;
		}

		$screen->add_help_tab(
			array(
				'id'      => 'woocommerce_support_tab',
				'title'   => __( 'Help &amp; Support', 'woocommerce' ),
				'content' =>
					'<h2>' . __( 'Help &amp; Support', 'woocommerce' ) . '</h2>' .
					'<p>' . sprintf(
						/* translators: %s: Documentation URL */
						__( 'Should you need help understanding, using, or extending WooCommerce, <a href="%s">please read our documentation</a>. You will find all kinds of resources including snippets, tutorials and much more.', 'woocommerce' ),
						'https://woocommerce.com/documentation/plugins/woocommerce/?utm_source=helptab&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin'
					) . '</p>' .
					'<p>' . sprintf(
						/* translators: %s: Forum URL */
						__( 'For further assistance with WooCommerce core, use the <a href="%1$s">community forum</a>. For help with premium extensions sold on WooCommerce.com, <a href="%2$s">open a support request at WooCommerce.com</a>.', 'woocommerce' ),
						'https://wordpress.org/support/plugin/woocommerce',
						'https://woocommerce.com/my-account/create-a-ticket/?utm_source=helptab&utm_medium=product&utm_content=tickets&utm_campaign=woocommerceplugin'
					) . '</p>' .
					'<p>' . __( 'Before asking for help, we recommend checking the system status page to identify any problems with your configuration.', 'woocommerce' ) . '</p>' .
					'<p><a href="' . admin_url( 'admin.php?page=wc-status' ) . '" class="button button-primary">' . __( 'System status', 'woocommerce' ) . '</a> <a href="https://wordpress.org/support/plugin/woocommerce" class="button">' . __( 'Community forum', 'woocommerce' ) . '</a> <a href="https://woocommerce.com/my-account/create-a-ticket/?utm_source=helptab&utm_medium=product&utm_content=tickets&utm_campaign=woocommerceplugin" class="button">' . __( 'WooCommerce.com support', 'woocommerce' ) . '</a></p>',
			)
		);

		$screen->add_help_tab(
			array(
				'id'      => 'woocommerce_bugs_tab',
				'title'   => __( 'Found a bug?', 'woocommerce' ),
				'content' =>
					'<h2>' . __( 'Found a bug?', 'woocommerce' ) . '</h2>' .
					/* translators: 1: GitHub issues URL 2: GitHub contribution guide URL 3: System status report URL */
					'<p>' . sprintf( __( 'If you find a bug within WooCommerce core you can create a ticket via <a href="%1$s">GitHub issues</a>. Ensure you read the <a href="%2$s">contribution guide</a> prior to submitting your report. To help us solve your issue, please be as descriptive as possible and include your <a href="%3$s">system status report</a>.', 'woocommerce' ), 'https://github.com/woocommerce/woocommerce/issues?state=open', 'https://github.com/woocommerce/woocommerce/blob/trunk/.github/CONTRIBUTING.md', admin_url( 'admin.php?page=wc-status' ) ) . '</p>' .
					'<p><a href="https://github.com/woocommerce/woocommerce/issues/new?assignees=&labels=&template=1-bug-report.yml" class="button button-primary">' . __( 'Report a bug', 'woocommerce' ) . '</a> <a href="' . admin_url( 'admin.php?page=wc-status' ) . '" class="button">' . __( 'System status', 'woocommerce' ) . '</a></p>',

			)
		);

		$screen->set_help_sidebar(
			'<p><strong>' . __( 'For more information:', 'woocommerce' ) . '</strong></p>' .
			'<p><a href="https://woocommerce.com/?utm_source=helptab&utm_medium=product&utm_content=about&utm_campaign=woocommerceplugin" target="_blank">' . __( 'About WooCommerce', 'woocommerce' ) . '</a></p>' .
			'<p><a href="https://wordpress.org/plugins/woocommerce/" target="_blank">' . __( 'WordPress.org project', 'woocommerce' ) . '</a></p>' .
			'<p><a href="https://github.com/woocommerce/woocommerce/" target="_blank">' . __( 'GitHub project', 'woocommerce' ) . '</a></p>' .
			'<p><a href="https://woocommerce.com/product-category/themes/?utm_source=helptab&utm_medium=product&utm_content=wcthemes&utm_campaign=woocommerceplugin" target="_blank">' . __( 'Official themes', 'woocommerce' ) . '</a></p>' .
			'<p><a href="https://woocommerce.com/product-category/woocommerce-extensions/?utm_source=helptab&utm_medium=product&utm_content=wcextensions&utm_campaign=woocommerceplugin" target="_blank">' . __( 'Official extensions', 'woocommerce' ) . '</a></p>'
		);
	}
}

return new WC_Admin_Help();
PK     tS\<wL  L  "  class-wc-admin-dashboard-setup.phpnu [        <?php
/**
 * Admin Dashboard - Setup
 *
 * @package     WooCommerce\Admin
 * @version     2.1.0
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

if ( ! class_exists( 'WC_Admin_Dashboard_Setup', false ) ) :

	/**
	 * WC_Admin_Dashboard_Setup Class.
	 */
	class WC_Admin_Dashboard_Setup {

		/**
		 * Check for task list initialization.
		 */
		private $initalized = false;

		/**
		 * The task list.
		 */
		private $task_list = null;

		/**
		 * The tasks.
		 */
		private $tasks = null;

		/**
		 * # of completed tasks.
		 *
		 * @var int
		 */
		private $completed_tasks_count = 0;

		/**
		 * WC_Admin_Dashboard_Setup constructor.
		 */
		public function __construct() {
			if ( $this->should_display_widget() ) {
				add_meta_box(
					'wc_admin_dashboard_setup',
					__( 'WooCommerce Setup', 'woocommerce' ),
					array( $this, 'render' ),
					'dashboard',
					'normal',
					'high'
				);
			}
		}

		/**
		 * Render meta box output.
		 */
		public function render() {
			$version = Constants::get_constant( 'WC_VERSION' );
			wp_enqueue_style( 'wc-dashboard-setup', WC()->plugin_url() . '/assets/css/dashboard-setup.css', array(), $version );

			$task = $this->get_next_task();
			if ( ! $task ) {
				return;
			}

			$button_link           = $this->get_button_link( $task );
			$completed_tasks_count = $this->get_completed_tasks_count();
			$step_number           = $this->get_completed_tasks_count() + 1;
			$tasks_count           = count( $this->get_tasks() );

			// Given 'r' (circle element's r attr), dashoffset = ((100-$desired_percentage)/100) * PI * (r*2).
			$progress_percentage = ( $completed_tasks_count / $tasks_count ) * 100;
			$circle_r            = 6.5;
			$circle_dashoffset   = ( ( 100 - $progress_percentage ) / 100 ) * ( pi() * ( $circle_r * 2 ) );

			include __DIR__ . '/views/html-admin-dashboard-setup.php';
		}

		/**
		 * Get the button link for a given task.
		 *
		 * @param Task $task Task.
		 * @return string
		 */
		public function get_button_link( $task ) {
			// Check if core profiler needs completion and redirect to it.
			if ( class_exists( OnboardingProfile::class ) ) {
				if ( OnboardingProfile::needs_completion() ) {
					return wc_admin_url( '&path=/setup-wizard' );
				}
			}

			$url = (string) $task->get_json()['actionUrl'];

			if ( substr( $url, 0, 4 ) === 'http' ) {
				return $url;
			} elseif ( $url ) {
				return wc_admin_url( '&path=' . $url );
			}

			return admin_url( 'admin.php?page=wc-admin&task=' . $task->get_id() );
		}

		/**
		 * Get the task list.
		 *
		 * @return array
		 */
		public function get_task_list() {
			if ( $this->task_list || $this->initalized ) {
				return $this->task_list;
			}

			$this->set_task_list( TaskLists::get_list( 'setup' ) );
			$this->initalized = true;
			return $this->task_list;
		}

		/**
		 * Set the task list.
		 */
		public function set_task_list( $task_list ) {
			return $this->task_list = $task_list;
		}

		/**
		 * Get the tasks.
		 *
		 * @return array
		 */
		public function get_tasks() {
			if ( $this->tasks ) {
				return $this->tasks;
			}

			$this->tasks = $this->get_task_list()->get_viewable_tasks();
			return $this->tasks;
		}

		/**
		 * Return # of completed tasks
		 *
		 * @return integer
		 */
		public function get_completed_tasks_count() {
			$completed_tasks = array_filter(
				$this->get_tasks(),
				function( $task ) {
					return $task->is_complete();
				}
			);

			return count( $completed_tasks );
		}

		/**
		 * Get the next task.
		 *
		 * @return array|null
		 */
		private function get_next_task() {
			foreach ( $this->get_tasks() as $task ) {
				if ( false === $task->is_complete() ) {
					return $task;
				}
			}

			return null;
		}

		/**
		 * Check to see if we should display the widget
		 *
		 * @return bool
		 */
		public function should_display_widget() {
			if ( ! class_exists( 'Automattic\WooCommerce\Admin\Features\Features' ) || ! class_exists( 'Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists' ) ) {
				return false;
			}

			if ( ! Features::is_enabled( 'onboarding' ) || ! WC()->is_wc_admin_active() ) {
				return false;
			}

			if ( ! current_user_can( 'manage_woocommerce' ) ) {
				return false;
			}

			if ( ! $this->get_task_list() || $this->get_task_list()->is_hidden() || $this->get_task_list()->is_complete() ) {
				return false;
			}

			return true;
		}

	}

endif;

return new WC_Admin_Dashboard_Setup();
PK     tS\-9  9    class-wc-admin-status.phpnu [        <?php
/**
 * Debug/Status page
 *
 * @package WooCommerce\Admin\System Status
 * @version 2.2.0
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Internal\Admin\Logging\PageController as LoggingPageController;

defined( 'ABSPATH' ) || exit;

/**
 * WC_Admin_Status Class.
 */
class WC_Admin_Status {
	/**
	 * An instance of the DB log handler list table.
	 *
	 * @var WC_Admin_Log_Table_List
	 */
	private static $db_log_list_table;

	/**
	 * Handles output of the reports page in admin.
	 */
	public static function output() {
		include_once __DIR__ . '/views/html-admin-page-status.php';
	}

	/**
	 * Handles output of report.
	 */
	public static function status_report() {
		// Used by the report template.
		if ( ! class_exists( 'WC_Plugin_Updates' ) ) {
			include_once __DIR__ . '/plugin-updates/class-wc-plugin-updates.php';
		}

		include_once __DIR__ . '/views/html-admin-page-status-report.php';
	}

	/**
	 * Handles output of tools.
	 */
	public static function status_tools() {
		if ( ! class_exists( 'WC_REST_System_Status_Tools_Controller' ) ) {
			wp_die( 'Cannot load the REST API to access WC_REST_System_Status_Tools_Controller.' );
		}

		$tools                 = self::get_tools();
		$tool_requires_refresh = false;

		if ( ! empty( $_GET['action'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_REQUEST['_wpnonce'] ), 'debug_action' ) ) { // WPCS: input var ok, sanitization ok.
			$tools_controller = new WC_REST_System_Status_Tools_Controller();
			$action           = wc_clean( wp_unslash( $_GET['action'] ) ); // WPCS: input var ok.

			if ( array_key_exists( $action, $tools ) ) {
				$response = $tools_controller->execute_tool( $action );

				$tool                  = $tools[ $action ];
				$tool_requires_refresh = $tool['requires_refresh'] ?? false;
				$tool                  = array(
					'id'          => $action,
					'name'        => $tool['name'],
					'action'      => $tool['button'],
					'description' => $tool['desc'],
					'disabled'    => $tool['disabled'] ?? false,
				);
				$tool                  = array_merge( $tool, $response );

				/**
				 * Fires after a WooCommerce system status tool has been executed.
				 *
				 * @param array  $tool  Details about the tool that has been executed.
				 */
				do_action( 'woocommerce_system_status_tool_executed', $tool );
			} else {
				$response = array(
					'success' => false,
					'message' => __( 'Tool does not exist.', 'woocommerce' ),
				);
			}

			if ( $response['success'] ) {
				echo '<div class="updated inline"><p>' . esc_html( $response['message'] ) . '</p></div>';
			} else {
				echo '<div class="error inline"><p>' . esc_html( $response['message'] ) . '</p></div>';
			}
		}

		// Display message if settings settings have been saved.
		if ( isset( $_REQUEST['settings-updated'] ) ) { // WPCS: input var ok.
			echo '<div class="updated inline"><p>' . esc_html__( 'Your changes have been saved.', 'woocommerce' ) . '</p></div>';
		}

		if ( $tool_requires_refresh ) {
			$tools = self::get_tools();
		}

		include_once __DIR__ . '/views/html-admin-page-status-tools.php';
	}

	/**
	 * Get tools.
	 *
	 * @return array of tools
	 */
	public static function get_tools() {
		$tools_controller = new WC_REST_System_Status_Tools_Controller();
		return $tools_controller->get_tools();
	}

	/**
	 * Show the logs page.
	 */
	public static function status_logs() {
		wc_get_container()->get( LoggingPageController::class )->render();
	}

	/**
	 * Show the log page contents for file log handler.
	 */
	public static function status_logs_file() {
		$logs = self::scan_log_files();

		if ( ! empty( $_REQUEST['log_file'] ) && isset( $logs[ sanitize_title( wp_unslash( $_REQUEST['log_file'] ) ) ] ) ) { // WPCS: input var ok, CSRF ok.
			$viewed_log = $logs[ sanitize_title( wp_unslash( $_REQUEST['log_file'] ) ) ]; // WPCS: input var ok, CSRF ok.
		} elseif ( ! empty( $logs ) ) {
			$viewed_log = current( $logs );
		}

		$handle = ! empty( $viewed_log ) ? self::get_log_file_handle( $viewed_log ) : '';

		if ( ! empty( $_REQUEST['handle'] ) ) { // WPCS: input var ok, CSRF ok.
			self::remove_log();
		}

		include_once __DIR__ . '/views/html-admin-page-status-logs.php';
	}

	/**
	 * Show the log page contents for db log handler.
	 */
	public static function status_logs_db() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce handled in flush_db_logs().
		if ( isset( $_REQUEST['flush-logs'] ) ) {
			self::flush_db_logs();
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce handled in log_table_bulk_actions().
		if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['log'] ) ) {
			self::log_table_bulk_actions();
		}

		$log_table_list = self::get_db_log_list_table();
		$log_table_list->prepare_items();

		include_once __DIR__ . '/views/html-admin-page-status-logs-db.php';
	}

	/**
	 * Retrieve metadata from a file. Based on WP Core's get_file_data function.
	 *
	 * @since  2.1.1
	 * @param  string $file Path to the file.
	 * @return string
	 */
	public static function get_file_version( $file ) {

		// Avoid notices if file does not exist.
		if ( ! file_exists( $file ) ) {
			return '';
		}

		// We don't need to write to the file, so just open for reading.
		$fp = fopen( $file, 'r' ); // @codingStandardsIgnoreLine.

		// Pull only the first 8kiB of the file in.
		$file_data = fread( $fp, 8192 ); // @codingStandardsIgnoreLine.

		// PHP will close file handle, but we are good citizens.
		fclose( $fp ); // @codingStandardsIgnoreLine.

		// Make sure we catch CR-only line endings.
		$file_data = str_replace( "\r", "\n", $file_data );
		$version   = '';

		if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( '@version', '/' ) . '(.*)$/mi', $file_data, $match ) && $match[1] ) {
			$version = _cleanup_header_comment( $match[1] );
		}

		return $version;
	}

	/**
	 * Return the log file handle.
	 *
	 * @param string $filename Filename to get the handle for.
	 * @return string
	 */
	public static function get_log_file_handle( $filename ) {
		return substr( $filename, 0, strlen( $filename ) > 48 ? strlen( $filename ) - 48 : strlen( $filename ) - 4 );
	}

	/**
	 * Scan the template files.
	 *
	 * @param  string $template_path Path to the template directory.
	 * @return array
	 */
	public static function scan_template_files( $template_path ) {
		$files  = is_string( $template_path ) ? @scandir( $template_path ) : array(); // @codingStandardsIgnoreLine.
		$result = array();

		if ( ! empty( $files ) ) {

			foreach ( $files as $key => $value ) {

				if ( ! in_array( $value, array( '.', '..' ), true ) ) {

					if ( is_dir( $template_path . DIRECTORY_SEPARATOR . $value ) ) {
						$sub_files = self::scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value );
						foreach ( $sub_files as $sub_file ) {
							$result[] = $value . DIRECTORY_SEPARATOR . $sub_file;
						}
					} else {
						$result[] = $value;
					}
				}
			}
		}
		return $result;
	}

	/**
	 * Scan the log files.
	 *
	 * @return array
	 */
	public static function scan_log_files() {
		return WC_Log_Handler_File::get_log_files();
	}

	/**
	 * Get latest version of a theme by slug.
	 *
	 * @param  object $theme WP_Theme object.
	 * @return string Version number if found.
	 */
	public static function get_latest_theme_version( $theme ) {
		include_once ABSPATH . 'wp-admin/includes/theme.php';

		$api = themes_api(
			'theme_information',
			array(
				'slug'   => $theme->get_stylesheet(),
				'fields' => array(
					'sections' => false,
					'tags'     => false,
				),
			)
		);

		$update_theme_version = 0;

		// Check .org for updates.
		if ( is_object( $api ) && ! is_wp_error( $api ) && isset( $api->version ) ) {
			$update_theme_version = $api->version;
		} elseif ( strstr( $theme->{'Author URI'}, 'woothemes' ) ) { // Check WooThemes Theme Version.
			$theme_dir          = substr( strtolower( str_replace( ' ', '', $theme->Name ) ), 0, 45 ); // @codingStandardsIgnoreLine.
			$theme_version_data = get_transient( $theme_dir . '_version_data' );

			if ( false === $theme_version_data ) {
				$theme_changelog = wp_safe_remote_get( 'http://dzv365zjfbd8v.cloudfront.net/changelogs/' . $theme_dir . '/changelog.txt' );
				$cl_lines        = explode( "\n", wp_remote_retrieve_body( $theme_changelog ) );
				if ( ! empty( $cl_lines ) ) {
					foreach ( $cl_lines as $line_num => $cl_line ) {
						if ( preg_match( '/^[0-9]/', $cl_line ) ) {
							$theme_date         = str_replace( '.', '-', trim( substr( $cl_line, 0, strpos( $cl_line, '-' ) ) ) );
							$theme_version      = preg_replace( '~[^0-9,.]~', '', stristr( $cl_line, 'version' ) );
							$theme_update       = trim( str_replace( '*', '', $cl_lines[ $line_num + 1 ] ) );
							$theme_version_data = array(
								'date'      => $theme_date,
								'version'   => $theme_version,
								'update'    => $theme_update,
								'changelog' => $theme_changelog,
							);
							set_transient( $theme_dir . '_version_data', $theme_version_data, DAY_IN_SECONDS );
							break;
						}
					}
				}
			}

			if ( ! empty( $theme_version_data['version'] ) ) {
				$update_theme_version = $theme_version_data['version'];
			}
		}

		return $update_theme_version;
	}

	/**
	 * Remove/delete the chosen file.
	 */
	public static function remove_log() {
		if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( wp_unslash( $_REQUEST['_wpnonce'] ), 'remove_log' ) ) { // WPCS: input var ok, sanitization ok.
			wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
		}

		if ( ! empty( $_REQUEST['handle'] ) ) {  // WPCS: input var ok.
			$log_handler = new WC_Log_Handler_File();
			$log_handler->remove( wp_unslash( $_REQUEST['handle'] ) ); // WPCS: input var ok, sanitization ok.
		}

		wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=wc-status&tab=logs' ) ) );
		exit();
	}

	/**
	 * Return a stored instance of the DB log list table class.
	 *
	 * @return WC_Admin_Log_Table_List
	 */
	public static function get_db_log_list_table() {
		if ( is_null( self::$db_log_list_table ) ) {
			self::$db_log_list_table = new WC_Admin_Log_Table_List();
		}

		return self::$db_log_list_table;
	}


	/**
	 * Clear DB log table.
	 *
	 * @since 3.0.0
	 */
	private static function flush_db_logs() {
		check_admin_referer( 'bulk-logs' );

		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_die( esc_html__( 'You do not have permission to manage log entries.', 'woocommerce' ) );
		}

		WC_Log_Handler_DB::flush();

		$sendback = wp_sanitize_redirect( admin_url( 'admin.php?page=wc-status&tab=logs' ) );

		wp_safe_redirect( $sendback );
		exit;
	}

	/**
	 * Bulk DB log table actions.
	 *
	 * @since 3.0.0
	 */
	private static function log_table_bulk_actions() {
		check_admin_referer( 'bulk-logs' );

		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_die( esc_html__( 'You do not have permission to manage log entries.', 'woocommerce' ) );
		}

		$log_ids = (array) filter_input( INPUT_GET, 'log', FILTER_CALLBACK, array( 'options' => 'absint' ) );

		$action = self::get_db_log_list_table()->current_action();

		if ( 'delete' === $action ) {
			WC_Log_Handler_DB::delete( $log_ids );

			$sendback = remove_query_arg( array( 'action', 'action2', 'log', '_wpnonce', '_wp_http_referer' ), wp_get_referer() );

			wp_safe_redirect( $sendback );
			exit();
		}
	}

	/**
	 * Prints table info if a base table is not present.
	 */
	private static function output_tables_info() {
		$missing_tables = WC_Install::verify_base_tables( false );
		if ( 0 === count( $missing_tables ) ) {
			return;
		}
		?>

		<br>
		<strong style="color:#a00;">
			<span class="dashicons dashicons-warning"></span>
			<?php
				echo esc_html(
					sprintf(
					// translators: Comma separated list of missing tables.
						__( 'Missing base tables: %s. Some WooCommerce functionality may not work as expected.', 'woocommerce' ),
						implode( ', ', $missing_tables )
					)
				);
			?>
		</strong>

		<?php
	}

	/**
	 * Prints the information about plugins for the system status report.
	 * Used for both active and inactive plugins sections.
	 *
	 * @param array $plugins List of plugins to display.
	 * @param array $untested_plugins List of plugins that haven't been tested with the current WooCommerce version.
	 * @return void
	 */
	private static function output_plugins_info( $plugins, $untested_plugins ) {
		$wc_version = Constants::get_constant( 'WC_VERSION' );

		if ( 'major' === Constants::get_constant( 'WC_SSR_PLUGIN_UPDATE_RELEASE_VERSION_TYPE' ) ) {
			// Since we're only testing against major, we don't need to show minor and patch version.
			$wc_version = $wc_version[0] . '.0';
		}

		foreach ( $plugins as $plugin ) {
			if ( ! empty( $plugin['name'] ) ) {
				// Link the plugin name to the plugin url if available.
				$plugin_name = esc_html( $plugin['name'] );
				if ( ! empty( $plugin['url'] ) ) {
					$plugin_name = '<a href="' . esc_url( $plugin['url'] ) . '" aria-label="' . esc_attr__( 'Visit plugin homepage', 'woocommerce' ) . '" target="_blank">' . $plugin_name . '</a>';
				}

				$has_newer_version = false;
				$version_string    = $plugin['version'];
				$network_string    = '';
				if ( strstr( $plugin['url'], 'woothemes.com' ) || strstr( $plugin['url'], 'woocommerce.com' ) || strstr( $plugin['url'], 'woo.com' ) ) {
					if ( ! empty( $plugin['version_latest'] ) && version_compare( $plugin['version_latest'], $plugin['version'], '>' ) ) {
						/* translators: 1: current version. 2: latest version */
						$version_string = sprintf( __( '%1$s (update to version %2$s is available)', 'woocommerce' ), $plugin['version'], $plugin['version_latest'] );
					}

					if ( false !== $plugin['network_activated'] ) {
						$network_string = ' &ndash; <strong style="color: black;">' . esc_html__( 'Network enabled', 'woocommerce' ) . '</strong>';
					}
				}
				$untested_string = '';
				if ( array_key_exists( $plugin['plugin'], $untested_plugins ) ) {
					$untested_string = ' &ndash; <strong style="color: #a00;">';

					/* translators: %s: version */
					$untested_string .= esc_html( sprintf( __( 'Installed version not tested with active version of WooCommerce %s', 'woocommerce' ), $wc_version ) );

					$untested_string .= '</strong>';
				}
				?>
				<tr>
					<td><?php echo wp_kses_post( $plugin_name ); ?></td>
					<td class="help">&nbsp;</td>
					<td>
						<?php
						/* translators: %s: plugin author */
						printf( esc_html__( 'by %s', 'woocommerce' ), esc_html( $plugin['author_name'] ) );
						echo ' &ndash; ' . esc_html( $version_string ) . $untested_string . $network_string; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
						?>
					</td>
				</tr>
				<?php
			}
		}
	}
}
PK     tS\փ(  (    class-wc-admin-reports.phpnu [        <?php
/**
 * Admin Reports
 *
 * Functions used for displaying sales and customer reports in admin.
 *
 * @author      WooThemes
 * @category    Admin
 * @package     WooCommerce\Admin\Reports
 * @version     2.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Admin_Reports', false ) ) {
	return;
}

/**
 * WC_Admin_Reports Class.
 */
class WC_Admin_Reports {

	/**
	 * Register the hook handlers for integrating with admin.
	 */
	public static function register_hook_handlers() {
		add_filter( 'woocommerce_after_dashboard_status_widget_parameter', array( __CLASS__, 'get_report_instance' ) );
		add_filter( 'woocommerce_dashboard_status_widget_reports', array( __CLASS__, 'replace_dashboard_status_widget_reports' ) );
	}

	/**
	 * Register the hook handlers for integrating with orders.
	 *
	 * @internal
	 * @since 10.6.0
	 */
	public static function register_orders_hook_handlers(): void {
		add_action( 'woocommerce_delete_shop_order_transients', array( __CLASS__, 'delete_legacy_reports_transients' ), 10, 1 );
		add_action( 'woocommerce_delete_legacy_report_transients', array( __CLASS__, 'delete_legacy_reports_transients' ), 10, 2 );
	}

	/**
	 * Execute legacy reports transient deletion (sync or async depending on the context)
	 *
	 * @internal
	 * @since 10.6.0
	 *
	 * @param int  $order_id Order ID (unused, exists for compatibility between the hooks we are integrating with).
	 * @param bool $defer    Whether to defer the deletion or execute.
	 * @return void
	 */
	public static function delete_legacy_reports_transients( int $order_id, bool $defer = true ): void {
		// Deferring is only making sense on sites without object cache enabled (if enabled, no SQLs being executed).
		if ( $defer && ! wp_using_ext_object_cache() ) {
			static $skip_consequent;

			// Schedule the deletion, cap the execution to single pending event at any given time.
			$schedule = ! $skip_consequent && ! as_has_scheduled_action( 'woocommerce_delete_legacy_report_transients', null, 'woocommerce' );
			if ( $schedule ) {
				as_schedule_single_action( time() + MINUTE_IN_SECONDS, 'woocommerce_delete_legacy_report_transients', array( $order_id, false ), 'woocommerce' );
			}
			$skip_consequent = true;

			return;
		}

		delete_transient( 'wc_admin_report' );
		foreach ( self::get_reports() as $report_group ) {
			foreach ( $report_group['reports'] as $report_key => $report ) {
				delete_transient( 'wc_report_' . $report_key );
			}
		}
	}

	/**
	 * Get an instance of WC_Admin_Report.
	 *
	 * @return WC_Admin_Report
	 */
	public static function get_report_instance() {
		include_once __DIR__ . '/reports/class-wc-admin-report.php';
		return new WC_Admin_Report();
	}

	/**
	 * Filter handler for replacing the data of the status widget on the Dashboard page.
	 *
	 * @param array $status_widget_reports The data to display in the status widget.
	 */
	public static function replace_dashboard_status_widget_reports( $status_widget_reports ) {
		$report = self::get_report_instance();

		include_once __DIR__ . '/reports/class-wc-report-sales-by-date.php';

		$sales_by_date                 = new WC_Report_Sales_By_Date();
		$sales_by_date->start_date     = strtotime( gmdate( 'Y-m-01', current_time( 'timestamp' ) ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
		$sales_by_date->end_date       = strtotime( gmdate( 'Y-m-d', current_time( 'timestamp' ) ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
		$sales_by_date->chart_groupby  = 'day';
		$sales_by_date->group_by_query = 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)';

		$status_widget_reports['net_sales_link']      = 'admin.php?page=wc-reports&tab=orders&range=month';
		$status_widget_reports['top_seller_link']     = 'admin.php?page=wc-reports&tab=orders&report=sales_by_product&range=month&product_ids=';
		$status_widget_reports['lowstock_link']       = 'admin.php?page=wc-reports&tab=stock&report=low_in_stock';
		$status_widget_reports['outofstock_link']     = 'admin.php?page=wc-reports&tab=stock&report=out_of_stock';
		$status_widget_reports['report_data']         = $sales_by_date->get_report_data();
		$status_widget_reports['get_sales_sparkline'] = array( $report, 'get_sales_sparkline' );

		return $status_widget_reports;
	}

	/**
	 * Handles output of the reports page in admin.
	 */
	public static function output() {
		$reports        = self::get_reports();
		$first_tab      = array_keys( $reports );
		$current_tab    = ! empty( $_GET['tab'] ) && array_key_exists( $_GET['tab'], $reports ) ? sanitize_title( $_GET['tab'] ) : $first_tab[0];
		$current_report = isset( $_GET['report'] ) ? sanitize_title( $_GET['report'] ) : current( array_keys( $reports[ $current_tab ]['reports'] ) );

		include_once dirname( __FILE__ ) . '/reports/class-wc-admin-report.php';
		include_once dirname( __FILE__ ) . '/views/html-admin-page-reports.php';
	}

	/**
	 * Returns the definitions for the reports to show in admin.
	 *
	 * @return array
	 */
	public static function get_reports() {
		$reports = array(
			'orders'    => array(
				'title'   => __( 'Orders', 'woocommerce' ),
				'reports' => array(
					'sales_by_date'     => array(
						'title'       => __( 'Sales by date', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
					'sales_by_product'  => array(
						'title'       => __( 'Sales by product', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
					'sales_by_category' => array(
						'title'       => __( 'Sales by category', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
					'coupon_usage'      => array(
						'title'       => __( 'Coupons by date', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
					'downloads'         => array(
						'title'       => __( 'Customer downloads', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
				),
			),
			'customers' => array(
				'title'   => __( 'Customers', 'woocommerce' ),
				'reports' => array(
					'customers'     => array(
						'title'       => __( 'Customers vs. guests', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
					'customer_list' => array(
						'title'       => __( 'Customer list', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
				),
			),
			'stock'     => array(
				'title'   => __( 'Stock', 'woocommerce' ),
				'reports' => array(
					'low_in_stock' => array(
						'title'       => __( 'Low in stock', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
					'out_of_stock' => array(
						'title'       => __( 'Out of stock', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
					'most_stocked' => array(
						'title'       => __( 'Most stocked', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
				),
			),
		);

		if ( wc_tax_enabled() ) {
			$reports['taxes'] = array(
				'title'   => __( 'Taxes', 'woocommerce' ),
				'reports' => array(
					'taxes_by_code' => array(
						'title'       => __( 'Taxes by code', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
					'taxes_by_date' => array(
						'title'       => __( 'Taxes by date', 'woocommerce' ),
						'description' => '',
						'hide_title'  => true,
						'callback'    => array( __CLASS__, 'get_report' ),
					),
				),
			);
		}

		/**
		 * Filter the list and add reports to the legacy _WooCommerce > Reports_.
		 *
		 * Array items should be in the format of
		 *
		 * $reports['automatewoo'] = array(
		 *     'title'   => 'AutomateWoo',
		 *     'reports' => array(
		 *         'runs_by_date' => array(
		 *             'title'       => __( 'Workflow Runs', 'automatewoo' ),
		 *             'description' => '',
		 *             'hide_title'  => false,
		 *             'callback'    => array( $this, 'get_runs_by_date' ),
		 *         ),
		 *         // ...
		 *     ),
		 * );
		 *
		 * This filter has a colliding name with the one in Automattic\WooCommerce\Admin\API\Reports\Controller.
		 * To make sure your code runs in the context of the legacy _WooCommerce > Reports_ screen, and not the REST endpoint,
		 * use the following:
		 *
		 * add_filter( 'woocommerce_admin_reports',
		 *     function( $reports ) {
		 *         if ( is_admin() ) {
		 *             // ...
		 *
		 * @param array $reports The associative array of reports.
		 */
		$reports = apply_filters( 'woocommerce_admin_reports', $reports );
		$reports = apply_filters( 'woocommerce_reports_charts', $reports ); // Backwards compatibility.

		foreach ( $reports as $key => &$report_group ) {
			if ( isset( $report_group['charts'] ) ) {
				$report_group['reports'] = $report_group['charts'];
			}

			// Silently ignore reports given for the filter in Automattic\WooCommerce\Admin\API\Reports\Controller.
			if ( ! isset( $report_group['reports'] ) ) {
				unset( $reports[ $key ] );
				continue;
			}

			foreach ( $report_group['reports'] as &$report ) {
				if ( isset( $report['function'] ) ) {
					$report['callback'] = $report['function'];
				}
			}
		}

		return $reports;
	}

	/**
	 * Get a report from our reports subfolder.
	 *
	 * @param string $name
	 */
	public static function get_report( $name ) {
		$name  = sanitize_title( str_replace( '_', '-', $name ) );
		$class = 'WC_Report_' . str_replace( '-', '_', $name );

		include_once apply_filters( 'wc_admin_reports_path', 'reports/class-wc-report-' . $name . '.php', $name, $class );

		if ( ! class_exists( $class ) ) {
			return;
		}

		$report = new $class();
		$report->output_report();
	}
}
PK     tS\4S  S  ,  reports/class-wc-report-sales-by-product.phpnu [        <?php
/**
 * Sales By Product Reporting
 *
 * @package WooCommerce\Admin\Reporting
 */

use Automattic\WooCommerce\Enums\OrderStatus;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Report_Sales_By_Product
 *
 * @package     WooCommerce\Admin\Reports
 * @version     2.1.0
 */
class WC_Report_Sales_By_Product extends WC_Admin_Report {

	/**
	 * Chart colors.
	 *
	 * @var array
	 */
	public $chart_colours = array();

	/**
	 * Product ids.
	 *
	 * @var array
	 */
	public $product_ids = array();

	/**
	 * Product ids with titles.
	 *
	 * @var array
	 */
	public $product_ids_titles = array();

	/**
	 * Constructor.
	 */
	public function __construct() {
		// @codingStandardsIgnoreStart
		if ( isset( $_GET['product_ids'] ) && is_array( $_GET['product_ids'] ) ) {
			$this->product_ids = array_filter( array_map( 'absint', $_GET['product_ids'] ) );
		} elseif ( isset( $_GET['product_ids'] ) ) {
			$this->product_ids = array_filter( array( absint( $_GET['product_ids'] ) ) );
		}
		// @codingStandardsIgnoreEnd
	}

	/**
	 * Get the legend for the main chart sidebar.
	 *
	 * @return array
	 */
	public function get_chart_legend() {

		if ( empty( $this->product_ids ) ) {
			return array();
		}

		$legend = array();

		$total_sales = $this->get_order_report_data(
			array(
				'data'         => array(
					'_line_total' => array(
						'type'            => 'order_item_meta',
						'order_item_type' => 'line_item',
						'function'        => 'SUM',
						'name'            => 'order_item_amount',
					),
				),
				'where_meta'   => array(
					'relation' => 'OR',
					array(
						'type'       => 'order_item_meta',
						'meta_key'   => array( '_product_id', '_variation_id' ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
						'meta_value' => $this->product_ids, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
						'operator'   => 'IN',
					),
				),
				'query_type'   => 'get_var',
				'filter_range' => true,
				'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
			)
		);

		$total_items = absint(
			$this->get_order_report_data(
				array(
					'data'         => array(
						'_qty' => array(
							'type'            => 'order_item_meta',
							'order_item_type' => 'line_item',
							'function'        => 'SUM',
							'name'            => 'order_item_count',
						),
					),
					'where_meta'   => array(
						'relation' => 'OR',
						array(
							'type'       => 'order_item_meta',
							'meta_key'   => array( '_product_id', '_variation_id' ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
							'meta_value' => $this->product_ids, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
							'operator'   => 'IN',
						),
					),
					'query_type'   => 'get_var',
					'filter_range' => true,
					'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
				)
			)
		);

		$legend[] = array(
			/* translators: %s: total items sold */
			'title'            => sprintf( __( '%s sales for the selected items', 'woocommerce' ), '<strong>' . wc_price( $total_sales ) . '</strong>' ),
			'color'            => $this->chart_colours['sales_amount'],
			'highlight_series' => 1,
		);

		$legend[] = array(
			/* translators: %s: total items purchased */
			'title'            => sprintf( __( '%s purchases for the selected items', 'woocommerce' ), '<strong>' . ( $total_items ) . '</strong>' ),
			'color'            => $this->chart_colours['item_count'],
			'highlight_series' => 0,
		);

		return $legend;
	}

	/**
	 * Output the report.
	 */
	public function output_report() {

		$ranges = array(
			'year'       => __( 'Year', 'woocommerce' ),
			'last_month' => __( 'Last month', 'woocommerce' ),
			'month'      => __( 'This month', 'woocommerce' ),
			'7day'       => __( 'Last 7 days', 'woocommerce' ),
		);

		$this->chart_colours = array(
			'sales_amount' => '#3498db',
			'item_count'   => '#d4d9dc',
		);

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; //phpcs:ignore WordPress.Security.NonceVerification.Recommended

		if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ), true ) ) {
			$current_range = '7day';
		}

		$this->check_current_range_nonce( $current_range );
		$this->calculate_current_range( $current_range );

		include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
	}

	/**
	 * Get chart widgets.
	 *
	 * @return array
	 */
	public function get_chart_widgets() {

		$widgets = array();

		if ( ! empty( $this->product_ids ) ) {
			$widgets[] = array(
				'title'    => __( 'Showing reports for:', 'woocommerce' ),
				'callback' => array( $this, 'current_filters' ),
			);
		}

		$widgets[] = array(
			'title'    => '',
			'callback' => array( $this, 'products_widget' ),
		);

		return $widgets;
	}

	/**
	 * Output current filters.
	 */
	public function current_filters() {

		$this->product_ids_titles = array();

		if ( ! empty( $this->product_ids ) ) {
			// Prime caches to reduce future queries.
			_prime_post_caches( $this->product_ids );
		}

		foreach ( $this->product_ids as $product_id ) {

			$product = wc_get_product( $product_id );

			if ( $product ) {
				$this->product_ids_titles[] = $product->get_formatted_name();
			} else {
				$this->product_ids_titles[] = '#' . $product_id;
			}
		}

		echo '<p><strong>' . wp_kses_post( implode( ', ', $this->product_ids_titles ) ) . '</strong></p>';
		echo '<p><a class="button" href="' . esc_url( remove_query_arg( 'product_ids' ) ) . '">' . esc_html__( 'Reset', 'woocommerce' ) . '</a></p>';
	}

	/**
	 * Output products widget.
	 */
	public function products_widget() {
		?>
		<h4 class="section_title"><span><?php esc_html_e( 'Product search', 'woocommerce' ); ?></span></h4>
		<div class="section">
			<form method="GET">
				<div>
					<?php // @codingStandardsIgnoreStart ?>
					<select class="wc-product-search" style="width:203px;" multiple="multiple" id="product_ids" name="product_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations"></select>
					<button type="submit" class="submit button" value="<?php esc_attr_e( 'Show', 'woocommerce' ); ?>"><?php esc_html_e( 'Show', 'woocommerce' ); ?></button>
					<input type="hidden" name="range" value="<?php echo ( ! empty( $_GET['range'] ) ) ? esc_attr( $_GET['range'] ) : ''; ?>" />
					<input type="hidden" name="start_date" value="<?php echo ( ! empty( $_GET['start_date'] ) ) ? esc_attr( $_GET['start_date'] ) : ''; ?>" />
					<input type="hidden" name="end_date" value="<?php echo ( ! empty( $_GET['end_date'] ) ) ? esc_attr( $_GET['end_date'] ) : ''; ?>" />
					<input type="hidden" name="page" value="<?php echo ( ! empty( $_GET['page'] ) ) ? esc_attr( $_GET['page'] ) : ''; ?>" />
					<input type="hidden" name="tab" value="<?php echo ( ! empty( $_GET['tab'] ) ) ? esc_attr( $_GET['tab'] ) : ''; ?>" />
					<input type="hidden" name="report" value="<?php echo ( ! empty( $_GET['report'] ) ) ? esc_attr( $_GET['report'] ) : ''; ?>" />
					<?php wp_nonce_field( 'custom_range', 'wc_reports_nonce', false ); ?>
					<?php // @codingStandardsIgnoreEnd ?>
				</div>
			</form>
		</div>
		<h4 class="section_title"><span><?php esc_html_e( 'Top sellers', 'woocommerce' ); ?></span></h4>
		<div class="section">
			<table cellspacing="0">
				<?php
				$top_sellers = $this->get_order_report_data(
					array(
						'data'         => array(
							'_product_id' => array(
								'type'            => 'order_item_meta',
								'order_item_type' => 'line_item',
								'function'        => '',
								'name'            => 'product_id',
							),
							'_qty'        => array(
								'type'            => 'order_item_meta',
								'order_item_type' => 'line_item',
								'function'        => 'SUM',
								'name'            => 'order_item_qty',
							),
						),
						'order_by'     => 'order_item_qty DESC',
						'group_by'     => 'product_id',
						'limit'        => 12,
						'query_type'   => 'get_results',
						'filter_range' => true,
						'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
					)
				);

				if ( $top_sellers ) {
					// @codingStandardsIgnoreStart
					foreach ( $top_sellers as $product ) {
						echo '<tr class="' . ( in_array( $product->product_id, $this->product_ids ) ? 'active' : '' ) . '">
							<td class="count">' . esc_html( $product->order_item_qty ) . '</td>
							<td class="name"><a href="' . esc_url( add_query_arg( 'product_ids', $product->product_id ) ) . '">' . esc_html( get_the_title( $product->product_id ) ) . '</a></td>
							<td class="sparkline">' . $this->sales_sparkline( $product->product_id, 7, 'count' ) . '</td>
						</tr>';
					}
					// @codingStandardsIgnoreEnd
				} else {
					echo '<tr><td colspan="3">' . esc_html__( 'No products found in range', 'woocommerce' ) . '</td></tr>';
				}
				?>
			</table>
		</div>
		<h4 class="section_title"><span><?php esc_html_e( 'Top freebies', 'woocommerce' ); ?></span></h4>
		<div class="section">
			<table cellspacing="0">
				<?php
				$top_freebies = $this->get_order_report_data(
					array(
						'data'         => array(
							'_product_id' => array(
								'type'            => 'order_item_meta',
								'order_item_type' => 'line_item',
								'function'        => '',
								'name'            => 'product_id',
							),
							'_qty'        => array(
								'type'            => 'order_item_meta',
								'order_item_type' => 'line_item',
								'function'        => 'SUM',
								'name'            => 'order_item_qty',
							),
						),
						'where_meta'   => array(
							array(
								'type'       => 'order_item_meta',
								'meta_key'   => '_line_subtotal', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
								'meta_value' => '0', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
								'operator'   => '=',
							),
						),
						'order_by'     => 'order_item_qty DESC',
						'group_by'     => 'product_id',
						'limit'        => 12,
						'query_type'   => 'get_results',
						'filter_range' => true,
					)
				);

				if ( $top_freebies ) {
					// @codingStandardsIgnoreStart
					foreach ( $top_freebies as $product ) {
						echo '<tr class="' . ( in_array( $product->product_id, $this->product_ids ) ? 'active' : '' ) . '">
							<td class="count">' . esc_html( $product->order_item_qty ) . '</td>
							<td class="name"><a href="' . esc_url( add_query_arg( 'product_ids', $product->product_id ) ) . '">' . esc_html( get_the_title( $product->product_id ) ) . '</a></td>
							<td class="sparkline">' . $this->sales_sparkline( $product->product_id, 7, 'count' ) . '</td>
						</tr>';
					}
					// @codingStandardsIgnoreEnd
				} else {
					echo '<tr><td colspan="3">' . esc_html__( 'No products found in range', 'woocommerce' ) . '</td></tr>';
				}
				?>
			</table>
		</div>
		<h4 class="section_title"><span><?php esc_html_e( 'Top earners', 'woocommerce' ); ?></span></h4>
		<div class="section">
			<table cellspacing="0">
				<?php
				$top_earners = $this->get_order_report_data(
					array(
						'data'         => array(
							'_product_id' => array(
								'type'            => 'order_item_meta',
								'order_item_type' => 'line_item',
								'function'        => '',
								'name'            => 'product_id',
							),
							'_line_total' => array(
								'type'            => 'order_item_meta',
								'order_item_type' => 'line_item',
								'function'        => 'SUM',
								'name'            => 'order_item_total',
							),
						),
						'order_by'     => 'order_item_total DESC',
						'group_by'     => 'product_id',
						'limit'        => 12,
						'query_type'   => 'get_results',
						'filter_range' => true,
						'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
					)
				);

				if ( $top_earners ) {
					// @codingStandardsIgnoreStart
					foreach ( $top_earners as $product ) {
						echo '<tr class="' . ( in_array( $product->product_id, $this->product_ids ) ? 'active' : '' ) . '">
							<td class="count">' . wc_price( $product->order_item_total ) . '</td>
							<td class="name"><a href="' . esc_url( add_query_arg( 'product_ids', $product->product_id ) ) . '">' . esc_html( get_the_title( $product->product_id ) ) . '</a></td>
							<td class="sparkline">' . $this->sales_sparkline( $product->product_id, 7, 'sales' ) . '</td>
						</tr>';
					}
					// @codingStandardsIgnoreEnd
				} else {
					echo '<tr><td colspan="3">' . esc_html__( 'No products found in range', 'woocommerce' ) . '</td></tr>';
				}
				?>
			</table>
		</div>
		<script type="text/javascript">
			jQuery( '.section_title' ).on( 'click', function() {
				var next_section = jQuery( this ).next( '.section' );

				if ( jQuery( next_section ).is( ':visible' ) ) {
					return false;
				}

				jQuery( '.section:visible' ).slideUp();
				jQuery( '.section_title' ).removeClass( 'open' );
				jQuery( this ).addClass( 'open' ).next( '.section' ).slideDown();

				return false;
			} );
			jQuery( '.section' ).slideUp( 100, function() {
				<?php if ( empty( $this->product_ids ) ) : ?>
					jQuery( '.section_title:eq(1)' ).trigger( 'click' );
				<?php endif; ?>
			} );
		</script>
		<?php
	}

	/**
	 * Output an export link.
	 */
	public function get_export_button() {

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
		?>
		<a
			href="#"
			download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_html( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv"
			class="export_csv"
			data-export="chart"
			data-xaxes="<?php esc_attr_e( 'Date', 'woocommerce' ); ?>"
			data-groupby="<?php echo $this->chart_groupby; ?>"<?php // @codingStandardsIgnoreLine ?>
		>
			<?php esc_html_e( 'Export CSV', 'woocommerce' ); ?>
		</a>
		<?php
	}

	/**
	 * Get the main chart.
	 */
	public function get_main_chart() {
		global $wp_locale;

		if ( empty( $this->product_ids ) ) {
			?>
			<div class="chart-container">
				<p class="chart-prompt"><?php esc_html_e( 'Choose a product to view stats', 'woocommerce' ); ?></p>
			</div>
			<?php
		} else {
			// Get orders and dates in range - we want the SUM of order totals, COUNT of order items, COUNT of orders, and the date.
			$order_item_counts = $this->get_order_report_data(
				array(
					'data'         => array(
						'_qty'        => array(
							'type'            => 'order_item_meta',
							'order_item_type' => 'line_item',
							'function'        => 'SUM',
							'name'            => 'order_item_count',
						),
						'post_date'   => array(
							'type'     => 'post_data',
							'function' => '',
							'name'     => 'post_date',
						),
						'_product_id' => array(
							'type'            => 'order_item_meta',
							'order_item_type' => 'line_item',
							'function'        => '',
							'name'            => 'product_id',
						),
					),
					'where_meta'   => array(
						'relation' => 'OR',
						array(
							'type'       => 'order_item_meta',
							'meta_key'   => array( '_product_id', '_variation_id' ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
							'meta_value' => $this->product_ids, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
							'operator'   => 'IN',
						),
					),
					'group_by'     => 'product_id,' . $this->group_by_query,
					'order_by'     => 'post_date ASC',
					'query_type'   => 'get_results',
					'filter_range' => true,
					'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
				)
			);

			$order_item_amounts = $this->get_order_report_data(
				array(
					'data'         => array(
						'_line_total' => array(
							'type'            => 'order_item_meta',
							'order_item_type' => 'line_item',
							'function'        => 'SUM',
							'name'            => 'order_item_amount',
						),
						'post_date'   => array(
							'type'     => 'post_data',
							'function' => '',
							'name'     => 'post_date',
						),
						'_product_id' => array(
							'type'            => 'order_item_meta',
							'order_item_type' => 'line_item',
							'function'        => '',
							'name'            => 'product_id',
						),
					),
					'where_meta'   => array(
						'relation' => 'OR',
						array(
							'type'       => 'order_item_meta',
							'meta_key'   => array( '_product_id', '_variation_id' ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
							'meta_value' => $this->product_ids, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
							'operator'   => 'IN',
						),
					),
					'group_by'     => 'product_id, ' . $this->group_by_query,
					'order_by'     => 'post_date ASC',
					'query_type'   => 'get_results',
					'filter_range' => true,
					'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
				)
			);

			// Prepare data for report.
			$order_item_counts  = $this->prepare_chart_data( $order_item_counts, 'post_date', 'order_item_count', $this->chart_interval, $this->start_date, $this->chart_groupby );
			$order_item_amounts = $this->prepare_chart_data( $order_item_amounts, 'post_date', 'order_item_amount', $this->chart_interval, $this->start_date, $this->chart_groupby );

			// Encode in json format.
			$chart_data = wp_json_encode(
				array(
					'order_item_counts'  => array_values( $order_item_counts ),
					'order_item_amounts' => array_values( $order_item_amounts ),
				)
			);
			?>
			<div class="chart-container">
				<div class="chart-placeholder main"></div>
			</div>
			<?php // @codingStandardsIgnoreStart ?>
			<script type="text/javascript">
				var main_chart;

				jQuery(function(){
					var order_data = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( $chart_data ); ?>' ) );

					var drawGraph = function( highlight ) {

						var series = [
							{
								label: "<?php echo esc_js( __( 'Number of items sold', 'woocommerce' ) ) ?>",
								data: order_data.order_item_counts,
								color: '<?php echo $this->chart_colours['item_count']; ?>',
								bars: { fillColor: '<?php echo $this->chart_colours['item_count']; ?>', fill: true, show: true, lineWidth: 0, barWidth: <?php echo $this->barwidth; ?> * 0.5, align: 'center' },
								shadowSize: 0,
								hoverable: false
							},
							{
								label: "<?php echo esc_js( __( 'Sales amount', 'woocommerce' ) ) ?>",
								data: order_data.order_item_amounts,
								yaxis: 2,
								color: '<?php echo $this->chart_colours['sales_amount']; ?>',
								points: { show: true, radius: 5, lineWidth: 3, fillColor: '#fff', fill: true },
								lines: { show: true, lineWidth: 4, fill: false },
								shadowSize: 0,
								<?php echo $this->get_currency_tooltip(); ?>
							}
						];

						if ( highlight !== 'undefined' && series[ highlight ] ) {
							highlight_series = series[ highlight ];

							highlight_series.color = '#9c5d90';

							if ( highlight_series.bars )
								highlight_series.bars.fillColor = '#9c5d90';

							if ( highlight_series.lines ) {
								highlight_series.lines.lineWidth = 5;
							}
						}

						main_chart = jQuery.plot(
							jQuery('.chart-placeholder.main'),
							series,
							{
								legend: {
									show: false
								},
								grid: {
									color: '#aaa',
									borderColor: 'transparent',
									borderWidth: 0,
									hoverable: true
								},
								xaxes: [ {
									color: '#aaa',
									position: "bottom",
									tickColor: 'transparent',
									mode: "time",
									timeformat: "<?php echo ( 'day' === $this->chart_groupby ) ? '%d %b' : '%b'; ?>",
									monthNames: JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( array_values( $wp_locale->month_abbrev ) ) ); ?>' ) ),
									tickLength: 1,
									minTickSize: [1, "<?php echo $this->chart_groupby; ?>"],
									font: {
										color: "#aaa"
									}
								} ],
								yaxes: [
									{
										min: 0,
										minTickSize: 1,
										tickDecimals: 0,
										color: '#ecf0f1',
										font: { color: "#aaa" }
									},
									{
										position: "right",
										min: 0,
										tickDecimals: 2,
										alignTicksWithAxis: 1,
										color: 'transparent',
										font: { color: "#aaa" }
									}
								],
							}
						);

						jQuery('.chart-placeholder').trigger( 'resize' );
					}

					drawGraph();

					jQuery('.highlight_series').on( 'mouseenter',
						function() {
							drawGraph( jQuery(this).data('series') );
						} ).on( 'mouseleave',
						function() {
							drawGraph();
						}
					);
				});
			</script>
			<?php
			// @codingStandardsIgnoreEnd
		}
	}
}
PK     tS\w)  )  %  reports/class-wc-report-downloads.phpnu [        <?php
/**
 * Download report.
 *
 * @author      WooThemes
 * @category    Admin
 * @package     WooCommerce\Admin\Reports
 * @version     3.3.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

/**
 * WC_Report_Downloads.
 */
class WC_Report_Downloads extends WP_List_Table {

	/**
	 * Max items.
	 *
	 * @var int
	 */
	protected $max_items;

	/**
	 * Constructor.
	 */
	public function __construct() {

		parent::__construct(
			array(
				'singular' => 'download',
				'plural'   => 'downloads',
				'ajax'     => false,
			)
		);
	}

	/**
	 * Don't need this.
	 *
	 * @param string $position Top or bottom.
	 */
	public function display_tablenav( $position ) {
		if ( 'top' !== $position ) {
			parent::display_tablenav( $position );
		}
	}

	/**
	 * Output the report.
	 */
	public function output_report() {

		$this->prepare_items();

		// Subtitle for permission if set.
		if ( ! empty( $_GET['permission_id'] ) ) { // WPCS: input var ok.
			$permission_id = absint( $_GET['permission_id'] ); // WPCS: input var ok.

			// Load the permission, order, etc. so we can render more information.
			$permission = null;
			$product    = null;

			try {
				$permission = new WC_Customer_Download( $permission_id );
				$product    = wc_get_product( $permission->product_id );
			} catch ( Exception $e ) {
				wp_die( sprintf( esc_html__( 'Permission #%d not found.', 'woocommerce' ), esc_html( $permission_id ) ) );
			}
		}

		echo '<h1>' . esc_html__( 'Customer downloads', 'woocommerce' );

		$filters      = $this->get_filter_vars();
		$filter_list  = array();
		$filter_names = array(
			'product_id'      => __( 'Product', 'woocommerce' ),
			'download_id'     => __( 'File ID', 'woocommerce' ),
			'permission_id'   => __( 'Permission ID', 'woocommerce' ),
			'order_id'        => __( 'Order', 'woocommerce' ),
			'user_id'         => __( 'User', 'woocommerce' ),
			'user_ip_address' => __( 'IP address', 'woocommerce' ),
		);

		foreach ( $filters as $key => $value ) {
			if ( is_null( $value ) ) {
				continue;
			}
			switch ( $key ) {
				case 'order_id':
					$order = wc_get_order( $value );
					if ( $order ) {
						$display_value = _x( '#', 'hash before order number', 'woocommerce' ) . $order->get_order_number();
					} else {
						break 2;
					}
					break;
				case 'product_id':
					$product = wc_get_product( $value );
					if ( $product ) {
						$display_value = $product->get_formatted_name();
					} else {
						break 2;
					}
					break;
				default:
					$display_value = $value;
					break;
			}
			$filter_list[] = $filter_names[ $key ] . ' ' . $display_value . ' <a href="' . esc_url( remove_query_arg( $key ) ) . '" class="woocommerce-reports-remove-filter">&times;</a>';
		}

		echo '</h1>';

		echo '<div id="active-filters" class="woocommerce-reports-wide"><h2>';
		echo esc_html__( 'Active filters', 'woocommerce' ) . ': ';
		echo $filter_list ? wp_kses_post( implode( ', ', $filter_list ) ) : '';
		echo '</h2></div>';

		echo '<div id="poststuff" class="woocommerce-reports-wide">';
		$this->display();
		echo '</div>';
	}

	/**
	 * Get column value.
	 *
	 * @param mixed  $item Item being displayed.
	 * @param string $column_name Column name.
	 */
	public function column_default( $item, $column_name ) {
		$permission = null;
		$product    = null;
		try {
			$permission = new WC_Customer_Download( $item->permission_id );
			$product    = wc_get_product( $permission->product_id );
		} catch ( Exception $e ) {
			// Ok to continue rendering other information even if permission and/or product is not found.
			return;
		}

		switch ( $column_name ) {
			case 'timestamp':
				echo esc_html( $item->timestamp );
				break;
			case 'product':
				if ( ! empty( $product ) ) {
					edit_post_link( esc_html( $product->get_formatted_name() ), '', '', $product->get_id(), 'view-link' );

					echo '<div class="row-actions">';
					echo '<a href="' . esc_url( add_query_arg( 'product_id', $product->get_id() ) ) . '">' . esc_html__( 'Filter by product', 'woocommerce' ) . '</a>';
					echo '</div>';
				}
				break;
			case 'file':
				if ( ! empty( $permission ) && ! empty( $product ) ) {
					// File information.
					$file = $product->get_file( $permission->get_download_id() );

					if ( false === $file ) {
						echo esc_html__( 'File does not exist', 'woocommerce' );
					} else {
						echo esc_html( $file->get_name() . ' - ' . basename( $file->get_file() ) );

						echo '<div class="row-actions">';
						echo '<a href="' . esc_url( add_query_arg( 'download_id', $permission->get_download_id() ) ) . '">' . esc_html__( 'Filter by file', 'woocommerce' ) . '</a>';
						echo '</div>';
					}
				}
				break;
			case 'order':
				if ( ! empty( $permission ) && ( $order = wc_get_order( $permission->order_id ) ) ) {
					edit_post_link( esc_html( _x( '#', 'hash before order number', 'woocommerce' ) . $order->get_order_number() ), '', '', $permission->order_id, 'view-link' );

					echo '<div class="row-actions">';
					echo '<a href="' . esc_url( add_query_arg( 'order_id', $order->get_id() ) ) . '">' . esc_html__( 'Filter by order', 'woocommerce' ) . '</a>';
					echo '</div>';
				}
				break;
			case 'user':
				if ( $item->user_id > 0 ) {
					$user = get_user_by( 'id', $item->user_id );

					if ( ! empty( $user ) ) {
						echo '<a href="' . esc_url( get_edit_user_link( $item->user_id ) ) . '">' . esc_html( $user->display_name ) . '</a>';
						echo '<div class="row-actions">';
						echo '<a href="' . esc_url( add_query_arg( 'user_id', $item->user_id ) ) . '">' . esc_html__( 'Filter by user', 'woocommerce' ) . '</a>';
						echo '</div>';
					}
				} else {
					esc_html_e( 'Guest', 'woocommerce' );
				}
				break;
			case 'user_ip_address':
				echo esc_html( $item->user_ip_address );

				echo '<div class="row-actions">';
				echo '<a href="' . esc_url( add_query_arg( 'user_ip_address', $item->user_ip_address ) ) . '">' . esc_html__( 'Filter by IP address', 'woocommerce' ) . '</a>';
				echo '</div>';
				break;
		}
	}

	/**
	 * Get columns.
	 *
	 * @return array
	 */
	public function get_columns() {
		$columns = array(
			'timestamp'       => __( 'Timestamp', 'woocommerce' ),
			'product'         => __( 'Product', 'woocommerce' ),
			'file'            => __( 'File', 'woocommerce' ),
			'order'           => __( 'Order', 'woocommerce' ),
			'user'            => __( 'User', 'woocommerce' ),
			'user_ip_address' => __( 'IP address', 'woocommerce' ),
		);

		return $columns;
	}

	/**
	 * Prepare download list items.
	 */
	public function prepare_items() {

		$this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
		$current_page          = absint( $this->get_pagenum() );
		// Allow filtering per_page value, but ensure it's at least 1.
		$per_page = max( 1, apply_filters( 'woocommerce_admin_downloads_report_downloads_per_page', 20 ) );

		$this->get_items( $current_page, $per_page );

		/**
		 * Pagination.
		 */
		$this->set_pagination_args(
			array(
				'total_items' => $this->max_items,
				'per_page'    => $per_page,
				'total_pages' => ceil( $this->max_items / $per_page ),
			)
		);
	}

	/**
	 * No items found text.
	 */
	public function no_items() {
		esc_html_e( 'No customer downloads found.', 'woocommerce' );
	}

	/**
	 * Get filters from querystring.
	 *
	 * @return object
	 */
	protected function get_filter_vars() {
		$product_id      = ! empty( $_GET['product_id'] ) ? absint( wp_unslash( $_GET['product_id'] ) ) : null; // WPCS: input var ok.
		$download_id     = ! empty( $_GET['download_id'] ) ? wc_clean( wp_unslash( $_GET['download_id'] ) ) : null; // WPCS: input var ok.
		$permission_id   = ! empty( $_GET['permission_id'] ) ? absint( wp_unslash( $_GET['permission_id'] ) ) : null; // WPCS: input var ok.
		$order_id        = ! empty( $_GET['order_id'] ) ? absint( wp_unslash( $_GET['order_id'] ) ) : null; // WPCS: input var ok.
		$user_id         = ! empty( $_GET['user_id'] ) ? absint( wp_unslash( $_GET['user_id'] ) ) : null; // WPCS: input var ok.
		$user_ip_address = ! empty( $_GET['user_ip_address'] ) ? wc_clean( wp_unslash( $_GET['user_ip_address'] ) ) : null; // WPCS: input var ok.

		return (object) array(
			'product_id'      => $product_id,
			'download_id'     => $download_id,
			'permission_id'   => $permission_id,
			'order_id'        => $order_id,
			'user_id'         => $user_id,
			'user_ip_address' => $user_ip_address,
		);
	}

	/**
	 * Get downloads matching criteria.
	 *
	 * @param int $current_page Current viewed page.
	 * @param int $per_page How many results to show per page.
	 */
	public function get_items( $current_page, $per_page ) {
		global $wpdb;

		$this->max_items = 0;
		$this->items     = array();
		$filters         = $this->get_filter_vars();

		// Get downloads from database.
		$table      = $wpdb->prefix . WC_Customer_Download_Log_Data_Store::get_table_name();
		$query_from = " FROM {$table} as downloads ";

		if ( ! is_null( $filters->product_id ) || ! is_null( $filters->download_id ) || ! is_null( $filters->order_id ) ) {
			$query_from .= " LEFT JOIN {$wpdb->prefix}woocommerce_downloadable_product_permissions as permissions on downloads.permission_id = permissions.permission_id ";
		}

		$query_from .= ' WHERE 1=1 ';

		if ( ! is_null( $filters->product_id ) ) {
			$query_from .= $wpdb->prepare( ' AND product_id = %d ', $filters->product_id );
		}

		if ( ! is_null( $filters->download_id ) ) {
			$query_from .= $wpdb->prepare( ' AND download_id = %s ', $filters->download_id );
		}

		if ( ! is_null( $filters->order_id ) ) {
			$query_from .= $wpdb->prepare( ' AND order_id = %d ', $filters->order_id );
		}

		if ( ! is_null( $filters->permission_id ) ) {
			$query_from .= $wpdb->prepare( ' AND downloads.permission_id = %d ', $filters->permission_id );
		}

		if ( ! is_null( $filters->user_id ) ) {
			$query_from .= $wpdb->prepare( ' AND downloads.user_id = %d ', $filters->user_id );
		}

		if ( ! is_null( $filters->user_ip_address ) ) {
			$query_from .= $wpdb->prepare( ' AND user_ip_address = %s ', $filters->user_ip_address );
		}

		$query_from  = apply_filters( 'woocommerce_report_downloads_query_from', $query_from );
		$query_order = $wpdb->prepare( 'ORDER BY timestamp DESC LIMIT %d, %d;', ( $current_page - 1 ) * $per_page, $per_page );

		$this->items     = $wpdb->get_results( "SELECT * {$query_from} {$query_order}" ); // WPCS: cache ok, db call ok, unprepared SQL ok.
		$this->max_items = $wpdb->get_var( "SELECT COUNT( DISTINCT download_log_id ) {$query_from};" ); // WPCS: cache ok, db call ok, unprepared SQL ok.
	}
}
PK     tS\,Z    (  reports/class-wc-report-most-stocked.phpnu [        <?php
/**
 * WC_Report_Most_Stocked.
 *
 * @package WooCommerce\Admin\Reports
 */

defined( 'ABSPATH' ) || exit;

if ( ! class_exists( 'WC_Report_Stock' ) ) {
	require_once dirname( __FILE__ ) . '/class-wc-report-stock.php';
}

/**
 * WC_Report_Most_Stocked.
 */
class WC_Report_Most_Stocked extends WC_Report_Stock {

	/**
	 * Get Products matching stock criteria.
	 *
	 * @param int $current_page Current page number.
	 * @param int $per_page How many results to show per page.
	 */
	public function get_items( $current_page, $per_page ) {
		global $wpdb;

		$this->max_items = 0;
		$this->items     = array();

		$stock = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 0 ) );

		$query_from = apply_filters(
			'woocommerce_report_most_stocked_query_from',
			$wpdb->prepare(
				"
				FROM {$wpdb->posts} as posts
				INNER JOIN {$wpdb->wc_product_meta_lookup} AS lookup ON posts.ID = lookup.product_id
				WHERE 1=1
				AND posts.post_type IN ( 'product', 'product_variation' )
				AND posts.post_status = 'publish'
				AND lookup.stock_quantity > %d
				",
				$stock
			)
		);

		$this->items     = $wpdb->get_results( $wpdb->prepare( "SELECT SQL_CALC_FOUND_ROWS posts.ID as id, posts.post_parent as parent {$query_from} ORDER BY lookup.stock_quantity DESC, id ASC LIMIT %d, %d;", ( $current_page - 1 ) * $per_page, $per_page ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
		$this->max_items = $wpdb->get_var( 'SELECT FOUND_ROWS();' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
	}
}
PK     tS\W,
E  E  (  reports/class-wc-report-coupon-usage.phpnu [        <?php
/**
 * Coupon usage report functionality
 *
 * @package WooCommerce\Admin\Reports
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Report_Coupon_Usage
 *
 * @package     WooCommerce\Admin\Reports
 * @version     2.1.0
 */
class WC_Report_Coupon_Usage extends WC_Admin_Report {

	/**
	 * Chart colors.
	 *
	 * @var array
	 */
	public $chart_colours = array();

	/**
	 * Coupon codes.
	 *
	 * @var array
	 */
	public $coupon_codes = array();

	/**
	 * Constructor.
	 */
	public function __construct() {
		if ( isset( $_GET['coupon_codes'] ) && is_array( $_GET['coupon_codes'] ) ) {
			$this->coupon_codes = array_filter( array_map( 'sanitize_text_field', wp_unslash( $_GET['coupon_codes'] ) ) );
		} elseif ( isset( $_GET['coupon_codes'] ) ) {
			$this->coupon_codes = array_filter( array( sanitize_text_field( wp_unslash( $_GET['coupon_codes'] ) ) ) );
		}
	}

	/**
	 * Get the legend for the main chart sidebar.
	 *
	 * @return array
	 */
	public function get_chart_legend() {
		$legend = array();

		$total_discount_query = array(
			'data'         => array(
				'discount_amount' => array(
					'type'            => 'order_item_meta',
					'order_item_type' => 'coupon',
					'function'        => 'SUM',
					'name'            => 'discount_amount',
				),
			),
			'where'        => array(
				array(
					'key'      => 'order_item_type',
					'value'    => 'coupon',
					'operator' => '=',
				),
			),
			'query_type'   => 'get_var',
			'filter_range' => true,
			'order_types'  => wc_get_order_types( 'order-count' ),
		);

		$total_coupons_query = array(
			'data'         => array(
				'order_item_id' => array(
					'type'            => 'order_item',
					'order_item_type' => 'coupon',
					'function'        => 'COUNT',
					'name'            => 'order_coupon_count',
				),
			),
			'where'        => array(
				array(
					'key'      => 'order_item_type',
					'value'    => 'coupon',
					'operator' => '=',
				),
			),
			'query_type'   => 'get_var',
			'filter_range' => true,
			'order_types'  => wc_get_order_types( 'order-count' ),
		);

		if ( ! empty( $this->coupon_codes ) ) {
			$coupon_code_query = array(
				'type'     => 'order_item',
				'key'      => 'order_item_name',
				'value'    => $this->coupon_codes,
				'operator' => 'IN',
			);

			$total_discount_query['where'][] = $coupon_code_query;
			$total_coupons_query['where'][]  = $coupon_code_query;
		}

		$total_discount = $this->get_order_report_data( $total_discount_query );
		$total_coupons  = absint( $this->get_order_report_data( $total_coupons_query ) );

		$legend[] = array(
			/* translators: %s: discount amount */
			'title'            => sprintf( __( '%s discounts in total', 'woocommerce' ), '<strong>' . wc_price( $total_discount ) . '</strong>' ),
			'color'            => $this->chart_colours['discount_amount'],
			'highlight_series' => 1,
		);

		$legend[] = array(
			/* translators: %s: coupons amount */
			'title'            => sprintf( __( '%s coupons used in total', 'woocommerce' ), '<strong>' . $total_coupons . '</strong>' ),
			'color'            => $this->chart_colours['coupon_count'],
			'highlight_series' => 0,
		);

		return $legend;
	}

	/**
	 * Output the report.
	 */
	public function output_report() {

		$ranges = array(
			'year'       => __( 'Year', 'woocommerce' ),
			'last_month' => __( 'Last month', 'woocommerce' ),
			'month'      => __( 'This month', 'woocommerce' ),
			'7day'       => __( 'Last 7 days', 'woocommerce' ),
		);

		$this->chart_colours = array(
			'discount_amount' => '#3498db',
			'coupon_count'    => '#d4d9dc',
		);

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day';

		if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ) ) ) {
			$current_range = '7day';
		}

		$this->check_current_range_nonce( $current_range );
		$this->calculate_current_range( $current_range );

		include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
	}

	/**
	 * Get chart widgets.
	 *
	 * @return array
	 */
	public function get_chart_widgets() {
		$widgets = array();

		$widgets[] = array(
			'title'    => '',
			'callback' => array( $this, 'coupons_widget' ),
		);

		return $widgets;
	}

	/**
	 * Output coupons widget.
	 */
	public function coupons_widget() {
		?>
		<h4 class="section_title"><span><?php esc_html_e( 'Filter by coupon', 'woocommerce' ); ?></span></h4>
		<div class="section">
			<form method="GET">
				<div>
					<?php
					$used_coupons = $this->get_order_report_data(
						array(
							'data'         => array(
								'order_item_name' => array(
									'type'            => 'order_item',
									'order_item_type' => 'coupon',
									'function'        => '',
									'distinct'        => true,
									'name'            => 'order_item_name',
								),
							),
							'where'        => array(
								array(
									'key'      => 'order_item_type',
									'value'    => 'coupon',
									'operator' => '=',
								),
							),
							'query_type'   => 'get_col',
							'filter_range' => false,
						)
					);

					if ( ! empty( $used_coupons ) && is_array( $used_coupons ) ) :
						?>
						<select id="coupon_codes" name="coupon_codes" class="wc-enhanced-select" data-placeholder="<?php esc_attr_e( 'Choose coupons&hellip;', 'woocommerce' ); ?>" style="width:100%;">
							<option value=""><?php esc_html_e( 'All coupons', 'woocommerce' ); ?></option>
							<?php
							foreach ( $used_coupons as $coupon ) {
								echo '<option value="' . esc_attr( $coupon ) . '"' . wc_selected( $coupon, $this->coupon_codes ) . '>' . esc_html( $coupon ) . '</option>';
							}
							?>
						</select>
						<?php // @codingStandardsIgnoreStart ?>
						<button type="submit" class="submit button" value="<?php esc_attr_e( 'Show', 'woocommerce' ); ?>"><?php esc_html_e( 'Show', 'woocommerce' ); ?></button>
						<input type="hidden" name="range" value="<?php echo ( ! empty( $_GET['range'] ) ) ? esc_attr( wp_unslash( $_GET['range'] ) ) : ''; ?>" />
						<input type="hidden" name="start_date" value="<?php echo ( ! empty( $_GET['start_date'] ) ) ? esc_attr( wp_unslash( $_GET['start_date'] ) ) : ''; ?>" />
						<input type="hidden" name="end_date" value="<?php echo ( ! empty( $_GET['end_date'] ) ) ? esc_attr( wp_unslash( $_GET['end_date'] ) ) : ''; ?>" />
						<input type="hidden" name="page" value="<?php echo ( ! empty( $_GET['page'] ) ) ? esc_attr( wp_unslash( $_GET['page'] ) ) : ''; ?>" />
						<input type="hidden" name="tab" value="<?php echo ( ! empty( $_GET['tab'] ) ) ? esc_attr( wp_unslash( $_GET['tab'] ) ) : ''; ?>" />
						<input type="hidden" name="report" value="<?php echo ( ! empty( $_GET['report'] ) ) ? esc_attr( wp_unslash( $_GET['report'] ) ) : ''; ?>" />
						<?php // @codingStandardsIgnoreEnd ?>
					<?php else : ?>
						<span><?php esc_html_e( 'No used coupons found', 'woocommerce' ); ?></span>
					<?php endif; ?>
				</div>
			</form>
		</div>
		<h4 class="section_title"><span><?php esc_html_e( 'Most popular', 'woocommerce' ); ?></span></h4>
		<div class="section">
			<table cellspacing="0">
				<?php
				$most_popular = $this->get_order_report_data(
					array(
						'data'         => array(
							'order_item_name' => array(
								'type'            => 'order_item',
								'order_item_type' => 'coupon',
								'function'        => '',
								'name'            => 'coupon_code',
							),
							'order_item_id'   => array(
								'type'            => 'order_item',
								'order_item_type' => 'coupon',
								'function'        => 'COUNT',
								'name'            => 'coupon_count',
							),
						),
						'where'        => array(
							array(
								'type'     => 'order_item',
								'key'      => 'order_item_type',
								'value'    => 'coupon',
								'operator' => '=',
							),
						),
						'order_by'     => 'coupon_count DESC',
						'group_by'     => 'order_item_name',
						'limit'        => 12,
						'query_type'   => 'get_results',
						'filter_range' => true,
					)
				);

				if ( ! empty( $most_popular ) && is_array( $most_popular ) ) {
					foreach ( $most_popular as $coupon ) {
						echo '<tr class="' . ( in_array( $coupon->coupon_code, $this->coupon_codes ) ? 'active' : '' ) . '">
							<td class="count" width="1%">' . esc_html( $coupon->coupon_count ) . '</td>
							<td class="name"><a href="' . esc_url( add_query_arg( 'coupon_codes', $coupon->coupon_code ) ) . '">' . esc_html( $coupon->coupon_code ) . '</a></td>
						</tr>';
					}
				} else {
					echo '<tr><td colspan="2">' . esc_html__( 'No coupons found in range', 'woocommerce' ) . '</td></tr>';
				}
				?>
			</table>
		</div>
		<h4 class="section_title"><span><?php esc_html_e( 'Most discount', 'woocommerce' ); ?></span></h4>
		<div class="section">
			<table cellspacing="0">
				<?php
				$most_discount = $this->get_order_report_data(
					array(
						'data'         => array(
							'order_item_name' => array(
								'type'            => 'order_item',
								'order_item_type' => 'coupon',
								'function'        => '',
								'name'            => 'coupon_code',
							),
							'discount_amount' => array(
								'type'            => 'order_item_meta',
								'order_item_type' => 'coupon',
								'function'        => 'SUM',
								'name'            => 'discount_amount',
							),
						),
						'where'        => array(
							array(
								'type'     => 'order_item',
								'key'      => 'order_item_type',
								'value'    => 'coupon',
								'operator' => '=',
							),
						),
						'order_by'     => 'discount_amount DESC',
						'group_by'     => 'order_item_name',
						'limit'        => 12,
						'query_type'   => 'get_results',
						'filter_range' => true,
					)
				);

				if ( ! empty( $most_discount ) && is_array( $most_discount ) ) {
					foreach ( $most_discount as $coupon ) {
						// @codingStandardsIgnoreStart
						echo '<tr class="' . ( in_array( $coupon->coupon_code, $this->coupon_codes ) ? 'active' : '' ) . '">
							<td class="count" width="1%">' . wc_price( $coupon->discount_amount ) . '</td>
							<td class="name"><a href="' . esc_url( add_query_arg( 'coupon_codes', $coupon->coupon_code ) ) . '">' . esc_html( $coupon->coupon_code ) . '</a></td>
						</tr>';
						// @codingStandardsIgnoreEnd
					}
				} else {
					echo '<tr><td colspan="3">' . esc_html__( 'No coupons found in range', 'woocommerce' ) . '</td></tr>';
				}
				?>
			</table>
		</div>
		<script type="text/javascript">
			jQuery( '.section_title' ).on( 'click', function() {
				var next_section = jQuery( this ).next( '.section' );

				if ( jQuery( next_section ).is( ':visible' ) ) {
					return false;
				}

				jQuery( '.section:visible' ).slideUp();
				jQuery( '.section_title' ).removeClass( 'open' );
				jQuery( this ).addClass( 'open' ).next( '.section' ).slideDown();

				return false;
			} );
			jQuery( '.section' ).slideUp( 100, function() {
				<?php if ( empty( $this->coupon_codes ) ) : ?>
					jQuery( '.section_title:eq(1)' ).trigger( 'click' );
				<?php else : ?>
					jQuery( '.section_title:eq(0)' ).trigger( 'click' );
				<?php endif; ?>
			} );
		</script>
		<?php
	}

	/**
	 * Output an export link.
	 */
	public function get_export_button() {
		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day';
		?>
		<a
			href="#"
			download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv"
			class="export_csv"
			data-export="chart"
			data-xaxes="<?php esc_attr_e( 'Date', 'woocommerce' ); ?>"
			data-groupby="<?php echo esc_attr( $this->chart_groupby ); ?>"
		>
			<?php esc_html_e( 'Export CSV', 'woocommerce' ); ?>
		</a>
		<?php
	}

	/**
	 * Get the main chart.
	 */
	public function get_main_chart() {
		global $wp_locale;

		// Get orders and dates in range - we want the SUM of order totals, COUNT of order items, COUNT of orders, and the date.
		$order_coupon_counts_query = array(
			'data'         => array(
				'order_item_name' => array(
					'type'            => 'order_item',
					'order_item_type' => 'coupon',
					'function'        => 'COUNT',
					'name'            => 'order_coupon_count',
				),
				'post_date'       => array(
					'type'     => 'post_data',
					'function' => '',
					'name'     => 'post_date',
				),
			),
			'where'        => array(
				array(
					'key'      => 'order_item_type',
					'value'    => 'coupon',
					'operator' => '=',
				),
			),
			'group_by'     => $this->group_by_query,
			'order_by'     => 'post_date ASC',
			'query_type'   => 'get_results',
			'filter_range' => true,
			'order_types'  => wc_get_order_types( 'order-count' ),
		);

		$order_discount_amounts_query = array(
			'data'         => array(
				'discount_amount' => array(
					'type'            => 'order_item_meta',
					'order_item_type' => 'coupon',
					'function'        => 'SUM',
					'name'            => 'discount_amount',
				),
				'post_date'       => array(
					'type'     => 'post_data',
					'function' => '',
					'name'     => 'post_date',
				),
			),
			'where'        => array(
				array(
					'key'      => 'order_item_type',
					'value'    => 'coupon',
					'operator' => '=',
				),
			),
			'group_by'     => $this->group_by_query . ', order_item_name',
			'order_by'     => 'post_date ASC',
			'query_type'   => 'get_results',
			'filter_range' => true,
			'order_types'  => wc_get_order_types( 'order-count' ),
		);

		if ( ! empty( $this->coupon_codes ) ) {
			$coupon_code_query = array(
				'type'     => 'order_item',
				'key'      => 'order_item_name',
				'value'    => $this->coupon_codes,
				'operator' => 'IN',
			);

			$order_coupon_counts_query['where'][]    = $coupon_code_query;
			$order_discount_amounts_query['where'][] = $coupon_code_query;
		}

		$order_coupon_counts    = $this->get_order_report_data( $order_coupon_counts_query );
		$order_discount_amounts = $this->get_order_report_data( $order_discount_amounts_query );

		// Prepare data for report.
		$order_coupon_counts    = $this->prepare_chart_data( $order_coupon_counts, 'post_date', 'order_coupon_count', $this->chart_interval, $this->start_date, $this->chart_groupby );
		$order_discount_amounts = $this->prepare_chart_data( $order_discount_amounts, 'post_date', 'discount_amount', $this->chart_interval, $this->start_date, $this->chart_groupby );

		// Encode in json format.
		$chart_data = wp_json_encode(
			array(
				'order_coupon_counts'    => array_values( $order_coupon_counts ),
				'order_discount_amounts' => array_values( $order_discount_amounts ),
			)
		);
		?>
		<div class="chart-container">
			<div class="chart-placeholder main"></div>
		</div>
		<script type="text/javascript">
			var main_chart;

			jQuery(function(){
				var order_data = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( $chart_data ); ?>' ) );

				var drawGraph = function( highlight ) {
					var series = [
						{
							label: "<?php echo esc_js( __( 'Number of coupons used', 'woocommerce' ) ); ?>",
							data: order_data.order_coupon_counts,
							color: '<?php echo esc_js( $this->chart_colours['coupon_count'] ); ?>',
							bars: { fillColor: '<?php echo esc_js( $this->chart_colours['coupon_count'] ); ?>', fill: true, show: true, lineWidth: 0, barWidth: <?php echo esc_js( $this->barwidth ); ?> * 0.5, align: 'center' },
							shadowSize: 0,
							hoverable: false
						},
						{
							label: "<?php echo esc_js( __( 'Discount amount', 'woocommerce' ) ); ?>",
							data: order_data.order_discount_amounts,
							yaxis: 2,
							color: '<?php echo esc_js( $this->chart_colours['discount_amount'] ); ?>',
							points: { show: true, radius: 5, lineWidth: 3, fillColor: '#fff', fill: true },
							lines: { show: true, lineWidth: 4, fill: false },
							shadowSize: 0,
							<?php echo $this->get_currency_tooltip(); ?><?php // @codingStandardsIgnoreLine ?>
						}
					];

					if ( highlight !== 'undefined' && series[ highlight ] ) {
						highlight_series = series[ highlight ];

						highlight_series.color = '#9c5d90';

						if ( highlight_series.bars )
							highlight_series.bars.fillColor = '#9c5d90';

						if ( highlight_series.lines ) {
							highlight_series.lines.lineWidth = 5;
						}
					}

					main_chart = jQuery.plot(
						jQuery('.chart-placeholder.main'),
						series,
						{
							legend: {
								show: false
							},
							grid: {
								color: '#aaa',
								borderColor: 'transparent',
								borderWidth: 0,
								hoverable: true
							},
							xaxes: [ {
								color: '#aaa',
								position: "bottom",
								tickColor: 'transparent',
								mode: "time",
								timeformat: "<?php echo ( 'day' === $this->chart_groupby ) ? '%d %b' : '%b'; ?>",
								monthNames: JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( array_values( $wp_locale->month_abbrev ) ) ); ?>' ) ),
								tickLength: 1,
								minTickSize: [1, "<?php echo esc_js( $this->chart_groupby ); ?>"],
								font: {
									color: "#aaa"
								}
							} ],
							yaxes: [
								{
									min: 0,
									minTickSize: 1,
									tickDecimals: 0,
									color: '#ecf0f1',
									font: { color: "#aaa" }
								},
								{
									position: "right",
									min: 0,
									tickDecimals: 2,
									alignTicksWithAxis: 1,
									color: 'transparent',
									font: { color: "#aaa" }
								}
							],
						}
					);

					jQuery('.chart-placeholder').trigger( 'resize' );
				}

				drawGraph();

				jQuery('.highlight_series').on( 'mouseenter',
					function() {
						drawGraph( jQuery(this).data('series') );
					} ).on( 'mouseleave',
					function() {
						drawGraph();
					}
				);
			});
		</script>
		<?php
	}
}
PK     tS\;iL  L  !  reports/class-wc-report-stock.phpnu [        <?php

use Automattic\WooCommerce\Enums\ProductType;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

/**
 * WC_Report_Stock.
 *
 * @author      WooThemes
 * @category    Admin
 * @package     WooCommerce\Admin\Reports
 * @version     2.1.0
 */
class WC_Report_Stock extends WP_List_Table {

	/**
	 * Max items.
	 *
	 * @var int
	 */
	protected $max_items;

	/**
	 * Constructor.
	 */
	public function __construct() {

		parent::__construct(
			array(
				'singular' => 'stock',
				'plural'   => 'stock',
				'ajax'     => false,
			)
		);
	}

	/**
	 * No items found text.
	 */
	public function no_items() {
		_e( 'No products found.', 'woocommerce' );
	}

	/**
	 * Don't need this.
	 *
	 * @param string $position
	 */
	public function display_tablenav( $position ) {

		if ( 'top' !== $position ) {
			parent::display_tablenav( $position );
		}
	}

	/**
	 * Output the report.
	 */
	public function output_report() {

		$this->prepare_items();
		echo '<div id="poststuff" class="woocommerce-reports-wide">';
		$this->display();
		echo '</div>';
	}

	/**
	 * Get column value.
	 *
	 * @param mixed  $item
	 * @param string $column_name
	 */
	public function column_default( $item, $column_name ) {
		global $product;

		if ( ! $product || $product->get_id() !== $item->id ) {
			$product = wc_get_product( $item->id );
		}

		if ( ! $product ) {
			return;
		}

		switch ( $column_name ) {

			case 'product':
				if ( $sku = $product->get_sku() ) {
					echo esc_html( $sku ) . ' - ';
				}

				echo esc_html( $product->get_name() );

				// Get variation data.
				if ( $product->is_type( ProductType::VARIATION ) ) {
					echo '<div class="description">' . wp_kses_post( wc_get_formatted_variation( $product, true ) ) . '</div>';
				}
				break;

			case 'parent':
				if ( $item->parent ) {
					echo esc_html( get_the_title( $item->parent ) );
				} else {
					echo '-';
				}
				break;

			case 'stock_status':
				if ( $product->is_on_backorder() ) {
					$stock_html = '<mark class="onbackorder">' . __( 'On backorder', 'woocommerce' ) . '</mark>';
				} elseif ( $product->is_in_stock() ) {
					$stock_html = '<mark class="instock">' . __( 'In stock', 'woocommerce' ) . '</mark>';
				} else {
					$stock_html = '<mark class="outofstock">' . __( 'Out of stock', 'woocommerce' ) . '</mark>';
				}
				echo apply_filters( 'woocommerce_admin_stock_html', $stock_html, $product );
				break;

			case 'stock_level':
				echo esc_html( $product->get_stock_quantity() );
				break;

			case 'wc_actions':
				?><p>
					<?php
					$actions   = array();
					$action_id = $product->is_type( ProductType::VARIATION ) ? $item->parent : $item->id;

					$actions['edit'] = array(
						'url'    => admin_url( 'post.php?post=' . $action_id . '&action=edit' ),
						'name'   => __( 'Edit', 'woocommerce' ),
						'action' => 'edit',
					);

					if ( $product->is_visible() ) {
						$actions['view'] = array(
							'url'    => get_permalink( $action_id ),
							'name'   => __( 'View', 'woocommerce' ),
							'action' => 'view',
						);
					}

					$actions = apply_filters( 'woocommerce_admin_stock_report_product_actions', $actions, $product );

					foreach ( $actions as $action ) {
						printf(
							'<a class="button tips %1$s" href="%2$s" data-tip="%3$s">%4$s</a>',
							esc_attr( $action['action'] ),
							esc_url( $action['url'] ),
							sprintf( esc_attr__( '%s product', 'woocommerce' ), $action['name'] ),
							esc_html( $action['name'] )
						);
					}
					?>
				</p>
				<?php
				break;
		}
	}

	/**
	 * Get columns.
	 *
	 * @return array
	 */
	public function get_columns() {

		$columns = array(
			'product'      => __( 'Product', 'woocommerce' ),
			'parent'       => __( 'Parent', 'woocommerce' ),
			'stock_level'  => __( 'Units in stock', 'woocommerce' ),
			'stock_status' => __( 'Stock status', 'woocommerce' ),
			'wc_actions'   => __( 'Actions', 'woocommerce' ),
		);

		return $columns;
	}

	/**
	 * Prepare customer list items.
	 */
	public function prepare_items() {

		$this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
		$current_page          = absint( $this->get_pagenum() );
		$per_page              = apply_filters( 'woocommerce_admin_stock_report_products_per_page', 20 );

		$this->get_items( $current_page, $per_page );

		/**
		 * Pagination.
		 */
		$this->set_pagination_args(
			array(
				'total_items' => $this->max_items,
				'per_page'    => $per_page,
				'total_pages' => ceil( $this->max_items / $per_page ),
			)
		);
	}
}
PK     tS\Ks-  -  %  reports/class-wc-report-customers.phpnu [        <?php
/**
 * Class WC_Report_Customers file.
 *
 * @package WooCommerce\Reports
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Report_Customers
 *
 * @package     WooCommerce\Admin\Reports
 * @version     2.1.0
 */
class WC_Report_Customers extends WC_Admin_Report {

	/**
	 * Chart colors.
	 *
	 * @var array
	 */
	public $chart_colours = array();

	/**
	 * Customers.
	 *
	 * @var array
	 */
	public $customers = array();

	/**
	 * Get the legend for the main chart sidebar.
	 *
	 * @return array
	 */
	public function get_chart_legend() {
		$legend = array();

		$legend[] = array(
			/* translators: %s: signups amount */
			'title'            => sprintf( __( '%s signups in this period', 'woocommerce' ), '<strong>' . count( $this->customers ) . '</strong>' ),
			'color'            => $this->chart_colours['signups'],
			'highlight_series' => 2,
		);

		return $legend;
	}

	/**
	 * Get chart widgets.
	 *
	 * @return array
	 */
	public function get_chart_widgets() {
		$widgets = array();

		$widgets[] = array(
			'title'    => '',
			'callback' => array( $this, 'customers_vs_guests' ),
		);

		return $widgets;
	}

	/**
	 * Output customers vs guests chart.
	 */
	public function customers_vs_guests() {

		$customer_order_totals = $this->get_order_report_data(
			array(
				'data'         => array(
					'ID' => array(
						'type'     => 'post_data',
						'function' => 'COUNT',
						'name'     => 'total_orders',
					),
				),
				'where_meta'   => array(
					array(
						'meta_key'   => '_customer_user',
						'meta_value' => '0',
						'operator'   => '>',
					),
				),
				'filter_range' => true,
			)
		);

		$guest_order_totals = $this->get_order_report_data(
			array(
				'data'         => array(
					'ID' => array(
						'type'     => 'post_data',
						'function' => 'COUNT',
						'name'     => 'total_orders',
					),
				),
				'where_meta'   => array(
					array(
						'meta_key'   => '_customer_user',
						'meta_value' => '0',
						'operator'   => '=',
					),
				),
				'filter_range' => true,
			)
		);
		?>
		<div class="chart-container">
			<div class="chart-placeholder customers_vs_guests pie-chart" style="height:200px"></div>
			<ul class="pie-chart-legend">
				<li style="border-color: <?php echo esc_attr( $this->chart_colours['customers'] ); ?>"><?php esc_html_e( 'Customer sales', 'woocommerce' ); ?></li>
				<li style="border-color: <?php echo esc_attr( $this->chart_colours['guests'] ); ?>"><?php esc_html_e( 'Guest sales', 'woocommerce' ); ?></li>
			</ul>
		</div>
		<script type="text/javascript">
			jQuery(function(){
				 jQuery.plot(
					jQuery('.chart-placeholder.customers_vs_guests'),
					[
						{
							label: '<?php esc_html_e( 'Customer orders', 'woocommerce' ); ?>',
							data:  "<?php echo esc_html( $customer_order_totals->total_orders ); ?>",
							color: '<?php echo esc_html( $this->chart_colours['customers'] ); ?>'
						},
						{
							label: '<?php esc_html_e( 'Guest orders', 'woocommerce' ); ?>',
							data:  "<?php echo esc_html( $guest_order_totals->total_orders ); ?>",
							color: '<?php echo esc_html( $this->chart_colours['guests'] ); ?>'
						}
					],
					{
						grid: {
							hoverable: true
						},
						series: {
							pie: {
								show: true,
								radius: 1,
								innerRadius: 0.6,
								label: {
									show: false
								}
							},
							enable_tooltip: true,
							append_tooltip: "<?php echo esc_html( ' ' . __( 'orders', 'woocommerce' ) ); ?>",
						},
						legend: {
							show: false
						}
					}
				);

				jQuery('.chart-placeholder.customers_vs_guests').trigger( 'resize' );
			});
		</script>
		<?php
	}

	/**
	 * Output the report.
	 */
	public function output_report() {

		$ranges = array(
			'year'       => __( 'Year', 'woocommerce' ),
			'last_month' => __( 'Last month', 'woocommerce' ),
			'month'      => __( 'This month', 'woocommerce' ),
			'7day'       => __( 'Last 7 days', 'woocommerce' ),
		);

		$this->chart_colours = array(
			'signups'   => '#3498db',
			'customers' => '#1abc9c',
			'guests'    => '#8fdece',
		);

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day';

		if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ), true ) ) {
			$current_range = '7day';
		}

		$this->check_current_range_nonce( $current_range );
		$this->calculate_current_range( $current_range );

		$privileged_users = new WP_User_Query(
			array(
				'fields'   => 'ID',
				'role__in' => array( 'administrator', 'shop_manager' ),
			),
		);
		$users_query      = new WP_User_Query(
			apply_filters(
				'woocommerce_admin_report_customers_user_query_args',
				array(
					'fields'  => array( 'user_registered' ),
					'exclude' => $privileged_users->get_results(),
				)
			)
		);

		$this->customers = $users_query->get_results();

		foreach ( $this->customers as $key => $customer ) {
			if ( strtotime( $customer->user_registered ) < $this->start_date || strtotime( $customer->user_registered ) > $this->end_date ) {
				unset( $this->customers[ $key ] );
			}
		}

		include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
	}

	/**
	 * Output an export link.
	 */
	public function get_export_button() {

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day';
		?>
		<a
			href="#"
			download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv"
			class="export_csv"
			data-export="chart"
			data-xaxes="<?php esc_attr_e( 'Date', 'woocommerce' ); ?>"
			data-groupby="<?php echo esc_attr( $this->chart_groupby ); ?>"
		>
			<?php esc_html_e( 'Export CSV', 'woocommerce' ); ?>
		</a>
		<?php
	}

	/**
	 * Output the main chart.
	 */
	public function get_main_chart() {
		global $wp_locale;

		$customer_orders = $this->get_order_report_data(
			array(
				'data'         => array(
					'ID'        => array(
						'type'     => 'post_data',
						'function' => 'COUNT',
						'name'     => 'total_orders',
					),
					'post_date' => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_date',
					),
				),
				'where_meta'   => array(
					array(
						'meta_key'   => '_customer_user',
						'meta_value' => '0',
						'operator'   => '>',
					),
				),
				'group_by'     => $this->group_by_query,
				'order_by'     => 'post_date ASC',
				'query_type'   => 'get_results',
				'filter_range' => true,
			)
		);

		$guest_orders = $this->get_order_report_data(
			array(
				'data'         => array(
					'ID'        => array(
						'type'     => 'post_data',
						'function' => 'COUNT',
						'name'     => 'total_orders',
					),
					'post_date' => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_date',
					),
				),
				'where_meta'   => array(
					array(
						'meta_key'   => '_customer_user',
						'meta_value' => '0',
						'operator'   => '=',
					),
				),
				'group_by'     => $this->group_by_query,
				'order_by'     => 'post_date ASC',
				'query_type'   => 'get_results',
				'filter_range' => true,
			)
		);

		$signups         = $this->prepare_chart_data( $this->customers, 'user_registered', '', $this->chart_interval, $this->start_date, $this->chart_groupby );
		$customer_orders = $this->prepare_chart_data( $customer_orders, 'post_date', 'total_orders', $this->chart_interval, $this->start_date, $this->chart_groupby );
		$guest_orders    = $this->prepare_chart_data( $guest_orders, 'post_date', 'total_orders', $this->chart_interval, $this->start_date, $this->chart_groupby );

		$chart_data = wp_json_encode(
			array(
				'signups'         => array_values( $signups ),
				'customer_orders' => array_values( $customer_orders ),
				'guest_orders'    => array_values( $guest_orders ),
			)
		);
		?>
		<div class="chart-container">
			<div class="chart-placeholder main"></div>
		</div>
		<script type="text/javascript">
			var main_chart;

			jQuery(function(){
				var chart_data = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( $chart_data ); ?>' ) );

				var drawGraph = function( highlight ) {
					var series = [
							{
								label: "<?php echo esc_js( __( 'Customer orders', 'woocommerce' ) ); ?>",
								data: chart_data.customer_orders,
								color: '<?php echo esc_html( $this->chart_colours['customers'] ); ?>',
								bars: { fillColor: '<?php echo esc_html( $this->chart_colours['customers'] ); ?>', fill: true, show: true, lineWidth: 0, barWidth: <?php echo esc_html( $this->barwidth ); ?> * 0.5, align: 'center' },
								shadowSize: 0,
								enable_tooltip: true,
								append_tooltip: "<?php echo esc_html( ' ' . __( 'customer orders', 'woocommerce' ) ); ?>",
								stack: true,
							},
							{
								label: "<?php echo esc_js( __( 'Guest orders', 'woocommerce' ) ); ?>",
								data: chart_data.guest_orders,
								color: '<?php echo esc_html( $this->chart_colours['guests'] ); ?>',
								bars: { fillColor: '<?php echo esc_html( $this->chart_colours['guests'] ); ?>', fill: true, show: true, lineWidth: 0, barWidth: <?php echo esc_html( $this->barwidth ); ?> * 0.5, align: 'center' },
								shadowSize: 0,
								enable_tooltip: true,
								append_tooltip: "<?php echo esc_html( ' ' . __( 'guest orders', 'woocommerce' ) ); ?>",
								stack: true,
							},
							{
								label: "<?php echo esc_js( __( 'Signups', 'woocommerce' ) ); ?>",
								data: chart_data.signups,
								color: '<?php echo esc_html( $this->chart_colours['signups'] ); ?>',
								points: { show: true, radius: 5, lineWidth: 3, fillColor: '#fff', fill: true },
								lines: { show: true, lineWidth: 4, fill: false },
								shadowSize: 0,
								enable_tooltip: true,
								append_tooltip: "<?php echo esc_html( ' ' . __( 'new users', 'woocommerce' ) ); ?>",
								stack: false
							},
						];

					if ( highlight !== 'undefined' && series[ highlight ] ) {
						highlight_series = series[ highlight ];

						highlight_series.color = '#9c5d90';

						if ( highlight_series.bars )
							highlight_series.bars.fillColor = '#9c5d90';

						if ( highlight_series.lines ) {
							highlight_series.lines.lineWidth = 5;
						}
					}

					main_chart = jQuery.plot(
						jQuery('.chart-placeholder.main'),
						series,
						{
							legend: {
								show: false
							},
							grid: {
								color: '#aaa',
								borderColor: 'transparent',
								borderWidth: 0,
								hoverable: true
							},
							xaxes: [ {
								color: '#aaa',
								position: "bottom",
								tickColor: 'transparent',
								mode: "time",
								timeformat: "<?php echo ( 'day' === $this->chart_groupby ) ? '%d %b' : '%b'; ?>",
								monthNames: JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( array_values( $wp_locale->month_abbrev ) ) ); ?>' ) ),
								tickLength: 1,
								minTickSize: [1, "<?php echo esc_html( $this->chart_groupby ); ?>"],
								tickSize: [1, "<?php echo esc_html( $this->chart_groupby ); ?>"],
								font: {
									color: "#aaa"
								}
							} ],
							yaxes: [
								{
									min: 0,
									minTickSize: 1,
									tickDecimals: 0,
									color: '#ecf0f1',
									font: { color: "#aaa" }
								}
							],
						}
					);
					jQuery('.chart-placeholder').trigger( 'resize' );
				}

				drawGraph();

				jQuery('.highlight_series').on( 'mouseenter',
					function() {
						drawGraph( jQuery(this).data('series') );
					} ).on( 'mouseleave',
					function() {
						drawGraph();
					}
				);
			});
		</script>
		<?php
	}
}
PK     tS\!Z    (  reports/class-wc-report-low-in-stock.phpnu [        <?php
/**
 * WC_Report_Low_In_Stock.
 *
 * @package WooCommerce\Admin\Reports
 */

defined( 'ABSPATH' ) || exit;

if ( ! class_exists( 'WC_Report_Stock' ) ) {
	require_once dirname( __FILE__ ) . '/class-wc-report-stock.php';
}

/**
 * Low stock report class.
 */
class WC_Report_Low_In_Stock extends WC_Report_Stock {

	/**
	 * No items found text.
	 */
	public function no_items() {
		esc_html_e( 'No low in stock products found.', 'woocommerce' );
	}

	/**
	 * Get Products matching stock criteria.
	 *
	 * @param int $current_page Current page number.
	 * @param int $per_page How many results to show per page.
	 */
	public function get_items( $current_page, $per_page ) {
		global $wpdb;

		$this->max_items = 0;
		$this->items     = array();

		$stock   = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
		$nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );

		$query_from = apply_filters(
			'woocommerce_report_low_in_stock_query_from',
			$wpdb->prepare(
				"
				FROM {$wpdb->posts} as posts
				INNER JOIN {$wpdb->wc_product_meta_lookup} AS lookup ON posts.ID = lookup.product_id
				WHERE 1=1
				AND posts.post_type IN ( 'product', 'product_variation' )
				AND posts.post_status = 'publish'
				AND lookup.stock_quantity <= %d
				AND lookup.stock_quantity > %d
				",
				$stock,
				$nostock
			)
		);

		$this->items     = $wpdb->get_results( $wpdb->prepare( "SELECT SQL_CALC_FOUND_ROWS posts.ID as id, posts.post_parent as parent {$query_from} ORDER BY posts.post_title DESC LIMIT %d, %d;", ( $current_page - 1 ) * $per_page, $per_page ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
		$this->max_items = $wpdb->get_var( 'SELECT FOUND_ROWS();' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
	}
}
PK     tS\G~  ~  )  reports/class-wc-report-sales-by-date.phpnu [        <?php
/**
 * WC_Report_Sales_By_Date
 *
 * @package     WooCommerce\Admin\Reports
 * @version     2.1.0
 */

use Automattic\WooCommerce\Enums\OrderStatus;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Report_Sales_By_Date
 */
class WC_Report_Sales_By_Date extends WC_Admin_Report {

	/**
	 * Chart colors.
	 *
	 * @var array
	 */
	public $chart_colours = array();

	/**
	 * The report data.
	 *
	 * @var stdClass
	 */
	private $report_data;

	/**
	 * Get report data.
	 *
	 * @return stdClass
	 */
	public function get_report_data() {
		if ( empty( $this->report_data ) ) {
			$this->query_report_data();
		}
		return $this->report_data;
	}

	/**
	 * Get all data needed for this report and store in the class.
	 */
	private function query_report_data() {
		$this->report_data = new stdClass();

		$this->report_data->order_counts = (array) $this->get_order_report_data(
			array(
				'data'         => array(
					'ID'        => array(
						'type'     => 'post_data',
						'function' => 'COUNT',
						'name'     => 'count',
						'distinct' => true,
					),
					'post_date' => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_date',
					),
				),
				'group_by'     => $this->group_by_query,
				'order_by'     => 'post_date ASC',
				'query_type'   => 'get_results',
				'filter_range' => true,
				'order_types'  => wc_get_order_types( 'order-count' ),
				'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
			)
		);

		$this->report_data->coupons = (array) $this->get_order_report_data(
			array(
				'data'         => array(
					'order_item_name' => array(
						'type'     => 'order_item',
						'function' => '',
						'name'     => 'order_item_name',
					),
					'discount_amount' => array(
						'type'            => 'order_item_meta',
						'order_item_type' => 'coupon',
						'function'        => 'SUM',
						'name'            => 'discount_amount',
					),
					'post_date'       => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_date',
					),
				),
				'where'        => array(
					array(
						'key'      => 'order_items.order_item_type',
						'value'    => 'coupon',
						'operator' => '=',
					),
				),
				'group_by'     => $this->group_by_query . ', order_item_name',
				'order_by'     => 'post_date ASC',
				'query_type'   => 'get_results',
				'filter_range' => true,
				'order_types'  => wc_get_order_types( 'order-count' ),
				'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
			)
		);

		// All items from orders - even those refunded.
		$this->report_data->order_items = (array) $this->get_order_report_data(
			array(
				'data'         => array(
					'_qty'      => array(
						'type'            => 'order_item_meta',
						'order_item_type' => 'line_item',
						'function'        => 'SUM',
						'name'            => 'order_item_count',
					),
					'post_date' => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_date',
					),
				),
				'where'        => array(
					array(
						'key'      => 'order_items.order_item_type',
						'value'    => 'line_item',
						'operator' => '=',
					),
				),
				'group_by'     => $this->group_by_query,
				'order_by'     => 'post_date ASC',
				'query_type'   => 'get_results',
				'filter_range' => true,
				'order_types'  => wc_get_order_types( 'order-count' ),
				'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
			)
		);

		/**
		 * Get total of fully refunded items.
		 */
		$this->report_data->refunded_order_items = absint(
			$this->get_order_report_data(
				array(
					'data'         => array(
						'_qty' => array(
							'type'            => 'order_item_meta',
							'order_item_type' => 'line_item',
							'function'        => 'SUM',
							'name'            => 'order_item_count',
						),
					),
					'where'        => array(
						array(
							'key'      => 'order_items.order_item_type',
							'value'    => 'line_item',
							'operator' => '=',
						),
					),
					'query_type'   => 'get_var',
					'filter_range' => true,
					'order_types'  => wc_get_order_types( 'order-count' ),
					'order_status' => array( OrderStatus::REFUNDED ),
				)
			)
		);

		/**
		 * Order totals by date. Charts should show GROSS amounts to avoid going -ve.
		 */
		$this->report_data->orders = (array) $this->get_order_report_data(
			array(
				'data'         => array(
					'_order_total'        => array(
						'type'     => 'meta',
						'function' => 'SUM',
						'name'     => 'total_sales',
					),
					'_order_shipping'     => array(
						'type'     => 'meta',
						'function' => 'SUM',
						'name'     => 'total_shipping',
					),
					'_order_tax'          => array(
						'type'     => 'meta',
						'function' => 'SUM',
						'name'     => 'total_tax',
					),
					'_order_shipping_tax' => array(
						'type'     => 'meta',
						'function' => 'SUM',
						'name'     => 'total_shipping_tax',
					),
					'post_date'           => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_date',
					),
				),
				'group_by'     => $this->group_by_query,
				'order_by'     => 'post_date ASC',
				'query_type'   => 'get_results',
				'filter_range' => true,
				'order_types'  => wc_get_order_types( 'sales-reports' ),
				'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
			)
		);

		/**
		 * If an order is 100% refunded we should look at the parent's totals, but the refunds dates.
		 * We also need to ensure each parent order's values are only counted/summed once.
		 */
		$this->report_data->full_refunds = (array) $this->get_order_report_data(
			array(
				'data'                => array(
					'_order_total'        => array(
						'type'     => 'parent_meta',
						'function' => '',
						'name'     => 'total_refund',
					),
					'_order_shipping'     => array(
						'type'     => 'parent_meta',
						'function' => '',
						'name'     => 'total_shipping',
					),
					'_order_tax'          => array(
						'type'     => 'parent_meta',
						'function' => '',
						'name'     => 'total_tax',
					),
					'_order_shipping_tax' => array(
						'type'     => 'parent_meta',
						'function' => '',
						'name'     => 'total_shipping_tax',
					),
					'post_date'           => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_date',
					),
				),
				'group_by'            => 'posts.post_parent',
				'query_type'          => 'get_results',
				'filter_range'        => true,
				'order_status'        => false,
				'parent_order_status' => array( OrderStatus::REFUNDED ),
			)
		);

		foreach ( $this->report_data->full_refunds as $key => $order ) {
			$total_refund       = is_numeric( $order->total_refund ) ? $order->total_refund : 0;
			$total_shipping     = is_numeric( $order->total_shipping ) ? $order->total_shipping : 0;
			$total_tax          = is_numeric( $order->total_tax ) ? $order->total_tax : 0;
			$total_shipping_tax = is_numeric( $order->total_shipping_tax ) ? $order->total_shipping_tax : 0;

			$this->report_data->full_refunds[ $key ]->net_refund = $total_refund - ( $total_shipping + $total_tax + $total_shipping_tax );
		}

		/**
		 * Partial refunds. This includes line items, shipping and taxes. Not grouped by date.
		 */
		$this->report_data->partial_refunds = (array) $this->get_order_report_data(
			array(
				'data'                => array(
					'ID'                  => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'refund_id',
					),
					'_refund_amount'      => array(
						'type'     => 'meta',
						'function' => '',
						'name'     => 'total_refund',
					),
					'post_date'           => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_date',
					),
					'order_item_type'     => array(
						'type'      => 'order_item',
						'function'  => '',
						'name'      => 'item_type',
						'join_type' => 'LEFT',
					),
					'_order_total'        => array(
						'type'     => 'meta',
						'function' => '',
						'name'     => 'total_sales',
					),
					'_order_shipping'     => array(
						'type'      => 'meta',
						'function'  => '',
						'name'      => 'total_shipping',
						'join_type' => 'LEFT',
					),
					'_order_tax'          => array(
						'type'      => 'meta',
						'function'  => '',
						'name'      => 'total_tax',
						'join_type' => 'LEFT',
					),
					'_order_shipping_tax' => array(
						'type'      => 'meta',
						'function'  => '',
						'name'      => 'total_shipping_tax',
						'join_type' => 'LEFT',
					),
					'_qty'                => array(
						'type'      => 'order_item_meta',
						'function'  => 'SUM',
						'name'      => 'order_item_count',
						'join_type' => 'LEFT',
					),
				),
				'group_by'            => 'refund_id',
				'order_by'            => 'post_date ASC',
				'query_type'          => 'get_results',
				'filter_range'        => true,
				'order_status'        => false,
				'parent_order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD ),
			)
		);

		foreach ( $this->report_data->partial_refunds as $key => $order ) {
			$this->report_data->partial_refunds[ $key ]->net_refund = (float) $order->total_refund - ( (float) $order->total_shipping + (float) $order->total_tax + (float) $order->total_shipping_tax );
		}

		/**
		 * Refund lines - all partial refunds on all order types so we can plot full AND partial refunds on the chart.
		 */
		$this->report_data->refund_lines = (array) $this->get_order_report_data(
			array(
				'data'                => array(
					'ID'                  => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'refund_id',
					),
					'_refund_amount'      => array(
						'type'     => 'meta',
						'function' => '',
						'name'     => 'total_refund',
					),
					'post_date'           => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_date',
					),
					'order_item_type'     => array(
						'type'      => 'order_item',
						'function'  => '',
						'name'      => 'item_type',
						'join_type' => 'LEFT',
					),
					'_order_total'        => array(
						'type'     => 'meta',
						'function' => '',
						'name'     => 'total_sales',
					),
					'_order_shipping'     => array(
						'type'      => 'meta',
						'function'  => '',
						'name'      => 'total_shipping',
						'join_type' => 'LEFT',
					),
					'_order_tax'          => array(
						'type'      => 'meta',
						'function'  => '',
						'name'      => 'total_tax',
						'join_type' => 'LEFT',
					),
					'_order_shipping_tax' => array(
						'type'      => 'meta',
						'function'  => '',
						'name'      => 'total_shipping_tax',
						'join_type' => 'LEFT',
					),
					'_qty'                => array(
						'type'      => 'order_item_meta',
						'function'  => 'SUM',
						'name'      => 'order_item_count',
						'join_type' => 'LEFT',
					),
				),
				'group_by'            => 'refund_id',
				'order_by'            => 'post_date ASC',
				'query_type'          => 'get_results',
				'filter_range'        => true,
				'order_status'        => false,
				'parent_order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD, OrderStatus::REFUNDED ),
			)
		);

		/**
		 * Total up refunds. Note: when an order is fully refunded, a refund line will be added.
		 */
		$this->report_data->total_tax_refunded          = 0;
		$this->report_data->total_shipping_refunded     = 0;
		$this->report_data->total_shipping_tax_refunded = 0;
		$this->report_data->total_refunds               = 0;

		$this->report_data->refunded_orders = array_merge( $this->report_data->partial_refunds, $this->report_data->full_refunds );

		foreach ( $this->report_data->refunded_orders as $key => $value ) {
			$this->report_data->total_tax_refunded          += floatval( $value->total_tax < 0 ? $value->total_tax * -1 : $value->total_tax );
			$this->report_data->total_refunds               += floatval( $value->total_refund );
			$this->report_data->total_shipping_tax_refunded += floatval( $value->total_shipping_tax < 0 ? $value->total_shipping_tax * -1 : $value->total_shipping_tax );
			$this->report_data->total_shipping_refunded     += floatval( $value->total_shipping < 0 ? $value->total_shipping * -1 : $value->total_shipping );

			// Only applies to partial.
			if ( isset( $value->order_item_count ) ) {
				$this->report_data->refunded_order_items += floatval( $value->order_item_count < 0 ? $value->order_item_count * -1 : $value->order_item_count );
			}
		}

		// Totals from all orders - including those refunded. Subtract refunded amounts.
		$this->report_data->total_tax          = wc_format_decimal( array_sum( wp_list_pluck( $this->report_data->orders, 'total_tax' ) ) - $this->report_data->total_tax_refunded, 2 );
		$this->report_data->total_shipping     = wc_format_decimal( array_sum( wp_list_pluck( $this->report_data->orders, 'total_shipping' ) ) - $this->report_data->total_shipping_refunded, 2 );
		$this->report_data->total_shipping_tax = wc_format_decimal( array_sum( wp_list_pluck( $this->report_data->orders, 'total_shipping_tax' ) ) - $this->report_data->total_shipping_tax_refunded, 2 );

		// Total the refunds and sales amounts. Sales subtract refunds. Note - total_sales also includes shipping costs.
		$this->report_data->total_sales = wc_format_decimal( array_sum( wp_list_pluck( $this->report_data->orders, 'total_sales' ) ) - $this->report_data->total_refunds, 2 );
		$this->report_data->net_sales   = wc_format_decimal( $this->report_data->total_sales - $this->report_data->total_shipping - max( 0, $this->report_data->total_tax ) - max( 0, $this->report_data->total_shipping_tax ), 2 );

		// Calculate average based on net.
		$this->report_data->average_sales       = wc_format_decimal( $this->report_data->net_sales / ( $this->chart_interval + 1 ), 2 );
		$this->report_data->average_total_sales = wc_format_decimal( $this->report_data->total_sales / ( $this->chart_interval + 1 ), 2 );

		// Total orders and discounts also includes those which have been refunded at some point.
		$this->report_data->total_coupons         = number_format( array_sum( wp_list_pluck( $this->report_data->coupons, 'discount_amount' ) ), 2, '.', '' );
		$this->report_data->total_refunded_orders = absint( count( $this->report_data->full_refunds ) );

		// Total orders in this period, even if refunded.
		$this->report_data->total_orders = absint( array_sum( wp_list_pluck( $this->report_data->order_counts, 'count' ) ) );

		// Item items ordered in this period, even if refunded.
		$this->report_data->total_items = absint( array_sum( wp_list_pluck( $this->report_data->order_items, 'order_item_count' ) ) );

		// 3rd party filtering of report data
		$this->report_data = apply_filters( 'woocommerce_admin_report_data', $this->report_data );
	}

	/**
	 * Get the legend for the main chart sidebar.
	 *
	 * @return array
	 */
	public function get_chart_legend() {
		$legend = array();
		$data   = $this->get_report_data();

		switch ( $this->chart_groupby ) {
			case 'day':
				$average_total_sales_title = sprintf(
					/* translators: %s: average total sales */
					__( '%s average gross daily sales', 'woocommerce' ),
					'<strong>' . wc_price( $data->average_total_sales ) . '</strong>'
				);
				$average_sales_title = sprintf(
					/* translators: %s: average sales */
					__( '%s average net daily sales', 'woocommerce' ),
					'<strong>' . wc_price( $data->average_sales ) . '</strong>'
				);
				break;
			case 'month':
			default:
				$average_total_sales_title = sprintf(
					/* translators: %s: average total sales */
					__( '%s average gross monthly sales', 'woocommerce' ),
					'<strong>' . wc_price( $data->average_total_sales ) . '</strong>'
				);
				$average_sales_title = sprintf(
					/* translators: %s: average sales */
					__( '%s average net monthly sales', 'woocommerce' ),
					'<strong>' . wc_price( $data->average_sales ) . '</strong>'
				);
				break;
		}

		$legend[] = array(
			'title'            => sprintf(
				/* translators: %s: total sales */
				__( '%s gross sales in this period', 'woocommerce' ),
				'<strong>' . wc_price( $data->total_sales ) . '</strong>'
			),
			'placeholder'      => __( 'This is the sum of the order totals after any refunds and including shipping and taxes.', 'woocommerce' ),
			'color'            => $this->chart_colours['sales_amount'],
			'highlight_series' => 6,
		);
		if ( $data->average_total_sales > 0 ) {
			$legend[] = array(
				'title'            => $average_total_sales_title,
				'color'            => $this->chart_colours['average'],
				'highlight_series' => 2,
			);
		}

		$legend[] = array(
			'title'            => sprintf(
				/* translators: %s: net sales */
				__( '%s net sales in this period', 'woocommerce' ),
				'<strong>' . wc_price( $data->net_sales ) . '</strong>'
			),
			'placeholder'      => __( 'This is the sum of the order totals after any refunds and excluding shipping and taxes.', 'woocommerce' ),
			'color'            => $this->chart_colours['net_sales_amount'],
			'highlight_series' => 7,
		);
		if ( $data->average_sales > 0 ) {
			$legend[] = array(
				'title'            => $average_sales_title,
				'color'            => $this->chart_colours['net_average'],
				'highlight_series' => 3,
			);
		}

		$legend[] = array(
			'title'            => sprintf(
				/* translators: %s: total orders */
				__( '%s orders placed', 'woocommerce' ),
				'<strong>' . $data->total_orders . '</strong>'
			),
			'color'            => $this->chart_colours['order_count'],
			'highlight_series' => 1,
		);

		$legend[] = array(
			'title'            => sprintf(
				/* translators: %s: total items */
				__( '%s items purchased', 'woocommerce' ),
				'<strong>' . $data->total_items . '</strong>'
			),
			'color'            => $this->chart_colours['item_count'],
			'highlight_series' => 0,
		);
		$legend[] = array(
			'title'            => sprintf(
				/* translators: 1: total refunds 2: total refunded orders 3: refunded items */
				_n( '%1$s refunded %2$d order (%3$d item)', '%1$s refunded %2$d orders (%3$d items)', $this->report_data->total_refunded_orders, 'woocommerce' ),
				'<strong>' . wc_price( $data->total_refunds ) . '</strong>',
				$this->report_data->total_refunded_orders,
				$this->report_data->refunded_order_items
			),
			'color'            => $this->chart_colours['refund_amount'],
			'highlight_series' => 8,
		);
		$legend[] = array(
			'title'            => sprintf(
				/* translators: %s: total shipping */
				__( '%s charged for shipping', 'woocommerce' ),
				'<strong>' . wc_price( $data->total_shipping ) . '</strong>'
			),
			'color'            => $this->chart_colours['shipping_amount'],
			'highlight_series' => 5,
		);
		$legend[] = array(
			'title'            => sprintf(
				/* translators: %s: total coupons */
				__( '%s worth of coupons used', 'woocommerce' ),
				'<strong>' . wc_price( $data->total_coupons ) . '</strong>'
			),
			'color'            => $this->chart_colours['coupon_amount'],
			'highlight_series' => 4,
		);

		return $legend;
	}

	/**
	 * Output the report.
	 */
	public function output_report() {
		$ranges = array(
			'year'       => __( 'Year', 'woocommerce' ),
			'last_month' => __( 'Last month', 'woocommerce' ),
			'month'      => __( 'This month', 'woocommerce' ),
			'7day'       => __( 'Last 7 days', 'woocommerce' ),
		);

		$this->chart_colours = array(
			'sales_amount'     => '#b1d4ea',
			'net_sales_amount' => '#3498db',
			'average'          => '#b1d4ea',
			'net_average'      => '#3498db',
			'order_count'      => '#dbe1e3',
			'item_count'       => '#ecf0f1',
			'shipping_amount'  => '#5cc488',
			'coupon_amount'    => '#f1c40f',
			'refund_amount'    => '#e74c3c',
		);

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ), true ) ) {
			$current_range = '7day';
		}

		$this->check_current_range_nonce( $current_range );
		$this->calculate_current_range( $current_range );

		include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
	}

	/**
	 * Output an export link.
	 */
	public function get_export_button() {
		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		?>
		<a
			href="#"
			download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv"
			class="export_csv"
			data-export="chart"
			data-xaxes="<?php esc_attr_e( 'Date', 'woocommerce' ); ?>"
			data-exclude_series="2"
			data-groupby="<?php echo esc_attr( $this->chart_groupby ); ?>"
		>
			<?php esc_html_e( 'Export CSV', 'woocommerce' ); ?>
		</a>
		<?php
	}

	/**
	 * Round our totals correctly.
	 *
	 * @param array|string $amount Chart total.
	 *
	 * @return array|string
	 */
	private function round_chart_totals( $amount ) {
		if ( is_array( $amount ) ) {
			return array( $amount[0], wc_format_decimal( $amount[1], wc_get_price_decimals() ) );
		} else {
			return wc_format_decimal( $amount, wc_get_price_decimals() );
		}
	}

	/**
	 * Get the main chart.
	 */
	public function get_main_chart() {
		global $wp_locale;

		// Prepare data for report.
		$data = array(
			'order_counts'         => $this->prepare_chart_data( $this->report_data->order_counts, 'post_date', 'count', $this->chart_interval, $this->start_date, $this->chart_groupby ),
			'order_item_counts'    => $this->prepare_chart_data( $this->report_data->order_items, 'post_date', 'order_item_count', $this->chart_interval, $this->start_date, $this->chart_groupby ),
			'order_amounts'        => $this->prepare_chart_data( $this->report_data->orders, 'post_date', 'total_sales', $this->chart_interval, $this->start_date, $this->chart_groupby ),
			'coupon_amounts'       => $this->prepare_chart_data( $this->report_data->coupons, 'post_date', 'discount_amount', $this->chart_interval, $this->start_date, $this->chart_groupby ),
			'shipping_amounts'     => $this->prepare_chart_data( $this->report_data->orders, 'post_date', 'total_shipping', $this->chart_interval, $this->start_date, $this->chart_groupby ),
			'refund_amounts'       => $this->prepare_chart_data( $this->report_data->refund_lines, 'post_date', 'total_refund', $this->chart_interval, $this->start_date, $this->chart_groupby ),
			'net_refund_amounts'   => $this->prepare_chart_data( $this->report_data->refunded_orders, 'post_date', 'net_refund', $this->chart_interval, $this->start_date, $this->chart_groupby ),
			'shipping_tax_amounts' => $this->prepare_chart_data( $this->report_data->orders, 'post_date', 'total_shipping_tax', $this->chart_interval, $this->start_date, $this->chart_groupby ),
			'tax_amounts'          => $this->prepare_chart_data( $this->report_data->orders, 'post_date', 'total_tax', $this->chart_interval, $this->start_date, $this->chart_groupby ),
			'net_order_amounts'    => array(),
			'gross_order_amounts'  => array(),
		);

		foreach ( $data['order_amounts'] as $order_amount_key => $order_amount_value ) {
			$data['gross_order_amounts'][ $order_amount_key ]     = $order_amount_value;
			$data['gross_order_amounts'][ $order_amount_key ][1] -= $data['refund_amounts'][ $order_amount_key ][1];

			$data['net_order_amounts'][ $order_amount_key ] = $order_amount_value;
			// Subtract the sum of the values from net order amounts.
			$data['net_order_amounts'][ $order_amount_key ][1] -=
				$data['net_refund_amounts'][ $order_amount_key ][1] +
				$data['shipping_amounts'][ $order_amount_key ][1] +
				$data['shipping_tax_amounts'][ $order_amount_key ][1] +
				$data['tax_amounts'][ $order_amount_key ][1];
		}

		// 3rd party filtering of report data.
		$data = apply_filters( 'woocommerce_admin_report_chart_data', $data );

		// Encode in json format.
		$chart_data = wp_json_encode(
			array(
				'order_counts'        => array_values( $data['order_counts'] ),
				'order_item_counts'   => array_values( $data['order_item_counts'] ),
				'order_amounts'       => array_map( array( $this, 'round_chart_totals' ), array_values( $data['order_amounts'] ) ),
				'gross_order_amounts' => array_map( array( $this, 'round_chart_totals' ), array_values( $data['gross_order_amounts'] ) ),
				'net_order_amounts'   => array_map( array( $this, 'round_chart_totals' ), array_values( $data['net_order_amounts'] ) ),
				'shipping_amounts'    => array_map( array( $this, 'round_chart_totals' ), array_values( $data['shipping_amounts'] ) ),
				'coupon_amounts'      => array_map( array( $this, 'round_chart_totals' ), array_values( $data['coupon_amounts'] ) ),
				'refund_amounts'      => array_map( array( $this, 'round_chart_totals' ), array_values( $data['refund_amounts'] ) ),
			)
		);
		?>
		<div class="chart-container">
			<div class="chart-placeholder main"></div>
		</div>
		<script type="text/javascript">

			var main_chart;

			jQuery(function(){
				var order_data = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( $chart_data ); ?>' ) );
				var drawGraph = function( highlight ) {
					var series = [
						{
							label: "<?php echo esc_js( __( 'Number of items sold', 'woocommerce' ) ); ?>",
							data: order_data.order_item_counts,
							color: '<?php echo esc_js( $this->chart_colours['item_count'] ); ?>',
							bars: { fillColor: '<?php echo esc_js( $this->chart_colours['item_count'] ); ?>', fill: true, show: true, lineWidth: 0, barWidth: <?php echo esc_js( $this->barwidth ); ?> * 0.5, align: 'center' },
							shadowSize: 0,
							hoverable: false
						},
						{
							label: "<?php echo esc_js( __( 'Number of orders', 'woocommerce' ) ); ?>",
							data: order_data.order_counts,
							color: '<?php echo esc_js( $this->chart_colours['order_count'] ); ?>',
							bars: { fillColor: '<?php echo esc_js( $this->chart_colours['order_count'] ); ?>', fill: true, show: true, lineWidth: 0, barWidth: <?php echo esc_js( $this->barwidth ); ?> * 0.5, align: 'center' },
							shadowSize: 0,
							hoverable: false
						},
						{
							label: "<?php echo esc_js( __( 'Average gross sales amount', 'woocommerce' ) ); ?>",
							data: [ [ <?php echo esc_js( min( array_keys( $data['order_amounts'] ) ) ); ?>, <?php echo esc_js( $this->report_data->average_total_sales ); ?> ], [ <?php echo esc_js( max( array_keys( $data['order_amounts'] ) ) ); ?>, <?php echo esc_js( $this->report_data->average_total_sales ); ?> ] ],
							yaxis: 2,
							color: '<?php echo esc_js( $this->chart_colours['average'] ); ?>',
							points: { show: false },
							lines: { show: true, lineWidth: 2, fill: false },
							shadowSize: 0,
							hoverable: false
						},
						{
							label: "<?php echo esc_js( __( 'Average net sales amount', 'woocommerce' ) ); ?>",
							data: [ [ <?php echo esc_js( min( array_keys( $data['order_amounts'] ) ) ); ?>, <?php echo esc_js( $this->report_data->average_sales ); ?> ], [ <?php echo esc_js( max( array_keys( $data['order_amounts'] ) ) ); ?>, <?php echo esc_js( $this->report_data->average_sales ); ?> ] ],
							yaxis: 2,
							color: '<?php echo esc_js( $this->chart_colours['net_average'] ); ?>',
							points: { show: false },
							lines: { show: true, lineWidth: 2, fill: false },
							shadowSize: 0,
							hoverable: false
						},
						{
							label: "<?php echo esc_js( __( 'Coupon amount', 'woocommerce' ) ); ?>",
							data: order_data.coupon_amounts,
							yaxis: 2,
							color: '<?php echo esc_js( $this->chart_colours['coupon_amount'] ); ?>',
							points: { show: true, radius: 5, lineWidth: 2, fillColor: '#fff', fill: true },
							lines: { show: true, lineWidth: 2, fill: false },
							shadowSize: 0,
							<?php echo $this->get_currency_tooltip();  // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?>
						},
						{
							label: "<?php echo esc_js( __( 'Shipping amount', 'woocommerce' ) ); ?>",
							data: order_data.shipping_amounts,
							yaxis: 2,
							color: '<?php echo esc_js( $this->chart_colours['shipping_amount'] ); ?>',
							points: { show: true, radius: 5, lineWidth: 2, fillColor: '#fff', fill: true },
							lines: { show: true, lineWidth: 2, fill: false },
							shadowSize: 0,
							prepend_tooltip: "<?php echo get_woocommerce_currency_symbol(); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?>"
						},
						{
							label: "<?php echo esc_js( __( 'Gross sales amount', 'woocommerce' ) ); ?>",
							data: order_data.gross_order_amounts,
							yaxis: 2,
							color: '<?php echo esc_js( $this->chart_colours['sales_amount'] ); ?>',
							points: { show: true, radius: 5, lineWidth: 2, fillColor: '#fff', fill: true },
							lines: { show: true, lineWidth: 2, fill: false },
							shadowSize: 0,
							<?php echo $this->get_currency_tooltip(); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?>
						},
						{
							label: "<?php echo esc_js( __( 'Net sales amount', 'woocommerce' ) ); ?>",
							data: order_data.net_order_amounts,
							yaxis: 2,
							color: '<?php echo esc_js( $this->chart_colours['net_sales_amount'] ); ?>',
							points: { show: true, radius: 6, lineWidth: 4, fillColor: '#fff', fill: true },
							lines: { show: true, lineWidth: 5, fill: false },
							shadowSize: 0,
							<?php echo $this->get_currency_tooltip(); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?>
						},
						{
							label: "<?php echo esc_js( __( 'Refund amount', 'woocommerce' ) ); ?>",
							data: order_data.refund_amounts,
							yaxis: 2,
							color: '<?php echo esc_js( $this->chart_colours['refund_amount'] ); ?>',
							points: { show: true, radius: 5, lineWidth: 2, fillColor: '#fff', fill: true },
							lines: { show: true, lineWidth: 2, fill: false },
							shadowSize: 0,
							prepend_tooltip: "<?php echo get_woocommerce_currency_symbol(); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?>"
						},
					];

					if ( highlight !== 'undefined' && series[ highlight ] ) {
						highlight_series = series[ highlight ];

						highlight_series.color = '#9c5d90';

						if ( highlight_series.bars ) {
							highlight_series.bars.fillColor = '#9c5d90';
						}

						if ( highlight_series.lines ) {
							highlight_series.lines.lineWidth = 5;
						}
					}

					main_chart = jQuery.plot(
						jQuery('.chart-placeholder.main'),
						series,
						{
							legend: {
								show: false
							},
							grid: {
								color: '#aaa',
								borderColor: 'transparent',
								borderWidth: 0,
								hoverable: true
							},
							xaxes: [ {
								color: '#aaa',
								position: "bottom",
								tickColor: 'transparent',
								mode: "time",
								timeformat: "<?php echo ( 'day' === $this->chart_groupby ) ? '%d %b' : '%b'; ?>",
								monthNames: JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( array_values( $wp_locale->month_abbrev ) ) ); ?>' ) ),
								tickLength: 1,
								minTickSize: [1, "<?php echo esc_js( $this->chart_groupby ); ?>"],
								font: {
									color: "#aaa"
								}
							} ],
							yaxes: [
								{
									min: 0,
									minTickSize: 1,
									tickDecimals: 0,
									color: '#d4d9dc',
									font: { color: "#aaa" }
								},
								{
									position: "right",
									min: 0,
									tickDecimals: 2,
									alignTicksWithAxis: 1,
									color: 'transparent',
									font: { color: "#aaa" }
								}
							],
						}
					);

					jQuery('.chart-placeholder').trigger( 'resize' );
				}

				drawGraph();

				jQuery('.highlight_series').on( 'mouseenter',
					function() {
						drawGraph( jQuery(this).data('series') );
					} ).on( 'mouseleave',
					function() {
						drawGraph();
					}
				);
			});
		</script>
		<?php
	}
}
PK     tS\MRg5  5  -  reports/class-wc-report-sales-by-category.phpnu [        <?php
/**
 * Sales by category report functionality
 *
 * @package WooCommerce\Admin\Reporting
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Report_Sales_By_Category
 *
 * @package     WooCommerce\Admin\Reports
 * @version     2.1.0
 */
class WC_Report_Sales_By_Category extends WC_Admin_Report {

	/**
	 * Chart colors.
	 *
	 * @var array
	 */
	public $chart_colours = array();

	/**
	 * Categories ids.
	 *
	 * @var array
	 */
	public $show_categories = array();

	/**
	 * Item sales.
	 *
	 * @var array
	 */
	private $item_sales = array();

	/**
	 * Item sales and times.
	 *
	 * @var array
	 */
	private $item_sales_and_times = array();

	/**
	 * Constructor.
	 */
	public function __construct() {
		if ( isset( $_GET['show_categories'] ) ) {
			$this->show_categories = is_array( $_GET['show_categories'] ) ? array_map( 'absint', $_GET['show_categories'] ) : array( absint( $_GET['show_categories'] ) );
		}
	}

	/**
	 * Get all product ids in a category (and its children).
	 *
	 * @param  int $category_id Category ID.
	 * @return array
	 */
	public function get_products_in_category( $category_id ) {
		$term_ids    = get_term_children( $category_id, 'product_cat' );
		$term_ids[]  = $category_id;
		$product_ids = get_objects_in_term( $term_ids, 'product_cat' );

		return array_unique( apply_filters( 'woocommerce_report_sales_by_category_get_products_in_category', $product_ids, $category_id ) );
	}

	/**
	 * Get the legend for the main chart sidebar.
	 *
	 * @return array
	 */
	public function get_chart_legend() {

		if ( empty( $this->show_categories ) ) {
			return array();
		}

		$legend = array();
		$index  = 0;

		foreach ( $this->show_categories as $category ) {

			$category    = get_term( $category, 'product_cat' );
			$total       = 0;
			$product_ids = $this->get_products_in_category( $category->term_id );

			foreach ( $product_ids as $id ) {

				if ( isset( $this->item_sales[ $id ] ) ) {
					$total += $this->item_sales[ $id ];
				}
			}

			$legend[] = array(
				/* translators: 1: total items sold 2: category name */
				'title'            => sprintf( __( '%1$s sales in %2$s', 'woocommerce' ), '<strong>' . wc_price( $total ) . '</strong>', $category->name ),
				'color'            => isset( $this->chart_colours[ $index ] ) ? $this->chart_colours[ $index ] : $this->chart_colours[0],
				'highlight_series' => $index,
			);

			$index++;
		}

		return $legend;
	}

	/**
	 * Output the report.
	 */
	public function output_report() {

		$ranges = array(
			'year'       => __( 'Year', 'woocommerce' ),
			'last_month' => __( 'Last month', 'woocommerce' ),
			'month'      => __( 'This month', 'woocommerce' ),
			'7day'       => __( 'Last 7 days', 'woocommerce' ),
		);

		$this->chart_colours = array( '#3498db', '#34495e', '#1abc9c', '#2ecc71', '#f1c40f', '#e67e22', '#e74c3c', '#2980b9', '#8e44ad', '#2c3e50', '#16a085', '#27ae60', '#f39c12', '#d35400', '#c0392b' );

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day';

		if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ) ) ) {
			$current_range = '7day';
		}

		$this->check_current_range_nonce( $current_range );
		$this->calculate_current_range( $current_range );

		// Get item sales data.
		if ( ! empty( $this->show_categories ) ) {
			$order_items = $this->get_order_report_data(
				array(
					'data'         => array(
						'_product_id' => array(
							'type'            => 'order_item_meta',
							'order_item_type' => 'line_item',
							'function'        => '',
							'name'            => 'product_id',
						),
						'_line_total' => array(
							'type'            => 'order_item_meta',
							'order_item_type' => 'line_item',
							'function'        => 'SUM',
							'name'            => 'order_item_amount',
						),
						'post_date'   => array(
							'type'     => 'post_data',
							'function' => '',
							'name'     => 'post_date',
						),
					),
					'group_by'     => 'ID, product_id, post_date',
					'query_type'   => 'get_results',
					'filter_range' => true,
				)
			);

			$this->item_sales           = array();
			$this->item_sales_and_times = array();

			if ( is_array( $order_items ) ) {

				foreach ( $order_items as $order_item ) {

					switch ( $this->chart_groupby ) {
						case 'day':
							$time = strtotime( gmdate( 'Ymd', strtotime( $order_item->post_date ) ) ) * 1000;
							break;
						case 'month':
						default:
							$time = strtotime( gmdate( 'Ym', strtotime( $order_item->post_date ) ) . '01' ) * 1000;
							break;
					}

					$this->item_sales_and_times[ $time ][ $order_item->product_id ] = isset( $this->item_sales_and_times[ $time ][ $order_item->product_id ] ) ? $this->item_sales_and_times[ $time ][ $order_item->product_id ] + $order_item->order_item_amount : $order_item->order_item_amount;

					$this->item_sales[ $order_item->product_id ] = isset( $this->item_sales[ $order_item->product_id ] ) ? $this->item_sales[ $order_item->product_id ] + $order_item->order_item_amount : $order_item->order_item_amount;
				}
			}
		}

		include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
	}

	/**
	 * Get chart widgets.
	 *
	 * @return array
	 */
	public function get_chart_widgets() {

		return array(
			array(
				'title'    => __( 'Categories', 'woocommerce' ),
				'callback' => array( $this, 'category_widget' ),
			),
		);
	}

	/**
	 * Output category widget.
	 */
	public function category_widget() {

		$categories = get_terms( 'product_cat', array( 'orderby' => 'name' ) );
		?>
		<form method="GET">
			<div>
				<select multiple="multiple" data-placeholder="<?php esc_attr_e( 'Select categories&hellip;', 'woocommerce' ); ?>" class="wc-enhanced-select" id="show_categories" name="show_categories[]" style="width: 205px;">
					<?php
						$r                 = array();
						$r['pad_counts']   = 1;
						$r['hierarchical'] = 1;
						$r['hide_empty']   = 1;
						$r['value']        = 'id';
						$r['selected']     = $this->show_categories;

						include_once WC()->plugin_path() . '/includes/walkers/class-wc-product-cat-dropdown-walker.php';

						echo wc_walk_category_dropdown_tree( $categories, 0, $r ); // @codingStandardsIgnoreLine
					?>
				</select>
				<?php // @codingStandardsIgnoreStart ?>
				<a href="#" class="select_none"><?php esc_html_e( 'None', 'woocommerce' ); ?></a>
				<a href="#" class="select_all"><?php esc_html_e( 'All', 'woocommerce' ); ?></a>
				<button type="submit" class="submit button" value="<?php esc_attr_e( 'Show', 'woocommerce' ); ?>"><?php esc_html_e( 'Show', 'woocommerce' ); ?></button>
				<input type="hidden" name="range" value="<?php echo ( ! empty( $_GET['range'] ) ) ? esc_attr( wp_unslash( $_GET['range'] ) ) : ''; ?>" />
				<input type="hidden" name="start_date" value="<?php echo ( ! empty( $_GET['start_date'] ) ) ? esc_attr( wp_unslash( $_GET['start_date'] ) ) : ''; ?>" />
				<input type="hidden" name="end_date" value="<?php echo ( ! empty( $_GET['end_date'] ) ) ? esc_attr( wp_unslash( $_GET['end_date'] ) ) : ''; ?>" />
				<input type="hidden" name="page" value="<?php echo ( ! empty( $_GET['page'] ) ) ? esc_attr( wp_unslash( $_GET['page'] ) ) : ''; ?>" />
				<input type="hidden" name="tab" value="<?php echo ( ! empty( $_GET['tab'] ) ) ? esc_attr( wp_unslash( $_GET['tab'] ) ) : ''; ?>" />
				<input type="hidden" name="report" value="<?php echo ( ! empty( $_GET['report'] ) ) ? esc_attr( wp_unslash( $_GET['report'] ) ) : ''; ?>" />
				<?php // @codingStandardsIgnoreEnd ?>
			</div>
			<script type="text/javascript">
				jQuery(function(){
					// Select all/None
					jQuery( '.chart-widget' ).on( 'click', '.select_all', function() {
						jQuery(this).closest( 'div' ).find( 'select option' ).attr( 'selected', 'selected' );
						jQuery(this).closest( 'div' ).find('select').trigger( 'change' );
						return false;
					});

					jQuery( '.chart-widget').on( 'click', '.select_none', function() {
						jQuery(this).closest( 'div' ).find( 'select option' ).prop( 'selected', false );
						jQuery(this).closest( 'div' ).find('select').trigger( 'change' );
						return false;
					});
				});
			</script>
		</form>
		<?php
	}

	/**
	 * Output an export link.
	 */
	public function get_export_button() {

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day';
		?>
		<a
			href="#"
			download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv"
			class="export_csv"
			data-export="chart"
			data-xaxes="<?php esc_attr_e( 'Date', 'woocommerce' ); ?>"
			data-groupby="<?php echo esc_attr( $this->chart_groupby ); ?>"
		>
			<?php esc_html_e( 'Export CSV', 'woocommerce' ); ?>
		</a>
		<?php
	}

	/**
	 * Get the main chart.
	 */
	public function get_main_chart() {
		global $wp_locale;

		if ( empty( $this->show_categories ) ) {
			?>
			<div class="chart-container">
				<p class="chart-prompt"><?php esc_html_e( 'Choose a category to view stats', 'woocommerce' ); ?></p>
			</div>
			<?php
		} else {
			$chart_data = array();
			$index      = 0;

			foreach ( $this->show_categories as $category ) {

				$category            = get_term( $category, 'product_cat' );
				$product_ids         = $this->get_products_in_category( $category->term_id );
				$category_chart_data = array();

				for ( $i = 0; $i <= $this->chart_interval; $i ++ ) {

					$interval_total = 0;

					switch ( $this->chart_groupby ) {
						case 'day':
							$time = strtotime( gmdate( 'Ymd', strtotime( "+{$i} DAY", $this->start_date ) ) ) * 1000;
							break;
						case 'month':
						default:
							$time = strtotime( gmdate( 'Ym', strtotime( "+{$i} MONTH", $this->start_date ) ) . '01' ) * 1000;
							break;
					}

					foreach ( $product_ids as $id ) {

						if ( isset( $this->item_sales_and_times[ $time ][ $id ] ) ) {
							$interval_total += $this->item_sales_and_times[ $time ][ $id ];
						}
					}

					$category_chart_data[] = array( $time, (float) wc_format_decimal( $interval_total, wc_get_price_decimals() ) );
				}

				$chart_data[ $category->term_id ]['category'] = $category->name;
				$chart_data[ $category->term_id ]['data']     = $category_chart_data;

				$index++;
			}
			?>
			<div class="chart-container">
				<div class="chart-placeholder main"></div>
			</div>
			<?php // @codingStandardsIgnoreStart ?>
			<script type="text/javascript">
				var main_chart;

				jQuery(function(){
					var drawGraph = function( highlight ) {
						var series = [
							<?php
								$index = 0;
								foreach ( $chart_data as $data ) {
									$color  = isset( $this->chart_colours[ $index ] ) ? $this->chart_colours[ $index ] : $this->chart_colours[0];
									$width  = $this->barwidth / count( $chart_data );
									$offset = ( $width * $index );
									$series = $data['data'];

									foreach ( $series as $key => $series_data ) {
										$series[ $key ][0] = $series_data[0] + $offset;
									}

									$series = wp_json_encode( $series );

									echo '{
											label: "' . esc_js( $data['category'] ) . '",
											data: JSON.parse( decodeURIComponent( "' . rawurlencode( $series ) . '" ) ),
											color: "' . $color . '",
											bars: {
												fillColor: "' . $color . '",
												fill: true,
												show: true,
												lineWidth: 1,
												align: "center",
												barWidth: ' . $width * 0.75 . ',
												stack: false
											},
											' . $this->get_currency_tooltip() . ',
											enable_tooltip: true,
											prepend_label: true
										},';
									$index++;
								}
							?>
						];

						if ( highlight !== 'undefined' && series[ highlight ] ) {
							highlight_series = series[ highlight ];

							highlight_series.color = '#9c5d90';

							if ( highlight_series.bars ) {
								highlight_series.bars.fillColor = '#9c5d90';
							}

							if ( highlight_series.lines ) {
								highlight_series.lines.lineWidth = 5;
							}
						}

						main_chart = jQuery.plot(
							jQuery('.chart-placeholder.main'),
							series,
							{
								legend: {
									show: false
								},
								grid: {
									color: '#aaa',
									borderColor: 'transparent',
									borderWidth: 0,
									hoverable: true
								},
								xaxes: [ {
									color: '#aaa',
									reserveSpace: true,
									position: "bottom",
									tickColor: 'transparent',
									mode: "time",
									timeformat: "<?php echo ( 'day' === $this->chart_groupby ) ? '%d %b' : '%b'; ?>",
									monthNames: JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( array_values( $wp_locale->month_abbrev ) ) ); ?>' ) ),
									tickLength: 1,
									minTickSize: [1, "<?php echo $this->chart_groupby; ?>"],
									tickSize: [1, "<?php echo $this->chart_groupby; ?>"],
									font: {
										color: "#aaa"
									}
								} ],
								yaxes: [
									{
										min: 0,
										tickDecimals: 2,
										color: 'transparent',
										font: { color: "#aaa" }
									}
								],
							}
						);

						jQuery('.chart-placeholder').trigger( 'resize' );

					}

					drawGraph();

					jQuery('.highlight_series').on( 'mouseenter',
						function() {
							drawGraph( jQuery(this).data('series') );
						} ).on( 'mouseleave',
						function() {
							drawGraph();
						}
					);
				});
			</script>
			<?php // @codingStandardsIgnoreEnd ?>
			<?php
		}
	}
}
PK     tS\ Wb  b  !  reports/class-wc-admin-report.phpnu [        <?php
/**
 * Admin report functionality.
 *
 * @package WooCommerce\Admin\Reports
 */

use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Utilities\ArrayUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Admin Report.
 *
 * Extended by reports to show charts and stats in admin.
 *
 * @package     WooCommerce\Admin\Reports
 * @version     2.1.0
 */
class WC_Admin_Report {

	/**
	 * List of transients name that have been updated and need persisting.
	 *
	 * @var array
	 */
	protected static $transients_to_update = array();

	/**
	 * The list of transients.
	 *
	 * @var array
	 */
	protected static $cached_results = array();

	/**
	 * The chart interval.
	 *
	 * @var int
	 */
	public $chart_interval;

	/**
	 * Group by SQL query.
	 *
	 * @var string
	 */
	public $group_by_query;

	/**
	 * The bar width.
	 *
	 * @var int
	 */
	public $barwidth;

	/**
	 * Group chart item by day or month.
	 *
	 * @var string
	 */
	public $chart_groupby;

	/**
	 * The start date of the report.
	 *
	 * @var int timestamp
	 */
	public $start_date;

	/**
	 * The end date of the report.
	 *
	 * @var int timestamp
	 */
	public $end_date;

	/**
	 * Get report totals such as order totals and discount amounts.
	 *
	 * Data example:
	 *
	 * '_order_total' => array(
	 *     'type'     => 'meta',
	 *     'function' => 'SUM',
	 *     'name'     => 'total_sales'
	 * )
	 *
	 * @param  array $args arguments for the report.
	 * @return mixed depending on query_type
	 */
	public function get_order_report_data( $args = array() ) {
		global $wpdb;

		$default_args = array(
			'data'                => array(),
			'where'               => array(),
			'where_meta'          => array(),
			'query_type'          => 'get_row',
			'group_by'            => '',
			'order_by'            => '',
			'limit'               => '',
			'filter_range'        => false,
			'nocache'             => false,
			'debug'               => false,
			'order_types'         => wc_get_order_types( 'reports' ),
			'order_status'        => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD ),
			'parent_order_status' => false,
		);
		$args         = apply_filters( 'woocommerce_reports_get_order_report_data_args', $args );
		$args         = wp_parse_args( $args, $default_args );

		// phpcs:ignore WordPress.PHP.DontExtract.extract_extract
		extract( $args );

		if ( empty( $data ) ) {
			return '';
		}

		$order_status = apply_filters( 'woocommerce_reports_order_statuses', $order_status );

		$query  = array();
		$select = array();

		foreach ( $data as $raw_key => $value ) {
			$key      = sanitize_key( $raw_key );
			$distinct = '';

			if ( isset( $value['distinct'] ) ) {
				$distinct = 'DISTINCT';
			}

			switch ( $value['type'] ) {
				case 'meta':
					$get_key = "meta_{$key}.meta_value";
					break;
				case 'parent_meta':
					$get_key = "parent_meta_{$key}.meta_value";
					break;
				case 'post_data':
					$get_key = "posts.{$key}";
					break;
				case 'order_item_meta':
					$get_key = "order_item_meta_{$key}.meta_value";
					break;
				case 'order_item':
					$get_key = "order_items.{$key}";
					break;
			}

			if ( empty( $get_key ) ) {
				// Skip to the next foreach iteration else the query will be invalid.
				continue;
			}

			if ( $value['function'] ) {
				$get = "{$value['function']}({$distinct} {$get_key})";
			} else {
				$get = "{$distinct} {$get_key}";
			}

			$select[] = "{$get} as {$value['name']}";
		}

		$query['select'] = 'SELECT ' . implode( ',', $select );
		$query['from']   = "FROM {$wpdb->posts} AS posts";

		// Joins.
		$joins = array();

		foreach ( ( $data + $where ) as $raw_key => $value ) {
			$join_type = isset( $value['join_type'] ) ? $value['join_type'] : 'INNER';
			$type      = isset( $value['type'] ) ? $value['type'] : false;
			$key       = sanitize_key( $raw_key );

			switch ( $type ) {
				case 'meta':
					$joins[ "meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS meta_{$key} ON ( posts.ID = meta_{$key}.post_id AND meta_{$key}.meta_key = '{$raw_key}' )";
					break;
				case 'parent_meta':
					$joins[ "parent_meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS parent_meta_{$key} ON (posts.post_parent = parent_meta_{$key}.post_id) AND (parent_meta_{$key}.meta_key = '{$raw_key}')";
					break;
				case 'order_item_meta':
					$joins['order_items'] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON (posts.ID = order_items.order_id)";

					if ( ! empty( $value['order_item_type'] ) ) {
						$joins['order_items'] .= " AND (order_items.order_item_type = '{$value['order_item_type']}')";
					}

					$joins[ "order_item_meta_{$key}" ] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_{$key} ON " .
														"(order_items.order_item_id = order_item_meta_{$key}.order_item_id) " .
														" AND (order_item_meta_{$key}.meta_key = '{$raw_key}')";
					break;
				case 'order_item':
					$joins['order_items'] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_items.order_id";
					break;
			}
		}

		if ( ! empty( $where_meta ) ) {
			foreach ( $where_meta as $value ) {
				if ( ! is_array( $value ) ) {
					continue;
				}
				$join_type = isset( $value['join_type'] ) ? $value['join_type'] : 'INNER';
				$type      = isset( $value['type'] ) ? $value['type'] : false;
				$key       = sanitize_key( is_array( $value['meta_key'] ) ? $value['meta_key'][0] . '_array' : $value['meta_key'] );

				if ( 'order_item_meta' === $type ) {

					$joins['order_items']              = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_items.order_id";
					$joins[ "order_item_meta_{$key}" ] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_{$key} ON order_items.order_item_id = order_item_meta_{$key}.order_item_id";

				} else {
					// If we have a where clause for meta, join the postmeta table.
					$joins[ "meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS meta_{$key} ON posts.ID = meta_{$key}.post_id";
				}
			}
		}

		if ( ! empty( $parent_order_status ) ) {
			$joins['parent'] = "LEFT JOIN {$wpdb->posts} AS parent ON posts.post_parent = parent.ID";
		}

		$query['join'] = implode( ' ', $joins );

		$query['where'] = "
			WHERE 	posts.post_type 	IN ( '" . implode( "','", $order_types ) . "' )
			";

		if ( ! empty( $order_status ) ) {
			$query['where'] .= "
				AND 	posts.post_status 	IN ( 'wc-" . implode( "','wc-", $order_status ) . "')
			";
		}

		if ( ! empty( $parent_order_status ) ) {
			if ( ! empty( $order_status ) ) {
				$query['where'] .= " AND ( parent.post_status IN ( 'wc-" . implode( "','wc-", $parent_order_status ) . "') OR parent.ID IS NULL ) ";
			} else {
				$query['where'] .= " AND parent.post_status IN ( 'wc-" . implode( "','wc-", $parent_order_status ) . "') ";
			}
		}

		// phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date
		if ( $filter_range ) {
			$query['where'] .= "
				AND 	posts.post_date >= '" . date( 'Y-m-d H:i:s', $this->start_date ) . "'
				AND 	posts.post_date < '" . date( 'Y-m-d H:i:s', strtotime( '+1 DAY', $this->end_date ) ) . "'
			";
		}
		// phpcs:enable WordPress.DateTime.RestrictedFunctions.date_date

		if ( ! empty( $where_meta ) ) {

			$relation = isset( $where_meta['relation'] ) ? $where_meta['relation'] : 'AND';

			$query['where'] .= ' AND (';

			foreach ( $where_meta as $index => $value ) {

				if ( ! is_array( $value ) ) {
					continue;
				}

				$key = sanitize_key( is_array( $value['meta_key'] ) ? $value['meta_key'][0] . '_array' : $value['meta_key'] );

				if ( strtolower( $value['operator'] ) === 'in' || strtolower( $value['operator'] ) === 'not in' ) {

					if ( ! empty( $value['meta_value'] ) && ! is_array( $value['meta_value'] ) ) {
						$value['meta_value'] = (array) $value['meta_value']; // @phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
					}

					if ( ! empty( $value['meta_value'] ) ) {
						$formats     = implode( ', ', array_fill( 0, count( $value['meta_value'] ), '%s' ) );
						$where_value = $value['operator'] . ' (' . $wpdb->prepare( $formats, $value['meta_value'] ) . ')'; // @phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
					}
				} else {
					$where_value = $value['operator'] . ' ' . $wpdb->prepare( '%s', $value['meta_value'] );
				}

				if ( ! empty( $where_value ) ) {
					if ( $index > 0 ) {
						$query['where'] .= ' ' . $relation;
					}

					if ( isset( $value['type'] ) && 'order_item_meta' === $value['type'] ) {

						if ( is_array( $value['meta_key'] ) ) {
							$query['where'] .= " ( order_item_meta_{$key}.meta_key   IN ('" . implode( "','", $value['meta_key'] ) . "')";
						} else {
							$query['where'] .= " ( order_item_meta_{$key}.meta_key   = '{$value['meta_key']}'";
						}

						$query['where'] .= " AND order_item_meta_{$key}.meta_value {$where_value} )";
					} else {

						if ( is_array( $value['meta_key'] ) ) {
							$query['where'] .= " ( meta_{$key}.meta_key   IN ('" . implode( "','", $value['meta_key'] ) . "')";
						} else {
							$query['where'] .= " ( meta_{$key}.meta_key   = '{$value['meta_key']}'";
						}

						$query['where'] .= " AND meta_{$key}.meta_value {$where_value} )";
					}
				}
			}

			$query['where'] .= ')';
		}

		if ( ! empty( $where ) ) {

			foreach ( $where as $value ) {

				if ( strtolower( $value['operator'] ) === 'in' || strtolower( $value['operator'] ) === 'not in' ) {

					if ( ! empty( $value['value'] ) && ! is_array( $value['value'] ) ) {
						$value['value'] = (array) $value['value'];
					}
					if ( ! empty( $value['value'] ) ) {
						$formats     = implode( ', ', array_fill( 0, count( $value['value'] ), '%s' ) );
						$where_value = $value['operator'] . ' (' . $wpdb->prepare( $formats, $value['value'] ) . ')'; // @phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
					}
				} else {
					$where_value = $value['operator'] . ' ' . $wpdb->prepare( '%s', $value['value'] );
				}

				if ( ! empty( $where_value ) ) {
					$query['where'] .= " AND {$value['key']} {$where_value}";
				}
			}
		}

		if ( $group_by ) {
			$query['group_by'] = "GROUP BY {$group_by}";
		}

		if ( $order_by ) {
			$query['order_by'] = "ORDER BY {$order_by}";
		}

		if ( $limit ) {
			$query['limit'] = "LIMIT {$limit}";
		}

		$query = apply_filters( 'woocommerce_reports_get_order_report_query', $query );
		$query = implode( ' ', $query );

		if ( $debug ) {
			echo '<pre>';
			wc_print_r( $query );
			echo '</pre>';
		}

		if ( $debug || $nocache ) {
			self::enable_big_selects();

			$result = apply_filters( 'woocommerce_reports_get_order_report_data', $wpdb->$query_type( $query ), $data );
		} else {
			$query_hash = md5( $query_type . $query );
			$result     = $this->get_cached_query( $query_hash );
			if ( null === $result ) {
				self::enable_big_selects();

				$result = apply_filters( 'woocommerce_reports_get_order_report_data', $wpdb->$query_type( $query ), $data );
			}
			$this->set_cached_query( $query_hash, $result );
		}

		return $result;
	}

	/**
	 * Init the static hooks of the class.
	 */
	protected static function add_update_transients_hook() {
		if ( ! has_action( 'shutdown', array( 'WC_Admin_Report', 'maybe_update_transients' ) ) ) {
			add_action( 'shutdown', array( 'WC_Admin_Report', 'maybe_update_transients' ) );
		}
	}

	/**
	 * Enables big mysql selects for reports, just once for this session.
	 */
	protected static function enable_big_selects() {
		static $big_selects = false;

		global $wpdb;

		if ( ! $big_selects ) {
			$wpdb->query( 'SET SESSION SQL_BIG_SELECTS=1' );
			$big_selects = true;
		}
	}

	/**
	 * Get the cached query result or null if it's not in the cache.
	 *
	 * @param string $query_hash The query hash.
	 *
	 * @return mixed
	 */
	protected function get_cached_query( $query_hash ) {
		$class = strtolower( get_class( $this ) );

		if ( ! isset( self::$cached_results[ $class ] ) ) {
			self::$cached_results[ $class ] = get_transient( strtolower( get_class( $this ) ) );
		}

		if ( isset( self::$cached_results[ $class ][ $query_hash ] ) ) {
			return self::$cached_results[ $class ][ $query_hash ];
		}

		return null;
	}

	/**
	 * Set the cached query result.
	 *
	 * @param string $query_hash The query hash.
	 * @param mixed  $data The data to cache.
	 */
	protected function set_cached_query( $query_hash, $data ) {
		$class = strtolower( get_class( $this ) );

		if ( ! isset( self::$cached_results[ $class ] ) ) {
			self::$cached_results[ $class ] = get_transient( $class );
		}

		if ( false === self::$cached_results[ $class ] ) {
			self::$cached_results[ $class ] = array();
		}

		self::add_update_transients_hook();

		self::$transients_to_update[ $class ]          = $class;
		self::$cached_results[ $class ][ $query_hash ] = $data;
	}

	/**
	 * Function to update the modified transients at the end of the request.
	 */
	public static function maybe_update_transients() {
		foreach ( self::$transients_to_update as $key => $transient_name ) {
			set_transient( $transient_name, self::$cached_results[ $transient_name ], DAY_IN_SECONDS );
		}
		// Transients have been updated reset the list.
		self::$transients_to_update = array();
	}

	/**
	 * Put data with post_date's into an array of times.
	 *
	 * @param  array  $data array of your data.
	 * @param  string $date_key key for the 'date' field. e.g. 'post_date'.
	 * @param  string $data_key key for the data you are charting.
	 * @param  int    $interval interval to use.
	 * @param  string $start_date start date.
	 * @param  string $group_by group by.
	 * @return array
	 */
	public function prepare_chart_data( $data, $date_key, $data_key, $interval, $start_date, $group_by ) {
		// phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date

		$prepared_data = array();

		// Ensure all days (or months) have values in this range.
		if ( 'day' === $group_by ) {
			for ( $i = 0; $i <= $interval; $i ++ ) {
				$time = strtotime( date( 'Ymd', strtotime( "+{$i} DAY", $start_date ) ) ) . '000';

				if ( ! isset( $prepared_data[ $time ] ) ) {
					$prepared_data[ $time ] = array( esc_js( $time ), 0 );
				}
			}
		} else {
			$current_yearnum  = date( 'Y', $start_date );
			$current_monthnum = date( 'm', $start_date );

			for ( $i = 0; $i <= $interval; $i ++ ) {
				$time = strtotime( $current_yearnum . str_pad( $current_monthnum, 2, '0', STR_PAD_LEFT ) . '01' ) . '000';

				if ( ! isset( $prepared_data[ $time ] ) ) {
					$prepared_data[ $time ] = array( esc_js( $time ), 0 );
				}

				$current_monthnum ++;

				if ( $current_monthnum > 12 ) {
					$current_monthnum = 1;
					$current_yearnum  ++;
				}
			}
		}

		foreach ( $data as $d ) {
			switch ( $group_by ) {
				case 'day':
					$time = strtotime( date( 'Ymd', strtotime( $d->$date_key ) ) ) . '000';
					break;
				case 'month':
				default:
					$time = strtotime( date( 'Ym', strtotime( $d->$date_key ) ) . '01' ) . '000';
					break;
			}

			if ( ! isset( $prepared_data[ $time ] ) ) {
				continue;
			}

			if ( $data_key ) {
				$prepared_data[ $time ][1] += is_numeric( $d->$data_key ) ? $d->$data_key : 0;
			} else {
				$prepared_data[ $time ][1] ++;
			}
		}

		return $prepared_data;

		// phpcs:enable WordPress.DateTime.RestrictedFunctions.date_date
	}

	/**
	 * Prepares the data for a sparkline to show sales in the last X days.
	 *
	 * @param  int    $id ID of the product to show. Blank to get all orders.
	 * @param  int    $days Days of stats to get. Default to 7 days.
	 * @param  string $type Type of sparkline to get. Ignored if ID is not set.
	 * @return array
	 */
	public function get_sales_sparkline( $id = '', $days = 7, $type = 'sales' ) {

		// phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date, WordPress.DateTime.CurrentTimeTimestamp.Requested

		if ( $id ) {
			$meta_key = ( 'sales' === $type ) ? '_line_total' : '_qty';

			$data = $this->get_order_report_data(
				array(
					'data'         => array(
						'_product_id' => array(
							'type'            => 'order_item_meta',
							'order_item_type' => 'line_item',
							'function'        => '',
							'name'            => 'product_id',
						),
						$meta_key     => array(
							'type'            => 'order_item_meta',
							'order_item_type' => 'line_item',
							'function'        => 'SUM',
							'name'            => 'sparkline_value',
						),
						'post_date'   => array(
							'type'     => 'post_data',
							'function' => '',
							'name'     => 'post_date',
						),
					),
					'where'        => array(
						array(
							'key'      => 'post_date',
							'value'    => date( 'Y-m-d', strtotime( 'midnight -' . ( $days - 1 ) . ' days', current_time( 'timestamp' ) ) ),
							'operator' => '>',
						),
						array(
							'key'      => 'order_item_meta__product_id.meta_value',
							'value'    => $id,
							'operator' => '=',
						),
					),
					'group_by'     => 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)',
					'query_type'   => 'get_results',
					'filter_range' => false,
				)
			);
		} else {

			$data = $this->get_order_report_data(
				array(
					'data'         => array(
						'_order_total' => array(
							'type'     => 'meta',
							'function' => 'SUM',
							'name'     => 'sparkline_value',
						),
						'post_date'    => array(
							'type'     => 'post_data',
							'function' => '',
							'name'     => 'post_date',
						),
					),
					'where'        => array(
						array(
							'key'      => 'post_date',
							'value'    => date( 'Y-m-d', strtotime( 'midnight -' . ( $days - 1 ) . ' days', current_time( 'timestamp' ) ) ),
							'operator' => '>',
						),
					),
					'group_by'     => 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)',
					'query_type'   => 'get_results',
					'filter_range' => false,
				)
			);
		}

		$total = 0;
		foreach ( $data as $d ) {
			$total += $d->sparkline_value;
		}

		$sparkline_data = array_values( $this->prepare_chart_data( $data, 'post_date', 'sparkline_value', $days - 1, strtotime( 'midnight -' . ( $days - 1 ) . ' days', current_time( 'timestamp' ) ), 'day' ) );

		// phpcs:enable WordPress.DateTime.RestrictedFunctions.date_date, WordPress.DateTime.CurrentTimeTimestamp.Requested

		return array(
			'total' => $total,
			'data'  => $sparkline_data,
		);
	}

	/**
	 * Prepares the markup for a sparkline to show sales in the last X days.
	 *
	 * @param  int    $id ID of the product to show. Blank to get all orders.
	 * @param  int    $days Days of stats to get. Default to 7 days.
	 * @param  string $type Type of sparkline to get.
	 * @return string
	 */
	public function sales_sparkline( $id = '', $days = 7, $type = 'sales' ) {
		$sparkline = $this->get_sales_sparkline( $id, $days, $type );
		$total     = $sparkline['total'];

		if ( 'sales' === $type ) {
			/* translators: 1: total income 2: days */
			$tooltip = sprintf( __( 'Sold %1$s worth in the last %2$d days', 'woocommerce' ), wp_strip_all_tags( wc_price( $total ) ), $days );
		} else {
			/* translators: 1: total items sold 2: days */
			$tooltip = sprintf( _n( 'Sold %1$d item in the last %2$d days', 'Sold %1$d items in the last %2$d days', $total, 'woocommerce' ), $total, $days );
		}

		$sparkline_data = $sparkline['data'];

		return '<span class="wc_sparkline ' . ( ( 'sales' === $type ) ? 'lines' : 'bars' ) . ' tips" data-color="#777" data-tip="' . esc_attr( $tooltip ) . '" data-barwidth="' . 60 * 60 * 16 * 1000 . '" data-sparkline="' . wc_esc_json( wp_json_encode( $sparkline_data ) ) . '"></span>';
	}

	/**
	 * Get the current range and calculate the start and end dates.
	 *
	 * @param  string $current_range Type of range.
	 */
	public function calculate_current_range( $current_range ) {

		// phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date, WordPress.DateTime.CurrentTimeTimestamp.Requested
		// phpcs:disable WordPress.Security.NonceVerification.Recommended

		switch ( $current_range ) {

			case 'custom':
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
				$this->start_date = max( strtotime( '-20 years' ), strtotime( sanitize_text_field( wp_unslash( $_GET['start_date'] ) ) ) );

				if ( empty( $_GET['end_date'] ) ) {
					$this->end_date = strtotime( 'midnight', current_time( 'timestamp' ) );
				} else {
					$this->end_date = strtotime( 'midnight', strtotime( sanitize_text_field( wp_unslash( $_GET['end_date'] ) ) ) );
				}

				$interval = 0;
				$min_date = $this->start_date;

				// phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
				while ( ( $min_date = strtotime( '+1 MONTH', $min_date ) ) <= $this->end_date ) {
					$interval ++;
				}

				// 3 months max for day view
				if ( $interval > 3 ) {
					$this->chart_groupby = 'month';
				} else {
					$this->chart_groupby = 'day';
				}
				break;

			case 'year':
				$this->start_date    = strtotime( date( 'Y-01-01', current_time( 'timestamp' ) ) );
				$this->end_date      = strtotime( 'midnight', current_time( 'timestamp' ) );
				$this->chart_groupby = 'month';
				break;

			case 'last_month':
				$first_day_current_month = strtotime( date( 'Y-m-01', current_time( 'timestamp' ) ) );
				$this->start_date        = strtotime( date( 'Y-m-01', strtotime( '-1 DAY', $first_day_current_month ) ) );
				$this->end_date          = strtotime( date( 'Y-m-t', strtotime( '-1 DAY', $first_day_current_month ) ) );
				$this->chart_groupby     = 'day';
				break;

			case 'month':
				$this->start_date    = strtotime( date( 'Y-m-01', current_time( 'timestamp' ) ) );
				$this->end_date      = strtotime( 'midnight', current_time( 'timestamp' ) );
				$this->chart_groupby = 'day';
				break;

			case '7day':
				$this->start_date    = strtotime( '-6 days', strtotime( 'midnight', current_time( 'timestamp' ) ) );
				$this->end_date      = strtotime( 'midnight', current_time( 'timestamp' ) );
				$this->chart_groupby = 'day';
				break;
		}

		// Group by.
		switch ( $this->chart_groupby ) {

			case 'day':
				$this->group_by_query = 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)';
				$this->chart_interval = absint( ceil( max( 0, ( $this->end_date - $this->start_date ) / ( 60 * 60 * 24 ) ) ) );
				$this->barwidth       = 60 * 60 * 24 * 1000;
				break;

			case 'month':
				$this->group_by_query = 'YEAR(posts.post_date), MONTH(posts.post_date)';
				$this->chart_interval = 0;
				$min_date             = strtotime( date( 'Y-m-01', $this->start_date ) );

				// phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
				while ( ( $min_date = strtotime( '+1 MONTH', $min_date ) ) <= $this->end_date ) {
					$this->chart_interval ++;
				}

				$this->barwidth = 60 * 60 * 24 * 7 * 4 * 1000;
				break;
		}

		// phpcs:enable WordPress.Security.NonceVerification.Recommended
		// phpcs:enable WordPress.DateTime.RestrictedFunctions.date_date, WordPress.DateTime.CurrentTimeTimestamp.Requested
	}

	/**
	 * Return currency tooltip JS based on WooCommerce currency position settings.
	 *
	 * @return string
	 */
	public function get_currency_tooltip() {
		switch ( get_option( 'woocommerce_currency_pos' ) ) {
			case 'right':
				$currency_tooltip = 'append_tooltip: "' . get_woocommerce_currency_symbol() . '"';
				break;
			case 'right_space':
				$currency_tooltip = 'append_tooltip: "&nbsp;' . get_woocommerce_currency_symbol() . '"';
				break;
			case 'left':
				$currency_tooltip = 'prepend_tooltip: "' . get_woocommerce_currency_symbol() . '"';
				break;
			case 'left_space':
			default:
				$currency_tooltip = 'prepend_tooltip: "' . get_woocommerce_currency_symbol() . '&nbsp;"';
				break;
		}

		return $currency_tooltip;
	}

	/**
	 * Get the main chart.
	 */
	public function get_main_chart() {}

	/**
	 * Get the legend for the main chart sidebar.
	 *
	 * @return array
	 */
	public function get_chart_legend() {
		return array();
	}

	/**
	 * Get chart widgets.
	 *
	 * @return array
	 */
	public function get_chart_widgets() {
		return array();
	}

	/**
	 * Get an export link if needed.
	 */
	public function get_export_button() {}

	/**
	 * Output the report.
	 */
	public function output_report() {}

	/**
	 * Check nonce for current range.
	 *
	 * @since  3.0.4
	 * @param  string $current_range Current range.
	 */
	public function check_current_range_nonce( $current_range ) {
		if ( 'custom' !== $current_range ) {
			return;
		}

		if ( ! isset( $_GET['wc_reports_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['wc_reports_nonce'] ), 'custom_range' ) ) {
			// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotValidated
			wp_die(
				/* translators: %1$s: open link, %2$s: close link */
				sprintf( esc_html__( 'This report link has expired. %1$sClick here to view the filtered report%2$s.', 'woocommerce' ), '<a href="' . esc_url( wp_nonce_url( esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'custom_range', 'wc_reports_nonce' ) ) . '">', '</a>' ),
				esc_attr__( 'Confirm navigation', 'woocommerce' )
			);
			// phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotValidated
			exit;
		}
	}
}
PK     tS\b@%  @%  )  reports/class-wc-report-taxes-by-date.phpnu [        <?php

use Automattic\WooCommerce\Enums\OrderStatus;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

/**
 * WC_Report_Taxes_By_Date
 *
 * @author      WooThemes
 * @category    Admin
 * @package     WooCommerce\Admin\Reports
 * @version     2.1.0
 */
class WC_Report_Taxes_By_Date extends WC_Admin_Report {

	/**
	 * Get the legend for the main chart sidebar.
	 *
	 * @return array
	 */
	public function get_chart_legend() {
		return array();
	}

	/**
	 * Output an export link.
	 */
	public function get_export_button() {

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( $_GET['range'] ) : 'last_month';
		?>
		<a
			href="#"
			download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo date_i18n( 'Y-m-d', current_time( 'timestamp' ) ); ?>.csv"
			class="export_csv"
			data-export="table"
		>
			<?php _e( 'Export CSV', 'woocommerce' ); ?>
		</a>
		<?php
	}

	/**
	 * Output the report.
	 */
	public function output_report() {

		$ranges = array(
			'year'       => __( 'Year', 'woocommerce' ),
			'last_month' => __( 'Last month', 'woocommerce' ),
			'month'      => __( 'This month', 'woocommerce' ),
		);

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( $_GET['range'] ) : 'last_month';

		if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ) ) ) {
			$current_range = 'last_month';
		}

		$this->check_current_range_nonce( $current_range );
		$this->calculate_current_range( $current_range );

		$hide_sidebar = true;

		include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
	}

	/**
	 * Get the main chart.
	 */
	public function get_main_chart() {
		$query_data = array(
			'_order_tax'          => array(
				'type'     => 'meta',
				'function' => 'SUM',
				'name'     => 'tax_amount',
			),
			'_order_shipping_tax' => array(
				'type'     => 'meta',
				'function' => 'SUM',
				'name'     => 'shipping_tax_amount',
			),
			'_order_total'        => array(
				'type'     => 'meta',
				'function' => 'SUM',
				'name'     => 'total_sales',
			),
			'_order_shipping'     => array(
				'type'     => 'meta',
				'function' => 'SUM',
				'name'     => 'total_shipping',
			),
			'ID'                  => array(
				'type'     => 'post_data',
				'function' => 'COUNT',
				'name'     => 'total_orders',
				'distinct' => true,
			),
			'post_date'           => array(
				'type'     => 'post_data',
				'function' => '',
				'name'     => 'post_date',
			),
		);

		// We exclude on-hold orders are they are still pending payment.
		$tax_rows_orders = $this->get_order_report_data(
			array(
				'data'         => $query_data,
				'group_by'     => $this->group_by_query,
				'order_by'     => 'post_date ASC',
				'query_type'   => 'get_results',
				'filter_range' => true,
				'order_types'  => wc_get_order_types( 'sales-reports' ),
				'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::REFUNDED ),
			)
		);

		$tax_rows_full_refunds = $this->get_order_report_data(
			array(
				'data'                => array(
					'ID'          => array(
						'type'     => 'post_data',
						'distinct' => true,
						'function' => '',
						'name'     => 'ID',
					),
					'post_parent' => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_parent',
					),
					'post_date'   => array(
						'type'     => 'post_data',
						'function' => '',
						'name'     => 'post_date',
					),
				),
				'query_type'          => 'get_results',
				'filter_range'        => true,
				'order_types'         => array( 'shop_order_refund' ),
				'parent_order_status' => array( OrderStatus::REFUNDED ),
			)
		);

		$tax_rows_partial_refunds = $this->get_order_report_data(
			array(
				'data'                => $query_data,
				'group_by'            => $this->group_by_query,
				'order_by'            => 'post_date ASC',
				'query_type'          => 'get_results',
				'filter_range'        => true,
				'order_types'         => array( 'shop_order_refund' ),
				'parent_order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING ), // Partial refunds inside refunded orders should be ignored.
			)
		);

		$tax_rows = array();

		foreach ( $tax_rows_orders + $tax_rows_partial_refunds as $tax_row ) {
			$key              = date( ( 'month' === $this->chart_groupby ) ? 'Ym' : 'Ymd', strtotime( $tax_row->post_date ) );
			$tax_rows[ $key ] = isset( $tax_rows[ $key ] ) ? $tax_rows[ $key ] : (object) array(
				'tax_amount'          => 0,
				'shipping_tax_amount' => 0,
				'total_sales'         => 0,
				'total_shipping'      => 0,
				'total_orders'        => 0,
			);
		}

		foreach ( $tax_rows_orders as $tax_row ) {
			$key                                    = date( ( 'month' === $this->chart_groupby ) ? 'Ym' : 'Ymd', strtotime( $tax_row->post_date ) );
			$tax_rows[ $key ]->total_orders        += $tax_row->total_orders;
			$tax_rows[ $key ]->tax_amount          += $tax_row->tax_amount;
			$tax_rows[ $key ]->shipping_tax_amount += $tax_row->shipping_tax_amount;
			$tax_rows[ $key ]->total_sales         += $tax_row->total_sales;
			$tax_rows[ $key ]->total_shipping      += $tax_row->total_shipping;
		}

		foreach ( $tax_rows_partial_refunds as $tax_row ) {
			$key                                    = date( ( 'month' === $this->chart_groupby ) ? 'Ym' : 'Ymd', strtotime( $tax_row->post_date ) );
			$tax_rows[ $key ]->tax_amount          += $tax_row->tax_amount;
			$tax_rows[ $key ]->shipping_tax_amount += $tax_row->shipping_tax_amount;
			$tax_rows[ $key ]->total_sales         += $tax_row->total_sales;
			$tax_rows[ $key ]->total_shipping      += $tax_row->total_shipping;
		}

		foreach ( $tax_rows_full_refunds as $tax_row ) {
			$key              = date( ( 'month' === $this->chart_groupby ) ? 'Ym' : 'Ymd', strtotime( $tax_row->post_date ) );
			$tax_rows[ $key ] = isset( $tax_rows[ $key ] ) ? $tax_rows[ $key ] : (object) array(
				'tax_amount'          => 0,
				'shipping_tax_amount' => 0,
				'total_sales'         => 0,
				'total_shipping'      => 0,
				'total_orders'        => 0,
			);
			$parent_order     = wc_get_order( $tax_row->post_parent );

			if ( $parent_order ) {
				$tax_rows[ $key ]->tax_amount          += $parent_order->get_cart_tax() * -1;
				$tax_rows[ $key ]->shipping_tax_amount += $parent_order->get_shipping_tax() * -1;
				$tax_rows[ $key ]->total_sales         += $parent_order->get_total() * -1;
				$tax_rows[ $key ]->total_shipping      += $parent_order->get_shipping_total() * -1;
			}
		}
		?>
		<table class="widefat">
			<thead>
				<tr>
					<th><?php _e( 'Period', 'woocommerce' ); ?></th>
					<th class="total_row"><?php _e( 'Number of orders', 'woocommerce' ); ?></th>
					<th class="total_row"><?php _e( 'Total sales', 'woocommerce' ); ?> <?php echo wc_help_tip( __( "This is the sum of the 'Order total' field within your orders.", 'woocommerce' ) ); ?></th>
					<th class="total_row"><?php _e( 'Total shipping', 'woocommerce' ); ?> <?php echo wc_help_tip( __( "This is the sum of the 'Shipping total' field within your orders.", 'woocommerce' ) ); ?></th>
					<th class="total_row"><?php _e( 'Total tax', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the total tax for the rate (shipping tax + product tax).', 'woocommerce' ) ); ?></th>
					<th class="total_row"><?php _e( 'Net profit', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'Total sales minus shipping and tax.', 'woocommerce' ) ); ?></th>
				</tr>
			</thead>
			<?php if ( ! empty( $tax_rows ) ) : ?>
				<tbody>
					<?php
					foreach ( $tax_rows as $date => $tax_row ) {
						$gross     = $tax_row->total_sales - $tax_row->total_shipping;
						$total_tax = $tax_row->tax_amount + $tax_row->shipping_tax_amount;
						?>
						<tr>
							<th scope="row">
								<?php echo ( 'month' === $this->chart_groupby ) ? date_i18n( 'F', strtotime( $date . '01' ) ) : date_i18n( get_option( 'date_format' ), strtotime( $date ) ); ?>
							</th>
							<td class="total_row"><?php echo $tax_row->total_orders; ?></td>
							<td class="total_row"><?php echo wc_price( $gross ); ?></td>
							<td class="total_row"><?php echo wc_price( $tax_row->total_shipping ); ?></td>
							<td class="total_row"><?php echo wc_price( $total_tax ); ?></td>
							<td class="total_row"><?php echo wc_price( $gross - $total_tax ); ?></td>
						</tr>
						<?php
					}
					?>
				</tbody>
				<tfoot>
					<?php
						$gross     = array_sum( wp_list_pluck( (array) $tax_rows, 'total_sales' ) ) - array_sum( wp_list_pluck( (array) $tax_rows, 'total_shipping' ) );
						$total_tax = array_sum( wp_list_pluck( (array) $tax_rows, 'tax_amount' ) ) + array_sum( wp_list_pluck( (array) $tax_rows, 'shipping_tax_amount' ) );
					?>
					<tr>
						<th scope="row"><?php _e( 'Totals', 'woocommerce' ); ?></th>
						<th class="total_row"><?php echo array_sum( wp_list_pluck( (array) $tax_rows, 'total_orders' ) ); ?></th>
						<th class="total_row"><?php echo wc_price( $gross ); ?></th>
						<th class="total_row"><?php echo wc_price( array_sum( wp_list_pluck( (array) $tax_rows, 'total_shipping' ) ) ); ?></th>
						<th class="total_row"><?php echo wc_price( $total_tax ); ?></th>
						<th class="total_row"><?php echo wc_price( $gross - $total_tax ); ?></th>
					</tr>
				</tfoot>
			<?php else : ?>
				<tbody>
					<tr>
						<td><?php _e( 'No taxes found in this period', 'woocommerce' ); ?></td>
					</tr>
				</tbody>
			<?php endif; ?>
		</table>
		<?php
	}
}
PK     tS\ 4"  4"  )  reports/class-wc-report-taxes-by-code.phpnu [        <?php
/**
 * Taxes by tax code report.
 *
 * @package     WooCommerce\Admin\Reports
 */

use Automattic\WooCommerce\Enums\OrderStatus;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Report_Taxes_By_Code
 *
 * @package     WooCommerce\Admin\Reports
 * @version     2.1.0
 */
class WC_Report_Taxes_By_Code extends WC_Admin_Report {

	/**
	 * Get the legend for the main chart sidebar.
	 *
	 * @return array
	 */
	public function get_chart_legend() {
		return array();
	}

	/**
	 * Output an export link.
	 */
	public function get_export_button() {

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'last_month';
		?>
		<a
			href="#"
			download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv"
			class="export_csv"
			data-export="table"
		>
			<?php esc_html_e( 'Export CSV', 'woocommerce' ); ?>
		</a>
		<?php
	}

	/**
	 * Output the report.
	 */
	public function output_report() {

		$ranges = array(
			'year'       => __( 'Year', 'woocommerce' ),
			'last_month' => __( 'Last month', 'woocommerce' ),
			'month'      => __( 'This month', 'woocommerce' ),
		);

		$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'last_month';

		if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ) ) ) {
			$current_range = 'last_month';
		}

		$this->check_current_range_nonce( $current_range );
		$this->calculate_current_range( $current_range );

		$hide_sidebar = true;

		include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
	}

	/**
	 * Get the main chart.
	 */
	public function get_main_chart() {
		global $wpdb;

		$query_data = array(
			'order_item_name'     => array(
				'type'     => 'order_item',
				'function' => '',
				'name'     => 'tax_rate',
			),
			'tax_amount'          => array(
				'type'            => 'order_item_meta',
				'order_item_type' => 'tax',
				'function'        => '',
				'name'            => 'tax_amount',
			),
			'shipping_tax_amount' => array(
				'type'            => 'order_item_meta',
				'order_item_type' => 'tax',
				'function'        => '',
				'name'            => 'shipping_tax_amount',
			),
			'rate_id'             => array(
				'type'            => 'order_item_meta',
				'order_item_type' => 'tax',
				'function'        => '',
				'name'            => 'rate_id',
			),
			'ID'                  => array(
				'type'     => 'post_data',
				'function' => '',
				'name'     => 'post_id',
			),
		);

		$query_where = array(
			array(
				'key'      => 'order_item_type',
				'value'    => 'tax',
				'operator' => '=',
			),
			array(
				'key'      => 'order_item_name',
				'value'    => '',
				'operator' => '!=',
			),
		);

		// We exclude on-hold orders as they are still pending payment.
		$tax_rows_orders = $this->get_order_report_data(
			array(
				'data'         => $query_data,
				'where'        => $query_where,
				'order_by'     => 'posts.post_date ASC',
				'query_type'   => 'get_results',
				'filter_range' => true,
				'order_types'  => wc_get_order_types( 'sales-reports' ),
				'order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::REFUNDED ),
			)
		);

		$tax_rows_partial_refunds = $this->get_order_report_data(
			array(
				'data'                => $query_data,
				'where'               => $query_where,
				'order_by'            => 'posts.post_date ASC',
				'query_type'          => 'get_results',
				'filter_range'        => true,
				'order_types'         => array( 'shop_order_refund' ),
				'parent_order_status' => array( OrderStatus::COMPLETED, OrderStatus::PROCESSING ), // Partial refunds inside refunded orders should be ignored.
			)
		);

		$tax_rows_full_refunds = $this->get_order_report_data(
			array(
				'data'                => $query_data,
				'where'               => $query_where,
				'order_by'            => 'posts.post_date ASC',
				'query_type'          => 'get_results',
				'filter_range'        => true,
				'order_types'         => array( 'shop_order_refund' ),
				'parent_order_status' => array( OrderStatus::REFUNDED ),
			)
		);

		// Merge.
		$tax_rows = array();
		// Initialize an associative array to store unique post_ids.
		$unique_post_ids = array();

		foreach ( $tax_rows_orders + $tax_rows_partial_refunds as $tax_row ) {
			$key                                    = $tax_row->tax_rate;
			$tax_rows[ $key ]                       = isset( $tax_rows[ $key ] ) ? $tax_rows[ $key ] : (object) array(
				'tax_amount'          => 0,
				'shipping_tax_amount' => 0,
				'total_orders'        => 0,
			);
			$tax_rows[ $key ]->tax_rate             = $tax_row->tax_rate;
			$tax_rows[ $key ]->tax_amount          += wc_round_tax_total( $tax_row->tax_amount );
			$tax_rows[ $key ]->shipping_tax_amount += wc_round_tax_total( $tax_row->shipping_tax_amount );
			if ( ! isset( $unique_post_ids[ $key ] ) || ! in_array( $tax_row->post_id, $unique_post_ids[ $key ], true ) ) {
				$unique_post_ids[ $key ]         = isset( $unique_post_ids[ $key ] ) ? $unique_post_ids[ $key ] : array();
				$unique_post_ids[ $key ][]       = $tax_row->post_id;
				$tax_rows[ $key ]->total_orders += 1;
			}
		}

		foreach ( $tax_rows_full_refunds as $tax_row ) {
			$key                                    = $tax_row->tax_rate;
			$tax_rows[ $key ]                       = isset( $tax_rows[ $key ] ) ? $tax_rows[ $key ] : (object) array(
				'tax_amount'          => 0,
				'shipping_tax_amount' => 0,
				'total_orders'        => 0,
			);
			$tax_rows[ $key ]->tax_rate             = $tax_row->tax_rate;
			$tax_rows[ $key ]->tax_amount          += wc_round_tax_total( $tax_row->tax_amount );
			$tax_rows[ $key ]->shipping_tax_amount += wc_round_tax_total( $tax_row->shipping_tax_amount );
		}
		?>
		<table class="widefat">
			<thead>
				<tr>
					<th><?php esc_html_e( 'Tax', 'woocommerce' ); ?></th>
					<th><?php esc_html_e( 'Rate', 'woocommerce' ); ?></th>
					<th class="total_row"><?php esc_html_e( 'Number of orders', 'woocommerce' ); ?></th>
					<th class="total_row"><?php esc_html_e( 'Tax amount', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the sum of the "Tax rows" tax amount within your orders.', 'woocommerce' ) ); ?></th>
					<th class="total_row"><?php esc_html_e( 'Shipping tax amount', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the sum of the "Tax rows" shipping tax amount within your orders.', 'woocommerce' ) ); ?></th>
					<th class="total_row"><?php esc_html_e( 'Total tax', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the total tax for the rate (shipping tax + product tax).', 'woocommerce' ) ); ?></th>
				</tr>
			</thead>
			<?php if ( ! empty( $tax_rows ) ) : ?>
				<tbody>
					<?php
					foreach ( $tax_rows as $rate_id => $tax_row ) {
						$rate = $wpdb->get_var( $wpdb->prepare( "SELECT tax_rate FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $rate_id ) );
						?>
						<tr>
							<th scope="row"><?php echo wp_kses_post( apply_filters( 'woocommerce_reports_taxes_tax_rate', $tax_row->tax_rate, $rate_id, $tax_row ) ); ?></th>
							<td><?php echo wp_kses_post( apply_filters( 'woocommerce_reports_taxes_rate', $rate, $rate_id, $tax_row ) ); ?>%</td>
							<td class="total_row"><?php echo esc_html( $tax_row->total_orders ); ?></td>
							<td class="total_row"><?php echo wc_price( $tax_row->tax_amount ); // phpcs:ignore ?></td>
							<td class="total_row"><?php echo wc_price( $tax_row->shipping_tax_amount ); // phpcs:ignore ?></td>
							<td class="total_row"><?php echo wc_price( $tax_row->tax_amount + $tax_row->shipping_tax_amount ); // phpcs:ignore ?></td>
						</tr>
						<?php
					}
					?>
				</tbody>
				<tfoot>
					<tr>
						<th scope="row" colspan="3"><?php esc_html_e( 'Total', 'woocommerce' ); ?></th>
						<th class="total_row"><?php echo wc_price( wc_round_tax_total( array_sum( wp_list_pluck( (array) $tax_rows, 'tax_amount' ) ) ) ); // phpcs:ignore ?></th>
						<th class="total_row"><?php echo wc_price( wc_round_tax_total( array_sum( wp_list_pluck( (array) $tax_rows, 'shipping_tax_amount' ) ) ) ); // phpcs:ignore ?></th>
						<th class="total_row"><strong><?php echo wc_price( wc_round_tax_total( array_sum( wp_list_pluck( (array) $tax_rows, 'tax_amount' ) ) + array_sum( wp_list_pluck( (array) $tax_rows, 'shipping_tax_amount' ) ) ) ); // phpcs:ignore ?></strong></th>
					</tr>
				</tfoot>
			<?php else : ?>
				<tbody>
					<tr>
						<td><?php esc_html_e( 'No taxes found in this period', 'woocommerce' ); ?></td>
					</tr>
				</tbody>
			<?php endif; ?>
		</table>
		<?php
	}
}
PK     tS\!  !  )  reports/class-wc-report-customer-list.phpnu [        <?php
/**
 * Class WC_Report_Customer_List file.
 *
 * @package WooCommerce\Reports
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

/**
 * WC_Report_Customer_List.
 *
 * @package     WooCommerce\Admin\Reports
 * @version     2.1.0
 */
class WC_Report_Customer_List extends WP_List_Table {

	/**
	 * Constructor.
	 */
	public function __construct() {

		parent::__construct(
			array(
				'singular' => 'customer',
				'plural'   => 'customers',
				'ajax'     => false,
			)
		);
	}

	/**
	 * No items found text.
	 */
	public function no_items() {
		esc_html_e( 'No customers found.', 'woocommerce' );
	}

	/**
	 * Output the report.
	 */
	public function output_report() {
		$this->prepare_items();

		echo '<div id="poststuff" class="woocommerce-reports-wide">';

		if ( ! empty( $_GET['link_orders'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'link_orders' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
			$linked = wc_update_new_customer_past_orders( absint( $_GET['link_orders'] ) );
			/* translators: single or plural number of orders */
			echo '<div class="updated"><p>' . esc_html( sprintf( _n( '%s previous order linked', '%s previous orders linked', $linked, 'woocommerce' ), $linked ) ) . '</p></div>';
		}

		if ( ! empty( $_GET['refresh'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'refresh' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
			$user_id = absint( $_GET['refresh'] );
			$user    = get_user_by( 'id', $user_id );

			delete_user_meta( $user_id, '_money_spent' );
			delete_user_meta( $user_id, '_order_count' );
			delete_user_meta( $user_id, '_last_order' );
			/* translators: User display name */
			echo '<div class="updated"><p>' . sprintf( esc_html__( 'Refreshed stats for %s', 'woocommerce' ), esc_html( $user->display_name ) ) . '</p></div>';
		}

		echo '<form method="post" id="woocommerce_customers">';

		$this->search_box( __( 'Search customers', 'woocommerce' ), 'customer_search' );
		$this->display();

		echo '</form>';
		echo '</div>';
	}

	/**
	 * Get column value.
	 *
	 * @param WP_User $user WP User object.
	 * @param string  $column_name Column name.
	 * @return string
	 */
	public function column_default( $user, $column_name ) {
		switch ( $column_name ) {

			case 'customer_name':
				if ( $user->last_name && $user->first_name ) {
					return $user->last_name . ', ' . $user->first_name;
				} else {
					return '-';
				}

			case 'username':
				return $user->user_login;

			case 'location':
				$state_code   = get_user_meta( $user->ID, 'billing_state', true );
				$country_code = get_user_meta( $user->ID, 'billing_country', true );

				$state   = isset( WC()->countries->states[ $country_code ][ $state_code ] ) ? WC()->countries->states[ $country_code ][ $state_code ] : $state_code;
				$country = isset( WC()->countries->countries[ $country_code ] ) ? WC()->countries->countries[ $country_code ] : $country_code;

				$value = '';

				if ( $state ) {
					$value .= $state . ', ';
				}

				$value .= $country;

				if ( $value ) {
					return $value;
				} else {
					return '-';
				}

			case 'email':
				return '<a href="mailto:' . $user->user_email . '">' . $user->user_email . '</a>';

			case 'spent':
				return wc_price( wc_get_customer_total_spent( $user->ID ) );

			case 'orders':
				return wc_get_customer_order_count( $user->ID );

			case 'last_order':
				$orders = wc_get_orders(
					array(
						'limit'    => 1,
						'status'   => array_map( 'wc_get_order_status_name', wc_get_is_paid_statuses() ),
						'customer' => $user->ID,
					)
				);

				if ( ! empty( $orders ) ) {
					$order = $orders[0];
					return '<a href="' . admin_url( 'post.php?post=' . $order->get_id() . '&action=edit' ) . '">' . _x( '#', 'hash before order number', 'woocommerce' ) . $order->get_order_number() . '</a> &ndash; ' . wc_format_datetime( $order->get_date_created() );
				} else {
					return '-';
				}

				break;

			case 'wc_actions':
				ob_start();
				?><p>
					<?php
					do_action( 'woocommerce_admin_user_actions_start', $user );

					$actions = array();

					$actions['refresh'] = array(
						'url'    => wp_nonce_url( add_query_arg( 'refresh', $user->ID ), 'refresh' ),
						'name'   => __( 'Refresh stats', 'woocommerce' ),
						'action' => 'refresh',
					);

					$actions['edit'] = array(
						'url'    => admin_url( 'user-edit.php?user_id=' . $user->ID ),
						'name'   => __( 'Edit', 'woocommerce' ),
						'action' => 'edit',
					);

					$actions['view'] = array(
						'url'    => admin_url( 'edit.php?post_type=shop_order&_customer_user=' . $user->ID ),
						'name'   => __( 'View orders', 'woocommerce' ),
						'action' => 'view',
					);

					$orders = wc_get_orders(
						array(
							'limit'    => 1,
							'status'   => array_map( 'wc_get_order_status_name', wc_get_is_paid_statuses() ),
							'customer' => array( array( 0, $user->user_email ) ),
						)
					);

					if ( $orders ) {
						$actions['link'] = array(
							'url'    => wp_nonce_url( add_query_arg( 'link_orders', $user->ID ), 'link_orders' ),
							'name'   => __( 'Link previous orders', 'woocommerce' ),
							'action' => 'link',
						);
					}

					$actions = apply_filters( 'woocommerce_admin_user_actions', $actions, $user );

					foreach ( $actions as $action ) {
						printf( '<a class="button tips %s" href="%s" data-tip="%s">%s</a>', esc_attr( $action['action'] ), esc_url( $action['url'] ), esc_attr( $action['name'] ), esc_attr( $action['name'] ) );
					}

					do_action( 'woocommerce_admin_user_actions_end', $user );
					?>
				</p>
				<?php
				$user_actions = ob_get_contents();
				ob_end_clean();

				return $user_actions;
		}

		return '';
	}

	/**
	 * Get columns.
	 *
	 * @return array
	 */
	public function get_columns() {
		$columns = array(
			'customer_name' => __( 'Name (Last, First)', 'woocommerce' ),
			'username'      => __( 'Username', 'woocommerce' ),
			'email'         => __( 'Email', 'woocommerce' ),
			'location'      => __( 'Location', 'woocommerce' ),
			'orders'        => __( 'Orders', 'woocommerce' ),
			'spent'         => __( 'Money spent', 'woocommerce' ),
			'last_order'    => __( 'Last order', 'woocommerce' ),
			'wc_actions'    => __( 'Actions', 'woocommerce' ),
		);

		return $columns;
	}

	/**
	 * Order users by name.
	 *
	 * @param WP_User_Query $query Query that gets passed through.
	 * @return WP_User_Query
	 */
	public function order_by_last_name( $query ) {
		global $wpdb;

		$s = ! empty( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

		$query->query_from   .= " LEFT JOIN {$wpdb->usermeta} as meta2 ON ({$wpdb->users}.ID = meta2.user_id) ";
		$query->query_where  .= " AND meta2.meta_key = 'last_name' ";
		$query->query_orderby = ' ORDER BY meta2.meta_value, user_login ASC ';

		if ( $s ) {
			$query->query_from   .= " LEFT JOIN {$wpdb->usermeta} as meta3 ON ({$wpdb->users}.ID = meta3.user_id)";
			$query->query_where  .= " AND ( user_login LIKE '%" . esc_sql( str_replace( '*', '', $s ) ) . "%' OR user_nicename LIKE '%" . esc_sql( str_replace( '*', '', $s ) ) . "%' OR meta3.meta_value LIKE '%" . esc_sql( str_replace( '*', '', $s ) ) . "%' ) ";
			$query->query_orderby = ' GROUP BY ID ' . $query->query_orderby;
		}

		return $query;
	}

	/**
	 * Prepare customer list items.
	 */
	public function prepare_items() {
		$current_page = absint( $this->get_pagenum() );
		$per_page     = 20;

		/**
		 * Init column headers.
		 */
		$this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );

		add_action( 'pre_user_query', array( $this, 'order_by_last_name' ) );

		$privileged_users = new WP_User_Query(
			array(
				'fields'   => 'ID',
				'role__in' => array( 'administrator', 'shop_manager' ),
			),
		);
		$query            = new WP_User_Query(
			apply_filters(
				'woocommerce_admin_report_customer_list_user_query_args',
				array(
					'exclude' => $privileged_users->get_results(),
					'number'  => $per_page,
					'offset'  => ( $current_page - 1 ) * $per_page,
				)
			)
		);

		$this->items = $query->get_results();

		remove_action( 'pre_user_query', array( $this, 'order_by_last_name' ) );

		/**
		 * Pagination.
		 */
		$this->set_pagination_args(
			array(
				'total_items' => $query->total_users,
				'per_page'    => $per_page,
				'total_pages' => ceil( $query->total_users / $per_page ),
			)
		);
	}
}
PK     tS\{  {  (  reports/class-wc-report-out-of-stock.phpnu [        <?php
/**
 * WC_Report_Out_Of_Stock.
 *
 * @package WooCommerce\Admin\Reports
 */

defined( 'ABSPATH' ) || exit;

if ( ! class_exists( 'WC_Report_Stock' ) ) {
	require_once dirname( __FILE__ ) . '/class-wc-report-stock.php';
}

/**
 * WC_Report_Out_Of_Stock class.
 */
class WC_Report_Out_Of_Stock extends WC_Report_Stock {

	/**
	 * No items found text.
	 */
	public function no_items() {
		esc_html_e( 'No out of stock products found.', 'woocommerce' );
	}

	/**
	 * Get Products matching stock criteria.
	 *
	 * @param int $current_page Current page number.
	 * @param int $per_page How many results to show per page.
	 */
	public function get_items( $current_page, $per_page ) {
		global $wpdb;

		$this->max_items = 0;
		$this->items     = array();

		$stock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );

		$query_from = apply_filters(
			'woocommerce_report_out_of_stock_query_from',
			$wpdb->prepare(
				"
				FROM {$wpdb->posts} as posts
				INNER JOIN {$wpdb->wc_product_meta_lookup} AS lookup ON posts.ID = lookup.product_id
				WHERE 1=1
				AND posts.post_type IN ( 'product', 'product_variation' )
				AND posts.post_status = 'publish'
				AND lookup.stock_quantity <= %d
				",
				$stock
			)
		);

		$this->items     = $wpdb->get_results( $wpdb->prepare( "SELECT SQL_CALC_FOUND_ROWS posts.ID as id, posts.post_parent as parent {$query_from} ORDER BY posts.post_title DESC LIMIT %d, %d;", ( $current_page - 1 ) * $per_page, $per_page ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
		$this->max_items = $wpdb->get_var( 'SELECT FOUND_ROWS();' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
	}
}
PK     tS\vIF  F    class-wc-admin-taxonomies.phpnu [        <?php
/**
 * Handles taxonomies in admin
 *
 * @class    WC_Admin_Taxonomies
 * @version  2.3.10
 * @package  WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

use Automattic\WooCommerce\Internal\AssignDefaultCategory;

/**
 * WC_Admin_Taxonomies class.
 */
class WC_Admin_Taxonomies {

	/**
	 * Class instance.
	 *
	 * @var WC_Admin_Taxonomies instance
	 */
	protected static $instance = false;

	/**
	 * Default category ID.
	 *
	 * @var int
	 */
	private $default_cat_id = 0;

	/**
	 * Get class instance
	 */
	public static function get_instance() {
		if ( ! self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor.
	 */
	public function __construct() {
		// Default category ID.
		$this->default_cat_id = get_option( 'default_product_cat', 0 );

		// Category/term ordering.
		add_action( 'create_term', array( $this, 'create_term' ), 5, 3 );
		add_action(
			'delete_product_cat',
			function() {
				wc_get_container()->get( AssignDefaultCategory::class )->schedule_action();
			}
		);

		// Add form.
		add_action( 'product_cat_add_form_fields', array( $this, 'add_category_fields' ) );
		add_action( 'product_cat_edit_form_fields', array( $this, 'edit_category_fields' ), 10 );
		add_action( 'created_term', array( $this, 'save_category_fields' ), 10, 3 );
		add_action( 'edit_term', array( $this, 'save_category_fields' ), 10, 3 );

		// Add columns.
		add_filter( 'manage_edit-product_cat_columns', array( $this, 'product_cat_columns' ) );
		add_filter( 'manage_product_cat_custom_column', array( $this, 'product_cat_column' ), 10, 3 );

		// Add row actions.
		add_filter( 'product_cat_row_actions', array( $this, 'product_cat_row_actions' ), 10, 2 );
		add_filter( 'admin_init', array( $this, 'handle_product_cat_row_actions' ) );

		// Taxonomy page descriptions.
		add_action( 'product_cat_pre_add_form', array( $this, 'product_cat_description' ) );
		add_action( 'after-product_cat-table', array( $this, 'product_cat_notes' ) );

		$attribute_taxonomies = wc_get_attribute_taxonomies();

		if ( ! empty( $attribute_taxonomies ) ) {
			foreach ( $attribute_taxonomies as $attribute ) {
				add_action( 'pa_' . $attribute->attribute_name . '_pre_add_form', array( $this, 'product_attribute_description' ) );
			}
		}

		// Maintain hierarchy of terms.
		add_filter( 'wp_terms_checklist_args', array( $this, 'disable_checked_ontop' ) );

		// Admin footer scripts for this product categories admin screen.
		add_action( 'admin_footer', array( $this, 'scripts_at_product_cat_screen_footer' ) );
	}

	/**
	 * Order term when created (put in position 0).
	 *
	 * @param mixed  $term_id Term ID.
	 * @param mixed  $tt_id Term taxonomy ID.
	 * @param string $taxonomy Taxonomy slug.
	 */
	public function create_term( $term_id, $tt_id = '', $taxonomy = '' ) {
		if ( 'product_cat' !== $taxonomy && ! taxonomy_is_product_attribute( $taxonomy ) ) {
			return;
		}

		update_term_meta( $term_id, 'order', 0 );
	}

	/**
	 * When a term is deleted, delete its meta.
	 *
	 * @deprecated 3.6.0 No longer needed.
	 * @param mixed $term_id Term ID.
	 */
	public function delete_term( $term_id ) {
		wc_deprecated_function( 'delete_term', '3.6' );
	}

	/**
	 * Category thumbnail fields.
	 */
	public function add_category_fields() {
		?>
		<div class="form-field term-display-type-wrap">
			<label for="display_type"><?php esc_html_e( 'Display type', 'woocommerce' ); ?></label>
			<select id="display_type" name="display_type" class="postform">
				<option value=""><?php esc_html_e( 'Default', 'woocommerce' ); ?></option>
				<option value="products"><?php esc_html_e( 'Products', 'woocommerce' ); ?></option>
				<option value="subcategories"><?php esc_html_e( 'Subcategories', 'woocommerce' ); ?></option>
				<option value="both"><?php esc_html_e( 'Both', 'woocommerce' ); ?></option>
			</select>
		</div>
		<div class="form-field term-thumbnail-wrap">
			<label><?php esc_html_e( 'Thumbnail', 'woocommerce' ); ?></label>
			<div id="product_cat_thumbnail" style="float: left; margin-right: 10px;"><img src="<?php echo esc_url( wc_placeholder_img_src() ); ?>" width="60px" height="60px" /></div>
			<div style="line-height: 60px;">
				<input type="hidden" id="product_cat_thumbnail_id" name="product_cat_thumbnail_id" />
				<button type="button" class="upload_image_button button"><?php esc_html_e( 'Upload/Add image', 'woocommerce' ); ?></button>
				<button type="button" class="remove_image_button button"><?php esc_html_e( 'Remove image', 'woocommerce' ); ?></button>
			</div>
			<script type="text/javascript">

				// Only show the "remove image" button when needed
				if ( ! jQuery( '#product_cat_thumbnail_id' ).val() ) {
					jQuery( '.remove_image_button' ).hide();
				}

				// Uploading files
				var file_frame;

				jQuery( document ).on( 'click', '.upload_image_button', function( event ) {

					event.preventDefault();

					// If the media frame already exists, reopen it.
					if ( file_frame ) {
						file_frame.open();
						return;
					}

					// Create the media frame.
					file_frame = wp.media.frames.downloadable_file = wp.media({
						title: '<?php esc_html_e( 'Choose an image', 'woocommerce' ); ?>',
						button: {
							text: '<?php esc_html_e( 'Use image', 'woocommerce' ); ?>'
						},
						multiple: false
					});

					// When an image is selected, run a callback.
					file_frame.on( 'select', function() {
						var attachment           = file_frame.state().get( 'selection' ).first().toJSON();
						var attachment_thumbnail = attachment.sizes.thumbnail || attachment.sizes.full;

						jQuery( '#product_cat_thumbnail_id' ).val( attachment.id );
						jQuery( '#product_cat_thumbnail' ).find( 'img' ).attr( 'src', attachment_thumbnail.url );
						jQuery( '.remove_image_button' ).show();
					});

					// Finally, open the modal.
					file_frame.open();
				});

				jQuery( document ).on( 'click', '.remove_image_button', function() {
					jQuery( '#product_cat_thumbnail' ).find( 'img' ).attr( 'src', '<?php echo esc_js( wc_placeholder_img_src() ); ?>' );
					jQuery( '#product_cat_thumbnail_id' ).val( '' );
					jQuery( '.remove_image_button' ).hide();
					return false;
				});

				jQuery( document ).ajaxComplete( function( event, request, options ) {
					if ( request && 4 === request.readyState && 200 === request.status
						&& options.data && 0 <= options.data.indexOf( 'action=add-tag' ) ) {

						var res = wpAjax.parseAjaxResponse( request.responseXML, 'ajax-response' );
						if ( ! res || res.errors ) {
							return;
						}
						// Clear Thumbnail fields on submit
						jQuery( '#product_cat_thumbnail' ).find( 'img' ).attr( 'src', '<?php echo esc_js( wc_placeholder_img_src() ); ?>' );
						jQuery( '#product_cat_thumbnail_id' ).val( '' );
						jQuery( '.remove_image_button' ).hide();
						// Clear Display type field on submit
						jQuery( '#display_type' ).val( '' );
						return;
					}
				} );

			</script>
			<div class="clear"></div>
		</div>
		<?php
	}

	/**
	 * Edit category thumbnail field.
	 *
	 * @param mixed $term Term (category) being edited.
	 */
	public function edit_category_fields( $term ) {

		$display_type = get_term_meta( $term->term_id, 'display_type', true );
		$thumbnail_id = absint( get_term_meta( $term->term_id, 'thumbnail_id', true ) );

		if ( $thumbnail_id ) {
			$image = wp_get_attachment_thumb_url( $thumbnail_id );
		} else {
			$image = wc_placeholder_img_src();
		}
		?>
		<tr class="form-field term-display-type-wrap">
			<th scope="row" valign="top"><label><?php esc_html_e( 'Display type', 'woocommerce' ); ?></label></th>
			<td>
				<select id="display_type" name="display_type" class="postform">
					<option value="" <?php selected( '', $display_type ); ?>><?php esc_html_e( 'Default', 'woocommerce' ); ?></option>
					<option value="products" <?php selected( 'products', $display_type ); ?>><?php esc_html_e( 'Products', 'woocommerce' ); ?></option>
					<option value="subcategories" <?php selected( 'subcategories', $display_type ); ?>><?php esc_html_e( 'Subcategories', 'woocommerce' ); ?></option>
					<option value="both" <?php selected( 'both', $display_type ); ?>><?php esc_html_e( 'Both', 'woocommerce' ); ?></option>
				</select>
			</td>
		</tr>
		<tr class="form-field term-thumbnail-wrap">
			<th scope="row" valign="top"><label><?php esc_html_e( 'Thumbnail', 'woocommerce' ); ?></label></th>
			<td>
				<div id="product_cat_thumbnail" style="float: left; margin-right: 10px;"><img src="<?php echo esc_url( $image ); ?>" width="60px" height="60px" /></div>
				<div style="line-height: 60px;">
					<input type="hidden" id="product_cat_thumbnail_id" name="product_cat_thumbnail_id" value="<?php echo esc_attr( $thumbnail_id ); ?>" />
					<button type="button" class="upload_image_button button"><?php esc_html_e( 'Upload/Add image', 'woocommerce' ); ?></button>
					<button type="button" class="remove_image_button button"><?php esc_html_e( 'Remove image', 'woocommerce' ); ?></button>
				</div>
				<script type="text/javascript">

					// Only show the "remove image" button when needed
					if ( '0' === jQuery( '#product_cat_thumbnail_id' ).val() ) {
						jQuery( '.remove_image_button' ).hide();
					}

					// Uploading files
					var file_frame;

					jQuery( document ).on( 'click', '.upload_image_button', function( event ) {

						event.preventDefault();

						// If the media frame already exists, reopen it.
						if ( file_frame ) {
							file_frame.open();
							return;
						}

						// Create the media frame.
						file_frame = wp.media.frames.downloadable_file = wp.media({
							title: '<?php esc_html_e( 'Choose an image', 'woocommerce' ); ?>',
							button: {
								text: '<?php esc_html_e( 'Use image', 'woocommerce' ); ?>'
							},
							multiple: false
						});

						// When an image is selected, run a callback.
						file_frame.on( 'select', function() {
							var attachment           = file_frame.state().get( 'selection' ).first().toJSON();
							var attachment_thumbnail = attachment.sizes.thumbnail || attachment.sizes.full;

							jQuery( '#product_cat_thumbnail_id' ).val( attachment.id );
							jQuery( '#product_cat_thumbnail' ).find( 'img' ).attr( 'src', attachment_thumbnail.url );
							jQuery( '.remove_image_button' ).show();
						});

						// Finally, open the modal.
						file_frame.open();
					});

					jQuery( document ).on( 'click', '.remove_image_button', function() {
						jQuery( '#product_cat_thumbnail' ).find( 'img' ).attr( 'src', '<?php echo esc_js( wc_placeholder_img_src() ); ?>' );
						jQuery( '#product_cat_thumbnail_id' ).val( '' );
						jQuery( '.remove_image_button' ).hide();
						return false;
					});

				</script>
				<div class="clear"></div>
			</td>
		</tr>
		<?php
	}

	/**
	 * Save category fields
	 *
	 * @param mixed  $term_id Term ID being saved.
	 * @param mixed  $tt_id Term taxonomy ID.
	 * @param string $taxonomy Taxonomy slug.
	 */
	public function save_category_fields( $term_id, $tt_id = '', $taxonomy = '' ) {
		if ( isset( $_POST['display_type'] ) && 'product_cat' === $taxonomy ) { // WPCS: CSRF ok, input var ok.
			update_term_meta( $term_id, 'display_type', esc_attr( $_POST['display_type'] ) ); // WPCS: CSRF ok, sanitization ok, input var ok.
		}
		if ( isset( $_POST['product_cat_thumbnail_id'] ) && 'product_cat' === $taxonomy ) { // WPCS: CSRF ok, input var ok.
			update_term_meta( $term_id, 'thumbnail_id', absint( $_POST['product_cat_thumbnail_id'] ) ); // WPCS: CSRF ok, input var ok.
		}
	}

	/**
	 * Description for product_cat page to aid users.
	 */
	public function product_cat_description() {
		echo wp_kses(
			wpautop( __( 'Product categories for your store can be managed here. To change the order of categories on the front-end you can drag and drop to sort them. To see more categories listed click the "screen options" link at the top-right of this page.', 'woocommerce' ) ),
			array( 'p' => array() )
		);
	}

	/**
	 * Add some notes to describe the behavior of the default category.
	 */
	public function product_cat_notes() {
		$category_id   = get_option( 'default_product_cat', 0 );
		$category      = get_term( $category_id, 'product_cat' );
		$category_name = ( ! $category || is_wp_error( $category ) ) ? _x( 'Uncategorized', 'Default category slug', 'woocommerce' ) : $category->name;
		?>
		<div class="form-wrap edit-term-notes">
			<p>
				<strong><?php esc_html_e( 'Note:', 'woocommerce' ); ?></strong><br>
				<?php
					printf(
						/* translators: %s: default category */
						esc_html__( 'Deleting a category does not delete the products in that category. Instead, products that were only assigned to the deleted category are set to the category %s.', 'woocommerce' ),
						'<strong>' . esc_html( $category_name ) . '</strong>'
					);
				?>
			</p>
		</div>
		<?php
	}

	/**
	 * Description for shipping class page to aid users.
	 */
	public function product_attribute_description() {
		echo wp_kses(
			wpautop( __( 'Attribute terms can be assigned to products and variations.<br/><br/><b>Note</b>: Deleting a term will remove it from all products and variations to which it has been assigned. Recreating a term will not automatically assign it back to products.', 'woocommerce' ) ),
			array( 'p' => array() )
		);
	}

	/**
	 * Thumbnail column added to category admin.
	 *
	 * @param mixed $columns Columns array.
	 * @return array
	 */
	public function product_cat_columns( $columns ) {
		$new_columns = array();

		if ( isset( $columns['cb'] ) ) {
			$new_columns['cb'] = $columns['cb'];
			unset( $columns['cb'] );
		}

		$new_columns['thumb'] = __( 'Image', 'woocommerce' );

		$columns           = array_merge( $new_columns, $columns );
		$columns['handle'] = '';

		return $columns;
	}

	/**
	 * Adjust row actions.
	 *
	 * @param array  $actions Array of actions.
	 * @param object $term Term object.
	 * @return array
	 */
	public function product_cat_row_actions( $actions, $term ) {
		$default_category_id = absint( get_option( 'default_product_cat', 0 ) );

		if ( $default_category_id !== $term->term_id && current_user_can( 'edit_term', $term->term_id ) ) {
			$actions['make_default'] = sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				wp_nonce_url( 'edit-tags.php?action=make_default&amp;taxonomy=product_cat&amp;post_type=product&amp;tag_ID=' . absint( $term->term_id ), 'make_default_' . absint( $term->term_id ) ),
				/* translators: %s: taxonomy term name */
				esc_attr( sprintf( __( 'Make &#8220;%s&#8221; the default category', 'woocommerce' ), $term->name ) ),
				__( 'Make default', 'woocommerce' )
			);
		}

		return $actions;
	}

	/**
	 * Handle custom row actions.
	 */
	public function handle_product_cat_row_actions() {
		if ( isset( $_GET['action'], $_GET['tag_ID'], $_GET['_wpnonce'] ) && 'make_default' === $_GET['action'] ) { // WPCS: CSRF ok, input var ok.
			$make_default_id = absint( $_GET['tag_ID'] ); // WPCS: Input var ok.

			if ( wp_verify_nonce( $_GET['_wpnonce'], 'make_default_' . $make_default_id ) && current_user_can( 'edit_term', $make_default_id ) ) { // WPCS: Sanitization ok, input var ok, CSRF ok.
				update_option( 'default_product_cat', $make_default_id );
			}
		}
	}

	/**
	 * Thumbnail column value added to category admin.
	 *
	 * @param string $columns Column HTML output.
	 * @param string $column Column name.
	 * @param int    $id Product ID.
	 *
	 * @return string
	 */
	public function product_cat_column( $columns, $column, $id ) {
		if ( 'thumb' === $column ) {
			// Prepend tooltip for default category.
			$default_category_id = absint( get_option( 'default_product_cat', 0 ) );

			if ( $default_category_id === $id ) {
				$columns .= wc_help_tip( __( 'This is the default category and it cannot be deleted. It will be automatically assigned to products with no category.', 'woocommerce' ) );
			}

			$thumbnail_id = get_term_meta( $id, 'thumbnail_id', true );

			if ( $thumbnail_id ) {
				$image = wp_get_attachment_thumb_url( $thumbnail_id );
			} else {
				$image = wc_placeholder_img_src();
			}

			// Prevent esc_url from breaking spaces in urls for image embeds. Ref: https://core.trac.wordpress.org/ticket/23605 .
			$image    = str_replace( ' ', '%20', $image );
			$columns .= '<img src="' . esc_url( $image ) . '" alt="' . esc_attr__( 'Thumbnail', 'woocommerce' ) . '" class="wp-post-image" height="48" width="48" />';
		}
		if ( 'handle' === $column ) {
			$columns .= '<input type="hidden" name="term_id" value="' . esc_attr( $id ) . '" />';
		}
		return $columns;
	}

	/**
	 * Maintain term hierarchy when editing a product.
	 *
	 * @param  array $args Term checklist args.
	 * @return array
	 */
	public function disable_checked_ontop( $args ) {
		if ( ! empty( $args['taxonomy'] ) && 'product_cat' === $args['taxonomy'] ) {
			$args['checked_ontop'] = false;
		}
		return $args;
	}

	/**
	 * Admin footer scripts for the product categories admin screen
	 *
	 * @return void
	 */
	public function scripts_at_product_cat_screen_footer() {
		if ( ! isset( $_GET['taxonomy'] ) || 'product_cat' !== $_GET['taxonomy'] ) { // WPCS: CSRF ok, input var ok.
			return;
		}

		// Ensure the tooltip is displayed when the image column is disabled on product categories.
		$handle = 'wc-admin-taxonomies';
		wp_register_script( $handle, '', array(), WC_VERSION, array( 'in_footer' => true ) );
		wp_enqueue_script( $handle );
		wp_add_inline_script(
			$handle,
			sprintf(
				"(function() {
                    'use strict';
                    const product_cat = document.getElementById('tag-%d');
                    if (product_cat) {
                        const th = product_cat.querySelector('th');
                        const thumbSpan = product_cat.querySelector('td.thumb span');
                        if (th && thumbSpan) {
                            th.innerHTML = '';
                            th.appendChild(thumbSpan);
                        }
                    }
                })();",
				absint( $this->default_cat_id )
			)
		);
	}
}

$wc_admin_taxonomies = WC_Admin_Taxonomies::get_instance();
PK     tS\#B:  B:    class-wc-admin-webhooks.phpnu [        <?php
/**
 * WooCommerce Admin Webhooks Class
 *
 * @package WooCommerce\Admin
 * @version 3.3.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * WC_Admin_Webhooks.
 */
class WC_Admin_Webhooks {

	/**
	 * Initialize the webhooks admin actions.
	 */
	public function __construct() {
		add_action( 'admin_init', array( $this, 'actions' ) );
		add_action( 'woocommerce_settings_page_init', array( $this, 'screen_option' ) );
		add_filter( 'woocommerce_save_settings_advanced_webhooks', array( $this, 'allow_save_settings' ) );
	}

	/**
	 * Check if should allow save settings.
	 * This prevents "Your settings have been saved." notices on the table list.
	 *
	 * @param  bool $allow If allow save settings.
	 * @return bool
	 */
	public function allow_save_settings( $allow ) {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( ! isset( $_GET['edit-webhook'] ) ) {
			return false;
		}

		return $allow;
	}

	/**
	 * Check if is webhook settings page.
	 *
	 * @return bool
	 */
	private function is_webhook_settings_page() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		return is_wc_admin_settings_page() && isset( $_GET['tab'], $_GET['section'] ) && 'advanced' === $_GET['tab'] && 'webhooks' === $_GET['section'];
	}

	/**
	 * Save method.
	 */
	private function save() {
		check_admin_referer( 'woocommerce-settings' );

		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_die( esc_html__( 'You do not have permission to update Webhooks', 'woocommerce' ) );
		}

		$errors = array();
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$webhook_id = isset( $_POST['webhook_id'] ) ? absint( $_POST['webhook_id'] ) : 0;
		$webhook    = new WC_Webhook( $webhook_id );

		// Name.
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( ! empty( $_POST['webhook_name'] ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$name = sanitize_text_field( wp_unslash( $_POST['webhook_name'] ) );
		} else {
			$name = sprintf(
				/* translators: %s: date */
				__( 'Webhook created on %s', 'woocommerce' ),
				// @codingStandardsIgnoreStart
				(new DateTime('now'))->format( _x( 'M d, Y @ h:i A', 'Webhook created on date parsed by DateTime::format', 'woocommerce' ) )
				// @codingStandardsIgnoreEnd
			);
		}

		$webhook->set_name( $name );

		if ( ! $webhook->get_user_id() ) {
			$webhook->set_user_id( get_current_user_id() );
		}

		// Status.
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$webhook->set_status( ! empty( $_POST['webhook_status'] ) ? sanitize_text_field( wp_unslash( $_POST['webhook_status'] ) ) : 'disabled' );

		// Delivery URL.
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$delivery_url = ! empty( $_POST['webhook_delivery_url'] ) ? esc_url_raw( wp_unslash( $_POST['webhook_delivery_url'] ) ) : '';

		if ( wc_is_valid_url( $delivery_url ) ) {
			$webhook->set_delivery_url( $delivery_url );
		}

		// Secret.
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$secret = ! empty( $_POST['webhook_secret'] ) ? sanitize_text_field( wp_unslash( $_POST['webhook_secret'] ) ) : wp_generate_password( 50, true, true );
		$webhook->set_secret( $secret );

		// Topic.
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( ! empty( $_POST['webhook_topic'] ) ) {
			$resource = '';
			$event    = '';

			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			switch ( $_POST['webhook_topic'] ) {
				case 'action':
					$resource = 'action';
					// phpcs:ignore WordPress.Security.NonceVerification.Recommended
					$event = ! empty( $_POST['webhook_action_event'] ) ? sanitize_text_field( wp_unslash( $_POST['webhook_action_event'] ) ) : '';
					break;

				default:
					// phpcs:ignore WordPress.Security.NonceVerification.Recommended
					list( $resource, $event ) = explode( '.', sanitize_text_field( wp_unslash( $_POST['webhook_topic'] ) ) );
					break;
			}

			$topic = $resource . '.' . $event;

			if ( wc_is_webhook_valid_topic( $topic ) ) {
				$webhook->set_topic( $topic );
			} else {
				$errors[] = __( 'Webhook topic unknown. Please select a valid topic.', 'woocommerce' );
			}
		}

		// API version.
		$rest_api_versions = wc_get_webhook_rest_api_versions();
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$webhook->set_api_version( ! empty( $_POST['webhook_api_version'] ) ? sanitize_text_field( wp_unslash( $_POST['webhook_api_version'] ) ) : end( $rest_api_versions ) );

		$webhook->save();

		// Run actions.
		do_action( 'woocommerce_webhook_options_save', $webhook->get_id() );
		if ( $errors ) {
			// Redirect to webhook edit page to avoid settings save actions.
			wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&edit-webhook=' . $webhook->get_id() . '&error=' . rawurlencode( implode( '|', $errors ) ) ) );
			exit();
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		} elseif ( isset( $_POST['webhook_status'] ) && 'active' === $_POST['webhook_status'] && $webhook->get_pending_delivery() ) {
			// Ping the webhook at the first time that is activated.
			$result = $webhook->deliver_ping();

			if ( is_wp_error( $result ) ) {
				// Redirect to webhook edit page to avoid settings save actions.
				wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&edit-webhook=' . $webhook->get_id() . '&error=' . rawurlencode( $result->get_error_message() ) ) );
				exit();
			}
		}

		// Redirect to webhook edit page to avoid settings save actions.
		wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&edit-webhook=' . $webhook->get_id() . '&updated=1' ) );
		exit();
	}

	/**
	 * Bulk delete.
	 *
	 * @param array $webhooks List of webhooks IDs.
	 */
	public static function bulk_delete( $webhooks ) {
		foreach ( $webhooks as $webhook_id ) {
			$webhook = new WC_Webhook( (int) $webhook_id );
			$webhook->delete( true );
		}

		$qty = count( $webhooks );
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$status = isset( $_GET['status'] ) ? '&status=' . sanitize_text_field( wp_unslash( $_GET['status'] ) ) : '';

		// Redirect to webhooks page.
		wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks' . $status . '&deleted=' . $qty ) );
		exit();
	}

	/**
	 * Delete webhook.
	 */
	private function delete() {
		check_admin_referer( 'delete-webhook' );

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( isset( $_GET['delete'] ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$webhook_id = absint( $_GET['delete'] );

			if ( $webhook_id ) {
				self::bulk_delete( array( $webhook_id ) );
			}
		}
	}

	/**
	 * Webhooks admin actions.
	 */
	public function actions() {
		if ( $this->is_webhook_settings_page() ) {
			// Save.
			// phpcs:ignore WordPress.Security.NonceVerification.Missing
			if ( isset( $_POST['save'] ) && isset( $_POST['webhook_id'] ) ) {
				$this->save();
			}

			// Delete webhook.
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			if ( isset( $_GET['delete'] ) ) {
				$this->delete();
			}
		}
	}

	/**
	 * Page output.
	 */
	public static function page_output() {
		// Hide the save button.
		$GLOBALS['hide_save_button'] = true;

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( isset( $_GET['edit-webhook'] ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$webhook_id = absint( $_GET['edit-webhook'] );
			$webhook    = new WC_Webhook( $webhook_id );

			include __DIR__ . '/settings/views/html-webhooks-edit.php';
			return;
		}

		self::table_list_output();
	}

	/**
	 * Notices.
	 */
	public static function notices() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( isset( $_GET['deleted'] ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$deleted = absint( $_GET['deleted'] );

			/* translators: %d: count */
			WC_Admin_Settings::add_message( sprintf( _n( '%d webhook permanently deleted.', '%d webhooks permanently deleted.', $deleted, 'woocommerce' ), $deleted ) );
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( isset( $_GET['updated'] ) ) {
			WC_Admin_Settings::add_message( __( 'Webhook updated successfully.', 'woocommerce' ) );
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( isset( $_GET['created'] ) ) {
			WC_Admin_Settings::add_message( __( 'Webhook created successfully.', 'woocommerce' ) );
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( isset( $_GET['error'] ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			foreach ( explode( '|', sanitize_text_field( wp_unslash( $_GET['error'] ) ) ) as $message ) {
				WC_Admin_Settings::add_error( trim( $message ) );
			}
		}
	}

	/**
	 * Add screen option.
	 */
	public function screen_option() {
		global $webhooks_table_list;

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( ! isset( $_GET['edit-webhook'] ) && $this->is_webhook_settings_page() ) {
			$webhooks_table_list = new WC_Admin_Webhooks_Table_List();

			// Add screen option.
			add_screen_option(
				'per_page',
				array(
					'default' => 10,
					'option'  => 'woocommerce_webhooks_per_page',
				)
			);
		}
	}

	/**
	 * Table list output.
	 */
	private static function table_list_output() {
		global $webhooks_table_list;

		echo '<h2 class="wc-table-list-header">' . esc_html__( 'Webhooks', 'woocommerce' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&edit-webhook=0' ) ) . '" class="page-title-action">' . esc_html__( 'Add webhook', 'woocommerce' ) . '</a></h2>';

		// Get the webhooks count.
		$data_store   = WC_Data_Store::load( 'webhook' );
		$num_webhooks = $data_store->get_count_webhooks_by_status();
		$count        = array_sum( $num_webhooks );

		if ( $count > 0 ) {
			$webhooks_table_list->process_bulk_action();
			$webhooks_table_list->prepare_items();

			echo '<input type="hidden" name="page" value="wc-settings" />';
			echo '<input type="hidden" name="tab" value="advanced" />';
			echo '<input type="hidden" name="section" value="webhooks" />';

			self::maybe_display_legacy_rest_api_warning();

			$webhooks_table_list->views();
			$webhooks_table_list->search_box( __( 'Search webhooks', 'woocommerce' ), 'webhook' );
			$webhooks_table_list->display();
		} else {
			echo '<div class="woocommerce-BlankState woocommerce-BlankState--webhooks">';
			?>
			<h2 class="woocommerce-BlankState-message"><?php esc_html_e( 'Webhooks are event notifications sent to URLs of your choice. They can be used to integrate with third-party services which support them.', 'woocommerce' ); ?></h2>
			<a class="woocommerce-BlankState-cta button-primary button" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&edit-webhook=0' ) ); ?>"><?php esc_html_e( 'Create a new webhook', 'woocommerce' ); ?></a>
			<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions { display: none; }</style>
			<?php
		}
	}

	/**
	 * Display a warning message if the Legacy REST API extension is not installed
	 * and there are webhooks configured to use the legacy payload format.
	 */
	private static function maybe_display_legacy_rest_api_warning() {
		global $webhooks_table_list;

		if ( WC()->legacy_rest_api_is_available() ) {
			return;
		}

		$legacy_api_webhooks_count = $webhooks_table_list->get_legacy_api_webhooks_count();
		if ( 0 === $legacy_api_webhooks_count ) {
			return;
		}

		?>
		<div class='error inline'>
			<p><strong>
				<?php echo esc_html__( 'Incompatible webhooks warning', 'woocommerce' ); ?>
			</strong></p>
			<p>
				<?php
				echo wp_kses_data(
					sprintf(
						/* translators: %s = webhooks count */
						_n(
							"There's %d webhook that is configured to be delivered using the Legacy REST API, which has been removed from WooCommerce. This webhook will fail to be sent.",
							'There are %d webhooks that are configured to be delivered using the Legacy REST API, which has been removed from WooCommerce. These webhooks will fail to be sent.',
							$legacy_api_webhooks_count,
							'woocommerce'
						),
						$legacy_api_webhooks_count,
						'woocommerce'
					)
				);
				?>
			</p>
			<p>
				<?php
				echo wp_kses(
					sprintf(
						/* translators: %s = URL */
						_n(
							'This webhook has the ⚠️ symbol in front of its name in the list below. Please either edit the webhook to use a different delivery format, or install and activate <a href="%s" target="_blank">the WooCommerce Legacy REST API extension</a>.',
							'These webhooks have the ⚠️ symbol in front of their names in the list below. Please either edit the webhooks to use a different delivery format, or install and activate <a href="%s" target="_blank">the WooCommerce Legacy REST API extension</a>.',
							$legacy_api_webhooks_count,
							'woocommerce'
						),
						'https://wordpress.org/plugins/woocommerce-legacy-rest-api/'
					),
					array(
						'a' => array(
							'href'   => array(),
							'target' => array(),
						),
					)
				);
				?>
			</p>
			<p><strong>
				<?php
				echo wp_kses_data(
					sprintf(
						/* translators: %s is an URL */
						__( "<a href='%s'>More information</a>", 'woocommerce' ),
						'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
					)
				);
				?>
			</strong></p>
		</div>
		<?php
	}

	/**
	 * Logs output.
	 *
	 * @deprecated 3.3.0
	 * @param WC_Webhook $webhook Deprecated.
	 */
	public static function logs_output( $webhook = 'deprecated' ) {
		wc_deprecated_function( 'WC_Admin_Webhooks::logs_output', '3.3' );
	}

	/**
	 * Get the webhook topic data.
	 *
	 * @param WC_Webhook $webhook Webhook instance.
	 *
	 * @return array
	 */
	public static function get_topic_data( $webhook ) {
		$topic    = $webhook->get_topic();
		$event    = '';
		$resource = '';

		if ( $topic ) {
			list( $resource, $event ) = explode( '.', $topic );

			if ( 'action' === $resource ) {
				$topic = 'action';
			} elseif ( ! in_array( $resource, array( 'coupon', 'customer', 'order', 'product' ), true ) ) {
				$topic = 'custom';
			}
		}

		return array(
			'topic'    => $topic,
			'event'    => $event,
			'resource' => $resource,
		);
	}

	/**
	 * Get the logs navigation.
	 *
	 * @deprecated 3.3.0
	 * @param int        $total Deprecated.
	 * @param WC_Webhook $webhook Deprecated.
	 */
	public static function get_logs_navigation( $total, $webhook ) {
		wc_deprecated_function( 'WC_Admin_Webhooks::get_logs_navigation', '3.3' );
	}
}

new WC_Admin_Webhooks();
PK     tS\w<A'  '    class-wc-admin-meta-boxes.phpnu [        <?php
/**
 * WooCommerce Meta Boxes
 *
 * Sets up the write panels used by products and orders (custom post types).
 *
 * @package WooCommerce\Admin\Meta Boxes
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Internal\Admin\Orders\Edit as OrderEdit;
use Automattic\WooCommerce\Utilities\OrderUtil;

defined( 'ABSPATH' ) || exit;

/**
 * WC_Admin_Meta_Boxes.
 */
class WC_Admin_Meta_Boxes {
	/**
	 * Name of the option used to store errors to be displayed at the next suitable opportunity.
	 *
	 * @since 6.5.0
	 */
	public const ERROR_STORE = 'woocommerce_meta_box_errors';

	/**
	 * Is meta boxes saved once?
	 *
	 * @var boolean
	 */
	private static $saved_meta_boxes = false;

	/**
	 * Meta box error messages.
	 *
	 * @var array
	 */
	public static $meta_box_errors = array();

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'add_meta_boxes', array( $this, 'remove_meta_boxes' ), 10 );
		add_action( 'add_meta_boxes', array( $this, 'rename_meta_boxes' ), 20 );
		add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 30 );
		add_action( 'add_meta_boxes', array( $this, 'add_product_boxes_sort_order' ), 40 );
		add_action( 'save_post', array( $this, 'save_meta_boxes' ), 1, 2 );

		OrderEdit::add_save_meta_boxes();

		// Save Product Meta Boxes.
		add_action( 'woocommerce_process_product_meta', 'WC_Meta_Box_Product_Data::save', 10, 2 );
		add_action( 'woocommerce_process_product_meta', 'WC_Meta_Box_Product_Images::save', 20, 2 );

		// Save Coupon Meta Boxes.
		add_action( 'woocommerce_process_shop_coupon_meta', 'WC_Meta_Box_Coupon_Data::save', 10, 2 );

		// Save Rating Meta Boxes.
		add_filter( 'wp_update_comment_data', 'WC_Meta_Box_Product_Reviews::save', 1 );

		// Error handling (for showing errors from meta boxes on next page load).
		add_action( 'admin_notices', array( $this, 'output_errors' ) );
		add_action( 'shutdown', array( $this, 'append_to_error_store' ) );

		add_filter( 'theme_product_templates', array( $this, 'remove_block_templates' ), 10, 1 );
	}

	/**
	 * Add an error message.
	 *
	 * @param string $text Error to add.
	 */
	public static function add_error( $text ) {
		self::$meta_box_errors[] = $text;
	}

	/**
	 * Save errors to an option.
	 *
	 * Note that calling this will overwrite any errors that have already been stored via the Options API.
	 * Unless you are sure you want this, consider using the append_to_error_store() method instead.
	 */
	public function save_errors() {
		update_option( self::ERROR_STORE, self::$meta_box_errors );
	}

	/**
	 * If additional errors have been added in the current request (ie, via the add_error() method) then they
	 * will be added to the persistent error store via the Options API.
	 *
	 * @since 6.5.0
	 */
	public function append_to_error_store() {
		if ( empty( self::$meta_box_errors ) ) {
			return;
		}

		$existing_errors = get_option( self::ERROR_STORE, array() );
		update_option( self::ERROR_STORE, array_unique( array_merge( $existing_errors, self::$meta_box_errors ) ) );
	}

	/**
	 * Show any stored error messages.
	 */
	public function output_errors() {
		$errors = array_filter( (array) get_option( self::ERROR_STORE ) );

		if ( ! empty( $errors ) ) {

			echo '<div id="woocommerce_errors" class="error notice is-dismissible">';

			foreach ( $errors as $error ) {
				echo '<p>' . wp_kses_post( $error ) . '</p>';
			}

			echo '</div>';

			// Clear.
			delete_option( self::ERROR_STORE );
		}
	}

	/**
	 * Add WC Meta boxes.
	 */
	public function add_meta_boxes() {
		$screen    = get_current_screen();
		$screen_id = $screen ? $screen->id : '';

		// Products.
		add_meta_box( 'postexcerpt', __( 'Product short description', 'woocommerce' ), 'WC_Meta_Box_Product_Short_Description::output', 'product', 'normal' );
		add_meta_box( 'woocommerce-product-data', __( 'Product data', 'woocommerce' ), 'WC_Meta_Box_Product_Data::output', 'product', 'normal', 'high' );
		add_meta_box( 'woocommerce-product-images', __( 'Product gallery', 'woocommerce' ), 'WC_Meta_Box_Product_Images::output', 'product', 'side', 'low' );

		// Orders.
		foreach ( wc_get_order_types( 'order-meta-boxes' ) as $type ) {
			$order_type_object = get_post_type_object( $type );
			OrderEdit::add_order_meta_boxes( $type, $order_type_object->labels->singular_name );
		}

		// Coupons.
		add_meta_box( 'woocommerce-coupon-data', __( 'Coupon data', 'woocommerce' ), 'WC_Meta_Box_Coupon_Data::output', 'shop_coupon', 'normal', 'high' );

		// Comment rating.
		if ( 'comment' === $screen_id && isset( $_GET['c'] ) && metadata_exists( 'comment', wc_clean( wp_unslash( $_GET['c'] ) ), 'rating' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			add_meta_box( 'woocommerce-rating', __( 'Rating', 'woocommerce' ), 'WC_Meta_Box_Product_Reviews::output', 'comment', 'normal', 'high' );
		}
	}

	/**
	 * Add default sort order for meta boxes on product page.
	 */
	public function add_product_boxes_sort_order() {
		$current_value = get_user_meta( get_current_user_id(), 'meta-box-order_product', true );

		if ( $current_value ) {
			return;
		}

		update_user_meta(
			get_current_user_id(),
			'meta-box-order_product',
			array(
				'side'     => 'submitdiv,postimagediv,woocommerce-product-images,product_catdiv,tagsdiv-product_tag',
				'normal'   => 'woocommerce-product-data,postcustom,slugdiv,postexcerpt',
				'advanced' => '',
			)
		);
	}

	/**
	 * Remove bloat.
	 */
	public function remove_meta_boxes() {
		remove_meta_box( 'postexcerpt', 'product', 'normal' );
		remove_meta_box( 'product_shipping_classdiv', 'product', 'side' );
		remove_meta_box( 'commentsdiv', 'product', 'normal' );
		remove_meta_box( 'commentstatusdiv', 'product', 'side' );
		remove_meta_box( 'commentstatusdiv', 'product', 'normal' );
		remove_meta_box( 'woothemes-settings', 'shop_coupon', 'normal' );
		remove_meta_box( 'commentstatusdiv', 'shop_coupon', 'normal' );
		remove_meta_box( 'slugdiv', 'shop_coupon', 'normal' );

		foreach ( wc_get_order_types( 'order-meta-boxes' ) as $type ) {
			remove_meta_box( 'commentsdiv', $type, 'normal' );
			remove_meta_box( 'woothemes-settings', $type, 'normal' );
			remove_meta_box( 'commentstatusdiv', $type, 'normal' );
			remove_meta_box( 'slugdiv', $type, 'normal' );
			remove_meta_box( 'submitdiv', $type, 'side' );
		}
	}

	/**
	 * Rename core meta boxes.
	 */
	public function rename_meta_boxes() {
		global $post;

		// Comments/Reviews.
		if ( isset( $post ) && ( 'publish' === $post->post_status || 'private' === $post->post_status ) && post_type_supports( 'product', 'comments' ) ) {
			remove_meta_box( 'commentsdiv', 'product', 'normal' );
			add_meta_box( 'commentsdiv', __( 'Reviews', 'woocommerce' ), 'post_comment_meta_box', 'product', 'normal' );
		}
	}

	/**
	 * Check if we're saving, the trigger an action based on the post type.
	 *
	 * @param  int    $post_id Post ID.
	 * @param  object $post Post object.
	 */
	public function save_meta_boxes( $post_id, $post ) {
		$post_id = absint( $post_id );

		// $post_id and $post are required
		if ( empty( $post_id ) || empty( $post ) || ! is_a( $post, 'WP_Post' ) || self::$saved_meta_boxes ) {
			return;
		}

		// Dont' save meta boxes for revisions or autosaves.
		if ( Constants::is_true( 'DOING_AUTOSAVE' ) || is_int( wp_is_post_revision( $post ) ) || is_int( wp_is_post_autosave( $post ) ) ) {
			return;
		}

		// Check the nonce.
		if ( empty( $_POST['woocommerce_meta_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['woocommerce_meta_nonce'] ), 'woocommerce_save_data' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			return;
		}

		// Check the post being saved == the $post_id to prevent triggering this call for other save_post events.
		if ( empty( $_POST['post_ID'] ) || absint( $_POST['post_ID'] ) !== $post_id ) {
			return;
		}

		// Check user has permission to edit.
		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			return;
		}

		// We need this save event to run once to avoid potential endless loops. This would have been perfect:
		// remove_action( current_filter(), __METHOD__ );
		// But cannot be used due to https://github.com/woocommerce/woocommerce/issues/6485
		// When that is patched in core we can use the above.
		self::$saved_meta_boxes = true;

		// Check the post type.
		if ( in_array( $post->post_type, wc_get_order_types( 'order-meta-boxes' ), true ) ) {
			if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
				return;
			}

			/**
			 * Save meta for shop order.
			 *
			 * @param int $post_id Post ID.
			 * @param object $post Post object.
			 *
			 * @since 2.1.0
			 */
			do_action( 'woocommerce_process_shop_order_meta', $post_id, $post );
		} elseif ( in_array( $post->post_type, array( 'product', 'shop_coupon' ), true ) ) {
			/**
			 * Save meta for product.
			 *
			 * @param int $post_id Post ID.
			 * @param object $post Post object.
			 *
			 * @since 2.1.0
			 */
			do_action( 'woocommerce_process_' . $post->post_type . '_meta', $post_id, $post );
		}
	}

	/**
	 * Remove irrelevant block templates from the list of available templates for products.
	 * This will also remove custom created templates.
	 *
	 * @param string[] $templates Array of template header names keyed by the template file name.
	 *
	 * @return string[] Templates array excluding block-based templates.
	 */
	public function remove_block_templates( $templates ) {
		if ( count( $templates ) === 0 || ! wp_is_block_theme() ) {
			return $templates;
		}

		$theme              = wp_get_theme()->get_stylesheet();
		$filtered_templates = array();

		foreach ( $templates as $template_key => $template_name ) {
			// Filter out the single-product.html template as this is a duplicate of "Default Template".
			if ( 'single-product' === $template_key ) {
				continue;
			}

			$block_template = get_block_template( $theme . '//' . $template_key );

			// If the block template has the product post type specified, include it.
			if ( $block_template && is_array( $block_template->post_types ) && in_array( 'product', $block_template->post_types ) ) {
				$filtered_templates[ $template_key ] = $template_name;
			}
		}

		return $filtered_templates;
	}
}

new WC_Admin_Meta_Boxes();
PK     tS\K  K    wc-admin-functions.phpnu [        <?php
/**
 * WooCommerce Admin Functions
 *
 * @package  WooCommerce\Admin\Functions
 * @version  2.4.0
 */

use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Internal\Orders\OrderNoteGroup;
use Automattic\WooCommerce\Utilities\OrderUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Get all WooCommerce screen ids.
 * Note, among other things, this is used to conditionally load some assets. See class-wc-admin-assets.php.
 *
 * @return array
 */
function wc_get_screen_ids() {
	$wc_screen_id = 'woocommerce';
	$screen_ids   = array(
		'toplevel_page_' . $wc_screen_id,
		$wc_screen_id . '_page_wc-orders',
		$wc_screen_id . '_page_wc-reports',
		$wc_screen_id . '_page_wc-shipping',
		$wc_screen_id . '_page_wc-settings',
		$wc_screen_id . '_page_wc-status',
		$wc_screen_id . '_page_wc-addons',
		'toplevel_page_wc-reports',
		'product_page_product_attributes',
		'product_page_product_exporter',
		'product_page_product_importer',
		'product_page_product-reviews',
		'edit-product',
		'product',
		'edit-shop_coupon',
		'shop_coupon',
		'edit-product_cat',
		'edit-product_tag',
		'edit-product-brand',
		'profile',
		'user-edit',
	);

	foreach ( wc_get_order_types() as $type ) {
		$screen_ids[] = $type;
		$screen_ids[] = 'edit-' . $type;
		$screen_ids[] = wc_get_page_screen_id( $type );
	}

	$attributes = wc_get_attribute_taxonomies();

	if ( $attributes ) {
		foreach ( $attributes as $attribute ) {
			$screen_ids[] = 'edit-' . wc_attribute_taxonomy_name( $attribute->attribute_name );
		}
	}

	/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
	return apply_filters( 'woocommerce_screen_ids', $screen_ids );
	/* phpcs: enable */
}

/**
 * Get page ID for a specific WC resource.
 *
 * @param string $for Name of the resource.
 *
 * @return string Page ID. Empty string if resource not found.
 */
function wc_get_page_screen_id( $for ) {
	$screen_id = '';
	$for       = str_replace( '-', '_', $for );

	if ( in_array( $for, wc_get_order_types( 'admin-menu' ), true ) ) {
		if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
			$screen_id = ( \WC_Admin_Menus::can_view_woocommerce_menu_item() ? 'woocommerce_page_wc-orders' : 'admin_page_wc-orders' ) . ( 'shop_order' === $for ? '' : '--' . $for );
		} else {
			$screen_id = $for;
		}
	}

	return $screen_id;
}

/**
 * Create a page and store the ID in an option.
 *
 * @param mixed  $slug Slug for the new page.
 * @param string $option Option name to store the page's ID.
 * @param string $page_title (default: '') Title for the new page.
 * @param string $page_content (default: '') Content for the new page.
 * @param int    $post_parent (default: 0) Parent for the new page.
 * @param string $post_status (default: publish) The post status of the new page.
 * @return int page ID.
 */
function wc_create_page( $slug, $option = '', $page_title = '', $page_content = '', $post_parent = 0, $post_status = 'publish' ) {
	global $wpdb;

	$option_value = get_option( $option );

	if ( $option_value > 0 ) {
		$page_object = get_post( $option_value );

		if ( $page_object && 'page' === $page_object->post_type && ! in_array( $page_object->post_status, array( 'pending', 'trash', 'future', 'auto-draft' ), true ) ) {
			// Valid page is already in place.
			return $page_object->ID;
		}
	}

	if ( strlen( $page_content ) > 0 ) {
		// Search for an existing page with the specified page content (typically a shortcode).
		$shortcode        = str_replace( array( '<!-- wp:shortcode -->', '<!-- /wp:shortcode -->' ), '', $page_content );
		$valid_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status NOT IN ( 'pending', 'trash', 'future', 'auto-draft' ) AND post_content LIKE %s LIMIT 1;", "%{$shortcode}%" ) );
	} else {
		// Search for an existing page with the specified page slug.
		$valid_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status NOT IN ( 'pending', 'trash', 'future', 'auto-draft' )  AND post_name = %s LIMIT 1;", $slug ) );
	}

	/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
	$valid_page_found = apply_filters( 'woocommerce_create_page_id', $valid_page_found, $slug, $page_content );
	/* phpcs: enable */

	if ( $valid_page_found ) {
		if ( $option ) {
			update_option( $option, $valid_page_found );
		}
		return $valid_page_found;
	}

	// Search for a matching valid trashed page.
	if ( strlen( $page_content ) > 0 ) {
		// Search for an existing page with the specified page content (typically a shortcode).
		$trashed_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status = 'trash' AND post_content LIKE %s LIMIT 1;", "%{$page_content}%" ) );
	} else {
		// Search for an existing page with the specified page slug.
		$trashed_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status = 'trash' AND post_name = %s LIMIT 1;", $slug ) );
	}

	if ( $trashed_page_found ) {
		$page_id   = $trashed_page_found;
		$page_data = array(
			'ID'          => $page_id,
			'post_status' => $post_status,
		);
		wp_update_post( $page_data );
	} else {
		$page_data = array(
			'post_status'    => $post_status,
			'post_type'      => 'page',
			'post_author'    => 1,
			'post_name'      => $slug,
			'post_title'     => $page_title,
			'post_content'   => $page_content,
			'post_parent'    => $post_parent,
			'comment_status' => 'closed',
		);
		$page_id   = wp_insert_post( $page_data );

		/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
		do_action( 'woocommerce_page_created', $page_id, $page_data );
		/* phpcs: enable */
	}

	if ( $option ) {
		update_option( $option, $page_id );
	}

	return $page_id;
}

/**
 * Output admin fields.
 *
 * Loops through the woocommerce options array and outputs each field.
 *
 * @param array $options Opens array to output.
 */
function woocommerce_admin_fields( $options ) {

	if ( ! class_exists( 'WC_Admin_Settings', false ) ) {
		include __DIR__ . '/class-wc-admin-settings.php';
	}

	WC_Admin_Settings::output_fields( $options );
}

/**
 * Update all settings which are passed.
 *
 * @param array $options Option fields to save.
 * @param array $data Passed data.
 */
function woocommerce_update_options( $options, $data = null ) {

	if ( ! class_exists( 'WC_Admin_Settings', false ) ) {
		include __DIR__ . '/class-wc-admin-settings.php';
	}

	WC_Admin_Settings::save_fields( $options, $data );
}

/**
 * Get a setting from the settings API.
 *
 * @param mixed $option_name Option name to save.
 * @param mixed $default Default value to save.
 * @return string
 */
function woocommerce_settings_get_option( $option_name, $default = '' ) {

	if ( ! class_exists( 'WC_Admin_Settings', false ) ) {
		include __DIR__ . '/class-wc-admin-settings.php';
	}

	return WC_Admin_Settings::get_option( $option_name, $default );
}

/**
 * Sees if line item stock has already reduced stock, and whether those values need adjusting e.g. after changing item qty.
 *
 * @since 3.6.0
 * @param WC_Order_Item $item Item object.
 * @param integer       $item_quantity Optional quantity to check against. Read from object if not passed.
 * @return boolean|array|WP_Error Array of changes or error object when stock is updated (@see wc_update_product_stock). False if nothing changes.
 */
function wc_maybe_adjust_line_item_product_stock( $item, $item_quantity = -1 ) {
	if ( 'line_item' !== $item->get_type() ) {
		return false;
	}

	/**
	 * Prevent adjust line item product stock.
	 *
	 * @since 3.7.1
	 * @param bool $prevent If should prevent.
	 * @param WC_Order_Item $item Item object.
	 * @param int           $item_quantity Optional quantity to check against.
	 */
	if ( apply_filters( 'woocommerce_prevent_adjust_line_item_product_stock', false, $item, $item_quantity ) ) {
		return false;
	}

	$product = $item->get_product();

	if ( ! $product || ! $product->managing_stock() ) {
		return false;
	}

	$item_quantity          = wc_stock_amount( $item_quantity >= 0 ? $item_quantity : $item->get_quantity() );
	$already_reduced_stock  = wc_stock_amount( $item->get_meta( '_reduced_stock', true ) );
	$restock_refunded_items = wc_stock_amount( $item->get_meta( '_restock_refunded_items', true ) );

	$diff = $item_quantity - $restock_refunded_items - $already_reduced_stock;

	/*
	 * 0 as $item_quantity usually indicates we're deleting the order item.
	 * Let's restore back the reduced count.
	 */
	if ( 0 === $item_quantity ) {
		$diff = $already_reduced_stock * -1;
	}

	if ( $diff < 0 ) {
		$new_stock = wc_update_product_stock( $product, $diff * -1, 'increase' );
	} elseif ( $diff > 0 ) {
		$new_stock = wc_update_product_stock( $product, $diff, 'decrease' );
	} else {
		return false;
	}

	if ( is_wp_error( $new_stock ) ) {
		return $new_stock;
	}

	$item->update_meta_data( '_reduced_stock', $item_quantity - $restock_refunded_items );
	$item->save();

	if ( $item_quantity > 0 ) {
		// If stock was reduced, then we need to mark this on parent order object as well so that cancel logic works properly.
		$order_data_store = WC_Data_Store::load( 'order' );
		if ( $item->get_order_id() && ! $order_data_store->get_stock_reduced( $item->get_order_id() ) ) {
			$order_data_store->set_stock_reduced( $item->get_order_id(), true );
		}
	}

	return array(
		'from' => $new_stock + $diff,
		'to'   => $new_stock,
	);
}

/**
 * Save order items. Uses the CRUD.
 *
 * @since 2.2
 * @param int   $order_id Order ID.
 * @param array $items Order items to save.
 */
function wc_save_order_items( $order_id, $items ) {
	// Allow other plugins to check change in order items before they are saved.
	/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
	do_action( 'woocommerce_before_save_order_items', $order_id, $items );
	/* phpcs: enable */

	$qty_change_order_notes = array();
	$order                  = wc_get_order( $order_id );

	// Line items and fees.
	if ( isset( $items['order_item_id'] ) ) {
		$data_keys = array(
			'line_tax'             => array(),
			'line_subtotal_tax'    => array(),
			'order_item_name'      => null,
			'order_item_qty'       => null,
			'order_item_tax_class' => null,
			'line_total'           => null,
			'line_subtotal'        => null,
		);
		foreach ( $items['order_item_id'] as $item_id ) {
			$item = WC_Order_Factory::get_order_item( absint( $item_id ) );

			if ( ! $item ) {
				continue;
			}

			$item_data = array();

			foreach ( $data_keys as $key => $default ) {
				$item_data[ $key ] = isset( $items[ $key ][ $item_id ] ) ? wc_check_invalid_utf8( wp_unslash( $items[ $key ][ $item_id ] ) ) : $default;
			}

			if ( '0' === $item_data['order_item_qty'] ) {
				$changed_stock = wc_maybe_adjust_line_item_product_stock( $item, 0 );
				if ( $changed_stock && ! is_wp_error( $changed_stock ) ) {
					$qty_change_order_notes[] = $item->get_name() . ' &ndash; ' . $changed_stock['from'] . '&rarr;' . $changed_stock['to'];
				}
				$item->delete();
				continue;
			}

			$item->set_props(
				array(
					'name'      => $item_data['order_item_name'],
					'quantity'  => $item_data['order_item_qty'],
					'tax_class' => $item_data['order_item_tax_class'],
					'total'     => $item_data['line_total'],
					'subtotal'  => $item_data['line_subtotal'],
					'taxes'     => array(
						'total'    => $item_data['line_tax'],
						'subtotal' => $item_data['line_subtotal_tax'],
					),
				)
			);

			if ( 'fee' === $item->get_type() ) {
				$item->set_amount( $item_data['line_total'] );
			}

			if ( isset( $items['meta_key'][ $item_id ], $items['meta_value'][ $item_id ] ) ) {
				foreach ( $items['meta_key'][ $item_id ] as $meta_id => $meta_key ) {
					$meta_key   = substr( wp_unslash( $meta_key ), 0, 255 );
					$meta_value = isset( $items['meta_value'][ $item_id ][ $meta_id ] ) ? wp_unslash( $items['meta_value'][ $item_id ][ $meta_id ] ) : '';

					if ( '' === $meta_key && '' === $meta_value ) {
						if ( ! strstr( $meta_id, 'new-' ) ) {
							$item->delete_meta_data_by_mid( $meta_id );
						}
					} elseif ( strstr( $meta_id, 'new-' ) ) {
						$item->add_meta_data( $meta_key, $meta_value, false );
					} else {
						$item->update_meta_data( $meta_key, $meta_value, $meta_id );
					}
				}
			}

			// Allow other plugins to change item object before it is saved.
			/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
			do_action( 'woocommerce_before_save_order_item', $item );
			/* phpcs: enable */

			$item->save();

			if ( in_array( $order->get_status(), array( OrderStatus::PROCESSING, OrderStatus::COMPLETED, OrderStatus::ON_HOLD ), true ) ) {
				$changed_stock = wc_maybe_adjust_line_item_product_stock( $item );
				if ( $changed_stock && ! is_wp_error( $changed_stock ) ) {
					$qty_change_order_notes[] = $item->get_name() . ' (' . $changed_stock['from'] . '&rarr;' . $changed_stock['to'] . ')';
				}
			}
		}
	}

	// Shipping Rows.
	if ( isset( $items['shipping_method_id'] ) ) {
		$data_keys = array(
			'shipping_method'       => null,
			'shipping_method_title' => null,
			'shipping_cost'         => 0,
			'shipping_taxes'        => array(),
		);

		foreach ( $items['shipping_method_id'] as $item_id ) {
			$item = WC_Order_Factory::get_order_item( absint( $item_id ) );

			if ( ! $item ) {
				continue;
			}

			$item_data = array();

			foreach ( $data_keys as $key => $default ) {
				$item_data[ $key ] = isset( $items[ $key ][ $item_id ] ) ? wc_clean( wp_unslash( $items[ $key ][ $item_id ] ) ) : $default;
			}

			$item->set_props(
				array(
					'method_id'    => $item_data['shipping_method'],
					'method_title' => $item_data['shipping_method_title'],
					'total'        => $item_data['shipping_cost'],
					'taxes'        => array(
						'total' => $item_data['shipping_taxes'],
					),
				)
			);

			if ( isset( $items['meta_key'][ $item_id ], $items['meta_value'][ $item_id ] ) ) {
				foreach ( $items['meta_key'][ $item_id ] as $meta_id => $meta_key ) {
					$meta_value = isset( $items['meta_value'][ $item_id ][ $meta_id ] ) ? wp_unslash( $items['meta_value'][ $item_id ][ $meta_id ] ) : '';

					if ( '' === $meta_key && '' === $meta_value ) {
						if ( ! strstr( $meta_id, 'new-' ) ) {
							$item->delete_meta_data_by_mid( $meta_id );
						}
					} elseif ( strstr( $meta_id, 'new-' ) ) {
						$item->add_meta_data( $meta_key, $meta_value, false );
					} else {
						$item->update_meta_data( $meta_key, $meta_value, $meta_id );
					}
				}
			}

			$item->save();
		}
	}

	$order = wc_get_order( $order_id );

	if ( ! empty( $qty_change_order_notes ) ) {
		/* translators: %s item name. */
		$order->add_order_note( sprintf( __( 'Adjusted stock: %s', 'woocommerce' ), implode( ', ', $qty_change_order_notes ) ), false, true, array( 'note_group' => OrderNoteGroup::PRODUCT_STOCK ) );
	}

	$order->update_taxes();
	$order->calculate_totals( false );

	// Inform other plugins that the items have been saved.
	/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
	do_action( 'woocommerce_saved_order_items', $order_id, $items );
	/* phpcs: enable */
}

/**
 * Get HTML for some action buttons. Used in list tables.
 *
 * @since 3.3.0
 * @param array $actions Actions to output.
 * @return string
 */
function wc_render_action_buttons( $actions ) {
	$actions_html = '';

	foreach ( $actions as $action ) {
		if ( isset( $action['group'] ) ) {
			$actions_html .= '<div class="wc-action-button-group"><label>' . $action['group'] . '</label> <span class="wc-action-button-group__items">' . wc_render_action_buttons( $action['actions'] ) . '</span></div>';
		} elseif ( isset( $action['action'], $action['url'], $action['name'] ) ) {
			$actions_html .= sprintf( '<a class="button wc-action-button wc-action-button-%1$s %1$s" href="%2$s" aria-label="%3$s" title="%3$s">%4$s</a>', esc_attr( $action['action'] ), esc_url( $action['url'] ), esc_attr( isset( $action['title'] ) ? $action['title'] : $action['name'] ), esc_html( $action['name'] ) );
		}
	}

	return $actions_html;
}

/**
 * Shows a notice if variations are missing prices.
 *
 * @since 3.6.0
 * @param WC_Product $product_object Product object.
 */
function wc_render_invalid_variation_notice( $product_object ) {
	global $wpdb;

	// Give ability for extensions to hide this notice.
	/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
	if ( ! apply_filters( 'woocommerce_show_invalid_variations_notice', true, $product_object ) ) {
		return;
	}
	/* phpcs: enable */

	$variation_ids = $product_object ? $product_object->get_children() : array();

	if ( empty( $variation_ids ) ) {
		return;
	}

	$variation_count = count( $variation_ids );

	// Check if a variation exists without pricing data.
	// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
	$valid_variation_count = $wpdb->get_var(
		"
		SELECT count(post_id) FROM {$wpdb->postmeta}
		WHERE post_id in (" . implode( ',', array_map( 'absint', $variation_ids ) ) . ")
		AND ( meta_key='_subscription_sign_up_fee' OR meta_key='_price' )
		AND meta_value >= 0
		AND meta_value != ''
		"
	);
	// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared

	$invalid_variation_count = $variation_count - $valid_variation_count;

	if ( 0 < $invalid_variation_count ) {
		?>
		<div id="message" class="inline notice notice-warning woocommerce-message woocommerce-notice-invalid-variation">
			<p>
			<?php
			echo wp_kses_post(
				sprintf(
					/* Translators: %d variation count. */
					_n( '%d variation does not have a price.', '%d variations do not have prices.', $invalid_variation_count, 'woocommerce' ),
					$invalid_variation_count
				) . '&nbsp;' .
				__( 'Variations (and their attributes) that do not have prices will not be shown in your store.', 'woocommerce' )
			);
			?>
			</p>
			<div class="woocommerce-add-variation-price-container">
				<button type="button" class="button add_price_for_variations"><?php esc_html_e( 'Add price', 'woocommerce' ); ?></button>
			</div>
		</div>
		<?php
	}
}

/**
 * Get current admin page URL.
 *
 * Returns an empty string if it cannot generate a URL.
 *
 * @internal
 * @since 4.4.0
 * @return string
 */
function wc_get_current_admin_url() {
	$uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
	$uri = preg_replace( '|^.*/wp-admin/|i', '', $uri );

	if ( ! $uri ) {
		return '';
	}

	return remove_query_arg( array( '_wpnonce', '_wc_notice_nonce', 'wc_db_update', 'wc_db_update_nonce', 'wc-hide-notice' ), admin_url( $uri ) );
}

/**
 * Get default product type options.
 *
 * @internal
 * @since 7.9.0
 * @return array
 */
function wc_get_default_product_type_options() {
	return array(
		'virtual'      => array(
			'id'            => '_virtual',
			'wrapper_class' => 'show_if_simple',
			'label'         => __( 'Virtual', 'woocommerce' ),
			'description'   => __( 'Virtual products are intangible and are not shipped.', 'woocommerce' ),
			'default'       => 'no',
		),
		'downloadable' => array(
			'id'            => '_downloadable',
			'wrapper_class' => 'show_if_simple',
			'label'         => __( 'Downloadable', 'woocommerce' ),
			'description'   => __( 'Downloadable products give access to a file upon purchase.', 'woocommerce' ),
			'default'       => 'no',
		),
	);
}
PK     tS\B$n6  6    class-wc-admin.phpnu [        <?php
/**
 * WooCommerce Admin
 *
 * @class    WC_Admin
 * @package  WooCommerce\Admin
 * @version  2.6.0
 */

declare(strict_types=1);

use Automattic\WooCommerce\Admin\PageController;
use Automattic\WooCommerce\Internal\Admin\EmailPreview\EmailPreview;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WC_Admin class.
 */
class WC_Admin {

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'init', array( $this, 'includes' ) );

		// Hook in early (priority 1) to make sure the PageController's hooks are added before any WC admin pages or
		// menus logic is run, including the enqueuing of assets via \Automattic\WooCommerce\Internal\Admin\WCAdminAssets.
		// While it may not sound like it, the admin_menu action is triggered quite early,
		// before the admin_init or admin_enqueue_scripts  action.
		// @see https://developer.wordpress.org/apis/hooks/action-reference/#actions-run-during-an-admin-page-request.
		add_action( 'admin_menu', array( $this, 'init_page_controller' ), 1 );

		add_action( 'current_screen', array( $this, 'conditional_includes' ) );
		add_action( 'admin_init', array( $this, 'buffer' ), 1 );
		add_action( 'admin_init', array( $this, 'preview_emails' ) );
		add_action( 'admin_init', array( $this, 'prevent_admin_access' ) );
		add_action( 'admin_init', array( $this, 'admin_redirects' ) );
		add_action( 'admin_footer', 'wc_print_js', 25 );
		add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 );
		add_filter( 'update_footer', array( $this, 'update_footer_version' ), 20 );

		// Disable WXR export of schedule action posts.
		add_filter( 'action_scheduler_post_type_args', array( $this, 'disable_webhook_post_export' ) );

		// Add body class for WP 5.3+ compatibility.
		add_filter( 'admin_body_class', array( $this, 'include_admin_body_class' ), 9999 );

		// Add body class for Marketplace and My Subscriptions pages.
		if ( isset( $_GET['page'] ) && 'wc-addons' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			add_filter( 'admin_body_class', array( 'WC_Admin_Addons', 'filter_admin_body_classes' ) );
		}
	}

	/**
	 * Output buffering allows admin screens to make redirects later on.
	 */
	public function buffer() {
		ob_start();
	}

	/**
	 * Include any classes we need within admin.
	 */
	public function includes() {
		include_once __DIR__ . '/wc-admin-functions.php';
		include_once __DIR__ . '/wc-meta-box-functions.php';
		include_once __DIR__ . '/class-wc-admin-post-types.php';
		include_once __DIR__ . '/class-wc-admin-taxonomies.php';
		include_once __DIR__ . '/class-wc-admin-menus.php';
		include_once __DIR__ . '/class-wc-admin-customize.php';
		include_once __DIR__ . '/class-wc-admin-notices.php';
		include_once __DIR__ . '/class-wc-admin-assets.php';
		include_once __DIR__ . '/class-wc-admin-api-keys.php';
		include_once __DIR__ . '/class-wc-admin-webhooks.php';
		include_once __DIR__ . '/class-wc-admin-pointers.php';
		include_once __DIR__ . '/class-wc-admin-importers.php';
		include_once __DIR__ . '/class-wc-admin-exporters.php';

		// Help Tabs.
		/**
		 * Filter to enable/disable admin help tab.
		 *
		 * @since 3.6.0
		 */
		if ( apply_filters( 'woocommerce_enable_admin_help_tab', true ) ) {
			include_once __DIR__ . '/class-wc-admin-help.php';
		}

		// Helper.
		include_once __DIR__ . '/helper/class-wc-helper.php';

		// Marketplace suggestions & related REST API.
		include_once __DIR__ . '/marketplace-suggestions/class-wc-marketplace-suggestions.php';
		include_once __DIR__ . '/marketplace-suggestions/class-wc-marketplace-updater.php';
	}

	/**
	 * Initialize the admin page controller logic.
	 */
	public function init_page_controller() {
		// We only need to make sure the controller is instantiated since the hooking is done in the constructor.
		PageController::get_instance();
	}

	/**
	 * Include admin files conditionally.
	 */
	public function conditional_includes() {
		$screen = get_current_screen();

		if ( ! $screen ) {
			return;
		}

		switch ( $screen->id ) {
			case 'dashboard':
			case 'dashboard-network':
				include __DIR__ . '/class-wc-admin-dashboard-setup.php';
				include __DIR__ . '/class-wc-admin-dashboard.php';
				break;
			case 'options-permalink':
				include __DIR__ . '/class-wc-admin-permalink-settings.php';
				break;
			case 'plugins':
				include __DIR__ . '/plugin-updates/class-wc-plugins-screen-updates.php';
				break;
			case 'update-core':
				include __DIR__ . '/plugin-updates/class-wc-updates-screen-updates.php';
				break;
			case 'users':
			case 'user':
			case 'profile':
			case 'user-edit':
				include __DIR__ . '/class-wc-admin-profile.php';
				break;
		}
	}

	/**
	 * Handle redirects:
	 * 1. Nonced plugin install redirects.
	 *
	 * The user must have access rights, and we must ignore the network/bulk plugin updaters.
	 */
	public function admin_redirects() {
		// Don't run this fn from Action Scheduler requests.
		if ( wc_is_running_from_async_action_scheduler() ) {
			return;
		}

		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		// Nonced plugin install redirects.
		if ( ! empty( $_GET['wc-install-plugin-redirect'] ) ) {
			$plugin_slug = wc_clean( wp_unslash( $_GET['wc-install-plugin-redirect'] ) );

			if ( current_user_can( 'install_plugins' ) && in_array( $plugin_slug, array( 'woocommerce-gateway-stripe' ), true ) ) {
				$nonce = wp_create_nonce( 'install-plugin_' . $plugin_slug );
				$url   = self_admin_url( 'update.php?action=install-plugin&plugin=' . $plugin_slug . '&_wpnonce=' . $nonce );
			} else {
				$url = admin_url( 'plugin-install.php?tab=search&type=term&s=' . $plugin_slug );
			}

			wp_safe_redirect( $url );
			exit;
		}
		// phpcs:enable WordPress.Security.NonceVerification.Recommended
	}

	/**
	 * Prevent any user who cannot 'edit_posts' (subscribers, customers etc) from accessing admin.
	 */
	public function prevent_admin_access() {
		$prevent_access = false;

		// Do not interfere with admin-post or admin-ajax requests.
		$exempted_paths = array( 'admin-post.php', 'admin-ajax.php' );

		if (
			/**
			 * This filter is documented in ../wc-user-functions.php
			 *
			 * @since 3.6.0
			 */
			apply_filters( 'woocommerce_disable_admin_bar', true )
			&& isset( $_SERVER['SCRIPT_FILENAME'] )
			&& ! in_array( basename( sanitize_text_field( wp_unslash( $_SERVER['SCRIPT_FILENAME'] ) ) ), $exempted_paths, true )
		) {
			$has_cap     = false;
			$access_caps = array( 'edit_posts', 'manage_woocommerce', 'view_admin_dashboard' );

			foreach ( $access_caps as $access_cap ) {
				if ( current_user_can( $access_cap ) ) {
					$has_cap = true;
					break;
				}
			}

			if ( ! $has_cap ) {
				$prevent_access = true;
			}
		}

		/**
		 * Filter to prevent admin access.
		 *
		 * @since 3.6.0
		 */
		if ( apply_filters( 'woocommerce_prevent_admin_access', $prevent_access ) ) {
			wp_safe_redirect( wc_get_page_permalink( 'myaccount' ) );
			exit;
		}
	}

	/**
	 * Preview email template.
	 */
	public function preview_emails() {

		if ( isset( $_GET['preview_woocommerce_mail'] ) ) {
			if ( ! ( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ), 'preview-mail' ) ) ) {
				die( 'Security check' );
			}

			$email_preview = wc_get_container()->get( EmailPreview::class );

			if ( isset( $_GET['type'] ) ) {
				$type_param = sanitize_text_field( wp_unslash( $_GET['type'] ) );
				try {
					$email_preview->set_email_type( $type_param );
				} catch ( InvalidArgumentException $e ) {
					wp_die( esc_html__( 'Invalid email type.', 'woocommerce' ), 400 );
				}
			}

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				$message = $email_preview->render();
				$message = $email_preview->ensure_links_open_in_new_tab( $message );
			} else {
				// Start output buffering to prevent partial renders with PHP notices or warnings.
				ob_start();
				try {
					$message = $email_preview->render();
					$message = $email_preview->ensure_links_open_in_new_tab( $message );
				} catch ( Throwable $e ) {
					ob_end_clean();
					wp_die(
						esc_html__(
							'There was an error rendering the email preview. This doesn\'t affect actual email delivery. Please contact the extension author for assistance.',
							'woocommerce'
						),
						404
					);
				}
				ob_end_clean();
			}

			// print the preview email.
			// phpcs:ignore WordPress.Security.EscapeOutput
			echo $message;
			// phpcs:enable
			exit;
		}
	}

	/**
	 * Change the admin footer text on WooCommerce admin pages.
	 *
	 * @since 2.3
	 *
	 * @param string $footer_text Footer text to be rendered.
	 * @return string
	 */
	public function admin_footer_text( $footer_text ) {
		if ( ! current_user_can( 'manage_woocommerce' ) || ! function_exists( 'wc_get_screen_ids' ) ) {
			return $footer_text;
		}
		$current_screen = get_current_screen();
		$wc_pages       = array_merge( wc_get_screen_ids(), array( 'woocommerce_page_wc-admin' ) );

		// Set only WC pages.
		$wc_pages = array_diff( $wc_pages, array( 'profile', 'user-edit' ) );

		/**
		 * Filter to determine if admin footer text should be displayed.
		 *
		 * @since 2.3
		 */
		if ( isset( $current_screen->id ) && apply_filters( 'woocommerce_display_admin_footer_text', in_array( $current_screen->id, $wc_pages, true ) ) ) {
			// Change the footer text.
			if ( ! get_option( 'woocommerce_admin_footer_text_rated' ) ) {
				$footer_text = sprintf(
					/* translators: 1: WooCommerce 2:: five stars */
					__( 'If you like %1$s please leave us a %2$s rating. A huge thanks in advance!', 'woocommerce' ),
					sprintf( '<strong>%s</strong>', esc_html__( 'WooCommerce', 'woocommerce' ) ),
					'<a href="https://wordpress.org/support/plugin/woocommerce/reviews?rate=5#new-post" target="_blank" class="wc-rating-link" aria-label="' . esc_attr__( 'five star', 'woocommerce' ) . '" data-rated="' . esc_attr__( 'Thanks :)', 'woocommerce' ) . '">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
				);

				$script = "
		            (function() {
		                'use strict';
		                var ratingLink = document.querySelector('a.wc-rating-link');
		                if (ratingLink) {
		                    ratingLink.addEventListener('click', function(e) {
		                        var link = e.currentTarget;
		                        var formData = new FormData();
		                        formData.append('action', 'woocommerce_rated');
		                        
		                        fetch('" . esc_js( WC()->ajax_url() ) . "', {
		                            method: 'POST',
		                            body: formData,
		                            credentials: 'same-origin'
		                        });
		                        
		                        var parent = link.parentElement;
		                        if (parent) {
		                            parent.textContent = link.getAttribute('data-rated');
		                        }
		                    });
		                }
		            })();
		            ";

				$handle = 'wc-admin-footer-rating';
				wp_register_script( $handle, '', array(), WC_VERSION, true );
				wp_enqueue_script( $handle );
				wp_add_inline_script( $handle, $script );
			} else {
				$footer_text = __( 'Thank you for selling with WooCommerce.', 'woocommerce' );
			}
		}

		return '<span id="footer-thankyou">' . $footer_text . '</span>';
	}

	/**
	 * Update the footer version text.
	 *
	 * @since 10.2.0
	 *
	 * @param string $version The current version string.
	 * @return string
	 */
	public function update_footer_version( $version ) {
		if ( ! function_exists( 'wc_get_screen_ids' ) ) {
			return $version;
		}
		$current_screen = get_current_screen();
		$wc_pages       = array_merge( wc_get_screen_ids(), array( 'woocommerce_page_wc-admin' ) );

		// Set only WC pages.
		$wc_pages = array_diff( $wc_pages, array( 'profile', 'user-edit' ) );

		// Check to make sure we're on a WooCommerce admin page.
		/**
		 * Filter to determine if update footer text should be displayed.
		 *
		 * @since 2.3
		 */
		if ( isset( $current_screen->id ) && apply_filters( 'woocommerce_display_update_footer_text', in_array( $current_screen->id, $wc_pages, true ) ) ) {
			// Replace WordPress version with WooCommerce version.
			$version = sprintf(
				/* translators: %s: WooCommerce version */
				__( 'Version %s', 'woocommerce' ),
				esc_html( WC()->version )
			);
		}

		return $version;
	}

	/**
	 * Check on a Jetpack install queued by the Setup Wizard.
	 *
	 * See: WC_Admin_Setup_Wizard::install_jetpack()
	 */
	public function setup_wizard_check_jetpack() {
		$jetpack_active = class_exists( 'Jetpack' );

		wp_send_json_success(
			array(
				'is_active' => $jetpack_active ? 'yes' : 'no',
			)
		);
	}

	/**
	 * Disable WXR export of scheduled action posts.
	 *
	 * @since 3.6.2
	 *
	 * @param array $args Scheduled action post type registration args.
	 *
	 * @return array
	 */
	public function disable_webhook_post_export( $args ) {
		$args['can_export'] = false;
		return $args;
	}

	/**
	 * Include admin classes.
	 *
	 * @since 4.2.0
	 * @param string $classes Body classes string.
	 * @return string
	 */
	public function include_admin_body_class( $classes ) {
		$raw_version = get_bloginfo( 'version' );

		if ( ! $raw_version ) {
			return $classes;
		}

		$version_parts = explode( '-', $raw_version );
		$version       = count( $version_parts ) > 1 ? $version_parts[0] : $raw_version;
		$class_list    = explode( ' ', $classes );

		// WP version compatibility classes.
		$version_classes = array(
			'5.3' => 'wc-wp-version-gte-53',
			'5.5' => 'wc-wp-version-gte-55',
			'7.0' => 'wc-wp-version-gte-70',
		);

		foreach ( $version_classes as $min_version => $class_name ) {
			if ( ! in_array( $class_name, $class_list, true ) && version_compare( $version, $min_version, '>=' ) ) {
				$classes .= ' ' . $class_name;
			}
		}

		return $classes;
	}
}

return new WC_Admin();
PK     tS\,ĪIq  Iq  2  list-tables/class-wc-admin-list-table-products.phpnu [        <?php
/**
 * List tables: products.
 *
 * @package  WooCommerce\Admin
 * @version  3.3.0
 */

use Automattic\WooCommerce\Enums\ProductType;
use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Admin_List_Table_Products', false ) ) {
	return;
}

if ( ! class_exists( 'WC_Admin_List_Table', false ) ) {
	include_once __DIR__ . '/abstract-class-wc-admin-list-table.php';
}

/**
 * WC_Admin_List_Table_Products Class.
 */
class WC_Admin_List_Table_Products extends WC_Admin_List_Table {

	/**
	 * Post type.
	 *
	 * @var string
	 */
	protected $list_table_type = 'product';

	/**
	 * Caches the value of the "COGS is enabled" flag.
	 *
	 * @var bool
	 */
	private bool $cogs_is_enabled;

	/**
	 * Flag indicating if the COGS value column in the product meta lookup table can be used.
	 *
	 * @var bool
	 */
	private bool $use_cogs_lookup_column;

	/**
	 * Constructor.
	 */
	public function __construct() {
		parent::__construct();
		add_filter( 'disable_months_dropdown', '__return_true' );
		add_filter( 'query_vars', array( $this, 'add_custom_query_var' ) );
		add_filter( 'views_edit-product', array( $this, 'product_views' ) );
		add_filter( 'get_search_query', array( $this, 'search_label' ) );
		add_filter( 'posts_clauses', array( $this, 'posts_clauses' ), 10, 2 );
		add_action( 'manage_product_posts_custom_column', array( $this, 'add_sample_product_badge' ), 9, 2 );

		$cogs_controller              = wc_get_container()->get( CostOfGoodsSoldController::class );
		$this->cogs_is_enabled        = $cogs_controller->feature_is_enabled();
		$this->use_cogs_lookup_column = $this->cogs_is_enabled && $cogs_controller->product_meta_lookup_table_cogs_value_columns_exist();
	}

	/**
	 * Render blank state.
	 */
	protected function render_blank_state() {
		echo '<div class="woocommerce-BlankState">';

		echo '<h2 class="woocommerce-BlankState-message">' . esc_html__( 'Ready to start selling something awesome?', 'woocommerce' ) . '</h2>';

		echo '<div class="woocommerce-BlankState-buttons">';

		echo '<a class="woocommerce-BlankState-cta button-primary button" href="' . esc_url( admin_url( 'post-new.php?post_type=product&tutorial=true' ) ) . '">' . esc_html__( 'Create Product', 'woocommerce' ) . '</a>';
		echo '<a class="woocommerce-BlankState-cta button" href="' . esc_url( admin_url( 'edit.php?post_type=product&page=product_importer' ) ) . '">' . esc_html__( 'Start Import', 'woocommerce' ) . '</a>';

		echo '</div>';

		echo '</div>';
	}

	/**
	 * Define primary column.
	 *
	 * @return string
	 */
	protected function get_primary_column() {
		return 'name';
	}

	/**
	 * Get row actions to show in the list table.
	 *
	 * @param array   $actions Array of actions.
	 * @param WP_Post $post Current post object.
	 * @return array
	 */
	protected function get_row_actions( $actions, $post ) {
		/* translators: %d: product ID. */
		return array_merge( array( 'id' => sprintf( __( 'ID: %d', 'woocommerce' ), $post->ID ) ), $actions );
	}

	/**
	 * Define which columns are sortable.
	 *
	 * @param array $columns Existing columns.
	 * @return array
	 */
	public function define_sortable_columns( $columns ) {
		$custom = array(
			'price'            => 'price',
			'sku'              => 'sku',
			'name'             => 'title',
			'global_unique_id' => 'global_unique_id',
		);

		if ( $this->use_cogs_lookup_column ) {
			$custom['cogs_value'] = 'cogs_value';
		}

		return wp_parse_args( $custom, $columns );
	}

	/**
	 * Define which columns to show on this screen.
	 *
	 * @param array $columns Existing columns.
	 * @return array
	 */
	public function define_columns( $columns ) {
		if ( empty( $columns ) && ! is_array( $columns ) ) {
			$columns = array();
		}

		unset( $columns['title'], $columns['comments'], $columns['date'] );

		$show_columns          = array();
		$show_columns['cb']    = '<input type="checkbox" />';
		$show_columns['thumb'] = '<span class="wc-image tips" data-tip="' . esc_attr__( 'Image', 'woocommerce' ) . '">' . __( 'Image', 'woocommerce' ) . '</span>';
		$show_columns['name']  = __( 'Name', 'woocommerce' );

		if ( wc_product_sku_enabled() ) {
			$show_columns['sku'] = __( 'SKU', 'woocommerce' );
		}

		$show_columns['global_unique_id'] = __( 'GTIN, UPC, EAN, or ISBN', 'woocommerce' );

		if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
			$show_columns['is_in_stock'] = __( 'Stock', 'woocommerce' );
		}

		$show_columns['price'] = __( 'Price', 'woocommerce' );
		if ( $this->cogs_is_enabled ) {
			$show_columns['cogs_value'] = __( 'Cost', 'woocommerce' );
		}
		$show_columns['product_cat'] = __( 'Categories', 'woocommerce' );
		$show_columns['product_tag'] = __( 'Tags', 'woocommerce' );
		$show_columns['featured']    = '<span class="wc-featured parent-tips" data-tip="' . esc_attr__( 'Featured', 'woocommerce' ) . '">' . __( 'Featured', 'woocommerce' ) . '</span>';
		$show_columns['date']        = __( 'Date', 'woocommerce' );

		return array_merge( $show_columns, $columns );
	}

	/**
	 * Pre-fetch any data for the row each column has access to it. the_product global is there for bw compat.
	 *
	 * @param int $post_id Post ID being shown.
	 */
	protected function prepare_row_data( $post_id ) {
		global $the_product;

		if ( empty( $this->object ) || $this->object->get_id() !== $post_id ) {
			$the_product  = wc_get_product( $post_id );
			$this->object = $the_product;
		}
	}

	/**
	 * Render column: thumb.
	 */
	protected function render_thumb_column() {
		echo '<a href="' . esc_url( get_edit_post_link( $this->object->get_id() ) ) . '">' . $this->object->get_image( 'thumbnail' ) . '</a>'; // WPCS: XSS ok.
	}

	/**
	 * Render column: name.
	 */
	protected function render_name_column() {
		global $post;

		$edit_link = get_edit_post_link( $this->object->get_id() );
		$title     = _draft_or_post_title();

		echo '<strong><a class="row-title" href="' . esc_url( $edit_link ) . '">' . esc_html( $title ) . '</a>';

		_post_states( $post );

		echo '</strong>';

		if ( $this->object->get_parent_id() > 0 ) {
			echo '&nbsp;&nbsp;&larr; <a href="' . esc_url( get_edit_post_link( $this->object->get_parent_id() ) ) . '">' . get_the_title( $this->object->get_parent_id() ) . '</a>'; // @codingStandardsIgnoreLine.
		}

		get_inline_data( $post );

		$cogs_value_html = $this->cogs_is_enabled ?
				'<div class="cogs_value">' . esc_html( $this->object->get_cogs_value() ?? '0' ) . '</div>' :
				'';

		// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- the COGS value is already escaped.
		/* Custom inline data for woocommerce. */
		echo '
			<div class="hidden" id="woocommerce_inline_' . absint( $this->object->get_id() ) . '">
				<div class="menu_order">' . esc_html( $this->object->get_menu_order() ) . '</div>
				<div class="sku">' . esc_html( $this->object->get_sku() ) . '</div>
				<div class="global_unique_id">' . esc_html( $this->object->get_global_unique_id() ) . '</div>
				<div class="regular_price">' . esc_html( $this->object->get_regular_price() ) . '</div>
				<div class="sale_price">' . esc_html( $this->object->get_sale_price() ) . '</div>
				<div class="weight">' . esc_html( $this->object->get_weight() ) . '</div>
				<div class="length">' . esc_html( $this->object->get_length() ) . '</div>
				<div class="width">' . esc_html( $this->object->get_width() ) . '</div>
				<div class="height">' . esc_html( $this->object->get_height() ) . '</div>
				<div class="shipping_class">' . esc_html( $this->object->get_shipping_class() ) . '</div>
				<div class="visibility">' . esc_html( $this->object->get_catalog_visibility() ) . '</div>
				<div class="stock_status">' . esc_html( $this->object->get_stock_status() ) . '</div>
				<div class="stock">' . esc_html( $this->object->get_stock_quantity() ) . '</div>
				<div class="manage_stock">' . esc_html( wc_bool_to_string( $this->object->get_manage_stock() ) ) . '</div>
				<div class="featured">' . esc_html( wc_bool_to_string( $this->object->get_featured() ) ) . '</div>
				<div class="product_type">' . esc_html( $this->object->get_type() ) . '</div>
				<div class="product_is_virtual">' . esc_html( wc_bool_to_string( $this->object->get_virtual() ) ) . '</div>
				<div class="tax_status">' . esc_html( $this->object->get_tax_status() ) . '</div>
				<div class="tax_class">' . esc_html( $this->object->get_tax_class() ) . '</div>
				<div class="backorders">' . esc_html( $this->object->get_backorders() ) . '</div>
				<div class="low_stock_amount">' . esc_html( $this->object->get_low_stock_amount() ) . '</div>'
				. $cogs_value_html .
			'</div>';
		// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
	}

	/**
	 * Render column: sku.
	 */
	protected function render_sku_column() {
		echo $this->object->get_sku() ? esc_html( $this->object->get_sku() ) : '<span class="na">&ndash;</span>';
	}

	/**
	 * Render column: global_unique_id.
	 */
	protected function render_global_unique_id_column() {
		echo $this->object->get_global_unique_id() ? esc_html( $this->object->get_global_unique_id() ) : '<span class="na">&ndash;</span>';
	}

	/**
	 * Render column: price.
	 */
	protected function render_price_column() {
		$html = $this->object->get_price_html();
		echo $html ? wp_kses_post( $html ) : '<span class="na">&ndash;</span>';
	}

	/**
	 * Render column: cost.
	 */
	protected function render_cogs_value_column() {
		$html = $this->object->get_cogs_value_html();
		echo $html ? wp_kses_post( $html ) : '<span class="na">&ndash;</span>';
	}

	/**
	 * Render column: product_cat.
	 */
	protected function render_product_cat_column() {
		$terms = get_the_terms( $this->object->get_id(), 'product_cat' );
		if ( ! $terms ) {
			echo '<span class="na">&ndash;</span>';
		} else {
			$termlist = array();
			foreach ( $terms as $term ) {
				$termlist[] = '<a href="' . esc_url( admin_url( 'edit.php?product_cat=' . $term->slug . '&post_type=product' ) ) . '">' . esc_html( $term->name ) . '</a>';
			}

			echo apply_filters( 'woocommerce_admin_product_term_list', implode( ', ', $termlist ), 'product_cat', $this->object->get_id(), $termlist, $terms ); // WPCS: XSS ok.
		}
	}

	/**
	 * Render column: product_tag.
	 */
	protected function render_product_tag_column() {
		$terms = get_the_terms( $this->object->get_id(), 'product_tag' );
		if ( ! $terms ) {
			echo '<span class="na">&ndash;</span>';
		} else {
			$termlist = array();
			foreach ( $terms as $term ) {
				$termlist[] = '<a href="' . esc_url( admin_url( 'edit.php?product_tag=' . $term->slug . '&post_type=product' ) ) . '">' . esc_html( $term->name ) . '</a>';
			}

			echo apply_filters( 'woocommerce_admin_product_term_list', implode( ', ', $termlist ), 'product_tag', $this->object->get_id(), $termlist, $terms ); // WPCS: XSS ok.
		}
	}

	/**
	 * Render column: featured.
	 */
	protected function render_featured_column() {
		$url = wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_feature_product&product_id=' . $this->object->get_id() ), 'woocommerce-feature-product' );
		echo '<a href="' . esc_url( $url ) . '" aria-label="' . esc_attr__( 'Toggle featured', 'woocommerce' ) . '">';
		if ( $this->object->is_featured() ) {
			echo '<span class="wc-featured tips" data-tip="' . esc_attr__( 'Yes', 'woocommerce' ) . '">' . esc_html__( 'Yes', 'woocommerce' ) . '</span>';
		} else {
			echo '<span class="wc-featured not-featured tips" data-tip="' . esc_attr__( 'No', 'woocommerce' ) . '">' . esc_html__( 'No', 'woocommerce' ) . '</span>';
		}
		echo '</a>';
	}

	/**
	 * Render column: is_in_stock.
	 */
	protected function render_is_in_stock_column() {
		if ( $this->object->is_on_backorder() ) {
			$stock_html = '<mark class="onbackorder">' . __( 'On backorder', 'woocommerce' ) . '</mark>';
		} elseif ( $this->object->is_in_stock() ) {
			$stock_html = '<mark class="instock">' . __( 'In stock', 'woocommerce' ) . '</mark>';
		} else {
			$stock_html = '<mark class="outofstock">' . __( 'Out of stock', 'woocommerce' ) . '</mark>';
		}

		if ( $this->object->managing_stock() ) {
			$stock_html .= ' (' . wc_stock_amount( $this->object->get_stock_quantity() ) . ')';
		}

		echo wp_kses_post( apply_filters( 'woocommerce_admin_stock_html', $stock_html, $this->object ) );
	}

	/**
	 * Query vars for custom searches.
	 *
	 * @param mixed $public_query_vars Array of query vars.
	 * @return array
	 */
	public function add_custom_query_var( $public_query_vars ) {
		$public_query_vars[] = 'sku';
		return $public_query_vars;
	}

	/**
	 * Render any custom filters and search inputs for the list table.
	 */
	protected function render_filters() {
		$filters = apply_filters(
			'woocommerce_products_admin_list_table_filters',
			array(
				'product_category' => array( $this, 'render_products_category_filter' ),
				'product_type'     => array( $this, 'render_products_type_filter' ),
				'stock_status'     => array( $this, 'render_products_stock_status_filter' ),
			)
		);

		ob_start();
		foreach ( $filters as $filter_callback ) {
			call_user_func( $filter_callback );
		}
		$output = ob_get_clean();

		echo apply_filters( 'woocommerce_product_filters', $output ); // WPCS: XSS ok.
	}

	/**
	 * Render the product category filter for the list table.
	 *
	 * @since 3.5.0
	 */
	protected function render_products_category_filter() {
		$categories_count = (int) wp_count_terms( 'product_cat' );

		if ( $categories_count <= apply_filters( 'woocommerce_product_category_filter_threshold', 100 ) ) {
			wc_product_dropdown_categories(
				array(
					'option_select_text' => __( 'Filter by category', 'woocommerce' ),
					'hide_empty'         => 0,
				)
			);
		} else {
			$current_category_slug = isset( $_GET['product_cat'] ) ? wc_clean( wp_unslash( $_GET['product_cat'] ) ) : false; // WPCS: input var ok, CSRF ok.
			$current_category      = $current_category_slug ? get_term_by( 'slug', $current_category_slug, 'product_cat' ) : false;
			?>
			<select class="wc-category-search" name="product_cat" data-placeholder="<?php esc_attr_e( 'Filter by category', 'woocommerce' ); ?>" data-allow_clear="true">
				<?php if ( $current_category_slug && $current_category ) : ?>
					<option value="<?php echo esc_attr( $current_category_slug ); ?>" selected="selected"><?php echo esc_html( htmlspecialchars( wp_kses_post( $current_category->name ) ) ); ?></option>
				<?php endif; ?>
			</select>
			<?php
		}
	}

	/**
	 * Render the product type filter for the list table.
	 *
	 * @since 3.5.0
	 */
	protected function render_products_type_filter() {
		$current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; // WPCS: input var ok, sanitization ok.
		$output               = '<select name="product_type" id="dropdown_product_type"><option value="">' . esc_html__( 'Filter by product type', 'woocommerce' ) . '</option>';

		foreach ( wc_get_product_types() as $value => $label ) {
			$output .= '<option value="' . esc_attr( $value ) . '" ';
			$output .= selected( $value, $current_product_type, false );
			$output .= '>' . esc_html( $label ) . '</option>';

			if ( ProductType::SIMPLE === $value ) {

				$output .= '<option value="downloadable" ';
				$output .= selected( 'downloadable', $current_product_type, false );
				$output .= '> ' . ( is_rtl() ? '&larr;' : '&rarr;' ) . ' ' . esc_html__( 'Downloadable', 'woocommerce' ) . '</option>';

				$output .= '<option value="virtual" ';
				$output .= selected( 'virtual', $current_product_type, false );
				$output .= '> ' . ( is_rtl() ? '&larr;' : '&rarr;' ) . ' ' . esc_html__( 'Virtual', 'woocommerce' ) . '</option>';
			}
		}

		$output .= '</select>';
		echo $output; // WPCS: XSS ok.
	}

	/**
	 * Render the stock status filter for the list table.
	 *
	 * @since 3.5.0
	 */
	public function render_products_stock_status_filter() {
		$current_stock_status = isset( $_REQUEST['stock_status'] ) ? wc_clean( wp_unslash( $_REQUEST['stock_status'] ) ) : false; // WPCS: input var ok, sanitization ok.
		$stock_statuses       = wc_get_product_stock_status_options();
		$output               = '<select name="stock_status"><option value="">' . esc_html__( 'Filter by stock status', 'woocommerce' ) . '</option>';

		foreach ( $stock_statuses as $status => $label ) {
			$output .= '<option ' . selected( $status, $current_stock_status, false ) . ' value="' . esc_attr( $status ) . '">' . esc_html( $label ) . '</option>';
		}

		$output .= '</select>';
		echo $output; // WPCS: XSS ok.
	}

	/**
	 * Search by SKU or ID for products.
	 *
	 * @deprecated 4.4.0 Logic moved to query_filters.
	 * @param string $where Where clause SQL.
	 * @return string
	 */
	public function sku_search( $where ) {
		wc_deprecated_function( 'WC_Admin_List_Table_Products::sku_search', '4.4.0', 'Logic moved to query_filters.' );
		return $where;
	}

	/**
	 * Change views on the edit product screen.
	 *
	 * @param  array $views Array of views.
	 * @return array
	 */
	public function product_views( $views ) {
		global $wp_query;

		// Products do not have authors.
		unset( $views['mine'] );

		// Add sorting link.
		if ( current_user_can( 'edit_others_products' ) ) {
			$class            = ( isset( $wp_query->query['orderby'] ) && 'menu_order title' === $wp_query->query['orderby'] ) ? 'current' : '';
			$query_string     = remove_query_arg( array( 'orderby', 'order' ) );
			$query_string     = add_query_arg( 'orderby', rawurlencode( 'menu_order title' ), $query_string );
			$query_string     = add_query_arg( 'order', rawurlencode( 'ASC' ), $query_string );
			$views['byorder'] = '<a href="' . esc_url( $query_string ) . '" class="' . esc_attr( $class ) . '">' . __( 'Sorting', 'woocommerce' ) . '</a>';
		}

		return $views;
	}

	/**
	 * Change the label when searching products
	 *
	 * @param string $query Search Query.
	 * @return string
	 */
	public function search_label( $query ) {
		global $pagenow, $typenow;

		if ( 'edit.php' !== $pagenow || 'product' !== $typenow || ! get_query_var( 'product_search' ) || ! isset( $_GET['s'] ) ) { // WPCS: input var ok.
			return $query;
		}

		return wc_clean( wp_unslash( $_GET['s'] ) ); // WPCS: input var ok, sanitization ok.
	}

	/**
	 * Handle any custom filters.
	 *
	 * @param array $query_vars Query vars.
	 * @return array
	 */
	protected function query_filters( $query_vars ) {
		$this->remove_ordering_args();
		// Custom order by arguments.
		if ( isset( $query_vars['orderby'] ) ) {
			$orderby = strtolower( $query_vars['orderby'] );
			$order   = isset( $query_vars['order'] ) ? strtoupper( $query_vars['order'] ) : 'DESC';

			if ( 'price' === $orderby ) {
				$callback = 'DESC' === $order ? 'order_by_price_desc_post_clauses' : 'order_by_price_asc_post_clauses';
				add_filter( 'posts_clauses', array( $this, $callback ) );
			}

			if ( 'sku' === $orderby ) {
				$callback = 'DESC' === $order ? 'order_by_sku_desc_post_clauses' : 'order_by_sku_asc_post_clauses';
				add_filter( 'posts_clauses', array( $this, $callback ) );
			}

			if ( 'cogs_value' === $orderby && $this->use_cogs_lookup_column ) {
				$callback = 'DESC' === $order ? 'order_by_cogs_value_desc_post_clauses' : 'order_by_cogs_value_asc_post_clauses';
				add_filter( 'posts_clauses', array( $this, $callback ) );
			}

			if ( 'global_unique_id' === $orderby ) {
				$callback = 'DESC' === $order ? 'order_by_global_unique_id_desc_post_clauses' : 'order_by_global_unique_id_asc_post_clauses';
				add_filter( 'posts_clauses', array( $this, $callback ) );
			}
		}

		// Type filtering.
		if ( isset( $query_vars['product_type'] ) ) {
			if ( 'downloadable' === $query_vars['product_type'] ) {
				$query_vars['product_type'] = '';
				add_filter( 'posts_clauses', array( $this, 'filter_downloadable_post_clauses' ) );
			} elseif ( 'virtual' === $query_vars['product_type'] ) {
				$query_vars['product_type'] = '';
				add_filter( 'posts_clauses', array( $this, 'filter_virtual_post_clauses' ) );
			}
		}

		// Stock status filter.
		if ( ! empty( $_GET['stock_status'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			add_filter( 'posts_clauses', array( $this, 'filter_stock_status_post_clauses' ) );
		}

		// Shipping class taxonomy.
		if ( ! empty( $_GET['product_shipping_class'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$query_vars['tax_query'][] = array(
				'taxonomy' => 'product_shipping_class',
				'field'    => 'slug',
				'terms'    => sanitize_title( wp_unslash( $_GET['product_shipping_class'] ) ),
				'operator' => 'IN',
			);
		}

		// Search using CRUD.
		if ( ! empty( $query_vars['s'] ) ) {
			$data_store                   = WC_Data_Store::load( 'product' );
			$ids                          = $data_store->search_products( wc_clean( wp_unslash( $query_vars['s'] ) ), '', true, true );
			$query_vars['post__in']       = array_merge( $ids, array( 0 ) );
			$query_vars['product_search'] = true;
			unset( $query_vars['s'] );
		}

		return $query_vars;
	}

	/**
	 * Undocumented function
	 *
	 * @param array    $args  Array of SELECT statement pieces (from, where, etc).
	 * @param WP_Query $query WP_Query instance.
	 * @return array
	 */
	public function posts_clauses( $args, $query ) {

		return $args;
	}

	/**
	 * Remove ordering queries.
	 *
	 * @param array $posts Posts array, keeping this for backwards compatibility defaulting to empty array.
	 * @return array
	 */
	public function remove_ordering_args( $posts = array() ) {
		remove_filter( 'posts_clauses', array( $this, 'order_by_price_asc_post_clauses' ) );
		remove_filter( 'posts_clauses', array( $this, 'order_by_price_desc_post_clauses' ) );
		remove_filter( 'posts_clauses', array( $this, 'order_by_sku_asc_post_clauses' ) );
		remove_filter( 'posts_clauses', array( $this, 'order_by_sku_desc_post_clauses' ) );
		remove_filter( 'posts_clauses', array( $this, 'order_by_global_unique_id_asc_post_clauses' ) );
		remove_filter( 'posts_clauses', array( $this, 'order_by_global_unique_id_desc_post_clauses' ) );
		remove_filter( 'posts_clauses', array( $this, 'filter_downloadable_post_clauses' ) );
		remove_filter( 'posts_clauses', array( $this, 'filter_virtual_post_clauses' ) );
		remove_filter( 'posts_clauses', array( $this, 'filter_stock_status_post_clauses' ) );
		if ( $this->use_cogs_lookup_column ) {
			remove_filter( 'posts_clauses', array( $this, 'order_by_cogs_value_asc_post_clauses' ) );
			remove_filter( 'posts_clauses', array( $this, 'order_by_cogs_value_desc_post_clauses' ) );
		}
		return $posts; // Keeping this here for backward compatibility.
	}

	/**
	 * Handle numeric price sorting.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function order_by_price_asc_post_clauses( $args ) {
		$args['join']    = $this->append_product_sorting_table_join( $args['join'] );
		$args['orderby'] = ' wc_product_meta_lookup.min_price ASC, wc_product_meta_lookup.product_id ASC ';
		return $args;
	}

	/**
	 * Handle numeric price sorting.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function order_by_price_desc_post_clauses( $args ) {
		$args['join']    = $this->append_product_sorting_table_join( $args['join'] );
		$args['orderby'] = ' wc_product_meta_lookup.max_price DESC, wc_product_meta_lookup.product_id DESC ';
		return $args;
	}

	/**
	 * Handle sku sorting.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function order_by_sku_asc_post_clauses( $args ) {
		$args['join']    = $this->append_product_sorting_table_join( $args['join'] );
		$args['orderby'] = ' wc_product_meta_lookup.sku ASC, wc_product_meta_lookup.product_id ASC ';
		return $args;
	}

	/**
	 * Handle sku sorting.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function order_by_sku_desc_post_clauses( $args ) {
		$args['join']    = $this->append_product_sorting_table_join( $args['join'] );
		$args['orderby'] = ' wc_product_meta_lookup.sku DESC, wc_product_meta_lookup.product_id DESC ';
		return $args;
	}

	/**
	 * Handle COGS value sorting.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function order_by_cogs_value_asc_post_clauses( $args ) {
		$args['join']    = $this->append_product_sorting_table_join( $args['join'] );
		$args['orderby'] = ' wc_product_meta_lookup.cogs_total_value ASC, wc_product_meta_lookup.product_id ASC ';
		return $args;
	}

	/**
	 * Handle COGS value sorting.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function order_by_cogs_value_desc_post_clauses( $args ) {
		$args['join']    = $this->append_product_sorting_table_join( $args['join'] );
		$args['orderby'] = ' wc_product_meta_lookup.cogs_total_value DESC, wc_product_meta_lookup.product_id DESC ';
		return $args;
	}

	/**
	 * Handle global unique ID sorting.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function order_by_global_unique_id_asc_post_clauses( $args ) {
		$args['join']    = $this->append_product_sorting_table_join( $args['join'] );
		$args['orderby'] = ' wc_product_meta_lookup.global_unique_id ASC, wc_product_meta_lookup.product_id ASC ';
		return $args;
	}

	/**
	 * Handle global unique ID sorting.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function order_by_global_unique_id_desc_post_clauses( $args ) {
		$args['join']    = $this->append_product_sorting_table_join( $args['join'] );
		$args['orderby'] = ' wc_product_meta_lookup.global_unique_id DESC, wc_product_meta_lookup.product_id DESC ';
		return $args;
	}

	/**
	 * Filter by type.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function filter_downloadable_post_clauses( $args ) {
		$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
		$args['where'] .= ' AND wc_product_meta_lookup.downloadable=1 ';
		return $args;
	}

	/**
	 * Filter by type.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function filter_virtual_post_clauses( $args ) {
		$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
		$args['where'] .= ' AND wc_product_meta_lookup.virtual=1 ';
		return $args;
	}

	/**
	 * Filter by stock status.
	 *
	 * @param array $args Query args.
	 * @return array
	 */
	public function filter_stock_status_post_clauses( $args ) {
		global $wpdb;
		if ( ! empty( $_GET['stock_status'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
			$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.stock_status=%s ', wc_clean( wp_unslash( $_GET['stock_status'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		}
		return $args;
	}

	/**
	 * Join wc_product_meta_lookup to posts if not already joined.
	 *
	 * @param string $sql SQL join.
	 * @return string
	 */
	private function append_product_sorting_table_join( $sql ) {
		global $wpdb;

		if ( ! strstr( $sql, 'wc_product_meta_lookup' ) ) {
			$sql .= " LEFT JOIN {$wpdb->wc_product_meta_lookup} wc_product_meta_lookup ON $wpdb->posts.ID = wc_product_meta_lookup.product_id ";
		}
		return $sql;
	}

	/**
	 * Modifies post query so that it includes parent products whose variations have particular shipping class assigned.
	 *
	 * @param array    $pieces   Array of SELECT statement pieces (from, where, etc).
	 * @param WP_Query $wp_query WP_Query instance.
	 * @return array             Array of products, including parents of variations.
	 */
	public function add_variation_parents_for_shipping_class( $pieces, $wp_query ) {
		global $wpdb;
		if ( isset( $_GET['product_shipping_class'] ) && '0' !== $_GET['product_shipping_class'] ) { // WPCS: input var ok.
			$replaced_where   = str_replace( ".post_type = 'product'", ".post_type = 'product_variation'", $pieces['where'] );
			$pieces['where'] .= " OR {$wpdb->posts}.ID in (
				SELECT {$wpdb->posts}.post_parent FROM
				{$wpdb->posts} LEFT JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)
				WHERE 1=1 $replaced_where
			)";
			return $pieces;
		}
		return $pieces;
	}

	/**
	 * Add a sample product badge to the product list table.
	 *
	 * @param string $column_name Column name.
	 * @param int    $post_id     Post ID.
	 *
	 * @since 8.8.0
	 */
	public function add_sample_product_badge( $column_name, $post_id ) {
		$is_sample_product = 'product' === get_post_type( $post_id ) && get_post_meta( $post_id, '_headstart_post', true );

		if ( $is_sample_product && 'name' === $column_name ) {
			echo '<span class="sample-product-badge" style="margin-right: 6px;border-radius: 4px; background: #F6F7F7; padding: 4px; color: #3C434A;font-size: 12px;font-style: normal;font-weight: 400;line-height: 16px; height: 24px;">' . esc_html__( 'Sample', 'woocommerce' ) . '</span>';
		}
	}

	/**
	 * Define which columns are hidden by default.
	 *
	 * @return array
	 */
	protected function define_hidden_columns() {
		return array(
			'global_unique_id',
		);
	}
}
PK     tS\*C    2  list-tables/abstract-class-wc-admin-list-table.phpnu [        <?php
/**
 * List tables.
 *
 * @package  WooCommerce\Admin
 * @version  3.3.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Admin_List_Table', false ) ) {
	return;
}

/**
 * WC_Admin_List_Table Class.
 */
abstract class WC_Admin_List_Table {

	/**
	 * Post type.
	 *
	 * @var string
	 */
	protected $list_table_type = '';

	/**
	 * Object being shown on the row.
	 *
	 * @var object|null
	 */
	protected $object = null;

	/**
	 * Constructor.
	 */
	public function __construct() {
		if ( $this->list_table_type ) {
			add_action( 'manage_posts_extra_tablenav', array( $this, 'maybe_render_blank_state' ) );
			add_filter( 'view_mode_post_types', array( $this, 'disable_view_mode' ) );
			add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) );
			add_filter( 'request', array( $this, 'request_query' ) );
			add_filter( 'post_row_actions', array( $this, 'row_actions' ), 100, 2 );
			add_filter( 'default_hidden_columns', array( $this, 'default_hidden_columns' ), 10, 2 );
			add_filter( 'list_table_primary_column', array( $this, 'list_table_primary_column' ), 10, 2 );
			add_filter( 'manage_edit-' . $this->list_table_type . '_sortable_columns', array( $this, 'define_sortable_columns' ) );
			add_filter( 'manage_' . $this->list_table_type . '_posts_columns', array( $this, 'define_columns' ) );
			add_filter( 'bulk_actions-edit-' . $this->list_table_type, array( $this, 'define_bulk_actions' ) );
			add_action( 'manage_' . $this->list_table_type . '_posts_custom_column', array( $this, 'render_columns' ), 10, 2 );
			add_filter( 'handle_bulk_actions-edit-' . $this->list_table_type, array( $this, 'handle_bulk_actions' ), 10, 3 );
		}
	}

	/**
	 * Show blank slate.
	 *
	 * @param string $which String which tablenav is being shown.
	 */
	public function maybe_render_blank_state( $which ) {
		global $post_type;

		if ( $post_type === $this->list_table_type && 'bottom' === $which ) {
			$counts = (array) wp_count_posts( $post_type );
			unset( $counts['auto-draft'] );
			$count = array_sum( $counts );

			if ( 0 < $count ) {
				return;
			}

			$this->render_blank_state();

			echo '<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions, .wrap .subsubsub  { display: none; } #posts-filter .tablenav.bottom { height: auto; } </style>';
		}
	}

	/**
	 * Render blank state. Extend to add content.
	 */
	protected function render_blank_state() {}

	/**
	 * Removes this type from list of post types that support "View Mode" switching.
	 * View mode is seen on posts where you can switch between list or excerpt. Our post types don't support
	 * it, so we want to hide the useless UI from the screen options tab.
	 *
	 * @param  array $post_types Array of post types supporting view mode.
	 * @return array             Array of post types supporting view mode, without this type.
	 */
	public function disable_view_mode( $post_types ) {
		unset( $post_types[ $this->list_table_type ] );
		return $post_types;
	}

	/**
	 * See if we should render search filters or not.
	 */
	public function restrict_manage_posts() {
		global $typenow;

		if ( $this->list_table_type === $typenow ) {
			$this->render_filters();
		}
	}

	/**
	 * Handle any filters.
	 *
	 * @param array $query_vars Query vars.
	 * @return array
	 */
	public function request_query( $query_vars ) {
		global $typenow;

		if ( $this->list_table_type === $typenow ) {
			return $this->query_filters( $query_vars );
		}

		return $query_vars;
	}

	/**
	 * Render any custom filters and search inputs for the list table.
	 */
	protected function render_filters() {}

	/**
	 * Handle any custom filters.
	 *
	 * @param array $query_vars Query vars.
	 * @return array
	 */
	protected function query_filters( $query_vars ) {
		return $query_vars;
	}

	/**
	 * Set row actions.
	 *
	 * @param array   $actions Array of actions.
	 * @param WP_Post $post Current post object.
	 * @return array
	 */
	public function row_actions( $actions, $post ) {
		if ( $this->list_table_type === $post->post_type ) {
			return $this->get_row_actions( $actions, $post );
		}
		return $actions;
	}

	/**
	 * Get row actions to show in the list table.
	 *
	 * @param array   $actions Array of actions.
	 * @param WP_Post $post Current post object.
	 * @return array
	 */
	protected function get_row_actions( $actions, $post ) {
		return $actions;
	}

	/**
	 * Adjust which columns are displayed by default.
	 *
	 * @param array  $hidden Current hidden columns.
	 * @param object $screen Current screen.
	 * @return array
	 */
	public function default_hidden_columns( $hidden, $screen ) {
		if ( isset( $screen->id ) && 'edit-' . $this->list_table_type === $screen->id ) {
			$hidden = array_merge( $hidden, $this->define_hidden_columns() );
		}
		return $hidden;
	}

	/**
	 * Set list table primary column.
	 *
	 * @param  string $default Default value.
	 * @param  string $screen_id Current screen ID.
	 * @return string
	 */
	public function list_table_primary_column( $default, $screen_id ) {
		if ( 'edit-' . $this->list_table_type === $screen_id && $this->get_primary_column() ) {
			return $this->get_primary_column();
		}
		return $default;
	}

	/**
	 * Define primary column.
	 *
	 * @return array
	 */
	protected function get_primary_column() {
		return '';
	}

	/**
	 * Define hidden columns.
	 *
	 * @return array
	 */
	protected function define_hidden_columns() {
		return array();
	}

	/**
	 * Define which columns are sortable.
	 *
	 * @param array $columns Existing columns.
	 * @return array
	 */
	public function define_sortable_columns( $columns ) {
		return $columns;
	}

	/**
	 * Define which columns to show on this screen.
	 *
	 * @param array $columns Existing columns.
	 * @return array
	 */
	public function define_columns( $columns ) {
		return $columns;
	}

	/**
	 * Define bulk actions.
	 *
	 * @param array $actions Existing actions.
	 * @return array
	 */
	public function define_bulk_actions( $actions ) {
		return $actions;
	}

	/**
	 * Pre-fetch any data for the row each column has access to it.
	 *
	 * @param int $post_id Post ID being shown.
	 */
	protected function prepare_row_data( $post_id ) {}

	/**
	 * Render individual columns.
	 *
	 * @param string $column Column ID to render.
	 * @param int    $post_id Post ID being shown.
	 */
	public function render_columns( $column, $post_id ) {
		$this->prepare_row_data( $post_id );

		if ( ! $this->object ) {
			return;
		}

		if ( is_callable( array( $this, 'render_' . $column . '_column' ) ) ) {
			$this->{"render_{$column}_column"}();
		}
	}

	/**
	 * Handle bulk actions.
	 *
	 * @param  string $redirect_to URL to redirect to.
	 * @param  string $action      Action name.
	 * @param  array  $ids         List of ids.
	 * @return string
	 */
	public function handle_bulk_actions( $redirect_to, $action, $ids ) {
		return esc_url_raw( $redirect_to );
	}
}
PK     tS\?w\  w\  0  list-tables/class-wc-admin-list-table-orders.phpnu [        <?php
/**
 * List tables: orders.
 *
 * @package WooCommerce\Admin
 * @version 3.3.0
 */

use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Internal\Admin\Orders\ListTable;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Admin_List_Table_Orders', false ) ) {
	return;
}

if ( ! class_exists( 'WC_Admin_List_Table', false ) ) {
	include_once __DIR__ . '/abstract-class-wc-admin-list-table.php';
}

/**
 * WC_Admin_List_Table_Orders Class.
 */
class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {

	/**
	 * Post type.
	 *
	 * @var string
	 */
	protected $list_table_type = 'shop_order';

	/**
	 * The data store-agnostic list table implementation (introduced to support custom order tables),
	 * which we use here to render columns.
	 *
	 * @var ListTable $orders_list_table
	 */
	private $orders_list_table;

	/**
	 * Constructor.
	 */
	public function __construct() {
		parent::__construct();
		$this->orders_list_table = wc_get_container()->get( ListTable::class );
		add_action( 'admin_notices', array( $this, 'bulk_admin_notices' ) );
		add_action( 'admin_footer', array( $this, 'order_preview_template' ) );
		add_filter( 'get_search_query', array( $this, 'search_label' ) );
		add_filter( 'query_vars', array( $this, 'add_custom_query_var' ) );
		add_action( 'parse_query', array( $this, 'search_custom_fields' ) );
	}

	/**
	 * Render blank state.
	 */
	protected function render_blank_state() {
		$this->orders_list_table->render_blank_state();
	}

	/**
	 * Define primary column.
	 *
	 * @return string
	 */
	protected function get_primary_column() {
		return 'order_number';
	}

	/**
	 * Get row actions to show in the list table.
	 *
	 * @param array   $actions Array of actions.
	 * @param WP_Post $post Current post object.
	 * @return array
	 */
	protected function get_row_actions( $actions, $post ) {
		return array();
	}

	/**
	 * Define hidden columns.
	 *
	 * @return array
	 */
	protected function define_hidden_columns() {
		return array(
			'shipping_address',
			'billing_address',
			'wc_actions',
		);
	}

	/**
	 * Define which columns are sortable.
	 *
	 * @param array $columns Existing columns.
	 * @return array
	 */
	public function define_sortable_columns( $columns ) {
		$custom = array(
			'order_number' => 'ID',
			'order_total'  => 'order_total',
			'order_date'   => 'date',
		);
		unset( $columns['comments'] );

		return wp_parse_args( $custom, $columns );
	}

	/**
	 * Define which columns to show on this screen.
	 *
	 * @param array $columns Existing columns.
	 * @return array
	 */
	public function define_columns( $columns ) {
		$show_columns                     = array();
		$show_columns['cb']               = $columns['cb'];
		$show_columns['order_number']     = __( 'Order', 'woocommerce' );
		$show_columns['order_date']       = __( 'Date', 'woocommerce' );
		$show_columns['order_status']     = __( 'Status', 'woocommerce' );
		$show_columns['billing_address']  = __( 'Billing', 'woocommerce' );
		$show_columns['shipping_address'] = __( 'Ship to', 'woocommerce' );
		$show_columns['order_total']      = __( 'Total', 'woocommerce' );
		$show_columns['wc_actions']       = __( 'Actions', 'woocommerce' );

		wp_enqueue_script( 'wc-orders' );

		return $show_columns;
	}

	/**
	 * Define bulk actions.
	 *
	 * @param array $actions Existing actions.
	 * @return array
	 */
	public function define_bulk_actions( $actions ) {
		if ( isset( $actions['edit'] ) ) {
			unset( $actions['edit'] );
		}

		$actions['mark_processing'] = __( 'Change status to processing', 'woocommerce' );
		$actions['mark_on-hold']    = __( 'Change status to on-hold', 'woocommerce' );
		$actions['mark_completed']  = __( 'Change status to completed', 'woocommerce' );
		$actions['mark_cancelled']  = __( 'Change status to cancelled', 'woocommerce' );

		if ( wc_string_to_bool( get_option( 'woocommerce_allow_bulk_remove_personal_data', 'no' ) ) ) {
			$actions['remove_personal_data'] = __( 'Remove personal data', 'woocommerce' );
		}

		return $actions;
	}

	/**
	 * Pre-fetch any data for the row each column has access to it. the_order global is there for bw compat.
	 *
	 * @param int $post_id Post ID being shown.
	 */
	protected function prepare_row_data( $post_id ) {
		global $the_order;

		if ( empty( $this->object ) || $this->object->get_id() !== $post_id ) {
			$this->object = wc_get_order( $post_id );
			$the_order    = $this->object;
		}
	}

	/**
	 * Render column: order_number.
	 */
	protected function render_order_number_column() {
		$this->orders_list_table->render_order_number_column( $this->object );
	}

	/**
	 * Render column: order_status.
	 */
	protected function render_order_status_column() {
		$this->orders_list_table->render_order_status_column( $this->object );
	}

	/**
	 * Render column: order_date.
	 */
	protected function render_order_date_column() {
		$this->orders_list_table->render_order_date_column( $this->object );
	}

	/**
	 * Render column: order_total.
	 */
	protected function render_order_total_column() {
		$this->orders_list_table->render_order_total_column( $this->object );
	}

	/**
	 * Render column: wc_actions.
	 */
	protected function render_wc_actions_column() {
		$this->orders_list_table->render_wc_actions_column( $this->object );
	}

	/**
	 * Render column: billing_address.
	 */
	protected function render_billing_address_column() {
		$this->orders_list_table->render_billing_address_column( $this->object );
	}

	/**
	 * Render column: shipping_address.
	 */
	protected function render_shipping_address_column() {
		$this->orders_list_table->render_shipping_address_column( $this->object );
	}

	/**
	 * Template for order preview.
	 *
	 * @since 3.3.0
	 */
	public function order_preview_template() {
		echo $this->orders_list_table->get_order_preview_template();
	}

	/**
	 * Get items to display in the preview as HTML.
	 *
	 * @param  WC_Order $order Order object.
	 * @return string
	 */
	public static function get_order_preview_item_html( $order ) {
		$hidden_order_itemmeta = apply_filters(
			'woocommerce_hidden_order_itemmeta',
			array(
				'_qty',
				'_tax_class',
				'_product_id',
				'_variation_id',
				'_line_subtotal',
				'_line_subtotal_tax',
				'_line_total',
				'_line_tax',
				'method_id',
				'cost',
				'_reduced_stock',
				'_restock_refunded_items',
			)
		);

		$line_items = apply_filters( 'woocommerce_admin_order_preview_line_items', $order->get_items(), $order );
		$columns    = apply_filters(
			'woocommerce_admin_order_preview_line_item_columns',
			array(
				'product'  => __( 'Product', 'woocommerce' ),
				'quantity' => __( 'Quantity', 'woocommerce' ),
				'tax'      => __( 'Tax', 'woocommerce' ),
				'total'    => __( 'Total', 'woocommerce' ),
			),
			$order
		);

		if ( ! wc_tax_enabled() ) {
			unset( $columns['tax'] );
		}

		$html = '
		<div class="wc-order-preview-table-wrapper">
			<table cellspacing="0" class="wc-order-preview-table">
				<thead>
					<tr>';

		foreach ( $columns as $column => $label ) {
			$html .= '<th class="wc-order-preview-table__column--' . esc_attr( $column ) . '">' . esc_html( $label ) . '</th>';
		}

		$html .= '
					</tr>
				</thead>
				<tbody>';

		$refunds = array();
		foreach ( $order->get_refunds() as $refund ) {
			foreach ( $refund->get_items() as $item ) {
				$product_id = $item->get_product_id();
				if ( array_key_exists( $product_id, $refunds ) ) {
					$refunds[ $product_id ]['quantity'] += absint( $item->get_quantity() );
					$refunds[ $product_id ]['total']    += abs( (float) $item->get_total() );
				} else {
					$refunds[ $product_id ] = array(
						'quantity' => absint( $item->get_quantity() ),
						'total'    => abs( (float) $item->get_total() ),
					);
				}
			}
		}

		$price_args = array( 'currency' => $order->get_currency() );
		foreach ( $line_items as $item_id => $item ) {

			$product_object = is_callable( array( $item, 'get_product' ) ) ? $item->get_product() : null;
			$row_class      = apply_filters( 'woocommerce_admin_html_order_preview_item_class', '', $item, $order );
			$refund         = $refunds[ $item->get_product_id() ] ?? null;

			$html .= '<tr class="wc-order-preview-table__item wc-order-preview-table__item--' . esc_attr( $item_id ) . ( $row_class ? ' ' . esc_attr( $row_class ) : '' ) . '">';

			foreach ( $columns as $column => $label ) {
				$html .= '<td class="wc-order-preview-table__column--' . esc_attr( $column ) . '">';
				switch ( $column ) {
					case 'product':
						$html .= wp_kses_post( $item->get_name() );

						if ( $product_object ) {
							$html .= '<div class="wc-order-item-sku">' . esc_html( $product_object->get_sku() ) . '</div>';
						}

						$meta_data = $item->get_all_formatted_meta_data( '' );

						if ( $meta_data ) {
							$html .= '<table cellspacing="0" class="wc-order-item-meta">';

							foreach ( $meta_data as $meta_id => $meta ) {
								if ( in_array( $meta->key, $hidden_order_itemmeta, true ) ) {
									continue;
								}
								$html .= '<tr><th>' . wp_kses_post( $meta->display_key ) . ':</th><td>' . wp_kses_post( force_balance_tags( $meta->display_value ) ) . '</td></tr>';
							}
							$html .= '</table>';
						}
						break;
					case 'quantity':
						$html .= esc_html( $item->get_quantity() );
						if ( $refund ) {
							$html .= "<div><small class='refunded'>-" . $refund['quantity'] . '</small></div><br/>';
						}
						break;
					case 'tax':
						$html .= wc_price( $item->get_total_tax(), $price_args );
						break;
					case 'total':
						$html .= wc_price( $item->get_total(), $price_args );
						if ( $refund ) {
							$html .= "<div><small class='refunded'>-" . wc_price( $refund['total'], $price_args ) . '</small></div><br/>';
						}
						break;
					default:
						$html .= apply_filters( 'woocommerce_admin_order_preview_line_item_column_' . sanitize_key( $column ), '', $item, $item_id, $order );
						break;
				}
				$html .= '</td>';
			}

			$html .= '</tr>';
		}

		$html .= '
				</tbody>
			</table>
		</div>';

		return $html;
	}

	/**
	 * Get actions to display in the preview as HTML.
	 *
	 * @param  WC_Order $order Order object.
	 * @return string
	 */
	public static function get_order_preview_actions_html( $order ) {
		$actions        = array();
		$status_actions = array();

		$wp_post_type = get_post_type_object( $order->get_type() ) ?? get_post_type_object( 'shop_order' );
		if ( ! current_user_can( $wp_post_type->cap->edit_post, $order->get_id() ) ) {
			return '';
		}

		if ( $order->has_status( array( OrderStatus::PENDING ) ) ) {
			$status_actions['on-hold'] = array(
				'url'    => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=on-hold&order_id=' . $order->get_id() ), 'woocommerce-mark-order-status' ),
				'name'   => __( 'On-hold', 'woocommerce' ),
				'title'  => __( 'Change order status to on-hold', 'woocommerce' ),
				'action' => 'on-hold',
			);
		}

		if ( $order->has_status( array( OrderStatus::PENDING, OrderStatus::ON_HOLD ) ) ) {
			$status_actions['processing'] = array(
				'url'    => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=processing&order_id=' . $order->get_id() ), 'woocommerce-mark-order-status' ),
				'name'   => __( 'Processing', 'woocommerce' ),
				'title'  => __( 'Change order status to processing', 'woocommerce' ),
				'action' => 'processing',
			);
		}

		if ( $order->has_status( array( OrderStatus::PENDING, OrderStatus::ON_HOLD, OrderStatus::PROCESSING ) ) ) {
			$status_actions['complete'] = array(
				'url'    => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=completed&order_id=' . $order->get_id() ), 'woocommerce-mark-order-status' ),
				'name'   => __( 'Completed', 'woocommerce' ),
				'title'  => __( 'Change order status to completed', 'woocommerce' ),
				'action' => 'complete',
			);
		}

		if ( $status_actions ) {
			$actions['status'] = array(
				'group'   => __( 'Change status: ', 'woocommerce' ),
				'actions' => $status_actions,
			);
		}

		return wc_render_action_buttons( apply_filters( 'woocommerce_admin_order_preview_actions', $actions, $order ) );
	}

	/**
	 * Get order details to send to the ajax endpoint for previews.
	 *
	 * @param  WC_Order $order Order object.
	 * @return array
	 */
	public static function order_preview_get_order_details( $order ) {
		if ( ! $order ) {
			return array();
		}

		$payment_via      = $order->get_payment_method_title();
		$payment_method   = $order->get_payment_method();
		$payment_gateways = WC()->payment_gateways() ? WC()->payment_gateways->payment_gateways() : array();
		$transaction_id   = $order->get_transaction_id();

		if ( $transaction_id ) {

			$url = isset( $payment_gateways[ $payment_method ] ) ? $payment_gateways[ $payment_method ]->get_transaction_url( $order ) : false;

			if ( $url ) {
				$payment_via .= ' (<a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $transaction_id ) . '</a>)';
			} else {
				$payment_via .= ' (' . esc_html( $transaction_id ) . ')';
			}
		}

		$billing_address  = $order->get_formatted_billing_address();
		$shipping_address = $order->get_formatted_shipping_address();

		$wp_post_type = get_post_type_object( $order->get_type() ) ?? get_post_type_object( 'shop_order' );
		$is_editable  = current_user_can( $wp_post_type->cap->edit_post, $order->get_id() );

		// phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment
		/**
		 * Filter to customize the order details data that the woocommerce_get_order_details action will send.
		 *
		 * @param array $order_details Order details.
		 */
		$order_details = apply_filters(
			'woocommerce_admin_order_preview_get_order_details',
			array(
				'data'                       => $order->get_data(),
				'is_editable'                => $is_editable,
				'order_number'               => $order->get_order_number(),
				'item_html'                  => self::get_order_preview_item_html( $order ),
				'actions_html'               => self::get_order_preview_actions_html( $order ),
				'ship_to_billing'            => wc_ship_to_billing_address_only(),
				'needs_shipping'             => $order->needs_shipping_address(),
				'formatted_billing_address'  => $billing_address ? $billing_address : __( 'N/A', 'woocommerce' ),
				'formatted_shipping_address' => $shipping_address ? $shipping_address : __( 'N/A', 'woocommerce' ),
				'shipping_address_map_url'   => $order->get_shipping_address_map_url(),
				'payment_via'                => $payment_via,
				'shipping_via'               => $order->get_shipping_method(),
				'status'                     => $order->get_status(),
				'status_name'                => wc_get_order_status_name( $order->get_status() ),
			),
			$order
		);
		// phpcs:enable WooCommerce.Commenting.CommentHooks.MissingSinceComment

		$order_details['data'] = array_intersect_key( $order_details['data'], array_flip( array( 'id', 'billing', 'shipping', 'customer_note' ) ) );

		return $order_details;
	}

	/**
	 * Handle bulk actions.
	 *
	 * @param  string $redirect_to URL to redirect to.
	 * @param  string $action      Action name.
	 * @param  array  $ids         List of ids.
	 * @return string
	 */
	public function handle_bulk_actions( $redirect_to, $action, $ids ) {
		$ids     = apply_filters( 'woocommerce_bulk_action_ids', array_reverse( array_map( 'absint', $ids ) ), $action, 'order' );
		$changed = 0;

		if ( 'remove_personal_data' === $action ) {
			$report_action = 'removed_personal_data';

			foreach ( $ids as $id ) {
				$order = wc_get_order( $id );

				if ( $order ) {
					do_action( 'woocommerce_remove_order_personal_data', $order );
					++$changed;
				}
			}
		} elseif ( false !== strpos( $action, 'mark_' ) ) {
			$order_statuses = wc_get_order_statuses();
			$new_status     = substr( $action, 5 ); // Get the status name from action.
			$report_action  = 'marked_' . $new_status;

			// Sanity check: bail out if this is actually not a status, or is not a registered status.
			if ( isset( $order_statuses[ 'wc-' . $new_status ] ) ) {
				// Initialize payment gateways in case order has hooked status transition actions.
				WC()->payment_gateways();

				foreach ( $ids as $id ) {
					$order = wc_get_order( $id );
					$order->update_status( $new_status, __( 'Order status changed by bulk edit:', 'woocommerce' ), true );
					do_action( 'woocommerce_order_edit_status', $id, $new_status );
					++$changed;
				}
			}
		}

		if ( $changed ) {
			$redirect_to = add_query_arg(
				array(
					'post_type'   => $this->list_table_type,
					'bulk_action' => $report_action,
					'changed'     => $changed,
					'ids'         => join( ',', $ids ),
				),
				$redirect_to
			);
		}

		return esc_url_raw( $redirect_to );
	}

	/**
	 * Show confirmation message that order status changed for number of orders.
	 */
	public function bulk_admin_notices() {
		global $post_type, $pagenow;

		// Bail out if not on shop order list page.
		if ( 'edit.php' !== $pagenow || 'shop_order' !== $post_type || ! isset( $_REQUEST['bulk_action'] ) ) { // WPCS: input var ok, CSRF ok.
			return;
		}

		$order_statuses = wc_get_order_statuses();
		$number         = isset( $_REQUEST['changed'] ) ? absint( $_REQUEST['changed'] ) : 0; // WPCS: input var ok, CSRF ok.
		$bulk_action    = wc_clean( wp_unslash( $_REQUEST['bulk_action'] ) ); // WPCS: input var ok, CSRF ok.

		// Check if any status changes happened.
		foreach ( $order_statuses as $slug => $name ) {
			if ( 'marked_' . str_replace( 'wc-', '', $slug ) === $bulk_action ) { // WPCS: input var ok, CSRF ok.
				/* translators: %d: orders count */
				$message = sprintf( _n( '%s order status changed.', '%s order statuses changed.', $number, 'woocommerce' ), number_format_i18n( $number ) );
				echo '<div class="updated"><p>' . esc_html( $message ) . '</p></div>';
				break;
			}
		}

		if ( 'removed_personal_data' === $bulk_action ) { // WPCS: input var ok, CSRF ok.
			/* translators: %d: orders count */
			$message = sprintf( _n( 'Removed personal data from %s order.', 'Removed personal data from %s orders.', $number, 'woocommerce' ), number_format_i18n( $number ) );
			echo '<div class="updated"><p>' . esc_html( $message ) . '</p></div>';
		}
	}

	/**
	 * See if we should render search filters or not.
	 */
	public function restrict_manage_posts() {
		global $typenow;

		if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ), true ) ) {
			$this->render_filters();
		}
	}

	/**
	 * Render any custom filters and search inputs for the list table.
	 */
	protected function render_filters() {
		$this->orders_list_table->created_via_filter();
		$this->orders_list_table->customers_filter();
	}

	/**
	 * Handle any filters.
	 *
	 * @param array $query_vars Query vars.
	 * @return array
	 */
	public function request_query( $query_vars ) {
		global $typenow;

		if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ), true ) ) {
			return $this->query_filters( $query_vars );
		}

		return $query_vars;
	}

	/**
	 * Handle any custom filters.
	 *
	 * @param array $query_vars Query vars.
	 * @return array
	 */
	protected function query_filters( $query_vars ) {
		global $wp_post_statuses;

		// Filter the orders by the posted customer.
		if ( ! empty( $_GET['_customer_user'] ) ) { // WPCS: input var ok.
			// @codingStandardsIgnoreStart.
			$query_vars['meta_query'] = array(
				array(
					'key'     => '_customer_user',
					'value'   => (int) $_GET['_customer_user'], // WPCS: input var ok, sanitization ok.
					'compare' => '=',
				),
			);
			// @codingStandardsIgnoreEnd
		}

		// Filter the orders by created via.
		if ( ! empty( $_GET['_created_via'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			// @codingStandardsIgnoreStart
			$created_via = explode(',', sanitize_text_field( wp_unslash( $_GET['_created_via'] ) ) );

			$query_vars['meta_query'] = array(
				array(
					'key'     => '_created_via',
					'value'   => $created_via,
					'compare' => 'IN',
				),
			);
			// @codingStandardsIgnoreEnd
		}

		// Sorting.
		if ( isset( $query_vars['orderby'] ) ) {
			if ( 'order_total' === $query_vars['orderby'] ) {
				// @codingStandardsIgnoreStart
				$query_vars = array_merge( $query_vars, array(
					'meta_key'  => '_order_total',
					'orderby'   => 'meta_value_num',
				) );
				// @codingStandardsIgnoreEnd
			}
		}

		// Status.
		if ( empty( $query_vars['post_status'] ) ) {
			$post_statuses = wc_get_order_statuses();

			foreach ( $post_statuses as $status => $value ) {
				if ( isset( $wp_post_statuses[ $status ] ) && false === $wp_post_statuses[ $status ]->show_in_admin_all_list ) {
					unset( $post_statuses[ $status ] );
				}
			}

			$query_vars['post_status'] = array_keys( $post_statuses );
		}

		return $query_vars;
	}

	/**
	 * Change the label when searching orders.
	 *
	 * @param mixed $query Current search query.
	 * @return string
	 */
	public function search_label( $query ) {
		global $pagenow, $typenow;

		if ( 'edit.php' !== $pagenow || 'shop_order' !== $typenow || ! get_query_var( 'shop_order_search' ) || ! isset( $_GET['s'] ) ) { // phpcs:ignore  WordPress.Security.NonceVerification.Recommended
			return $query;
		}

		return wc_clean( wp_unslash( $_GET['s'] ) ); // WPCS: input var ok, sanitization ok.
	}

	/**
	 * Query vars for custom searches.
	 *
	 * @param mixed $public_query_vars Array of query vars.
	 * @return array
	 */
	public function add_custom_query_var( $public_query_vars ) {
		$public_query_vars[] = 'shop_order_search';
		return $public_query_vars;
	}

	/**
	 * Search custom fields as well as content.
	 *
	 * @param WP_Query $wp Query object.
	 */
	public function search_custom_fields( $wp ) {
		global $pagenow;

		if ( 'edit.php' !== $pagenow || ! isset( $wp->query_vars['post_type'] ) || 'shop_order' !== $wp->query_vars['post_type'] ) { // phpcs:ignore  WordPress.Security.NonceVerification.Recommended
			return;
		}

		$post_ids = isset( $_GET['s'] ) && ! empty( $wp->query_vars['s'] ) ? wc_order_search( wc_clean( wp_unslash( $_GET['s'] ) ) ) : array(); // phpcs:ignore  WordPress.Security.NonceVerification.Recommended

		if ( ! empty( $post_ids ) ) {
			// Remove "s" - we don't want to search order name.
			unset( $wp->query_vars['s'] );

			// so we know we're doing this.
			$wp->query_vars['shop_order_search'] = true;

			// Search by found posts.
			$wp->query_vars['post__in'] = array_merge( $post_ids, array( 0 ) );
		}

		if ( isset( $_GET['order_date_type'] ) && isset( $_GET['m'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$date_type  = wc_clean( wp_unslash( $_GET['order_date_type'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$date_query = wc_clean( wp_unslash( $_GET['m'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			// date_paid and date_completed are stored in postmeta, so we need to do a meta query.
			if ( 'date_paid' === $date_type || 'date_completed' === $date_type ) {
				$date_start = \DateTime::createFromFormat( 'Ymd H:i:s', "$date_query 00:00:00" );
				$date_end   = \DateTime::createFromFormat( 'Ymd H:i:s', "$date_query 23:59:59" );

				unset( $wp->query_vars['m'] );

				if ( $date_start && $date_end ) {
					$wp->query_vars['meta_key']     = "_$date_type"; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
					$wp->query_vars['meta_value']   = array( strval( $date_start->getTimestamp() ), strval( $date_end->getTimestamp() ) ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
					$wp->query_vars['meta_compare'] = 'BETWEEN';
				}
			}
		}
	}
}
PK     tS\-#
4  4  1  list-tables/class-wc-admin-list-table-coupons.phpnu [        <?php
/**
 * List tables: coupons.
 *
 * @package  WooCommerce\Admin
 * @version  3.3.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Admin_List_Table_Coupons', false ) ) {
	return;
}

if ( ! class_exists( 'WC_Admin_List_Table', false ) ) {
	include_once __DIR__ . '/abstract-class-wc-admin-list-table.php';
}

/**
 * WC_Admin_List_Table_Coupons Class.
 */
class WC_Admin_List_Table_Coupons extends WC_Admin_List_Table {

	/**
	 * Post type.
	 *
	 * @var string
	 */
	protected $list_table_type = 'shop_coupon';

	/**
	 * Constructor.
	 */
	public function __construct() {
		parent::__construct();
		add_filter( 'disable_months_dropdown', '__return_true' );
	}

	/**
	 * Render blank state.
	 */
	protected function render_blank_state() {
		echo '<div class="woocommerce-BlankState">';
		echo '<h2 class="woocommerce-BlankState-message">' . esc_html__( 'Coupons are a great way to offer discounts and rewards to your customers. They will appear here once created.', 'woocommerce' ) . '</h2>';
		echo '<a class="woocommerce-BlankState-cta button-primary button" href="' . esc_url( admin_url( 'post-new.php?post_type=shop_coupon' ) ) . '">' . esc_html__( 'Create your first coupon', 'woocommerce' ) . '</a>';
		echo '<a class="woocommerce-BlankState-cta button" target="_blank" href="https://woocommerce.com/document/coupon-management/?utm_source=blankslate&utm_medium=product&utm_content=couponsdoc&utm_campaign=woocommerceplugin">' . esc_html__( 'Learn more about coupons', 'woocommerce' ) . '</a>';
		echo '</div>';
	}

	/**
	 * Define primary column.
	 *
	 * @return string
	 */
	protected function get_primary_column() {
		return 'coupon_code';
	}

	/**
	 * Get row actions to show in the list table.
	 *
	 * @param array   $actions Array of actions.
	 * @param WP_Post $post Current post object.
	 * @return array
	 */
	protected function get_row_actions( $actions, $post ) {
		unset( $actions['inline hide-if-no-js'] );
		return $actions;
	}

	/**
	 * Define which columns to show on this screen.
	 *
	 * @param array $columns Existing columns.
	 * @return array
	 */
	public function define_columns( $columns ) {
		$show_columns                = array();
		$show_columns['cb']          = $columns['cb'];
		$show_columns['coupon_code'] = __( 'Code', 'woocommerce' );
		$show_columns['type']        = __( 'Coupon type', 'woocommerce' );
		$show_columns['amount']      = __( 'Coupon amount', 'woocommerce' );
		$show_columns['description'] = __( 'Description', 'woocommerce' );
		$show_columns['products']    = __( 'Product IDs', 'woocommerce' );
		$show_columns['usage']       = __( 'Usage / Limit', 'woocommerce' );
		$show_columns['expiry_date'] = __( 'Expiry date', 'woocommerce' );

		return $show_columns;
	}

	/**
	 * Pre-fetch any data for the row each column has access to it. the_coupon global is there for bw compat.
	 *
	 * @param int $post_id Post ID being shown.
	 */
	protected function prepare_row_data( $post_id ) {
		global $the_coupon;

		if ( empty( $this->object ) || $this->object->get_id() !== $post_id ) {
			$this->object = new WC_Coupon( $post_id );
			$the_coupon   = $this->object;
		}
	}

	/**
	 * Render column: coupon_code.
	 */
	protected function render_coupon_code_column() {
		global $post;

		$edit_link = get_edit_post_link( $this->object->get_id() );
		$title     = $this->object->get_code();

		echo '<strong><a class="row-title" href="' . esc_url( $edit_link ) . '">' . esc_html( $title ) . '</a>';
		_post_states( $post );
		echo '</strong>';
	}

	/**
	 * Render column: type.
	 */
	protected function render_type_column() {
		echo esc_html( wc_get_coupon_type( $this->object->get_discount_type() ) );
	}

	/**
	 * Render column: amount.
	 */
	protected function render_amount_column() {
		echo esc_html( wc_format_localized_price( $this->object->get_amount() ) );
	}
	/**
	 * Render column: products.
	 */
	protected function render_products_column() {
		$product_ids = $this->object->get_product_ids();
		if ( is_array( $product_ids ) && count( $product_ids ) > 0 ) {
			echo esc_html( implode( ', ', $product_ids ) );
		} else {
			echo '&ndash;';
		}
	}

	/**
	 * Render column: usage_limit.
	 */
	protected function render_usage_limit_column() {
		$usage_limit = $this->object->get_usage_limit();

		if ( $usage_limit ) {
			echo esc_html( $usage_limit );
		} else {
			echo '&ndash;';
		}
	}

	/**
	 * Render column: usage.
	 */
	protected function render_usage_column() {
		$usage_count = $this->object->get_usage_count();
		$usage_limit = $this->object->get_usage_limit();

		printf(
			/* translators: 1: count 2: limit */
			__( '%1$s / %2$s', 'woocommerce' ),
			esc_html( $usage_count ),
			$usage_limit ? esc_html( $usage_limit ) : '&infin;'
		);
	}

	/**
	 * Render column: expiry_date.
	 */
	protected function render_expiry_date_column() {
		$expiry_date = $this->object->get_date_expires();

		if ( $expiry_date ) {
			echo esc_html( $expiry_date->date_i18n( 'F j, Y' ) );
		} else {
			echo '&ndash;';
		}
	}

	/**
	 * Render column: description.
	 */
	protected function render_description_column() {
		echo wp_kses_post( $this->object->get_description() ? $this->object->get_description() : '&ndash;' );
	}

	/**
	 * Render any custom filters and search inputs for the list table.
	 */
	protected function render_filters() {
		?>
		<select name="coupon_type" id="dropdown_shop_coupon_type">
			<option value=""><?php esc_html_e( 'Show all types', 'woocommerce' ); ?></option>
			<?php
			$types = wc_get_coupon_types();

			foreach ( $types as $name => $type ) {
				echo '<option value="' . esc_attr( $name ) . '"';

				if ( isset( $_GET['coupon_type'] ) ) { // WPCS: input var ok.
					selected( $name, wc_clean( wp_unslash( $_GET['coupon_type'] ) ) ); // WPCS: input var ok, sanitization ok.
				}

				echo '>' . esc_html( $type ) . '</option>';
			}
			?>
		</select>
		<?php
	}

	/**
	 * Handle any custom filters.
	 *
	 * @param array $query_vars Query vars.
	 * @return array
	 */
	protected function query_filters( $query_vars ) {
		if ( ! empty( $_GET['coupon_type'] ) ) { // WPCS: input var ok, sanitization ok.
			$query_vars['meta_key']   = 'discount_type'; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
			$query_vars['meta_value'] = wc_clean( wp_unslash( $_GET['coupon_type'] ) ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value, WordPress.VIP.SuperGlobalInputUsage.AccessDetected
		}
		return $query_vars;
	}
}
PK     tS\d-  -  &  notes/class-wc-notes-run-db-update.phpnu [        <?php
/**
 * WooCommerce: Db update note.
 *
 * Adds a note to complete the WooCommerce db update after the upgrade in the WC Admin context.
 *
 * @package WooCommerce
 */

defined( 'ABSPATH' ) || exit;

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\Notes\Note;

/**
 * WC_Notes_Run_Db_Update.
 */
class WC_Notes_Run_Db_Update {
	const NOTE_NAME = 'wc-update-db-reminder';

	/**
	 * Checks whether the note needs an update based on the current db update status.
	 * Hooked onto the 'woocommerce_get_note_from_db' filter. See {@see \WC_Install}.
	 *
	 * @since 10.3.0
	 *
	 * @param Note $note Note to check.
	 * @return Note
	 */
	public static function maybe_update_notice( $note ) {
		if ( ! $note instanceof Note || $note->get_name() !== self::NOTE_NAME ) {
			return $note;
		}

		// If the legacy notice is not set, hide the note. This should not normally happen, but serves as a fallback.
		if ( ! in_array( 'update', \WC_Admin_Notices::get_notices(), true ) ) {
			$note->set_status( Note::E_WC_ADMIN_NOTE_ACTIONED );
			$note->save();

			return $note;
		}

		$needs_db_update = \WC_Install::needs_db_update();

		if ( ! $needs_db_update ) {
			// If there's no need to update the database and the note has not been actioned, update it to the thank you note.
			if ( Note::E_WC_ADMIN_NOTE_ACTIONED !== $note->get_status() ) {
				self::update_done_notice( $note );
			}
		} else {
			// If a db update is needed...
			$next_scheduled_date = WC()->queue()->get_next( 'woocommerce_run_update_callback', null, 'woocommerce-db-updates' );

			if ( $next_scheduled_date ) {
				// ... and scheduled, update the note to "in progress".
				self::update_in_progress_notice( $note );
			} else {
				// ... and not scheduled, nudge to run the db update.
				self::update_needed_notice( $note );
			}
		}

		return $note;
	}

	/**
	 * Get current notice id from the database.
	 *
	 * Retrieves the first notice of this type.
	 *
	 * @return Note|null Note or null in case no note was found.
	 */
	private static function get_current_notice() {
		try {
			$data_store = \WC_Data_Store::load( 'admin-note' );
		} catch ( Exception $e ) {
			return;
		}
		$note_ids = $data_store->get_notes_with_name( self::NOTE_NAME );

		if ( empty( $note_ids ) ) {
			return;
		}

		$current_note_id = array_shift( $note_ids );

		// Remove weird duplicates. Leave the first one.
		foreach ( $note_ids as $note_id ) {
			$note = new Note( $note_id );
			$data_store->delete( $note );
		}

		return new Note( $current_note_id );
	}

	/**
	 * Set this notice to an actioned one, so that it's no longer displayed.
	 */
	public static function set_notice_actioned() {
		$note = self::get_current_notice();
		if ( ! $note ) {
			return;
		}

		if ( Note::E_WC_ADMIN_NOTE_ACTIONED !== $note->get_status() ) {
			$note->set_status( Note::E_WC_ADMIN_NOTE_ACTIONED );
			$note->save();
		}
	}

	/**
	 * Check whether the note is up to date for a fresh display.
	 *
	 * The check tests if
	 *  - actions are set up for the first 'Update database' notice, and
	 *  - URL for note's action is equal to the given URL (to check for potential nonce update).
	 *
	 * @param Note               $note            Note to check.
	 * @param string             $update_url      URL to check the note against.
	 * @param array<int, string> $current_actions List of actions to check for.
	 * @return bool
	 */
	private static function note_up_to_date( $note, $update_url, $current_actions ) {
		$actions = $note->get_actions();
		return $note->get_id()
			&& count( $current_actions ) === count( array_intersect( wp_list_pluck( $actions, 'name' ), $current_actions ) )
			&& in_array( $update_url, wp_list_pluck( $actions, 'query' ), true );
	}

	/**
	 * Create and set up the first (out of 3) 'Database update needed' notice and store it in the database.
	 *
	 * If a $note_id is given, the method updates the note instead of creating a new one.
	 *
	 * @param null|Note $note Note db record to update. NULL to create a new one.
	 */
	private static function update_needed_notice( ?Note $note = null ) {
		if ( is_null( $note ) ) {
			$note = new Note();
		}

		$update_url =
			add_query_arg(
				array(
					'do_update_woocommerce' => 'true',
					'return_url'            => 'wc-admin-referer',
				),
				admin_url()
			);

		$note_actions = array(
			array(
				'name'         => 'update-db_run',
				'label'        => __( 'Update WooCommerce Database', 'woocommerce' ),
				'url'          => $update_url,
				'status'       => 'unactioned',
				'primary'      => true,
				'nonce_action' => 'wc_db_update',
				'nonce_name'   => 'wc_db_update_nonce',
			),
			array(
				'name'    => 'update-db_learn-more',
				'label'   => __( 'Learn more about updates', 'woocommerce' ),
				'url'     => 'https://woocommerce.com/document/how-to-update-woocommerce/',
				'status'  => 'unactioned',
				'primary' => false,
			),
		);

		// Check if the note needs to be updated (e.g. expired nonce or different note type stored in the previous run).
		if ( Note::E_WC_ADMIN_NOTE_UNACTIONED === $note->get_status() && self::note_up_to_date( $note, $update_url, wp_list_pluck( $note_actions, 'name' ) ) ) {
			return $note;
		}

		$note->set_title( __( 'WooCommerce database update required', 'woocommerce' ) );
		$note->set_content(
			__( 'WooCommerce has been updated! To keep things running smoothly, we have to update your database to the newest version.', 'woocommerce' )
			/* translators: %1$s: opening <a> tag %2$s: closing </a> tag*/
			. sprintf( ' ' . esc_html__( 'The database update process runs in the background and may take a little while, so please be patient. Advanced users can alternatively update via %1$sWP CLI%2$s.', 'woocommerce' ), '<a href="https://developer.woocommerce.com/docs/wc-cli/wc-cli-examples/#upgrading-the-database-using-wp-cli">', '</a>' )
		);
		$note->set_type( Note::E_WC_ADMIN_NOTE_UPDATE );
		$note->set_name( self::NOTE_NAME );
		$note->set_content_data( (object) array() );
		$note->set_source( 'woocommerce-core' );
		// In case db version is out of sync with WC version or during the next update, the notice needs to show up again,
		// so set it to unactioned.
		$note->set_status( Note::E_WC_ADMIN_NOTE_UNACTIONED );

		// Set new actions.
		$note->clear_actions();
		foreach ( $note_actions as $note_action ) {
			$note->add_action( ...array_values( $note_action ) );

			if ( isset( $note_action['nonce_action'] ) ) {
				$note->add_nonce_to_action( $note_action['name'], $note_action['nonce_action'], $note_action['nonce_name'] );
			}
		}

		$note->save();
	}

	/**
	 * Update the existing note with $note_id with information about the db upgrade being in progress.
	 *
	 * This is the second out of 3 notices displayed to the user.
	 *
	 * @param Note $note Note to update.
	 */
	private static function update_in_progress_notice( Note $note ) {
		// Same actions as in includes/admin/views/html-notice-updating.php. This just redirects, performs no action, so without nonce.
		$pending_actions_url = admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=woocommerce_run_update&status=pending' );
		$cron_disabled       = Constants::is_true( 'DISABLE_WP_CRON' );
		$cron_cta            = $cron_disabled ? __( 'You can manually run queued updates here.', 'woocommerce' ) : __( 'View progress →', 'woocommerce' );

		$note->set_title( __( 'WooCommerce database update in progress', 'woocommerce' ) );
		$note->set_content( __( 'WooCommerce is updating the database in the background. The database update process may take a little while, so please be patient.', 'woocommerce' ) );

		$note->clear_actions();
		$note->add_action(
			'update-db_see-progress',
			$cron_cta,
			$pending_actions_url,
			'unactioned',
			false
		);

		$note->save();
	}

	/**
	 * Update the existing note with $note_id with information that db upgrade is done.
	 *
	 * This is the last notice (3 out of 3 notices) displayed to the user.
	 *
	 * @param Note $note Note to update.
	 */
	private static function update_done_notice( Note $note ) {
		$hide_notices_url = html_entity_decode( // to convert &amp;s to normal &, otherwise produces invalid link.
			add_query_arg(
				array(
					'wc-hide-notice' => 'update',
				),
				admin_url( 'admin.php?page=wc-settings' )
			)
		);

		$note_actions = array(
			array(
				'name'         => 'update-db_done',
				'label'        => __( 'Thanks!', 'woocommerce' ),
				'url'          => $hide_notices_url,
				'status'       => 'actioned',
				'primary'      => true,
				'nonce_action' => 'woocommerce_hide_notices_nonce',
				'nonce_name'   => '_wc_notice_nonce',
			),
		);

		// Check if the note needs to be updated (e.g. expired nonce or different note type stored in the previous run).
		if ( self::note_up_to_date( $note, $hide_notices_url, wp_list_pluck( $note_actions, 'name' ) ) ) {
			return;
		}

		$note->set_title( __( 'WooCommerce database update done', 'woocommerce' ) );
		$note->set_content( __( 'WooCommerce database update complete. Thank you for updating to the latest version!', 'woocommerce' ) );

		$note->clear_actions();
		foreach ( $note_actions as $note_action ) {
			$note->add_action( ...array_values( $note_action ) );

			if ( isset( $note_action['nonce_action'] ) ) {
				$note->add_nonce_to_action( $note_action['name'], $note_action['nonce_action'], $note_action['nonce_name'] );
			}
		}

		$note->save();
	}

	/**
	 * Creates the db update note if needed.
	 *
	 * @since 10.3.0
	 */
	public static function add_notice() {
		$note = self::get_current_notice();
		if ( ! $note ) {
			$note = new Note();
			$note->set_name( self::NOTE_NAME );
			$note->save();
		}

		self::maybe_update_notice( $note );
	}

	/**
	 * Prepare the correct content of the db update note to be displayed by WC Admin.
	 *
	 * This one gets called on each page load, so try to bail quickly.
	 *
	 * If the db needs an update, the notice should be always shown.
	 * If the db does not need an update, but the notice has *not* been actioned (i.e. after the db update, when
	 * store owner hasn't acknowledged the successful db update), still show the Thanks notice.
	 * If the db does not need an update, and the notice has been actioned, then notice should *not* be shown.
	 * The notice should also be hidden if the db does not need an update and the notice does not exist.
	 *
	 * @deprecated 10.3.0
	 */
	public static function show_reminder() {
		$needs_db_update = \WC_Install::needs_db_update();

		$note_id = self::get_current_notice();
		if ( ! $needs_db_update ) {
			// Db update not needed && note does not exist -> don't show it.
			if ( ! $note_id ) {
				return;
			}

			$note = new Note( $note_id );
			if ( $note::E_WC_ADMIN_NOTE_ACTIONED === $note->get_status() ) {
				// Db update not needed && note actioned -> don't show it.
				return;
			} else {
				// Db update not needed && notice is unactioned -> Thank you note.
				self::update_done_notice( $note );
				return;
			}
		} else {
			// Db needs update &&.
			if ( ! $note_id ) {
				// Db needs update && no notice exists -> create one that shows Nudge to update.
				self::update_needed_notice();
				return;
			}

			$note = new Note( $note_id );

			$next_scheduled_date = WC()->queue()->get_next( 'woocommerce_run_update_callback', null, 'woocommerce-db-updates' );

			if ( $next_scheduled_date || ! empty( $_GET['do_update_woocommerce'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
				// Db needs update && db update is scheduled -> update note to In progress.
				self::update_in_progress_notice( $note );
			} else {
				// Db needs update && db update is not scheduled -> Nudge to run the db update.
				self::update_needed_notice( $note );
			}
		}
	}
}
PK     tS\A>  >  '  notes/class-wc-notes-refund-returns.phpnu [        <?php
/**
 * Refund and Returns Policy Page Note Provider.
 *
 * Adds notes to the merchant's inbox concerning the created page.
 *
 * @package WooCommerce
 */

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Admin\Notes\Note;

/**
 * WC_Notes_Refund_Returns.
 */
class WC_Notes_Refund_Returns {
	/**
	 * Name of the note for use in the database.
	 */
	const NOTE_NAME = 'wc-refund-returns-page';

	/**
	 * Attach hooks.
	 */
	public static function init() {
		add_action( 'woocommerce_newly_installed', array( __CLASS__, 'on_newly_installed' ) );
		add_filter( 'woocommerce_get_note_from_db', array( __CLASS__, 'get_note_from_db' ), 10, 1 );
	}

	/**
	 * Add the note when WooCommerce is newly installed.
	 *
	 * @since 10.5.0
	 * @return void
	 */
	public static function on_newly_installed() {
		$page_id = get_option( 'woocommerce_refund_returns_page_id' );
		if ( $page_id ) {
			self::possibly_add_note( $page_id );
		}
	}

	/**
	 * Maybe add a note to the inbox.
	 *
	 * @param int $page_id The ID of the page.
	 */
	public static function possibly_add_note( $page_id ) {
		if ( ! WC()->is_wc_admin_active() ) {
			return;
		}

		$data_store = \WC_Data_Store::load( 'admin-note' );

		// Do we already have this note?
		$note_id = $data_store->get_notes_with_name( self::NOTE_NAME );

		if ( ! empty( $note_id ) ) {
			$note = new Note( $note_id );

			if ( false !== $note || $note::E_WC_ADMIN_NOTE_ACTIONED === $note->get_status() ) {
				// note actioned -> don't show it.
				return;
			}
		}

		// Add note.
		$note = self::get_note( $page_id );
		$note->save();
		delete_option( 'woocommerce_refund_returns_page_created' );
	}

	/**
	 * Get the note.
	 *
	 * @param int $page_id The ID of the page.
	 * @return object $note The note object.
	 */
	public static function get_note( $page_id ) {
		$note = new Note();
		$note->set_title( __( 'Setup a Refund and Returns Policy page to boost your store\'s credibility.', 'woocommerce' ) );
		$note->set_content( __( 'We have created a sample draft Refund and Returns Policy page for you. Please have a look and update it to fit your store.', 'woocommerce' ) );
		$note->set_type( Note::E_WC_ADMIN_NOTE_INFORMATIONAL );
		$note->set_name( self::NOTE_NAME );
		$note->set_content_data( (object) array() );
		$note->set_source( 'woocommerce-core' );
		$note->add_action(
			'notify-refund-returns-page',
			__( 'Edit page', 'woocommerce' ),
			admin_url( sprintf( 'post.php?post=%d&action=edit', (int) $page_id ) )
		);

		return $note;
	}

	/**
	 * Get the note.
	 *
	 * @param Note $note_from_db The note object from the database.
	 * @return Note $note The note object.
	 */
	public static function get_note_from_db( $note_from_db ) {
		if ( ! $note_from_db instanceof Note || get_user_locale() === $note_from_db->get_locale() ) {
			return $note_from_db;
		}

		if ( self::NOTE_NAME === $note_from_db->get_name() ) {
			$note = self::get_note( 0 );
			$note_from_db->set_title( $note->get_title() );
			$note_from_db->set_content( $note->get_content() );

			$action_from_db    = $note_from_db->get_action( 'notify-refund-returns-page' );
			$action_from_class = $note->get_action( 'notify-refund-returns-page' );

			if ( $action_from_db && $action_from_class ) {
				$action_from_db->label = $action_from_class->label;
				$note_from_db->set_actions( array( $action_from_db ) );
			}
		}

		return $note_from_db;
	}
}
PK     tS\ \d'  d'    class-wc-admin-profile.phpnu [        <?php
/**
 * Add extra profile fields for users in admin
 *
 * @author   WooThemes
 * @category Admin
 * @package  WooCommerce\Admin
 * @version  2.4.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

if ( ! class_exists( 'WC_Admin_Profile', false ) ) :

	/**
	 * WC_Admin_Profile Class.
	 */
	class WC_Admin_Profile {

		/**
		 * Hook in tabs.
		 */
		public function __construct() {
			add_action( 'show_user_profile', array( $this, 'add_customer_meta_fields' ) );
			add_action( 'edit_user_profile', array( $this, 'add_customer_meta_fields' ) );

			add_action( 'personal_options_update', array( $this, 'save_customer_meta_fields' ) );
			add_action( 'edit_user_profile_update', array( $this, 'save_customer_meta_fields' ) );
		}

		/**
		 * Get Address Fields for the edit user pages.
		 *
		 * @return array Fields to display which are filtered through woocommerce_customer_meta_fields before being returned
		 */
		public function get_customer_meta_fields() {
			$show_fields = apply_filters(
				'woocommerce_customer_meta_fields',
				array(
					'billing'  => array(
						'title'  => __( 'Customer billing address', 'woocommerce' ),
						'fields' => array(
							'billing_first_name' => array(
								'label'       => __( 'First name', 'woocommerce' ),
								'description' => '',
							),
							'billing_last_name'  => array(
								'label'       => __( 'Last name', 'woocommerce' ),
								'description' => '',
							),
							'billing_company'    => array(
								'label'       => __( 'Company', 'woocommerce' ),
								'description' => '',
							),
							'billing_address_1'  => array(
								'label'       => __( 'Address line 1', 'woocommerce' ),
								'description' => '',
							),
							'billing_address_2'  => array(
								'label'       => __( 'Address line 2', 'woocommerce' ),
								'description' => '',
							),
							'billing_city'       => array(
								'label'       => __( 'City', 'woocommerce' ),
								'description' => '',
							),
							'billing_postcode'   => array(
								'label'       => __( 'Postcode / ZIP', 'woocommerce' ),
								'description' => '',
							),
							'billing_country'    => array(
								'label'       => __( 'Country / Region', 'woocommerce' ),
								'description' => '',
								'class'       => 'js_field-country',
								'type'        => 'select',
								'options'     => array( '' => __( 'Select a country / region&hellip;', 'woocommerce' ) ) + WC()->countries->get_allowed_countries(),
							),
							'billing_state'      => array(
								'label'       => __( 'State / County', 'woocommerce' ),
								'description' => __( 'State / County or state code', 'woocommerce' ),
								'class'       => 'js_field-state',
							),
							'billing_phone'      => array(
								'label'       => __( 'Phone', 'woocommerce' ),
								'description' => '',
							),
							'billing_email'      => array(
								'label'       => __( 'Email address', 'woocommerce' ),
								'description' => '',
							),
						),
					),
					'shipping' => array(
						'title'  => __( 'Customer shipping address', 'woocommerce' ),
						'fields' => array(
							'copy_billing'        => array(
								'label'       => __( 'Copy from billing address', 'woocommerce' ),
								'description' => '',
								'class'       => 'js_copy-billing',
								'type'        => 'button',
								'text'        => __( 'Copy', 'woocommerce' ),
							),
							'shipping_first_name' => array(
								'label'       => __( 'First name', 'woocommerce' ),
								'description' => '',
							),
							'shipping_last_name'  => array(
								'label'       => __( 'Last name', 'woocommerce' ),
								'description' => '',
							),
							'shipping_company'    => array(
								'label'       => __( 'Company', 'woocommerce' ),
								'description' => '',
							),
							'shipping_address_1'  => array(
								'label'       => __( 'Address line 1', 'woocommerce' ),
								'description' => '',
							),
							'shipping_address_2'  => array(
								'label'       => __( 'Address line 2', 'woocommerce' ),
								'description' => '',
							),
							'shipping_city'       => array(
								'label'       => __( 'City', 'woocommerce' ),
								'description' => '',
							),
							'shipping_postcode'   => array(
								'label'       => __( 'Postcode / ZIP', 'woocommerce' ),
								'description' => '',
							),
							'shipping_country'    => array(
								'label'       => __( 'Country / Region', 'woocommerce' ),
								'description' => '',
								'class'       => 'js_field-country',
								'type'        => 'select',
								'options'     => array( '' => __( 'Select a country / region&hellip;', 'woocommerce' ) ) + WC()->countries->get_allowed_countries(),
							),
							'shipping_state'      => array(
								'label'       => __( 'State / County', 'woocommerce' ),
								'description' => __( 'State / County or state code', 'woocommerce' ),
								'class'       => 'js_field-state',
							),
							'shipping_phone'      => array(
								'label'       => __( 'Phone', 'woocommerce' ),
								'description' => '',
							),
						),
					),
				)
			);
			return $show_fields;
		}

		/**
		 * Show Address Fields on edit user pages.
		 *
		 * @param WP_User $user
		 */
		public function add_customer_meta_fields( $user ) {
			if ( ! apply_filters( 'woocommerce_current_user_can_edit_customer_meta_fields', current_user_can( 'manage_woocommerce' ), $user->ID ) ) {
				return;
			}

			$show_fields = $this->get_customer_meta_fields();

			foreach ( $show_fields as $fieldset_key => $fieldset ) :
				?>
				<h2><?php echo $fieldset['title']; ?></h2>
				<table class="form-table" id="<?php echo esc_attr( 'fieldset-' . $fieldset_key ); ?>">
					<?php foreach ( $fieldset['fields'] as $key => $field ) : ?>
						<tr>
							<th>
								<label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ); ?></label>
							</th>
							<td>
								<?php if ( ! empty( $field['type'] ) && 'select' === $field['type'] ) : ?>
									<select name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" class="<?php echo isset( $field['class'] ) ? esc_attr( $field['class'] ) : ''; ?>" style="width: 25em;">
										<?php
											$selected = esc_attr( get_user_meta( $user->ID, $key, true ) );
										foreach ( $field['options'] as $option_key => $option_value ) :
											?>
											<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( $selected, $option_key, true ); ?>><?php echo esc_html( $option_value ); ?></option>
										<?php endforeach; ?>
									</select>
								<?php elseif ( ! empty( $field['type'] ) && 'checkbox' === $field['type'] ) : ?>
									<input type="checkbox" name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" value="1" class="<?php echo esc_attr( $field['class'] ); ?>" <?php checked( (int) get_user_meta( $user->ID, $key, true ), 1, true ); ?> />
								<?php elseif ( ! empty( $field['type'] ) && 'button' === $field['type'] ) : ?>
									<button type="button" id="<?php echo esc_attr( $key ); ?>" class="button <?php echo esc_attr( $field['class'] ); ?>"><?php echo esc_html( $field['text'] ); ?></button>
								<?php else : ?>
									<input type="text" name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" value="<?php echo esc_attr( $this->get_user_meta( $user->ID, $key ) ); ?>" class="<?php echo ( ! empty( $field['class'] ) ? esc_attr( $field['class'] ) : 'regular-text' ); ?>" />
								<?php endif; ?>
								<?php if ( ! empty( $field['description'] ) ) : ?>
									<p class="description"><?php echo wp_kses_post( $field['description'] ); ?></p>
								<?php endif; ?>
							</td>
						</tr>
					<?php endforeach; ?>
				</table>
				<?php
			endforeach;
		}

		/**
		 * Save Address Fields on edit user pages.
		 *
		 * @param int $user_id User ID of the user being saved
		 */
		public function save_customer_meta_fields( $user_id ) {
			if ( ! apply_filters( 'woocommerce_current_user_can_edit_customer_meta_fields', current_user_can( 'manage_woocommerce' ), $user_id ) ) {
				return;
			}

			$save_fields = $this->get_customer_meta_fields();

			foreach ( $save_fields as $fieldset_type => $fieldset ) {

				foreach ( $fieldset['fields'] as $key => $field ) {

					if ( isset( $field['type'] ) && 'checkbox' === $field['type'] ) {
						update_user_meta( $user_id, $key, isset( $_POST[ $key ] ) );
					} elseif ( isset( $_POST[ $key ] ) ) {
						update_user_meta( $user_id, $key, wc_clean( $_POST[ $key ] ) );
					}
				}

				// Skip firing the action for any non-internal fieldset types.
				if ( ! in_array( $fieldset_type, array( 'billing', 'shipping' ), true ) ) {
					continue;
				}

				// Fieldset type is an internal address type.
				$address_type = $fieldset_type;

				/**
				 * Hook: woocommerce_customer_save_address.
				 *
				 * Fires after a customer address has been saved on the user profile admin screen.
				 *
				 * @since 8.5.0
				 * @param int    $user_id User ID being saved.
				 * @param string $address_type Type of address; 'billing' or 'shipping'.
				 */
				do_action( 'woocommerce_customer_save_address', $user_id, $address_type );
			}
		}

		/**
		 * Get user meta for a given key, with fallbacks to core user info for pre-existing fields.
		 *
		 * @since 3.1.0
		 * @param int    $user_id User ID of the user being edited
		 * @param string $key     Key for user meta field
		 * @return string
		 */
		protected function get_user_meta( $user_id, $key ) {
			$value           = get_user_meta( $user_id, $key, true );
			$existing_fields = array( 'billing_first_name', 'billing_last_name' );
			if ( ! $value && in_array( $key, $existing_fields ) ) {
				$value = get_user_meta( $user_id, str_replace( 'billing_', '', $key ), true );
			} elseif ( ! $value && ( 'billing_email' === $key ) ) {
				$user  = get_userdata( $user_id );
				$value = $user->user_email;
			}

			return $value;
		}
	}

endif;

return new WC_Admin_Profile();
PK     tS\}k$  k$  %  class-wc-admin-permalink-settings.phpnu [        <?php
/**
 * Adds settings to the permalinks admin settings page
 *
 * @class       WC_Admin_Permalink_Settings
 * @package     WooCommerce\Admin
 * @version     2.3.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Admin_Permalink_Settings', false ) ) {
	return new WC_Admin_Permalink_Settings();
}

/**
 * WC_Admin_Permalink_Settings Class.
 */
class WC_Admin_Permalink_Settings {

	/**
	 * Permalink settings.
	 *
	 * @var array
	 */
	private $permalinks = array();

	/**
	 * Hook in tabs.
	 */
	public function __construct() {
		$this->settings_init();
		$this->settings_save();
	}

	/**
	 * Init our settings.
	 */
	public function settings_init() {
		add_settings_section( 'woocommerce-permalink', __( 'Product permalinks', 'woocommerce' ), array( $this, 'settings' ), 'permalink' );

		add_settings_field(
			'woocommerce_product_category_slug',
			__( 'Product category base', 'woocommerce' ),
			array( $this, 'product_category_slug_input' ),
			'permalink',
			'optional'
		);
		add_settings_field(
			'woocommerce_product_tag_slug',
			__( 'Product tag base', 'woocommerce' ),
			array( $this, 'product_tag_slug_input' ),
			'permalink',
			'optional'
		);
		add_settings_field(
			'woocommerce_product_attribute_slug',
			__( 'Product attribute base', 'woocommerce' ),
			array( $this, 'product_attribute_slug_input' ),
			'permalink',
			'optional'
		);

		$this->permalinks = wc_get_permalink_structure();
	}

	/**
	 * Show a slug input box.
	 */
	public function product_category_slug_input() {
		?>
		<input name="woocommerce_product_category_slug" type="text" class="regular-text code" value="<?php echo esc_attr( $this->permalinks['category_base'] ); ?>" placeholder="<?php echo esc_attr_x( 'product-category', 'slug', 'woocommerce' ); ?>" />
		<?php
	}

	/**
	 * Show a slug input box.
	 */
	public function product_tag_slug_input() {
		?>
		<input name="woocommerce_product_tag_slug" type="text" class="regular-text code" value="<?php echo esc_attr( $this->permalinks['tag_base'] ); ?>" placeholder="<?php echo esc_attr_x( 'product-tag', 'slug', 'woocommerce' ); ?>" />
		<?php
	}

	/**
	 * Show a slug input box.
	 */
	public function product_attribute_slug_input() {
		?>
		<input name="woocommerce_product_attribute_slug" type="text" class="regular-text code" value="<?php echo esc_attr( $this->permalinks['attribute_base'] ); ?>" /><code>/attribute-name/attribute/</code>
		<?php
	}

	/**
	 * Show the settings.
	 */
	public function settings() {
		/* translators: %s: Home URL */
		echo wp_kses_post( wpautop( sprintf( __( 'If you like, you may enter custom structures for your product URLs here. For example, using <code>shop</code> would make your product links like <code>%sshop/sample-product/</code>. This setting affects product URLs only, not things such as product categories.', 'woocommerce' ), esc_url( home_url( '/' ) ) ) ) );

		$shop_page_id = wc_get_page_id( 'shop' );
		$base_slug    = urldecode( ( $shop_page_id > 0 && get_post( $shop_page_id ) ) ? get_page_uri( $shop_page_id ) : _x( 'shop', 'default-slug', 'woocommerce' ) );
		$product_base = _x( 'product', 'default-slug', 'woocommerce' );

		$structures = array(
			0 => '',
			1 => '/' . trailingslashit( $base_slug ),
			2 => '/' . trailingslashit( $base_slug ) . trailingslashit( '%product_cat%' ),
		);
		?>
		<table class="form-table wc-permalink-structure">
			<tbody>
				<tr>
					<th><label><input name="product_permalink" type="radio" value="<?php echo esc_attr( $structures[0] ); ?>" class="wctog" <?php checked( $structures[0], $this->permalinks['product_base'] ); ?> /> <?php esc_html_e( 'Default', 'woocommerce' ); ?></label></th>
					<td><code class="default-example"><?php echo esc_html( home_url() ); ?>/?product=sample-product</code> <code class="non-default-example"><?php echo esc_html( home_url() ); ?>/<?php echo esc_html( $product_base ); ?>/sample-product/</code></td>
				</tr>
				<?php if ( $shop_page_id ) : ?>
					<tr>
						<th><label><input name="product_permalink" type="radio" value="<?php echo esc_attr( $structures[1] ); ?>" class="wctog" <?php checked( $structures[1], $this->permalinks['product_base'] ); ?> /> <?php esc_html_e( 'Shop base', 'woocommerce' ); ?></label></th>
						<td><code><?php echo esc_html( home_url() ); ?>/<?php echo esc_html( $base_slug ); ?>/sample-product/</code></td>
					</tr>
					<tr>
						<th><label><input name="product_permalink" type="radio" value="<?php echo esc_attr( $structures[2] ); ?>" class="wctog" <?php checked( $structures[2], $this->permalinks['product_base'] ); ?> /> <?php esc_html_e( 'Shop base with category', 'woocommerce' ); ?></label></th>
						<td><code><?php echo esc_html( home_url() ); ?>/<?php echo esc_html( $base_slug ); ?>/product-category/sample-product/</code></td>
					</tr>
				<?php endif; ?>
				<tr>
					<th><label><input name="product_permalink" id="woocommerce_custom_selection" type="radio" value="custom" class="tog" <?php checked( in_array( $this->permalinks['product_base'], $structures, true ), false ); ?> />
						<?php esc_html_e( 'Custom base', 'woocommerce' ); ?></label></th>
					<td>
						<input name="product_permalink_structure" id="woocommerce_permalink_structure" type="text" value="<?php echo esc_attr( $this->permalinks['product_base'] ? trailingslashit( $this->permalinks['product_base'] ) : '' ); ?>" class="regular-text code"> <span class="description"><?php esc_html_e( 'Enter a custom base to use. A base must be set or WordPress will use default instead.', 'woocommerce' ); ?></span>
					</td>
				</tr>
			</tbody>
		</table>
		<?php wp_nonce_field( 'wc-permalinks', 'wc-permalinks-nonce' ); ?>
		<script type="text/javascript">
			jQuery( function() {
				jQuery('input.wctog').on( 'change', function() {
					jQuery('#woocommerce_permalink_structure').val( jQuery( this ).val() );
				});
				jQuery('.permalink-structure input').on( 'change', function() {
					jQuery('.wc-permalink-structure').find('code.non-default-example, code.default-example').hide();
					if ( jQuery(this).val() ) {
						jQuery('.wc-permalink-structure code.non-default-example').show();
						jQuery('.wc-permalink-structure input').prop('disabled', false);
					} else {
						jQuery('.wc-permalink-structure code.default-example').show();
						jQuery('.wc-permalink-structure input:eq(0)').trigger( 'click' );
						jQuery('.wc-permalink-structure input').attr('disabled', 'disabled');
					}
				});
				jQuery('.permalink-structure input:checked').trigger( 'change' );
				jQuery('#woocommerce_permalink_structure').on( 'focus', function(){
					jQuery('#woocommerce_custom_selection').trigger( 'click' );
				} );
			} );
		</script>
		<?php
	}

	/**
	 * Save the settings.
	 */
	public function settings_save() {
		if ( ! is_admin() ) {
			return;
		}

		// We need to save the options ourselves; settings api does not trigger save for the permalinks page.
		if ( isset( $_POST['permalink_structure'], $_POST['wc-permalinks-nonce'], $_POST['woocommerce_product_category_slug'], $_POST['woocommerce_product_tag_slug'], $_POST['woocommerce_product_attribute_slug'] ) && wp_verify_nonce( wp_unslash( $_POST['wc-permalinks-nonce'] ), 'wc-permalinks' ) ) { // WPCS: input var ok, sanitization ok.
			wc_switch_to_site_locale();

			$permalinks                   = (array) get_option( 'woocommerce_permalinks', array() );
			$permalinks['category_base']  = wc_sanitize_permalink( wp_unslash( $_POST['woocommerce_product_category_slug'] ) ); // WPCS: input var ok, sanitization ok.
			$permalinks['tag_base']       = wc_sanitize_permalink( wp_unslash( $_POST['woocommerce_product_tag_slug'] ) ); // WPCS: input var ok, sanitization ok.
			$permalinks['attribute_base'] = wc_sanitize_permalink( wp_unslash( $_POST['woocommerce_product_attribute_slug'] ) ); // WPCS: input var ok, sanitization ok.

			// Generate product base.
			$product_base = isset( $_POST['product_permalink'] ) ? wc_clean( wp_unslash( $_POST['product_permalink'] ) ) : ''; // WPCS: input var ok, sanitization ok.

			if ( 'custom' === $product_base ) {
				if ( isset( $_POST['product_permalink_structure'] ) ) { // WPCS: input var ok.
					$product_base = preg_replace( '#/+#', '/', '/' . str_replace( '#', '', trim( wp_unslash( $_POST['product_permalink_structure'] ) ) ) ); // WPCS: input var ok, sanitization ok.
				} else {
					$product_base = '/';
				}

				// This is an invalid base structure and breaks pages.
				if ( '/%product_cat%/' === trailingslashit( $product_base ) ) {
					$product_base = '/' . _x( 'product', 'slug', 'woocommerce' ) . $product_base;
				}
			} elseif ( empty( $product_base ) ) {
				$product_base = _x( 'product', 'slug', 'woocommerce' );
			}

			$permalinks['product_base'] = wc_sanitize_permalink( $product_base );

			// Shop base may require verbose page rules if nesting pages.
			$shop_page_id   = wc_get_page_id( 'shop' );
			$shop_permalink = ( $shop_page_id > 0 && get_post( $shop_page_id ) ) ? get_page_uri( $shop_page_id ) : _x( 'shop', 'default-slug', 'woocommerce' );

			if ( $shop_page_id && stristr( trim( $permalinks['product_base'], '/' ), $shop_permalink ) ) {
				$permalinks['use_verbose_page_rules'] = true;
			}

			update_option( 'woocommerce_permalinks', $permalinks );
			wc_restore_locale();
		}
	}
}

return new WC_Admin_Permalink_Settings();
PK     tS\Jj*3N  3N    class-wc-admin-menus.phpnu [        <?php
/**
 * Setup menus in WP admin.
 *
 * @package WooCommerce\Admin
 * @version 2.5.0
 */

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Internal\Admin\Marketplace;
use Automattic\WooCommerce\Internal\Admin\Orders\COTRedirectionController;
use Automattic\WooCommerce\Internal\Admin\Orders\PageController as Custom_Orders_PageController;
use Automattic\WooCommerce\Internal\Admin\Logging\PageController as LoggingPageController;
use Automattic\WooCommerce\Internal\Admin\Logging\FileV2\{ FileListTable, SearchListTable };
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
use Automattic\WooCommerce\Utilities\FeaturesUtil;

defined( 'ABSPATH' ) || exit;

if ( class_exists( 'WC_Admin_Menus', false ) ) {
	return new WC_Admin_Menus();
}

/**
 * WC_Admin_Menus Class.
 */
class WC_Admin_Menus {

	/**
	 * The CSS classes used to hide the submenu items in navigation.
	 *
	 * @var string
	 */
	const HIDE_CSS_CLASS = 'hide-if-js';

	/**
	 * Hook in tabs.
	 */
	public function __construct() {
		// Add menus.
		add_action( 'admin_menu', array( $this, 'menu_highlight' ) );
		add_action( 'admin_menu', array( $this, 'menu_order_count' ) );
		add_action( 'admin_menu', array( $this, 'maybe_add_new_product_management_experience' ) );
		add_action( 'admin_menu', array( $this, 'admin_menu' ), 9 );
		add_action( 'admin_menu', array( $this, 'orders_menu' ), 9 );
		add_action( 'admin_menu', array( $this, 'reports_menu' ), 20 );
		add_action( 'admin_menu', array( $this, 'settings_menu' ), 50 );
		add_action( 'admin_menu', array( $this, 'status_menu' ), 60 );

		/**
		 * Controls whether we add a submenu item for the WooCommerce Addons page.
		 * Woo Express uses this filter.
		 *
		 * @since 8.2.1
		 *
		 * @param bool $show_addons_page If the addons page should be included.
		 */
		if ( apply_filters( 'woocommerce_show_addons_page', true ) ) {
			$container = wc_get_container();
			$container->get( Marketplace::class );

			add_action( 'admin_menu', array( $this, 'addons_my_subscriptions' ), 70 );
		}

		add_filter( 'menu_order', array( $this, 'menu_order' ) );
		add_filter( 'custom_menu_order', array( $this, 'custom_menu_order' ) );
		add_filter( 'set-screen-option', array( $this, 'set_screen_option' ), 10, 3 );

		// Add endpoints custom URLs in Appearance > Menus > Pages.
		add_action( 'admin_head-nav-menus.php', array( $this, 'add_nav_menu_meta_boxes' ) );

		// Admin bar menus.
		if ( apply_filters( 'woocommerce_show_admin_bar_visit_store', true ) ) {
			add_action( 'admin_bar_menu', array( $this, 'admin_bar_menus' ), 31 );
		}

		// Handle saving settings earlier than load-{page} hook to avoid race conditions in conditional menus.
		add_action( 'wp_loaded', array( $this, 'save_settings' ) );
	}

	/**
	 * Add menu items.
	 *
	 * @return void
	 */
	public function admin_menu() {
		global $menu, $admin_page_hooks;

		$woocommerce_icon = 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDg1LjkgNDcuNiI+CjxwYXRoIGZpbGw9IiNhMmFhYjIiIGQ9Ik03Ny40LDAuMWMtNC4zLDAtNy4xLDEuNC05LjYsNi4xTDU2LjQsMjcuN1Y4LjZjMC01LjctMi43LTguNS03LjctOC41cy03LjEsMS43LTkuNiw2LjVMMjguMywyNy43VjguOAoJYzAtNi4xLTIuNS04LjctOC42LTguN0g3LjNDMi42LDAuMSwwLDIuMywwLDYuM3MyLjUsNi40LDcuMSw2LjRoNS4xdjI0LjFjMCw2LjgsNC42LDEwLjgsMTEuMiwxMC44UzMzLDQ1LDM2LjMsMzguOWw3LjItMTMuNXYxMS40CgljMCw2LjcsNC40LDEwLjgsMTEuMSwxMC44czkuMi0yLjMsMTMtOC43bDE2LjYtMjhjMy42LTYuMSwxLjEtMTAuOC02LjktMTAuOEM3Ny4zLDAuMSw3Ny4zLDAuMSw3Ny40LDAuMXoiLz4KPC9zdmc+Cg==';

		if ( self::can_view_woocommerce_menu_item() ) {
			$menu[] = array( '', 'read', 'separator-woocommerce', '', 'wp-menu-separator woocommerce' ); // WPCS: override ok.
		}

		add_menu_page( __( 'WooCommerce', 'woocommerce' ), __( 'WooCommerce', 'woocommerce' ), 'edit_others_shop_orders', 'woocommerce', null, $woocommerce_icon, '55.5' );

		// Work around https://github.com/woocommerce/woocommerce/issues/35677 (and related https://core.trac.wordpress.org/ticket/18857).
		// Translating the menu item breaks screen IDs and page hooks, so we force the hookname to be untranslated.
		$admin_page_hooks['woocommerce'] = 'woocommerce'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited

		add_submenu_page( 'edit.php?post_type=product', __( 'Attributes', 'woocommerce' ), __( 'Attributes', 'woocommerce' ), 'manage_product_terms', 'product_attributes', array( $this, 'attributes_page' ) );
	}

	/**
	 * Add menu item.
	 *
	 * @return void
	 */
	public function reports_menu() {
		if ( self::can_view_woocommerce_menu_item() ) {
			add_submenu_page( 'woocommerce', __( 'Reports', 'woocommerce' ), __( 'Reports', 'woocommerce' ), 'view_woocommerce_reports', 'wc-reports', array( $this, 'reports_page' ) );
		} else {
			add_menu_page( __( 'Sales reports', 'woocommerce' ), __( 'Sales reports', 'woocommerce' ), 'view_woocommerce_reports', 'wc-reports', array( $this, 'reports_page' ), 'dashicons-chart-bar', '55.6' );
		}
	}

	/**
	 * Add menu item.
	 *
	 * @return void
	 */
	public function settings_menu() {
		$settings_page = add_submenu_page(
			'woocommerce',
			__( 'WooCommerce settings', 'woocommerce' ),
			__( 'Settings', 'woocommerce' ),
			'manage_woocommerce',
			'wc-settings',
			array( $this, 'settings_page' )
		);

		add_action( 'load-' . $settings_page, array( $this, 'settings_page_init' ) );
	}

	/**
	 * Check if the user can access the top-level WooCommerce item.
	 *
	 * @return bool
	 */
	public static function can_view_woocommerce_menu_item() {
		return current_user_can( 'edit_others_shop_orders' );
	}

	/**
	 * Loads gateways and shipping methods into memory for use within settings.
	 *
	 * @return void
	 */
	public function settings_page_init() {
		WC()->payment_gateways();
		WC()->shipping();

		// Include settings pages.
		WC_Admin_Settings::get_settings_pages();

		// Add any posted messages.
		if ( ! empty( $_GET['wc_error'] ) ) { // WPCS: input var okay, CSRF ok.
			WC_Admin_Settings::add_error( wp_kses_post( wp_unslash( $_GET['wc_error'] ) ) ); // WPCS: input var okay, CSRF ok.
		}

		if ( ! empty( $_GET['wc_message'] ) ) { // WPCS: input var okay, CSRF ok.
			WC_Admin_Settings::add_message( wp_kses_post( wp_unslash( $_GET['wc_message'] ) ) ); // WPCS: input var okay, CSRF ok.
		}

		do_action( 'woocommerce_settings_page_init' );
	}

	/**
	 * Handle saving of settings.
	 *
	 * @return void
	 */
	public function save_settings() {
		global $current_tab, $current_section;

		// We should only save on the settings page.
		if ( ! is_wc_admin_settings_page() ) {
			return;
		}

		// Include settings pages.
		WC_Admin_Settings::get_settings_pages();

		// Get current tab/section.
		$current_tab     = empty( $_GET['tab'] ) ? 'general' : sanitize_title( wp_unslash( $_GET['tab'] ) ); // WPCS: input var okay, CSRF ok.
		$current_section = empty( $_REQUEST['section'] ) ? '' : sanitize_title( wp_unslash( $_REQUEST['section'] ) ); // WPCS: input var okay, CSRF ok.

		// Save settings if data has been posted.
		if ( '' !== $current_section && apply_filters( "woocommerce_save_settings_{$current_tab}_{$current_section}", ! empty( $_POST['save'] ) ) ) { // WPCS: input var okay, CSRF ok.
			WC_Admin_Settings::save();
		} elseif ( '' === $current_section && apply_filters( "woocommerce_save_settings_{$current_tab}", ! empty( $_POST['save'] ) ) ) { // WPCS: input var okay, CSRF ok.
			WC_Admin_Settings::save();
		}
	}

	/**
	 * Add menu item.
	 *
	 * @return void
	 */
	public function status_menu() {
		$status_page = add_submenu_page( 'woocommerce', __( 'WooCommerce status', 'woocommerce' ), __( 'Status', 'woocommerce' ), 'manage_woocommerce', 'wc-status', array( $this, 'status_page' ) );

		add_action(
			'load-' . $status_page,
			function () {
				if ( 'logs' === filter_input( INPUT_GET, 'tab' ) ) {
					// Initialize the logging page controller early so that it can hook into things.
					wc_get_container()->get( LoggingPageController::class );
				}
			},
			1
		);
	}

	/**
	 * Addons menu item.
	 *
	 * @deprecated 10.5.0 The marketplace feature is now always enabled. Use the Extensions menu instead.
	 *
	 * @return void
	 */
	public function addons_menu() {
		wc_deprecated_function( __METHOD__, '10.5.0' );

		$count_html = WC_Helper_Updater::get_updates_count_html();
		/* translators: %s: extensions count */
		$menu_title = sprintf( __( 'Extensions %s', 'woocommerce' ), $count_html );
		add_submenu_page( 'woocommerce', __( 'WooCommerce extensions', 'woocommerce' ), $menu_title, 'manage_woocommerce', 'wc-addons', array( $this, 'addons_page' ) );
	}

	/**
	 * Registers the wc-addons page within the WooCommerce menu.
	 * Temporary measure till we convert the whole page to React.
	 *
	 * @return void
	 */
	public function addons_my_subscriptions() {
		add_submenu_page( 'woocommerce', __( 'WooCommerce extensions', 'woocommerce' ), null, 'manage_woocommerce', 'wc-addons', array( $this, 'addons_page' ) );
		// Temporarily hide the submenu item we've just added.
		$this->hide_submenu_page( 'woocommerce', 'wc-addons' );
	}

	/**
	 * Highlights the correct top level admin menu item for post type add screens.
	 *
	 * @return void
	 */
	public function menu_highlight() {
		global $parent_file, $submenu_file, $post_type;

		switch ( $post_type ) {
			case 'shop_order':
			case 'shop_coupon':
				$parent_file = 'woocommerce'; // WPCS: override ok.
				break;
			case 'product':
				$screen = get_current_screen();
				if ( $screen && taxonomy_is_product_attribute( $screen->taxonomy ) ) {
					$submenu_file = 'product_attributes'; // WPCS: override ok.
					$parent_file  = 'edit.php?post_type=product'; // WPCS: override ok.
				}
				break;
		}
	}

	/**
	 * Adds the order processing count to the menu.
	 *
	 * @return void
	 */
	public function menu_order_count() {
		global $submenu;

		if ( isset( $submenu['woocommerce'] ) ) {
			// Remove 'WooCommerce' sub menu item.
			unset( $submenu['woocommerce'][0] );

			// Add count if user has access.
			if ( apply_filters( 'woocommerce_include_processing_order_count_in_menu', true ) && current_user_can( 'edit_others_shop_orders' ) ) {
				$order_count = apply_filters( 'woocommerce_menu_order_count', wc_processing_order_count() );

				if ( $order_count ) {
					foreach ( $submenu['woocommerce'] as $key => $menu_item ) {
						if ( 0 === strpos( $menu_item[0], _x( 'Orders', 'Admin menu name', 'woocommerce' ) ) ) {
							$submenu['woocommerce'][ $key ][0] .= ' <span class="menu-counter count-' . esc_attr( $order_count ) . '"><span class="processing-count">' . number_format_i18n( $order_count ) . '</span></span>'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
							break;
						}
					}
				}
			}
		}
	}

	/**
	 * Reorder the WC menu items in admin.
	 *
	 * @param int $menu_order Menu order.
	 * @return array
	 */
	public function menu_order( $menu_order ) {
		// Initialize our custom order array.
		$woocommerce_menu_order = array();

		// Get the index of our custom separator.
		$woocommerce_separator = array_search( 'separator-woocommerce', $menu_order, true );

		// Get index of product menu.
		$woocommerce_product = array_search( 'edit.php?post_type=product', $menu_order, true );

		// Loop through menu order and do some rearranging.
		foreach ( $menu_order as $index => $item ) {

			if ( 'woocommerce' === $item ) {
				$woocommerce_menu_order[] = 'separator-woocommerce';
				$woocommerce_menu_order[] = $item;
				$woocommerce_menu_order[] = 'edit.php?post_type=product';
				unset( $menu_order[ $woocommerce_separator ] );
				unset( $menu_order[ $woocommerce_product ] );
			} elseif ( ! in_array( $item, array( 'separator-woocommerce' ), true ) ) {
				$woocommerce_menu_order[] = $item;
			}
		}

		// Return order.
		return $woocommerce_menu_order;
	}

	/**
	 * Custom menu order.
	 *
	 * @param bool $enabled Whether custom menu ordering is already enabled.
	 * @return bool
	 */
	public function custom_menu_order( $enabled ) {
		return $enabled || self::can_view_woocommerce_menu_item();
	}

	/**
	 * Validate screen options on update.
	 *
	 * @param bool|int $status Screen option value. Default false to skip.
	 * @param string   $option The option name.
	 * @param int      $value  The number of rows to use.
	 * @return bool|int
	 */
	public function set_screen_option( $status, $option, $value ) {
		$screen_options = array(
			'woocommerce_keys_per_page',
			'woocommerce_webhooks_per_page',
			FileListTable::PER_PAGE_USER_OPTION_KEY,
			SearchListTable::PER_PAGE_USER_OPTION_KEY,
			WC_Admin_Log_Table_List::PER_PAGE_USER_OPTION_KEY,
		);

		if ( in_array( $option, $screen_options, true ) ) {
			return $value;
		}

		return $status;
	}

	/**
	 * Init the reports page.
	 *
	 * @return void
	 */
	public function reports_page() {
		WC_Admin_Reports::output();
	}

	/**
	 * Init the settings page.
	 *
	 * @return void
	 */
	public function settings_page() {
		if ( Features::is_enabled( 'settings' ) ) {
			echo '<div id="wc-settings-page"/>';
		} else {
			WC_Admin_Settings::output();
		}
	}

	/**
	 * Init the attributes page.
	 *
	 * @return void
	 */
	public function attributes_page() {
		WC_Admin_Attributes::output();
	}

	/**
	 * Init the status page.
	 *
	 * @return void
	 */
	public function status_page() {
		WC_Admin_Status::output();
	}

	/**
	 * Init the addons page.
	 *
	 * @return void
	 */
	public function addons_page() {
		WC_Admin_Addons::handle_legacy_marketplace_redirects();
	}

	/**
	 * Link to the order admin list table from the main WooCommerce menu.
	 *
	 * @return void
	 */
	public function orders_menu(): void {
		if ( wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() ) {
			wc_get_container()->get( Custom_Orders_PageController::class )->setup();
		} else {
			wc_get_container()->get( COTRedirectionController::class )->setup();
		}
	}

	/**
	 * Add custom nav meta box.
	 *
	 * Adapted from http://www.johnmorrisonline.com/how-to-add-a-fully-functional-custom-meta-box-to-wordpress-navigation-menus/.
	 *
	 * @return void
	 */
	public function add_nav_menu_meta_boxes() {
		add_meta_box( 'woocommerce_endpoints_nav_link', __( 'WooCommerce endpoints', 'woocommerce' ), array( $this, 'nav_menu_links' ), 'nav-menus', 'side', 'low' );
	}

	/**
	 * Output menu links.
	 *
	 * @return void
	 */
	public function nav_menu_links() {
		// Get items from account menu.
		$endpoints = wc_get_account_menu_items();

		// Remove dashboard item.
		if ( isset( $endpoints['dashboard'] ) ) {
			unset( $endpoints['dashboard'] );
		}

		// Include missing lost password endpoint, if set in WooCommerce > Settings > Advanced > Account endpoints.
		if ( ! empty( get_option( 'woocommerce_myaccount_lost_password_endpoint' ) ) ) {
			$endpoints['lost-password'] = __( 'Lost password', 'woocommerce' );
		}

		$endpoints = apply_filters( 'woocommerce_custom_nav_menu_items', $endpoints );

		?>
		<div id="posttype-woocommerce-endpoints" class="posttypediv">
			<div id="tabs-panel-woocommerce-endpoints" class="tabs-panel tabs-panel-active">
				<ul id="woocommerce-endpoints-checklist" class="categorychecklist form-no-clear">
					<?php
					$i = -1;
					foreach ( $endpoints as $key => $value ) :
						?>
						<li>
							<label class="menu-item-title">
								<input type="checkbox" class="menu-item-checkbox" name="menu-item[<?php echo esc_attr( $i ); ?>][menu-item-object-id]" value="<?php echo esc_attr( $i ); ?>" /> <?php echo esc_html( $value ); ?>
							</label>
							<input type="hidden" class="menu-item-type" name="menu-item[<?php echo esc_attr( $i ); ?>][menu-item-type]" value="custom" />
							<input type="hidden" class="menu-item-title" name="menu-item[<?php echo esc_attr( $i ); ?>][menu-item-title]" value="<?php echo esc_attr( $value ); ?>" />
							<input type="hidden" class="menu-item-url" name="menu-item[<?php echo esc_attr( $i ); ?>][menu-item-url]" value="<?php echo esc_url( wc_get_account_endpoint_url( $key ) ); ?>" />
							<input type="hidden" class="menu-item-classes" name="menu-item[<?php echo esc_attr( $i ); ?>][menu-item-classes]" />
						</li>
						<?php
						--$i;
					endforeach;
					?>
				</ul>
			</div>
			<p class="button-controls" data-items-type="posttype-woocommerce-endpoints">
				<span class="list-controls">
					<label>
						<input type="checkbox" class="select-all" />
						<?php esc_html_e( 'Select all', 'woocommerce' ); ?>
					</label>
				</span>
				<span class="add-to-menu">
					<button type="submit" class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e( 'Add to menu', 'woocommerce' ); ?>" name="add-post-type-menu-item" id="submit-posttype-woocommerce-endpoints"><?php esc_html_e( 'Add to menu', 'woocommerce' ); ?></button>
					<span class="spinner"></span>
				</span>
			</p>
		</div>
		<?php
	}

	/**
	 * Add the "Visit Store" link in admin bar main menu.
	 *
	 * @since 2.4.0
	 * @param WP_Admin_Bar $wp_admin_bar Admin bar instance.
	 * @return void
	 */
	public function admin_bar_menus( $wp_admin_bar ) {
		if ( ! is_admin() || ! is_admin_bar_showing() ) {
			return;
		}

		// Show only when the user is a member of this site, or they're a super admin.
		if ( ! is_user_member_of_blog() && ! is_super_admin() ) {
			return;
		}

		// Don't display when shop page is the same of the page on front.
		if ( intval( get_option( 'page_on_front' ) ) === wc_get_page_id( 'shop' ) ) {
			return;
		}

		// Add an option to visit the store.
		$wp_admin_bar->add_node(
			array(
				'parent' => 'site-name',
				'id'     => 'view-store',
				'title'  => __( 'Visit Store', 'woocommerce' ),
				'href'   => wc_get_page_permalink( 'shop' ),
			)
		);
	}

	/**
	 * Maybe add new management product experience.
	 *
	 * @return void
	 */
	public function maybe_add_new_product_management_experience() {
		if ( FeaturesUtil::feature_is_enabled( 'product_block_editor' ) ) {
			global $submenu;
			if ( isset( $submenu['edit.php?post_type=product'][10] ) ) {
				// Disable phpcs since we need to override submenu classes.
				// Note that `phpcs:ignore WordPress.Variables.GlobalVariables.OverrideProhibited` does not work to disable this check.
				// phpcs:disable
				$submenu['edit.php?post_type=product'][10][2] = 'admin.php?page=wc-admin&path=/add-product';
				// phps:enableWordPress.Variables.GlobalVariables.OverrideProhibited
			}
		}
	}

	/**
	 * Hide the submenu page based on slug and return the item that was hidden.
	 *
	 * Borrowed from Jetpack's Base_Admin_Menu class.
	 *
	 * Instead of actually removing the submenu item, a safer approach is to hide it and filter it in the API response.
	 * In this manner we'll avoid breaking third-party plugins depending on items that no longer exist.
	 *
	 * A false|array value is returned to be consistent with remove_submenu_page() function
	 *
	 * @param string $menu_slug The parent menu slug.
	 * @param string $submenu_slug The submenu slug that should be hidden.
	 * @return false|array
	 */
	public function hide_submenu_page( $menu_slug, $submenu_slug ) {
		global $submenu;

		if ( ! isset( $submenu[ $menu_slug ] ) ) {
			return false;
		}

		foreach ( $submenu[ $menu_slug ] as $i => $item ) {
			if ( $submenu_slug !== $item[2] ) {
				continue;
			}

			$this->hide_submenu_element( $i, $menu_slug, $item );

			return $item;
		}

		return false;
	}

	/**
	 * Apply the hide-if-js CSS class to a submenu item.
	 *
	 * Borrowed from Jetpack's Base_Admin_Menu class.
	 *
	 * @param int    $index The position of a submenu item in the submenu array.
	 * @param string $parent_slug The parent slug.
	 * @param array  $item The submenu item.
	 * @return void
	 */
	public function hide_submenu_element( $index, $parent_slug, $item ) {
		global $submenu;

		$css_classes = empty( $item[4] ) ? self::HIDE_CSS_CLASS : $item[4] . ' ' . self::HIDE_CSS_CLASS;

		// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
		$submenu [ $parent_slug ][ $index ][4] = $css_classes;
	}
}

return new WC_Admin_Menus();
PK     tS\#j  j    class-wc-admin-brands.phpnu [        <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName.
/**
 * Brands Admin Page
 *
 * Important: For internal use only by the Automattic\WooCommerce\Internal\Brands package.
 *
 * @package WooCommerce\Admin
 * @version x.x.x
 */

declare( strict_types = 1);

use Automattic\Jetpack\Constants;

/**
 * WC_Brands_Admin class.
 */
class WC_Brands_Admin {

	/**
	 * Settings array (Deprecated).
	 *
	 * @var array
	 */
	public $settings_tabs;

	/**
	 * Settings form fields (Deprecated).
	 *
	 * @var array
	 */
	private $settings;

	/**
	 * Admin fields.
	 *
	 * @var array
	 */
	public $fields = array();

	/**
	 * __construct function.
	 */
	public function __construct() {

		add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'styles' ) );
		add_action( 'product_brand_add_form_fields', array( $this, 'add_thumbnail_field' ) );
		add_action( 'product_brand_edit_form_fields', array( $this, 'edit_thumbnail_field' ), 10, 1 );
		add_action( 'created_term', array( $this, 'thumbnail_field_save' ), 10, 1 );
		add_action( 'edit_term', array( $this, 'thumbnail_field_save' ), 10, 1 );
		add_action( 'product_brand_pre_add_form', array( $this, 'taxonomy_description' ) );
		add_filter( 'woocommerce_sortable_taxonomies', array( $this, 'sort_brands' ) );
		add_filter( 'manage_edit-product_brand_columns', array( $this, 'columns' ) );
		add_filter( 'manage_product_brand_custom_column', array( $this, 'column' ), 10, 3 );
		add_filter( 'manage_product_posts_columns', array( $this, 'product_columns' ), 20, 1 );
		add_filter(
			'woocommerce_products_admin_list_table_filters',
			function ( $args ) {
				$args['product_brand'] = array( $this, 'render_product_brand_filter' );
				return $args;
			}
		);

		// Hiding setting for future deprecation. Only users who have touched these settings should see it.
		$setting_value = get_option( 'wc_brands_show_description' );
		if ( is_string( $setting_value ) ) {

			// Add the settings fields to each tab.
			add_action(
				'before_woocommerce_init',
				function () {
					$this->init_form_fields();
					$this->settings_tabs = array(
						'brands' => __( 'Brands', 'woocommerce' ),
					);
				}
			);
			add_action( 'woocommerce_get_sections_products', array( $this, 'add_settings_tab' ) );
			add_action( 'woocommerce_get_settings_products', array( $this, 'add_settings_section' ), null, 2 );
		}

		add_action( 'woocommerce_update_options_catalog', array( $this, 'save_admin_settings' ) );

		/* 2.1 */
		add_action( 'woocommerce_update_options_products', array( $this, 'save_admin_settings' ) );

		// Add brands filtering to the coupon creation screens.
		add_action( 'woocommerce_coupon_options_usage_restriction', array( $this, 'add_coupon_brands_fields' ) );
		add_action( 'woocommerce_coupon_options_save', array( $this, 'save_coupon_brands' ) );

		// Permalinks.
		add_filter( 'pre_update_option_woocommerce_permalinks', array( $this, 'validate_product_base' ) );

		add_action( 'current_screen', array( $this, 'add_brand_base_setting' ) );

		// CSV Import/Export Support.
		// https://woocommerce.com/document/product-csv-importer-exporter/
		// Import.
		add_filter( 'woocommerce_csv_product_import_mapping_options', array( $this, 'add_column_to_importer_exporter' ), 10 );
		add_filter( 'woocommerce_csv_product_import_mapping_default_columns', array( $this, 'add_default_column_mapping' ), 10 );
		add_filter( 'woocommerce_product_importer_formatting_callbacks', array( $this, 'add_formatting_callback' ), 10, 2 );
		add_filter( 'woocommerce_product_import_inserted_product_object', array( $this, 'process_import' ), 10, 2 );

		// Export.
		add_filter( 'woocommerce_product_export_column_names', array( $this, 'add_column_to_importer_exporter' ), 10 );
		add_filter( 'woocommerce_product_export_product_default_columns', array( $this, 'add_column_to_importer_exporter' ), 10 );
		add_filter( 'woocommerce_product_export_product_column_brand_ids', array( $this, 'get_column_value_brand_ids' ), 10, 2 );
	}

	/**
	 * Add the settings for the new "Brands" subtab.
	 *
	 * @since  9.4.0
	 *
	 * @param array $settings Settings.
	 * @param array $current_section Current section.
	 */
	public function add_settings_section( $settings, $current_section ) {
		if ( 'brands' === $current_section ) {
			$settings = $this->settings;
		}
		return $settings;
	}

	/**
	 * Add a new "Brands" subtab to the "Products" tab.
	 *
	 * @since  9.4.0
	 * @param array $sections Sections.
	 */
	public function add_settings_tab( $sections ) {
		$sections = array_merge( $sections, $this->settings_tabs );
		return $sections;
	}

	/**
	 * Display coupon filter fields relating to brands.
	 *
	 * @since  9.4.0
	 * @return  void
	 */
	public function add_coupon_brands_fields() {
		global $post;
		// Brands.
		?>
		<div class="options_group"><div class="hr-section hr-section-coupon_restrictions"><?php echo esc_html__( 'And', 'woocommerce' ); ?></div>
		<p class="form-field"><label for="product_brands"><?php esc_html_e( 'Product brands', 'woocommerce' ); ?></label>
			<select id="product_brands" name="product_brands[]" style="width: 50%;"  class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'Any brand', 'woocommerce' ); ?>">
				<?php
				$category_ids = (array) get_post_meta( $post->ID, 'product_brands', true );
				$categories   = get_terms(
					array(
						'taxonomy'   => 'product_brand',
						'orderby'    => 'name',
						'hide_empty' => false,
					)
				);

				if ( $categories ) {
					foreach ( $categories as $cat ) {
						echo '<option value="' . esc_attr( $cat->term_id ) . '"' . selected( in_array( $cat->term_id, $category_ids, true ), true, false ) . '>' . esc_html( $cat->name ) . '</option>';
					}
				}
				?>
			</select>
			<?php
				echo wc_help_tip( esc_html__( 'A product must be associated with this brand for the coupon to remain valid or, for "Product Discounts", products with these brands will be discounted.', 'woocommerce' ) );
				// Exclude Brands.
			?>
		<p class="form-field"><label for="exclude_product_brands"><?php esc_html_e( 'Exclude brands', 'woocommerce' ); ?></label>
			<select id="exclude_product_brands" name="exclude_product_brands[]" style="width: 50%;"  class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No brands', 'woocommerce' ); ?>">
				<?php
				$category_ids = (array) get_post_meta( $post->ID, 'exclude_product_brands', true );
				$categories   = get_terms(
					array(
						'taxonomy'   => 'product_brand',
						'orderby'    => 'name',
						'hide_empty' => false,
					)
				);

				if ( $categories ) {
					foreach ( $categories as $cat ) {
						echo '<option value="' . esc_attr( $cat->term_id ) . '"' . selected( in_array( $cat->term_id, $category_ids, true ), true, false ) . '>' . esc_html( $cat->name ) . '</option>';
					}
				}
				?>
			</select>
			<?php
				echo wc_help_tip( esc_html__( 'Product must not be associated with these brands for the coupon to remain valid or, for "Product Discounts", products associated with these brands will not be discounted.', 'woocommerce' ) );
			?>
		</div>
		<?php
	}

	/**
	 * Save coupon filter fields relating to brands.
	 *
	 * @since  9.4.0
	 * @param int $post_id Post ID.
	 * @return  void
	 */
	public function save_coupon_brands( $post_id ) {
		$product_brands         = isset( $_POST['product_brands'] ) ? array_map( 'intval', $_POST['product_brands'] ) : array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
		$exclude_product_brands = isset( $_POST['exclude_product_brands'] ) ? array_map( 'intval', $_POST['exclude_product_brands'] ) : array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing

		// Save.
		update_post_meta( $post_id, 'product_brands', $product_brands );
		update_post_meta( $post_id, 'exclude_product_brands', $exclude_product_brands );
	}

	/**
	 * Prepare form fields to be used in the various tabs.
	 */
	public function init_form_fields() {

		/**
		 * Filter Brands settings.
		 *
		 * @since 9.4.0
		 *
		 * @param array $settings Brands settings.
		 */
		$this->settings = apply_filters(
			'woocommerce_brands_settings_fields',
			array(
				array(
					'name' => __( 'Brands Archives', 'woocommerce' ),
					'type' => 'title',
					'desc' => '',
					'id'   => 'brands_archives',
				),
				array(
					'name' => __( 'Show description', 'woocommerce' ),
					'desc' => __( 'Choose to show the brand description on the archive page. Turn this off if you intend to use the description widget instead. Please note: this is only for themes that do not show the description.', 'woocommerce' ),
					'tip'  => '',
					'id'   => 'wc_brands_show_description',
					'css'  => '',
					'std'  => 'yes',
					'type' => 'checkbox',
				),
				array(
					'type' => 'sectionend',
					'id'   => 'brands_archives',
				),
			)
		);
	}

	/**
	 * Enqueue scripts.
	 *
	 * @return void
	 */
	public function scripts() {
		$screen  = get_current_screen();
		$version = Constants::get_constant( 'WC_VERSION' );
		$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';

		if ( 'edit-product' === $screen->id ) {
			wp_register_script(
				'wc-brands-enhanced-select',
				WC()->plugin_url() . '/assets/js/admin/wc-brands-enhanced-select' . $suffix . '.js',
				array( 'jquery', 'selectWoo', 'wc-enhanced-select', 'wp-api' ),
				$version,
				true
			);
			wp_localize_script(
				'wc-brands-enhanced-select',
				'wc_brands_enhanced_select_params',
				array( 'ajax_url' => get_rest_url() . 'brands/search' )
			);
			wp_enqueue_script( 'wc-brands-enhanced-select' );
		}

		if ( in_array( $screen->id, array( 'edit-product_brand' ), true ) ) {
			wp_enqueue_media();
			wp_enqueue_style( 'woocommerce_admin_styles' );
		}
	}

	/**
	 * Enqueue styles.
	 *
	 * @return void
	 */
	public function styles() {
		$version = Constants::get_constant( 'WC_VERSION' );
		wp_enqueue_style( 'brands-admin-styles', WC()->plugin_url() . '/assets/css/brands-admin.css', array(), $version );
	}

	/**
	 * Admin settings function.
	 */
	public function admin_settings() {
		woocommerce_admin_fields( $this->settings );
	}

	/**
	 * Save admin settings function.
	 */
	public function save_admin_settings() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( isset( $_GET['section'] ) && 'brands' === $_GET['section'] ) {
			woocommerce_update_options( $this->settings );
		}
	}

	/**
	 * Category thumbnails.
	 */
	public function add_thumbnail_field() {
		global $woocommerce;
		?>
		<div class="form-field">
			<label><?php esc_html_e( 'Thumbnail', 'woocommerce' ); ?></label>
			<div id="product_cat_thumbnail" style="float:left;margin-right:10px;"><img src="<?php echo esc_url( wc_placeholder_img_src() ); ?>" width="60px" height="60px" /></div>
			<div style="line-height:60px;">
				<input type="hidden" id="product_cat_thumbnail_id" name="product_cat_thumbnail_id" />
				<button type="button" class="upload_image_button button"><?php esc_html_e( 'Upload/Add image', 'woocommerce' ); ?></button>
				<button type="button" class="remove_image_button button"><?php esc_html_e( 'Remove image', 'woocommerce' ); ?></button>
			</div>
			<script type="text/javascript">

				jQuery(function(){
					// Only show the "remove image" button when needed
					if ( ! jQuery('#product_cat_thumbnail_id').val() ) {
						jQuery('.remove_image_button').hide();
					}

					// Uploading files
					var file_frame;

					function clearThumbnailField() {
						jQuery('#product_cat_thumbnail img').attr('src', '<?php echo esc_js( wc_placeholder_img_src() ); ?>');
						jQuery('#product_cat_thumbnail_id').val('');
						jQuery('.remove_image_button').hide();
					}

					jQuery(document).on( 'click', '.upload_image_button', function( event ){

						event.preventDefault();

						// If the media frame already exists, reopen it.
						if ( file_frame ) {
							file_frame.open();
							return;
						}

						// Create the media frame.
						file_frame = wp.media.frames.downloadable_file = wp.media({
							title: '<?php echo esc_js( __( 'Choose an image', 'woocommerce' ) ); ?>',
							button: {
								text: '<?php echo esc_js( __( 'Use image', 'woocommerce' ) ); ?>',
							},
							multiple: false
						});

						// When an image is selected, run a callback.
						file_frame.on( 'select', function() {
							attachment = file_frame.state().get('selection').first().toJSON();

							jQuery('#product_cat_thumbnail_id').val( attachment.id );
							jQuery('#product_cat_thumbnail img').attr('src', attachment.url );
							jQuery('.remove_image_button').show();
						});

						// Finally, open the modal.
						file_frame.open();
					});

					jQuery(document).on( 'click', '.remove_image_button', function( event ){
						clearThumbnailField();
						return false;
					});

					jQuery( document ).on( 'ajaxComplete', function( event, request, options ) {
						if ( request && 4 === request.readyState && 200 === request.status
							&& options.data && 0 <= options.data.indexOf( 'action=add-tag' ) ) {

							var res = wpAjax.parseAjaxResponse( request.responseXML, 'ajax-response' );
							if ( ! res || res.errors ) {
								return;
							}

							clearThumbnailField();

							return;
						}
					} );
				});

			</script>
			<div class="clear"></div>
		</div>
		<?php
	}

	/**
	 * Edit thumbnail field row.
	 *
	 * @param WP_Term $term     Current taxonomy term object.
	 */
	public function edit_thumbnail_field( $term ) {
		global $woocommerce;

		$image        = '';
		$thumbnail_id = get_term_meta( $term->term_id, 'thumbnail_id', true );
		if ( $thumbnail_id ) {
			$image = wp_get_attachment_url( $thumbnail_id );
		}
		if ( empty( $image ) ) {
			$image = wc_placeholder_img_src();
		}
		?>
		<tr class="form-field">
			<th scope="row" valign="top"><label><?php esc_html_e( 'Thumbnail', 'woocommerce' ); ?></label></th>
			<td>
				<div id="product_cat_thumbnail" style="float:left;margin-right:10px;"><img src="<?php echo esc_url( $image ); ?>" width="60px" height="60px" /></div>
				<div style="line-height:60px;">
					<input type="hidden" id="product_cat_thumbnail_id" name="product_cat_thumbnail_id" value="<?php echo esc_attr( $thumbnail_id ); ?>" />
					<button type="button" class="upload_image_button button"><?php esc_html_e( 'Upload/Add image', 'woocommerce' ); ?></button>
					<button type="button" class="remove_image_button button"><?php esc_html_e( 'Remove image', 'woocommerce' ); ?></button>
				</div>
				<script type="text/javascript">

					jQuery(function(){

						// Only show the "remove image" button when needed
						if ( ! jQuery('#product_cat_thumbnail_id').val() )
							jQuery('.remove_image_button').hide();

						// Uploading files
						var file_frame;

						jQuery(document).on( 'click', '.upload_image_button', function( event ){

							event.preventDefault();

							// If the media frame already exists, reopen it.
							if ( file_frame ) {
								file_frame.open();
								return;
							}

							// Create the media frame.
							file_frame = wp.media.frames.downloadable_file = wp.media({
								title: '<?php echo esc_js( __( 'Choose an image', 'woocommerce' ) ); ?>',
								button: {
									text: '<?php echo esc_js( __( 'Use image', 'woocommerce' ) ); ?>',
								},
								multiple: false
							});

							// When an image is selected, run a callback.
							file_frame.on( 'select', function() {
								attachment = file_frame.state().get('selection').first().toJSON();

								jQuery('#product_cat_thumbnail_id').val( attachment.id );
								jQuery('#product_cat_thumbnail img').attr('src', attachment.url );
								jQuery('.remove_image_button').show();
							});

							// Finally, open the modal.
							file_frame.open();
						});

						jQuery(document).on( 'click', '.remove_image_button', function( event ){
							jQuery('#product_cat_thumbnail img').attr('src', '<?php echo esc_js( wc_placeholder_img_src() ); ?>');
							jQuery('#product_cat_thumbnail_id').val('');
							jQuery('.remove_image_button').hide();
							return false;
						});
					});

				</script>
				<div class="clear"></div>
			</td>
		</tr>
		<?php
	}

	/**
	 * Saves thumbnail field.
	 *
	 * @param int $term_id Term ID.
	 *
	 * @return void
	 */
	public function thumbnail_field_save( $term_id ) {
		if ( isset( $_POST['product_cat_thumbnail_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
			update_term_meta( $term_id, 'thumbnail_id', absint( $_POST['product_cat_thumbnail_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
		}
	}

	/**
	 * Brand taxonomy description.
	 */
	public function taxonomy_description() {
		echo wp_kses_post( wpautop( __( 'Brands can be added and managed from this screen. You can optionally upload a brand image to display in brand widgets and on brand archives', 'woocommerce' ) ) );
	}

	/**
	 * Sort brands function.
	 *
	 * @param array $sortable Sortable array.
	 */
	public function sort_brands( $sortable ) {
		$sortable[] = 'product_brand';
		return $sortable;
	}

	/**
	 * Add brands column in second-to-last position.
	 *
	 * @since 9.4.0
	 * @param mixed $columns Columns.
	 * @return array
	 */
	public function product_columns( $columns ) {
		if ( empty( $columns ) ) {
			return $columns;
		}

		$column_index  = 'taxonomy-product_brand';
		$brands_column = $columns[ $column_index ];
		unset( $columns[ $column_index ] );
		return array_merge(
			array_slice( $columns, 0, -2, true ),
			array( $column_index => $brands_column ),
			array_slice( $columns, -2, null, true )
		);
	}


	/**
	 * Columns function.
	 *
	 * @param mixed $columns Columns.
	 */
	public function columns( $columns ) {
		if ( empty( $columns ) ) {
			return $columns;
		}

		$new_columns          = array();
		$new_columns['cb']    = $columns['cb'];
		$new_columns['thumb'] = __( 'Image', 'woocommerce' );
		unset( $columns['cb'] );
		$columns = array_merge( $new_columns, $columns );
		return $columns;
	}

	/**
	 * Column function.
	 *
	 * @param mixed $columns Columns.
	 * @param mixed $column Column.
	 * @param mixed $id ID.
	 */
	public function column( $columns, $column, $id ) {
		if ( 'thumb' === $column ) {
			global $woocommerce;

			$image        = '';
			$thumbnail_id = get_term_meta( $id, 'thumbnail_id', true );

			if ( $thumbnail_id ) {
				$image = wp_get_attachment_url( $thumbnail_id );
			}
			if ( empty( $image ) ) {
				$image = wc_placeholder_img_src();
			}

			$columns .= '<img src="' . $image . '" alt="Thumbnail" class="wp-post-image" height="48" width="48" />';

		}
		return $columns;
	}

	/**
	 * Renders either dropdown or a search field for brands depending on the threshold value of
	 * woocommerce_product_brand_filter_threshold filter.
	 */
	public function render_product_brand_filter() {
		// phpcs:disable WordPress.Security.NonceVerification
		$brands_count       = (int) wp_count_terms( 'product_brand' );
		$current_brand_slug = wc_clean( wp_unslash( $_GET['product_brand'] ?? '' ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

		/**
		 * Filter the brands threshold count.
		 *
		 * @since 9.4.0
		 *
		 * @param int $value Threshold.
		 */
		if ( $brands_count <= apply_filters( 'woocommerce_product_brand_filter_threshold', 100 ) ) {
			wc_product_dropdown_categories(
				array(
					'pad_counts'        => true,
					'show_count'        => true,
					'orderby'           => 'name',
					'selected'          => $current_brand_slug,
					'show_option_none'  => __( 'Filter by brand', 'woocommerce' ),
					'option_none_value' => '',
					'value_field'       => 'slug',
					'taxonomy'          => 'product_brand',
					'name'              => 'product_brand',
					'class'             => 'dropdown_product_brand',
				)
			);
		} else {
			$current_brand   = $current_brand_slug ? get_term_by( 'slug', $current_brand_slug, 'product_brand' ) : '';
			$selected_option = '';
			if ( $current_brand_slug && $current_brand ) {
				$selected_option = '<option value="' . esc_attr( $current_brand_slug ) . '" selected="selected">' . esc_html( htmlspecialchars( wp_kses_post( $current_brand->name ) ) ) . '</option>';
			}
			$placeholder = esc_attr__( 'Filter by brand', 'woocommerce' );
			?>
			<select class="wc-brands-search" name="product_brand" data-placeholder="<?php echo $placeholder; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>" data-allow_clear="true">
				<?php echo $selected_option; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
			</select>
			<?php
		}
		// phpcs:enable WordPress.Security.NonceVerification
	}

	/**
	 * Add brand base permalink setting.
	 */
	public function add_brand_base_setting() {
		$screen = get_current_screen();
		if ( ! $screen || 'options-permalink' !== $screen->id ) {
			return;
		}

		add_settings_field(
			'woocommerce_product_brand_slug',
			__( 'Product brand base', 'woocommerce' ),
			array( $this, 'product_brand_slug_input' ),
			'permalink',
			'optional'
		);

		$this->save_permalink_settings();
	}

	/**
	 * Add a slug input box.
	 */
	public function product_brand_slug_input() {
		$permalink = get_option( 'woocommerce_brand_permalink', '' );
		?>
		<input name="woocommerce_product_brand_slug" type="text" class="regular-text code" value="<?php echo esc_attr( $permalink ); ?>" placeholder="<?php echo esc_attr_x( 'brand', 'slug', 'woocommerce' ); ?>" />
		<?php
	}

	/**
	 * Save permalink settings.
	 *
	 * We need to save the options ourselves;
	 * settings api does not trigger save for the permalink page.
	 */
	public function save_permalink_settings() {
		if ( ! is_admin() ) {
			return;
		}

		if ( isset( $_POST['permalink_structure'], $_POST['wc-permalinks-nonce'], $_POST['woocommerce_product_brand_slug'] ) && wp_verify_nonce( wp_unslash( $_POST['wc-permalinks-nonce'] ), 'wc-permalinks' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			update_option( 'woocommerce_brand_permalink', wc_sanitize_permalink( trim( wc_clean( wp_unslash( $_POST['woocommerce_product_brand_slug'] ) ) ) ) );
		}
	}

	/**
	 * Validate the product base.
	 *
	 * Must have an additional slug, not just the brand as the base.
	 *
	 * @param array $value Value.
	 */
	public function validate_product_base( $value ) {
		if ( '/%product_brand%/' === trailingslashit( $value['product_base'] ) ) {
			$value['product_base'] = '/' . _x( 'product', 'slug', 'woocommerce' ) . $value['product_base'];
		}

		return $value;
	}

	/**
	 * Add csv column for importing/exporting.
	 *
	 * @param  array $options Mapping options.
	 * @return array $options
	 */
	public function add_column_to_importer_exporter( $options ) {
		$options['brand_ids'] = __( 'Brands', 'woocommerce' );
		return $options;
	}

	/**
	 * Add default column mapping.
	 *
	 * @param  array $mappings Mappings.
	 * @return array $mappings
	 */
	public function add_default_column_mapping( $mappings ) {
		$new_mapping = array( __( 'Brands', 'woocommerce' ) => 'brand_ids' );
		return array_merge( $mappings, $new_mapping );
	}

	/**
	 * Add formatting callback for brand_ids during CSV import.
	 *
	 * @param  array               $callbacks Formatting callbacks.
	 * @param  WC_Product_Importer $importer  Importer instance.
	 * @return array $callbacks
	 */
	public function add_formatting_callback( $callbacks, $importer ) {
		$mapped_keys = $importer->get_mapped_keys();

		// Find the index of brand_ids in the mapped keys.
		$brand_ids_index = array_search( 'brand_ids', $mapped_keys, true );

		// If brand_ids exists in the mapping, add our custom parser.
		if ( false !== $brand_ids_index ) {
			$callbacks[ $brand_ids_index ] = array( $this, 'parse_brands_field' );
		}

		return $callbacks;
	}

	/**
	 * Add brands to newly imported product.
	 *
	 * @param WC_Product $product Product being imported.
	 * @param array      $data    Raw CSV data.
	 */
	public function process_import( $product, $data ) {
		if ( empty( $data['brand_ids'] ) || ! is_array( $data['brand_ids'] ) ) {
			return;
		}

		$brand_ids = array_map( 'intval', $data['brand_ids'] );
		wp_set_object_terms( $product->get_id(), $brand_ids, 'product_brand' );
	}

	/**
	 * Parse brands field from a CSV during import.
	 *
	 * Based on WC_Product_CSV_Importer::parse_categories_field()
	 *
	 * @param string $value Field value.
	 * @return array
	 */
	public function parse_brands_field( $value ) {

		if ( empty( $value ) ) {
			return array();
		}

		// Based on WC_Product_Importer::explode_values().
		$values    = str_replace( '\\,', '::separator::', explode( ',', $value ) );
		$row_terms = array();
		foreach ( $values as $row_value ) {
			$row_terms[] = trim( str_replace( '::separator::', ',', $row_value ) );
		}

		$brands = array();
		foreach ( $row_terms as $row_term ) {
			$parent = null;
			$_terms = array_map( 'trim', explode( '>', $row_term ) );
			$total  = count( $_terms );

			foreach ( $_terms as $index => $_term ) {
				// Don't allow users without capabilities to create new brands.
				if ( ! current_user_can( 'manage_product_terms' ) ) {
					break;
				}

				$term = term_exists( $_term, 'product_brand', $parent );

				if ( is_array( $term ) ) {
					$term_id = $term['term_id'];
				} else {
					$term = wp_insert_term( $_term, 'product_brand', array( 'parent' => intval( $parent ) ) );

					if ( is_wp_error( $term ) ) {
						break; // We cannot continue if the term cannot be inserted.
					}

					$term_id = $term['term_id'];
				}

				// Only requires assign the last category.
				if ( ( 1 + $index ) === $total ) {
					$brands[] = $term_id;
				} else {
					// Store parent to be able to insert or query brands based in parent ID.
					$parent = $term_id;
				}
			}
		}

		return $brands;
	}

	/**
	 * Get brands column value for csv export.
	 *
	 * @param string     $value   What will be exported.
	 * @param WC_Product $product Product being exported.
	 * @return string    Brands separated by commas and child brands as "parent > child".
	 */
	public function get_column_value_brand_ids( $value, $product ) {
		$brand_ids = wp_parse_id_list( wp_get_post_terms( $product->get_id(), 'product_brand', array( 'fields' => 'ids' ) ) );

		if ( ! count( $brand_ids ) ) {
			return '';
		}

		// Based on WC_CSV_Exporter::format_term_ids().
		$formatted_brands = array();
		foreach ( $brand_ids as $brand_id ) {
			$formatted_term = array();
			$ancestor_ids   = array_reverse( get_ancestors( $brand_id, 'product_brand' ) );

			foreach ( $ancestor_ids as $ancestor_id ) {
				$term = get_term( $ancestor_id, 'product_brand' );
				if ( $term && ! is_wp_error( $term ) ) {
					$formatted_term[] = $term->name;
				}
			}

			$term = get_term( $brand_id, 'product_brand' );

			if ( $term && ! is_wp_error( $term ) ) {
				$formatted_term[] = $term->name;
			}

			$formatted_brands[] = implode( ' > ', $formatted_term );
		}

		// Based on WC_CSV_Exporter::implode_values().
		$values_to_implode = array();
		foreach ( $formatted_brands as $brand ) {
			$brand               = (string) is_scalar( $brand ) ? $brand : '';
			$values_to_implode[] = str_replace( ',', '\\,', $brand );
		}

		return implode( ', ', $values_to_implode );
	}
}

$GLOBALS['WC_Brands_Admin'] = new WC_Brands_Admin();
PK     tS\?9,  9,  &  class-wc-admin-webhooks-table-list.phpnu [        <?php
/**
 * WooCommerce Webhooks Table List
 *
 * @package WooCommerce\Admin
 * @version 3.3.0
 */

use Automattic\WooCommerce\Internal\Utilities\WebhookUtil;

defined( 'ABSPATH' ) || exit;

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

/**
 * Webhooks table list class.
 */
class WC_Admin_Webhooks_Table_List extends WP_List_Table {

	/**
	 * Initialize the webhook table list.
	 */
	public function __construct() {
		parent::__construct(
			array(
				'singular' => 'webhook',
				'plural'   => 'webhooks',
				'ajax'     => false,
			)
		);
	}

	/**
	 * No items found text.
	 */
	public function no_items() {
		esc_html_e( 'No webhooks found.', 'woocommerce' );
	}

	/**
	 * Get list columns.
	 *
	 * @return array
	 */
	public function get_columns() {
		return array(
			'cb'           => '<input type="checkbox" />',
			'title'        => __( 'Name', 'woocommerce' ),
			'status'       => __( 'Status', 'woocommerce' ),
			'topic'        => __( 'Topic', 'woocommerce' ),
			'delivery_url' => __( 'Delivery URL', 'woocommerce' ),
		);
	}

	/**
	 * Column cb.
	 *
	 * @param  WC_Webhook $webhook Webhook instance.
	 * @return string
	 */
	public function column_cb( $webhook ) {
		return sprintf( '<input type="checkbox" name="%1$s[]" value="%2$s" />', $this->_args['singular'], $webhook->get_id() );
	}

	/**
	 * Return title column.
	 *
	 * @param  WC_Webhook $webhook Webhook instance.
	 * @return string
	 */
	public function column_title( $webhook ) {
		$edit_link = admin_url( 'admin.php?page=wc-settings&amp;tab=advanced&amp;section=webhooks&amp;edit-webhook=' . $webhook->get_id() );
		$output    = '';

		// Title.
		$warning_prefix =
			$this->uses_legacy_rest_api( $webhook ) && ! WC()->legacy_rest_api_is_available() ?
			sprintf(
				"<span title='%s'>⚠️</span>️ ",
				esc_html__( 'This webhook is configured to be delivered using the Legacy REST API, but the Legacy REST API plugin is not installed on this site.', 'woocommerce' )
			) : '';
		$output        .= '<strong>' . $warning_prefix . '<a href="' . esc_url( $edit_link ) . '" class="row-title">' . esc_html( $webhook->get_name() ) . '</a></strong>';

		// Get actions.
		$actions = array(
			/* translators: %s: webhook ID. */
			'id'     => sprintf( __( 'ID: %d', 'woocommerce' ), $webhook->get_id() ),
			'edit'   => '<a href="' . esc_url( $edit_link ) . '">' . esc_html__( 'Edit', 'woocommerce' ) . '</a>',
			/* translators: %s: webhook name */
			'delete' => '<a class="submitdelete" aria-label="' . esc_attr( sprintf( __( 'Delete "%s" permanently', 'woocommerce' ), $webhook->get_name() ) ) . '" href="' . esc_url(
				wp_nonce_url(
					add_query_arg(
						array(
							'delete' => $webhook->get_id(),
						),
						admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks' )
					),
					'delete-webhook'
				)
			) . '">' . esc_html__( 'Delete permanently', 'woocommerce' ) . '</a>',
		);

		$actions     = apply_filters( 'webhook_row_actions', $actions, $webhook );
		$row_actions = array();

		foreach ( $actions as $action => $link ) {
			$row_actions[] = '<span class="' . esc_attr( $action ) . '">' . $link . '</span>';
		}

		$output .= '<div class="row-actions">' . implode( ' | ', $row_actions ) . '</div>';

		return $output;
	}

	/**
	 * Return status column.
	 *
	 * @param  WC_Webhook $webhook Webhook instance.
	 * @return string
	 */
	public function column_status( $webhook ) {
		return $webhook->get_i18n_status();
	}

	/**
	 * Return topic column.
	 *
	 * @param  WC_Webhook $webhook Webhook instance.
	 * @return string
	 */
	public function column_topic( $webhook ) {
		return $webhook->get_topic();
	}

	/**
	 * Return delivery URL column.
	 *
	 * @param  WC_Webhook $webhook Webhook instance.
	 * @return string
	 */
	public function column_delivery_url( $webhook ) {
		return $webhook->get_delivery_url();
	}

	/**
	 * Get the status label for webhooks.
	 *
	 * @param string $status_name Status name.
	 * @param int    $amount      Amount of webhooks.
	 * @return array
	 */
	private function get_status_label( $status_name, $amount ) {
		$statuses = wc_get_webhook_statuses();

		if ( isset( $statuses[ $status_name ] ) ) {
			return array(
				'singular' => sprintf( '%s <span class="count">(%s)</span>', esc_html( $statuses[ $status_name ] ), $amount ),
				'plural'   => sprintf( '%s <span class="count">(%s)</span>', esc_html( $statuses[ $status_name ] ), $amount ),
				'context'  => '',
				'domain'   => 'woocommerce',
			);
		}

		return array(
			'singular' => sprintf( '%s <span class="count">(%s)</span>', esc_html( $status_name ), $amount ),
			'plural'   => sprintf( '%s <span class="count">(%s)</span>', esc_html( $status_name ), $amount ),
			'context'  => '',
			'domain'   => 'woocommerce',
		);
	}

	/**
	 * Table list views.
	 *
	 * @return array
	 */
	protected function get_views() {
		$status_links   = array();
		$data_store     = WC_Data_Store::load( 'webhook' );
		$num_webhooks   = $data_store->get_count_webhooks_by_status();
		$total_webhooks = array_sum( (array) $num_webhooks );
		$statuses       = array_keys( wc_get_webhook_statuses() );
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$class = empty( $_REQUEST['status'] ) && empty( $_REQUEST['legacy'] ) ? ' class="current"' : '';

		/* translators: %s: count */
		$status_links['all'] = "<a href='admin.php?page=wc-settings&amp;tab=advanced&amp;section=webhooks'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_webhooks, 'posts', 'woocommerce' ), number_format_i18n( $total_webhooks ) ) . '</a>';

		foreach ( $statuses as $status_name ) {
			$class = '';

			if ( empty( $num_webhooks[ $status_name ] ) ) {
				continue;
			}

			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			if ( isset( $_REQUEST['status'] ) && sanitize_key( wp_unslash( $_REQUEST['status'] ) ) === $status_name ) {
				$class = ' class="current"';
			}

			$label = $this->get_status_label( $status_name, $num_webhooks[ $status_name ] );

			$status_links[ $status_name ] = "<a href='admin.php?page=wc-settings&amp;tab=advanced&amp;section=webhooks&amp;status=$status_name'$class>" . sprintf( translate_nooped_plural( $label, $num_webhooks[ $status_name ] ), number_format_i18n( $num_webhooks[ $status_name ] ) ) . '</a>';
		}

		$legacy_webhooks_count = wc_get_container()->get( WebhookUtil::class )->get_legacy_webhooks_count();
		if ( $legacy_webhooks_count > 0 ) {
			$class = '';

			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			if ( 'true' === sanitize_key( wp_unslash( $_REQUEST['legacy'] ?? '' ) ) ) {
				$class = ' class="current"';
			}

			$label = $this->get_status_label( __( 'Legacy', 'woocommerce' ), $legacy_webhooks_count );

			$status_links['legacy'] = "<a href='admin.php?page=wc-settings&amp;tab=advanced&amp;section=webhooks&amp;legacy=true'$class>" . sprintf( translate_nooped_plural( $label, $legacy_webhooks_count ), number_format_i18n( $legacy_webhooks_count ) ) . '</a>';
		}

		return $status_links;
	}

	/**
	 * Get bulk actions.
	 *
	 * @return array
	 */
	protected function get_bulk_actions() {
		return array(
			'delete' => __( 'Delete permanently', 'woocommerce' ),
		);
	}

	/**
	 * Process bulk actions.
	 */
	public function process_bulk_action() {
		$action   = $this->current_action();
		$webhooks = isset( $_REQUEST['webhook'] ) ? array_map( 'absint', (array) $_REQUEST['webhook'] ) : array(); // WPCS: input var okay, CSRF ok.

		if ( false !== $action ) {
			check_admin_referer( 'woocommerce-settings' );

			if ( ! current_user_can( 'manage_woocommerce' ) ) {
				wp_die( esc_html__( 'You do not have permission to edit Webhooks', 'woocommerce' ) );
			}

			if ( 'delete' === $action ) {
				WC_Admin_Webhooks::bulk_delete( $webhooks );
			}
		}
	}

	/**
	 * Generate the table navigation above or below the table.
	 * Included to remove extra nonce input.
	 *
	 * @param string $which The location of the extra table nav markup: 'top' or 'bottom'.
	 */
	protected function display_tablenav( $which ) {
		echo '<div class="tablenav ' . esc_attr( $which ) . '">';

		if ( $this->has_items() ) {
			echo '<div class="alignleft actions bulkactions">';
			$this->bulk_actions( $which );
			echo '</div>';
		}

		$this->extra_tablenav( $which );
		$this->pagination( $which );
		echo '<br class="clear" />';
		echo '</div>';
	}

	/**
	 * Search box.
	 *
	 * @param  string $text     Button text.
	 * @param  string $input_id Input ID.
	 */
	public function search_box( $text, $input_id ) {
		if ( empty( $_REQUEST['s'] ) && ! $this->has_items() ) { // WPCS: input var okay, CSRF ok.
			return;
		}

		$input_id     = $input_id . '-search-input';
		$search_query = isset( $_REQUEST['s'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) : ''; // WPCS: input var okay, CSRF ok.

		echo '<p class="search-box">';
		echo '<label class="screen-reader-text" for="' . esc_attr( $input_id ) . '">' . esc_html( $text ) . ':</label>';
		echo '<input type="search" id="' . esc_attr( $input_id ) . '" name="s" value="' . esc_attr( $search_query ) . '" />';
		submit_button(
			$text,
			'',
			'',
			false,
			array(
				'id' => 'search-submit',
			)
		);
		echo '</p>';
	}

	/**
	 * Prepare table list items.
	 */
	public function prepare_items() {
		$per_page     = $this->get_items_per_page( 'woocommerce_webhooks_per_page' );
		$current_page = $this->get_pagenum();

		// Query args.
		$args = array(
			'limit'  => $per_page,
			'offset' => $per_page * ( $current_page - 1 ),
		);

		// Handle the status query.
		if ( ! empty( $_REQUEST['status'] ) ) { // WPCS: input var okay, CSRF ok.
			$args['status'] = sanitize_key( wp_unslash( $_REQUEST['status'] ) ); // WPCS: input var okay, CSRF ok.
		}

		if ( ! empty( $_REQUEST['s'] ) ) { // WPCS: input var okay, CSRF ok.
			$args['search'] = sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ); // WPCS: input var okay, CSRF ok.
		}

		$args['paginate'] = true;

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( 'true' === sanitize_key( wp_unslash( $_REQUEST['legacy'] ?? null ) ) ) {
			$args['api_version'] = -1;
		}

		// Get the webhooks.
		$data_store  = WC_Data_Store::load( 'webhook' );
		$webhooks    = $data_store->search_webhooks( $args );
		$this->items = array_map( 'wc_get_webhook', $webhooks->webhooks );

		// Set the pagination.
		$this->set_pagination_args(
			array(
				'total_items' => $webhooks->total,
				'per_page'    => $per_page,
				'total_pages' => $webhooks->max_num_pages,
			)
		);
	}

	/**
	 * Get how many of the existing webhooks are configured to use the legacy payload format.
	 *
	 * @since 9.0.0
	 *
	 * @return int Count of existing webhooks are configured to use the legacy payload format.
	 */
	public function get_legacy_api_webhooks_count() {
		return count( array_filter( $this->items, array( $this, 'uses_legacy_rest_api' ) ) );
	}

	/**
	 * Check if a given webhook is configured to use the legacy payload format.
	 *
	 * @param WC_Webhook $webhook Webhook object.
	 * @return bool True if the webhook is configured to use the legacy payload format.
	 */
	private function uses_legacy_rest_api( $webhook ) {
		return 0 === strpos( $webhook->get_api_version(), 'legacy' );
	}
}
PK     tS\KdC4  C4  !  class-wc-admin-log-table-list.phpnu [        <?php
/**
 * WooCommerce Log Table List
 *
 * @author   WooThemes
 * @category Admin
 * @package  WooCommerce\Admin
 * @version  1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

class WC_Admin_Log_Table_List extends WP_List_Table {
	/**
	 * The key for the user option of how many list table items to display per page.
	 *
	 * @const string
	 */
	public const PER_PAGE_USER_OPTION_KEY = 'woocommerce_status_log_items_per_page';

	/**
	 * The key for the option that stores the list of unique sources that exist in the log table.
	 *
	 * @const string
	 */
	public const SOURCE_CACHE_OPTION_KEY = 'woocommerce_status_log_db_sources';

	/**
	 * If the number of log entries is over this number, cache the query that gets the total count.
	 */
	private const ITEM_COUNT_CACHE_THRESHOLD = 100000;

	/**
	 * Initialize the log table list.
	 */
	public function __construct() {
		parent::__construct(
			array(
				'singular' => 'log',
				'plural'   => 'logs',
				'ajax'     => false,
			)
		);
	}

	/**
	 * Display level dropdown
	 *
	 * @global wpdb $wpdb
	 */
	public function level_dropdown() {
		$labels = WC_Log_Levels::get_all_level_labels();

		$levels = array_reduce(
			array_keys( $labels ),
			function( $carry, $item ) use ( $labels ) {
				$carry[] = array(
					'value' => $item,
					'label' => $labels[ $item ],
				);

				return $carry;
			},
			array()
		);

		$selected_level = isset( $_REQUEST['level'] ) ? $_REQUEST['level'] : '';
		?>
			<label for="filter-by-level" class="screen-reader-text"><?php esc_html_e( 'Filter by level', 'woocommerce' ); ?></label>
			<select name="level" id="filter-by-level">
				<option<?php selected( $selected_level, '' ); ?> value=""><?php esc_html_e( 'All levels', 'woocommerce' ); ?></option>
				<?php
				foreach ( $levels as $l ) {
					printf(
						'<option%1$s value="%2$s">%3$s</option>',
						selected( $selected_level, $l['value'], false ),
						esc_attr( $l['value'] ),
						esc_html( $l['label'] )
					);
				}
				?>
			</select>
		<?php
	}

	/**
	 * Generates the table rows.
	 *
	 * @return void
	 */
	public function display_rows() {
		foreach ( $this->items as $log ) {
			$this->single_row( $log );
			if ( ! empty( $log['context'] ) ) {
				$this->context_row( $log );
			}
		}
	}

	/**
	 * Render the additional table row that contains extra log context data.
	 *
	 * @param array $log Log entry data.
	 *
	 * @return void
	 */
	protected function context_row( $log ) {
		// Maintains alternating row background colors.
		?>
		<tr style="display: none"><td></td></tr>
		<tr id="log-context-<?php echo esc_attr( $log['log_id'] ); ?>" class="log-context">
			<td colspan="<?php echo esc_attr( $this->get_column_count() ); ?>">
				<p><strong><?php esc_html_e( 'Additional context', 'woocommerce' ); ?></strong></p>
				<pre><?php echo esc_html( $log['context'] ); ?></pre>
			</td>
		</tr>
		<?php
	}

	/**
	 * Get list columns.
	 *
	 * @return array
	 */
	public function get_columns() {
		return array(
			'cb'        => '<input type="checkbox" />',
			'timestamp' => __( 'Timestamp', 'woocommerce' ),
			'level'     => __( 'Level', 'woocommerce' ),
			'message'   => __( 'Message', 'woocommerce' ),
			'source'    => __( 'Source', 'woocommerce' ),
			'context'   => __( 'Context', 'woocommerce' ),
		);
	}

	/**
	 * Column cb.
	 *
	 * @param  array $log
	 * @return string
	 */
	public function column_cb( $log ) {
		return sprintf( '<input type="checkbox" name="log[]" value="%1$s" />', esc_attr( $log['log_id'] ) );
	}

	/**
	 * Timestamp column.
	 *
	 * @param  array $log
	 * @return string
	 */
	public function column_timestamp( $log ) {
		return esc_html(
			mysql2date(
				'Y-m-d H:i:s',
				$log['timestamp']
			)
		);
	}

	/**
	 * Level column.
	 *
	 * @param  array $log
	 * @return string
	 */
	public function column_level( $log ) {
		$level_key = WC_Log_Levels::get_severity_level( $log['level'] );
		$levels    = WC_Log_Levels::get_all_level_labels();

		if ( ! isset( $levels[ $level_key ] ) ) {
			return '';
		}

		$level       = $levels[ $level_key ];
		$level_class = sanitize_html_class( 'log-level--' . $level_key );
		return '<span class="log-level ' . $level_class . '">' . esc_html( $level ) . '</span>';
	}

	/**
	 * Message column.
	 *
	 * @param  array $log
	 * @return string
	 */
	public function column_message( $log ) {
		return sprintf(
			'<pre>%s</pre>',
			esc_html( $log['message'] )
		);
	}

	/**
	 * Source column.
	 *
	 * @param  array $log
	 * @return string
	 */
	public function column_source( $log ) {
		return esc_html( $log['source'] );
	}

	/**
	 * Context column.
	 *
	 * @param array $log Log entry data.
	 *
	 * @return string
	 */
	public function column_context( $log ) {
		$content = '';

		if ( ! empty( $log['context'] ) ) {
			ob_start();
			?>
				<button
					class="log-toggle button button-secondary button-small"
					data-log-id="<?php echo esc_attr( $log['log_id'] ); ?>"
					data-toggle-status="off"
					data-label-show="<?php esc_attr_e( 'Show context', 'woocommerce' ); ?>"
					data-label-hide="<?php esc_attr_e( 'Hide context', 'woocommerce' ); ?>"
				>
					<span class="dashicons dashicons-arrow-down-alt2"></span>
					<span class="log-toggle-label screen-reader-text"><?php esc_html_e( 'Show context', 'woocommerce' ); ?></span>
				</button>
			<?php
			$content = ob_get_clean();
		}

		return $content;
	}

	/**
	 * Get bulk actions.
	 *
	 * @return array
	 */
	protected function get_bulk_actions() {
		return array(
			'delete' => __( 'Delete', 'woocommerce' ),
		);
	}

	/**
	 * Extra controls to be displayed between bulk actions and pagination.
	 *
	 * @param string $which
	 */
	protected function extra_tablenav( $which ) {
		if ( 'top' === $which ) {
			echo '<div class="alignleft actions">';
				$this->level_dropdown();
				$this->source_dropdown();
				submit_button( __( 'Filter', 'woocommerce' ), '', 'filter-action', false );
			echo '</div>';
		}
	}

	/**
	 * Get a list of sortable columns.
	 *
	 * @return array
	 */
	protected function get_sortable_columns() {
		return array(
			'timestamp' => array( 'timestamp', true ),
			'level'     => array( 'level', true ),
			'source'    => array( 'source', true ),
		);
	}

	/**
	 * Display source dropdown
	 *
	 * @global wpdb $wpdb
	 */
	protected function source_dropdown() {
		$sources = $this->get_sources();

		if ( ! empty( $sources ) ) {
			$selected_source = isset( $_REQUEST['source'] ) ? $_REQUEST['source'] : '';
			?>
				<label for="filter-by-source" class="screen-reader-text"><?php esc_html_e( 'Filter by source', 'woocommerce' ); ?></label>
				<select name="source" id="filter-by-source">
					<option<?php selected( $selected_source, '' ); ?> value=""><?php esc_html_e( 'All sources', 'woocommerce' ); ?></option>
					<?php
					foreach ( $sources as $s ) {
						printf(
							'<option%1$s value="%2$s">%3$s</option>',
							selected( $selected_source, $s, false ),
							esc_attr( $s ),
							esc_html( $s )
						);
					}
					?>
				</select>
			<?php
		}
	}

	/**
	 * Get the list of unique sources in the log table.
	 *
	 * The query in this method can be slow when there are a high number of log entries. The list of sources also
	 * most likely doesn't change that often. So this indefinitely caches the list into the WP options table. The
	 * cache will get cleared by the log handler if a new source is being added. See WC_Log_Handler_DB::handle().
	 *
	 * @return array
	 */
	protected function get_sources() {
		global $wpdb;

		$sources = get_option( self::SOURCE_CACHE_OPTION_KEY, null );
		if ( is_array( $sources ) ) {
			return $sources;
		}

		$sql = "
			SELECT DISTINCT source
			FROM {$wpdb->prefix}woocommerce_log
			WHERE source != ''
			ORDER BY source ASC
		";

		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Not necessary.
		$sources = $wpdb->get_col( $sql );

		update_option( self::SOURCE_CACHE_OPTION_KEY, $sources );

		return $sources;
	}

	/**
	 * Prepare table list items.
	 *
	 * @global wpdb $wpdb
	 */
	public function prepare_items() {
		global $wpdb;

		$this->prepare_column_headers();

		$per_page = $this->get_items_per_page(
			self::PER_PAGE_USER_OPTION_KEY,
			$this->get_per_page_default()
		);

		$where  = $this->get_items_query_where();
		$order  = $this->get_items_query_order();
		$limit  = $this->get_items_query_limit();
		$offset = $this->get_items_query_offset();

		$query_items = "
			SELECT log_id, timestamp, level, message, source, context
			FROM {$wpdb->prefix}woocommerce_log
			{$where} {$order} {$limit} {$offset}
		";

		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- The query parts are prepared in their respective methods.
		$this->items = $wpdb->get_results( $query_items, ARRAY_A );
		$total_items = $this->get_total_items_count();

		$this->set_pagination_args(
			array(
				'total_items' => $total_items,
				'per_page'    => $per_page,
				'total_pages' => ceil( $total_items / $per_page ),
			)
		);
	}

	/**
	 * Get the total count of log entries in the database.
	 *
	 * The query in this method can be slow if there are a large (100k+) rows in the database table, so this
	 * uses a transient to cache the count for 10 minutes if the count is over that threshold.
	 *
	 * @return int
	 */
	protected function get_total_items_count() {
		global $wpdb;

		$where         = $this->get_items_query_where();
		$version       = \WC_Cache_Helper::get_transient_version( 'logs-db' );
		$transient_key = 'wc-log-total-items-count-' . md5( $where );
		$transient     = get_transient( $transient_key );
		if (
			false !== $transient
			&& isset( $transient['value'], $transient['version'] )
			&& $transient['version'] === $version
		) {
			return $transient['value'];
		}

		$count_query = "
			SELECT COUNT(*)
			FROM {$wpdb->prefix}woocommerce_log
			{$where}
		";

		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- The where clause is prepared in a separate method.
		$count = intval( $wpdb->get_var( $count_query ) );

		if ( $count > self::ITEM_COUNT_CACHE_THRESHOLD ) {
			$transient = array(
				'value'   => $count,
				'version' => \WC_Cache_Helper::get_transient_version( 'logs-db', true ),
			);

			set_transient( $transient_key, $transient, 10 * MINUTE_IN_SECONDS );
		} else {
			delete_transient( $transient_key );
		}

		return $count;
	}

	/**
	 * Get prepared LIMIT clause for items query
	 *
	 * @global wpdb $wpdb
	 *
	 * @return string Prepared LIMIT clause for items query.
	 */
	protected function get_items_query_limit() {
		global $wpdb;

		$per_page = $this->get_items_per_page(
			self::PER_PAGE_USER_OPTION_KEY,
			$this->get_per_page_default()
		);

		return $wpdb->prepare( 'LIMIT %d', $per_page );
	}

	/**
	 * Get prepared OFFSET clause for items query
	 *
	 * @global wpdb $wpdb
	 *
	 * @return string Prepared OFFSET clause for items query.
	 */
	protected function get_items_query_offset() {
		global $wpdb;

		$per_page     = $this->get_items_per_page(
			self::PER_PAGE_USER_OPTION_KEY,
			$this->get_per_page_default()
		);
		$current_page = $this->get_pagenum();
		if ( 1 < $current_page ) {
			$offset = $per_page * ( $current_page - 1 );
		} else {
			$offset = 0;
		}

		return $wpdb->prepare( 'OFFSET %d', $offset );
	}

	/**
	 * Get prepared ORDER BY clause for items query
	 *
	 * @return string Prepared ORDER BY clause for items query.
	 */
	protected function get_items_query_order() {
		$valid_orders = array( 'level', 'source', 'timestamp' );
		if ( ! empty( $_REQUEST['orderby'] ) && in_array( $_REQUEST['orderby'], $valid_orders ) ) {
			$by = wc_clean( $_REQUEST['orderby'] );
		} else {
			$by = 'log_id';
		}
		$by = esc_sql( $by );

		if ( ! empty( $_REQUEST['order'] ) && 'asc' === strtolower( $_REQUEST['order'] ) ) {
			$order = 'ASC';
		} else {
			$order = 'DESC';
		}

		$orderby = "ORDER BY {$by} {$order}";
		if ( 'log_id' !== $by ) {
			$orderby .= ", log_id {$order}";
		}

		return $orderby;
	}

	/**
	 * Get prepared WHERE clause for items query
	 *
	 * @global wpdb $wpdb
	 *
	 * @return string Prepared WHERE clause for items query.
	 */
	protected function get_items_query_where() {
		global $wpdb;

		$where_conditions = array();
		$where_values     = array();
		if ( ! empty( $_REQUEST['level'] ) && WC_Log_Levels::is_valid_level( $_REQUEST['level'] ) ) {
			$where_conditions[] = 'level >= %d';
			$where_values[]     = WC_Log_Levels::get_level_severity( $_REQUEST['level'] );
		}
		if ( ! empty( $_REQUEST['source'] ) ) {
			$where_conditions[] = 'source = %s';
			$where_values[]     = wc_clean( $_REQUEST['source'] );
		}
		if ( ! empty( $_REQUEST['s'] ) ) {
			$where_conditions[] = 'message like %s';
			$where_values[]     = '%' . $wpdb->esc_like( wc_clean( wp_unslash( $_REQUEST['s'] ) ) ) . '%';
		}

		if ( empty( $where_conditions ) ) {
			return '';
		}

		return $wpdb->prepare( 'WHERE 1 = 1 AND ' . implode( ' AND ', $where_conditions ), $where_values );
	}

	/**
	 * Set _column_headers property for table list
	 */
	protected function prepare_column_headers() {
		$this->_column_headers = array(
			$this->get_columns(),
			array(),
			$this->get_sortable_columns(),
		);
	}

	/**
	 * Helper to get the default value for the per_page arg.
	 *
	 * @return int
	 */
	public function get_per_page_default(): int {
		return 20;
	}
}
PK     tS\%987  87  "  settings/class-wc-settings-tax.phpnu [        <?php
/**
 * WooCommerce Tax Settings
 *
 * @package     WooCommerce\Admin
 * @version     2.1.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Settings_Tax', false ) ) {
	return new WC_Settings_Tax();
}

/**
 * WC_Settings_Tax.
 */
class WC_Settings_Tax extends WC_Settings_Page {

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id    = 'tax';
		$this->label = __( 'Tax', 'woocommerce' );

		add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
		add_action( 'woocommerce_admin_field_conflict_error', array( $this, 'conflict_error' ) );
		if ( wc_tax_enabled() ) {
			add_action( 'woocommerce_sections_' . $this->id, array( $this, 'output_sections' ) );
			add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
			add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
			add_action( 'admin_notices', array( $this, 'tax_configuration_validation_notice' ) );
		}
	}

	/**
	 * Setting page icon.
	 *
	 * @var string
	 */
	public $icon = 'percent';

	/**
	 * Creates the React mount point for the embedded banner.
	 */
	public function conflict_error() {
		?>
		<tr valign="top">
							<th scope="row" class="titledesc woocommerce_admin_tax_settings_slotfill_th">
							</th>
							<td class="forminp forminp-text woocommerce_admin_tax_settings_slotfill_td">
		<div id="wc_tax_settings_slotfill"> </div>
	</td>
	</tr>
		<?php
	}

	/**
	 * Add this page to settings.
	 *
	 * @param array $pages Existing pages.
	 * @return array|mixed
	 */
	public function add_settings_page( $pages ) {
		if ( wc_tax_enabled() ) {
			return parent::add_settings_page( $pages );
		} else {
			return $pages;
		}
	}

	/**
	 * Get own sections.
	 *
	 * @return array
	 */
	protected function get_own_sections() {
		$sections = array(
			''         => __( 'Tax options', 'woocommerce' ),
			'standard' => __( 'Standard rates', 'woocommerce' ),
		);

		// Get tax classes and display as links.
		$tax_classes = WC_Tax::get_tax_classes();

		foreach ( $tax_classes as $class ) {
			/* translators: $s tax rate section name */
			$sections[ sanitize_title( $class ) ] = sprintf( __( '%s rates', 'woocommerce' ), $class );
		}

		return $sections;
	}

	/**
	 * Get settings array.
	 *
	 * @return array
	 */
	public function get_settings_for_default_section() {
		return include __DIR__ . '/views/settings-tax.php';
	}

	/**
	 * Output the settings.
	 */
	public function output() {
		global $current_section;

		$tax_classes = WC_Tax::get_tax_class_slugs();

		if ( 'standard' === $current_section || in_array( $current_section, array_filter( $tax_classes ), true ) ) {
			$this->output_tax_rates();
		} else {
			parent::output();
		}
	}

	/**
	 * Save settings.
	 */
	public function save() {
		// phpcs:disable WordPress.Security.NonceVerification.Missing
		global $current_section;

		if ( ! $current_section ) {
			$this->save_settings_for_current_section();

			if ( isset( $_POST['woocommerce_tax_classes'] ) ) {
				$this->save_tax_classes( wp_unslash( $_POST['woocommerce_tax_classes'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			}
		} elseif ( ! empty( $_POST['tax_rate_country'] ) ) {
			$this->save_tax_rates();
		} else {
			$this->save_settings_for_current_section();
		}

		$this->do_update_options_action();

		// Invalidate caches.
		WC_Cache_Helper::invalidate_cache_group( 'taxes' );
		WC_Cache_Helper::get_transient_version( 'shipping', true );
		// phpcs:enable WordPress.Security.NonceVerification.Missing
	}

	/**
	 * Saves tax classes defined in the textarea to the tax class table instead of an option.
	 *
	 * @param string $raw_tax_classes Posted value.
	 * @return null
	 */
	public function save_tax_classes( $raw_tax_classes ) {
		$tax_classes          = array_filter( array_map( 'trim', explode( "\n", $raw_tax_classes ) ) );
		$existing_tax_classes = WC_Tax::get_tax_classes();
		$removed              = array_diff( $existing_tax_classes, $tax_classes );
		$added                = array_diff( $tax_classes, $existing_tax_classes );

		foreach ( $removed as $name ) {
			WC_Tax::delete_tax_class_by( 'name', $name );
		}

		foreach ( $added as $name ) {
			$tax_class = WC_Tax::create_tax_class( $name );

			// Display any error that could be triggered while creating tax classes.
			if ( is_wp_error( $tax_class ) ) {
				WC_Admin_Settings::add_error(
					sprintf(
						/* translators: 1: tax class name 2: error message */
						esc_html__( 'Additional tax class "%1$s" couldn\'t be saved. %2$s.', 'woocommerce' ),
						esc_html( $name ),
						$tax_class->get_error_message()
					)
				);
			}
		}

		return null;
	}

	/**
	 * Output tax rate tables.
	 */
	public function output_tax_rates() {
		global $current_section;

		$current_class = self::get_current_tax_class();

		$countries = array();
		foreach ( WC()->countries->get_allowed_countries() as $value => $label ) {
			$countries[] = array(
				'value' => $value,
				'label' => esc_js( html_entity_decode( $label ) ),
			);
		}

		$states = array();
		foreach ( WC()->countries->get_allowed_country_states() as $label ) {
			foreach ( $label as $code => $state ) {
				$states[] = array(
					'value' => $code,
					'label' => esc_js( html_entity_decode( $state ) ),
				);
			}
		}

		$base_url = admin_url(
			add_query_arg(
				array(
					'page'    => 'wc-settings',
					'tab'     => 'tax',
					'section' => $current_section,
				),
				'admin.php'
			)
		);

		// Localize and enqueue our js.
		wp_localize_script(
			'wc-settings-tax',
			'htmlSettingsTaxLocalizeScript',
			array(
				'current_class' => $current_class,
				'wc_tax_nonce'  => wp_create_nonce( 'wc_tax_nonce-class:' . $current_class ),
				'base_url'      => $base_url,
				'rates'         => array_values( WC_Tax::get_rates_for_tax_class( $current_class ) ),
				'page'          => ! empty( $_GET['p'] ) ? absint( $_GET['p'] ) : 1, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
				'limit'         => 100,
				'countries'     => $countries,
				'states'        => $states,
				'default_rate'  => array(
					'tax_rate_id'       => 0,
					'tax_rate_country'  => '',
					'tax_rate_state'    => '',
					'tax_rate'          => '',
					'tax_rate_name'     => '',
					'tax_rate_priority' => 1,
					'tax_rate_compound' => 0,
					'tax_rate_shipping' => 1,
					'tax_rate_order'    => null,
					'tax_rate_class'    => $current_class,
				),
				'strings'       => array(
					'no_rows_selected'        => __( 'No row(s) selected', 'woocommerce' ),
					'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
					'csv_data_cols'           => array(
						__( 'Country code', 'woocommerce' ),
						__( 'State code', 'woocommerce' ),
						__( 'Postcode / ZIP', 'woocommerce' ),
						__( 'City', 'woocommerce' ),
						__( 'Rate %', 'woocommerce' ),
						__( 'Tax name', 'woocommerce' ),
						__( 'Priority', 'woocommerce' ),
						__( 'Compound', 'woocommerce' ),
						__( 'Shipping', 'woocommerce' ),
						__( 'Tax class', 'woocommerce' ),
					),
				),
			)
		);
		wp_enqueue_script( 'wc-settings-tax' );

		include __DIR__ . '/views/html-settings-tax.php';
	}

	/**
	 * Get tax class being edited.
	 *
	 * @return string
	 */
	private static function get_current_tax_class() {
		global $current_section;

		$tax_classes   = WC_Tax::get_tax_classes();
		$current_class = '';

		foreach ( $tax_classes as $class ) {
			if ( sanitize_title( $class ) === $current_section ) {
				$current_class = $class;
			}
		}

		return $current_class;
	}

	/**
	 * Get a posted tax rate.
	 *
	 * @param string $key   Key of tax rate in the post data array.
	 * @param int    $order Position/order of rate.
	 * @param string $class Tax class for rate.
	 * @return array
	 */
	private function get_posted_tax_rate( $key, $order, $class ) {
		// phpcs:disable WordPress.Security.NonceVerification.Missing -- this is called from 'save_tax_rates' only, where nonce is already verified.
		$tax_rate      = array();
		$tax_rate_keys = array(
			'tax_rate_country',
			'tax_rate_state',
			'tax_rate',
			'tax_rate_name',
			'tax_rate_priority',
		);

		// phpcs:disable WordPress.Security.NonceVerification.Missing
		foreach ( $tax_rate_keys as $tax_rate_key ) {
			if ( isset( $_POST[ $tax_rate_key ], $_POST[ $tax_rate_key ][ $key ] ) ) {
				$tax_rate[ $tax_rate_key ] = wc_clean( wp_unslash( $_POST[ $tax_rate_key ][ $key ] ) );
			}
		}

		$tax_rate['tax_rate_compound'] = isset( $_POST['tax_rate_compound'][ $key ] ) ? 1 : 0;
		$tax_rate['tax_rate_shipping'] = isset( $_POST['tax_rate_shipping'][ $key ] ) ? 1 : 0;
		$tax_rate['tax_rate_order']    = $order;
		$tax_rate['tax_rate_class']    = $class;
		// phpcs:enable WordPress.Security.NonceVerification.Missing

		return $tax_rate;
		// phpcs:enable WordPress.Security.NonceVerification.Missing
	}

	/**
	 * Save tax rates.
	 */
	public function save_tax_rates() {
		// phpcs:disable WordPress.Security.NonceVerification.Missing -- this is called via "do_action('woocommerce_settings_save_'...") in base class, where nonce is verified first.
		global $wpdb;

		$current_class = sanitize_title( self::get_current_tax_class() );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.NonceVerification.Missing
		$posted_countries = wc_clean( wp_unslash( $_POST['tax_rate_country'] ) );

		// get the tax rate id of the first submitted row.
		$first_tax_rate_id = key( $posted_countries );

		// get the order position of the first tax rate id.
		$tax_rate_order = absint( $wpdb->get_var( $wpdb->prepare( "SELECT tax_rate_order FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $first_tax_rate_id ) ) );

		$index = isset( $tax_rate_order ) ? $tax_rate_order : 0;

		// Loop posted fields.
		// phpcs:disable WordPress.Security.NonceVerification.Missing
		foreach ( $posted_countries as $key => $value ) {
			$mode     = ( 0 === strpos( $key, 'new-' ) ) ? 'insert' : 'update';
			$tax_rate = $this->get_posted_tax_rate( $key, $index ++, $current_class );

			if ( 'insert' === $mode ) {
				$tax_rate_id = WC_Tax::_insert_tax_rate( $tax_rate );
			} elseif ( isset( $_POST['remove_tax_rate'][ $key ] ) && 1 === absint( $_POST['remove_tax_rate'][ $key ] ) ) {
				$tax_rate_id = absint( $key );
				WC_Tax::_delete_tax_rate( $tax_rate_id );
				continue;
			} else {
				$tax_rate_id = absint( $key );
				WC_Tax::_update_tax_rate( $tax_rate_id, $tax_rate );
			}

			if ( isset( $_POST['tax_rate_postcode'][ $key ] ) ) {
				WC_Tax::_update_tax_rate_postcodes( $tax_rate_id, wc_clean( wp_unslash( $_POST['tax_rate_postcode'][ $key ] ) ) );
			}
			if ( isset( $_POST['tax_rate_city'][ $key ] ) ) {
				WC_Tax::_update_tax_rate_cities( $tax_rate_id, wc_clean( wp_unslash( $_POST['tax_rate_city'][ $key ] ) ) );
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification.Missing
	}

	/**
	 * Display admin notice when tax-inclusive pricing is enabled without a base tax rate.
	 *
	 * @since 10.5.0
	 * @internal This method is public only because it is used as a hook callback.
	 *
	 * @return void
	 */
	public function tax_configuration_validation_notice(): void {
		// Only show on WooCommerce settings pages.
		$screen = get_current_screen();
		if ( ! $screen || 'woocommerce_page_wc-settings' !== $screen->id ) {
			return;
		}

		// Don't show if taxes are disabled.
		if ( ! wc_tax_enabled() ) {
			return;
		}

		// Check if prices are entered with tax.
		if ( 'yes' !== get_option( 'woocommerce_prices_include_tax' ) ) {
			return;
		}

		/**
		 * Filters if taxes should be removed from locations outside the store base location.
		 *
		 * The woocommerce_adjust_non_base_location_prices filter can stop base taxes being taken off when dealing
		 * with out of base locations. e.g. If a product costs 10 including tax, all users will pay 10
		 * regardless of location and taxes.
		 *
		 * @since 2.4.7
		 *
		 * @param bool $adjust_non_base_location_prices True by default.
		 */
		if ( ! apply_filters( 'woocommerce_adjust_non_base_location_prices', true ) ) {
			return;
		}

		// Check if base location has tax rates configured.
		$base_location = wc_get_base_location();
		if ( empty( $base_location['country'] ) ) {
			return;
		}

		$has_base_rate = $this->has_standard_tax_rate_for_country( $base_location['country'] );

		// If no base rates exist, show warning.
		if ( ! $has_base_rate ) {
			/**
			 * Filter whether to show the tax configuration incomplete notice.
			 *
			 * @since 10.5.0
			 *
			 * @param bool $show_notice Whether to show the notice. Default true.
			 */
			if ( ! apply_filters( 'woocommerce_show_tax_configuration_notice', true ) ) {
				return;
			}
			?>
			<div class="notice notice-warning">
				<p>
					<strong><?php esc_html_e( 'Tax configuration incomplete', 'woocommerce' ); ?></strong>
				</p>
				<p>
					<?php
					echo wp_kses_post(
						sprintf(
							/* translators: 1: country code, 2: opening link tag, 3: closing link tag */
							__( 'You have enabled "Prices entered with tax" but have not configured a standard tax rate for your base location (%1$s). Please %2$sconfigure standard tax rates%3$s to ensure accurate tax calculations.', 'woocommerce' ),
							esc_html( $base_location['country'] ),
							'<a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=tax&section=standard' ) ) . '">',
							'</a>'
						)
					);
					?>
				</p>
			</div>
			<?php
		}
	}

	/**
	 * Check if a standard tax rate exists for a given country.
	 *
	 * @since 10.5.0
	 *
	 * @param string $country Country code.
	 * @return bool True if at least one standard tax rate exists for the country.
	 */
	private function has_standard_tax_rate_for_country( $country ) {
		global $wpdb;

		$count = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_tax_rates WHERE (tax_rate_country = %s OR tax_rate_country = '') AND tax_rate_class = ''",
				$country
			)
		);

		return $count > 0;
	}
}

return new WC_Settings_Tax();
PK     tS\_2P  P  ,  settings/class-wc-settings-point-of-sale.phpnu [        <?php
/**
 * WooCommerce Point of Sale Settings
 *
 * @package WooCommerce\Admin
 */

declare(strict_types=1);

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Internal\Settings\PointOfSaleDefaultSettings;
use Automattic\WooCommerce\Utilities\FeaturesUtil;

defined( 'ABSPATH' ) || exit;

if ( class_exists( 'WC_Settings_Point_Of_Sale', false ) ) {
	return new WC_Settings_Point_Of_Sale();
}

/**
 * WC_Settings_Point_Of_Sale.
 */
class WC_Settings_Point_Of_Sale extends WC_Settings_Page {

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id    = 'point-of-sale';
		$this->label = __( 'Point of Sale', 'woocommerce' );

		parent::__construct();

		add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
	}

	/**
	 * Setting page icon.
	 *
	 * @var string
	 */
	public $icon = 'store';

	/**
	 * Add Point of Sale page to settings if the feature is enabled.
	 *
	 * @param array $pages Existing pages.
	 * @return array|mixed
	 *
	 * @internal For exclusive usage within this class, backwards compatibility not guaranteed.
	 */
	public function add_settings_page( $pages ) {
		if ( FeaturesUtil::feature_is_enabled( 'point_of_sale' ) ) {
			return parent::add_settings_page( $pages );
		} else {
			return $pages;
		}
	}

	/**
	 * Get settings for the default section.
	 *
	 * @return array
	 */
	protected function get_settings_for_default_section() {
		return array(
			array(
				'title' => __( 'Store details', 'woocommerce' ),
				'type'  => 'title',
				'desc'  => __( 'Details about the store that are shown in email receipts.', 'woocommerce' ),
				'id'    => 'store_details',
			),

			array(
				'title'             => __( 'Store name', 'woocommerce' ),
				'desc'              => __( 'The name of your physical store.', 'woocommerce' ),
				'id'                => 'woocommerce_pos_store_name',
				'default'           => PointOfSaleDefaultSettings::get_default_store_name(),
				'type'              => 'text',
				'css'               => 'min-width:300px;',
				'skip_initial_save' => true,
			),

			array(
				'title'    => __( 'Physical address', 'woocommerce' ),
				'id'       => 'woocommerce_pos_store_address',
				'default'  => PointOfSaleDefaultSettings::get_default_store_address(),
				'type'     => 'textarea',
				'css'      => 'min-width:300px; height: 100px;',
				'desc_tip' => true,
			),

			array(
				'title'   => __( 'Phone number', 'woocommerce' ),
				'id'      => 'woocommerce_pos_store_phone',
				'default' => '',
				'type'    => 'text',
				'css'     => 'min-width:300px;',
			),

			array(
				'title'   => __( 'Email', 'woocommerce' ),
				'desc'    => __( 'Your store contact email.', 'woocommerce' ),
				'id'      => 'woocommerce_pos_store_email',
				'default' => PointOfSaleDefaultSettings::get_default_store_email(),
				'type'    => 'email',
				'css'     => 'min-width:300px;',
			),

			array(
				'title'    => __( 'Refund & Returns Policy', 'woocommerce' ),
				'desc'     => __( 'Brief statement that will appear on the receipts.', 'woocommerce' ),
				'id'       => 'woocommerce_pos_refund_returns_policy',
				'default'  => '',
				'type'     => 'textarea',
				'css'      => 'min-width:300px; height: 100px;',
				'desc_tip' => true,
			),

			array(
				'type' => 'sectionend',
				'id'   => 'store_details',
			),
		);
	}
}

return new WC_Settings_Point_Of_Sale();
PK     tS\*TCo  o  .  settings/class-wc-settings-site-visibility.phpnu [        <?php
/**
 * WooCommerce site visibility settings
 *
 * @package  WooCommerce\Admin
 */

defined( 'ABSPATH' ) || exit;

/**
 * Settings for API.
 */
if ( class_exists( 'WC_Settings_Site_Visibility', false ) ) {
	return new WC_Settings_Site_Visibility();
}

/**
 * WC_Settings_Advanced.
 */
class WC_Settings_Site_Visibility extends WC_Settings_Page {

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id    = 'site-visibility';
		$this->label = __( 'Site visibility', 'woocommerce' );

		parent::__construct();
	}


	/**
	 * Get settings for the default section.
	 *
	 * @return array
	 */
	protected function get_settings_for_default_section() {
		$settings =
			array(
				array(
					'id'   => 'wc_settings_site_visibility_slotfill',
					'type' => 'slotfill_placeholder',
				),
			);

		return $settings;
	}
}


return new WC_Settings_Site_Visibility();
PK     tS\0y9  9  /  settings/class-wc-settings-payment-gateways.phpnu [        <?php
/**
 * WooCommerce Checkout Settings
 *
 * @package WooCommerce\Admin
 */

declare( strict_types = 1 );

use Automattic\WooCommerce\Internal\Admin\Loader;

defined( 'ABSPATH' ) || exit;

if ( class_exists( 'WC_Settings_Payment_Gateways', false ) ) {
	return new WC_Settings_Payment_Gateways();
}

/**
 * WC_Settings_Payment_Gateways.
 */
class WC_Settings_Payment_Gateways extends WC_Settings_Page {

	const TAB_NAME = 'checkout';

	const MAIN_SECTION_NAME    = 'main';
	const OFFLINE_SECTION_NAME = 'offline';
	const COD_SECTION_NAME     = 'cod';  // Cash on delivery.
	const BACS_SECTION_NAME    = 'bacs';  // Direct bank transfer.
	const CHEQUE_SECTION_NAME  = 'cheque';  // Cheque payments.

	/**
	 * Setting page icon.
	 *
	 * @var string
	 */
	public $icon = 'payment';

	/**
	 * Memoized list of sections to render using React.
	 *
	 * @var array|null
	 */
	private ?array $reactified_sections_memo = null;

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id    = self::TAB_NAME;
		$this->label = esc_html_x( 'Payments', 'Settings tab label', 'woocommerce' );

		// Add filters and actions.
		add_filter( 'admin_body_class', array( $this, 'add_body_classes' ), 30 );
		add_action( 'admin_head', array( $this, 'hide_help_tabs' ) );
		// Hook in as late as possible - `in_admin_header` is the last action before the `admin_notices` action is fired.
		// It is too risky to hook into `admin_notices` with a low priority because the callbacks might be cached.
		add_action( 'in_admin_header', array( $this, 'suppress_admin_notices' ), PHP_INT_MAX );

		// Do not show any store alerts (WC admin notes with type: 'error,update' and status: 'unactioned')
		// on the WooCommerce Payments settings page and Reactified sections.
		add_filter( 'woocommerce_admin_features', array( $this, 'suppress_store_alerts' ), PHP_INT_MAX );

		parent::__construct();
	}

	/**
	 * Check if the given section should be rendered using React.
	 *
	 * @param mixed $section The section name to check.
	 *                       Since this value originates from the global `$current_section` variable,
	 *                       it is best to accept anything and standardize it to a string.
	 *
	 * @return bool Whether the section should be rendered using React.
	 */
	public function should_render_react_section( $section ): bool {
		return in_array( $this->standardize_section_name( $section ), $this->get_reactified_sections(), true );
	}

	/**
	 * Add body classes.
	 *
	 * @param string $classes The existing body classes.
	 *
	 * @return string The modified body classes.
	 */
	public function add_body_classes( $classes ) {
		global $current_tab, $current_section;

		// Bail if the $classes variable is not a string.
		if ( ! is_string( $classes ) ) {
			return $classes;
		}

		// If we are not on the WooCommerce Payments settings page, return the classes as they are.
		if ( self::TAB_NAME !== $current_tab ) {
			return $classes;
		}

		if ( ! $this->should_render_react_section( $current_section ) ) {
			// Add a class to indicate that the payments settings section page is rendered in legacy mode.
			$classes .= ' woocommerce-settings-payments-section_legacy';
			// Add a class to indicate that the current section is rendered in legacy mode.
			$classes .= ' woocommerce_page_wc-settings-checkout-section-' . esc_attr( $this->standardize_section_name( $current_section ) ) . '_legacy';
		}

		return $classes;
	}

	/**
	 * Output the settings.
	 */
	public function output() {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		global $current_section;

		// We don't want to output anything from the action for now. So we buffer it and discard it.
		ob_start();
		/**
		 * Fires before the payment gateways settings fields are rendered.
		 *
		 * @since 1.5.7
		 */
		do_action( 'woocommerce_admin_field_payment_gateways' );
		ob_end_clean();

		if ( is_string( $current_section ) && $this->should_render_react_section( $current_section ) ) {
			$this->render_react_section( $this->standardize_section_name( $current_section ) );
		} elseif ( is_string( $current_section ) && ! empty( $current_section ) ) {
			// Load gateways so we can show any global options they may have.
			$payment_gateways = WC()->payment_gateways()->payment_gateways;
			$this->render_classic_gateway_settings_page( $payment_gateways, $current_section );
		} else {
			$this->render_react_section( self::MAIN_SECTION_NAME );
		}

		parent::output();
		//phpcs:enable
	}

	/**
	 * Get settings array.
	 *
	 * This is just for backward compatibility with the rest of the codebase (primarily API responses).
	 *
	 * @return array
	 */
	protected function get_settings_for_default_section() {
		return array(
			array(
				'type' => 'title',
				// this is needed as <table> tag is generated by this element, even if it has no other content.
			),
			array(
				'type' => 'sectionend',
				'id'   => 'payment_gateways_options',
			),
		);
	}

	/**
	 * Get the whitelist of sections to render using React.
	 *
	 * @return array List of section identifiers.
	 */
	private function get_reactified_sections(): array {
		if ( ! is_null( $this->reactified_sections_memo ) ) {
			return $this->reactified_sections_memo;
		}

		// These sections are always rendered using React.
		$reactified_sections = array(
			self::MAIN_SECTION_NAME,
			self::OFFLINE_SECTION_NAME,
		);

		// These sections are optional and can be modified by plugins or themes.
		$optional_reactified_sections = array(
			self::COD_SECTION_NAME,
			self::BACS_SECTION_NAME,
			self::CHEQUE_SECTION_NAME,
		);

		/**
		 * Modify the optional set of payments settings sections to be rendered using React.
		 *
		 * This filter allows plugins to add or remove optional sections (typically offline gateways)
		 * that should be rendered using React. Sections should be identified by their gateway IDs.
		 * Note: The main Payments page ("main") and the Offline overview ("offline") are always React-only
		 * and cannot be disabled via this filter.
		 *
		 * @since 9.3.0
		 *
		 * @param array $sections List of section identifiers to be rendered using React.
		 */
		$optional_reactified_sections = apply_filters( 'experimental_woocommerce_admin_payment_reactify_render_sections', $optional_reactified_sections );
		if ( empty( $optional_reactified_sections ) || ! is_array( $optional_reactified_sections ) ) {
			// Sanity check: use empty array if the filter returns something unexpected.
			$optional_reactified_sections = array();
		} else {
			// Enforce a list format and string-only values for section identifiers.
			$optional_reactified_sections = array_values( array_filter( $optional_reactified_sections, 'is_string' ) );
		}

		$this->reactified_sections_memo = array_unique( array_merge( $reactified_sections, $optional_reactified_sections ) );

		return $this->reactified_sections_memo;
	}

	/**
	 * Standardize the current section name.
	 *
	 * @param mixed $section The section name to standardize.
	 *
	 * @return string The standardized section name.
	 */
	private function standardize_section_name( $section ): string {
		$section = (string) $section;
		// If the section is empty, we are on the main settings page/section. Use a standardized name.
		if ( '' === $section ) {
			return self::MAIN_SECTION_NAME;
		}

		return $section;
	}

	/**
	 * Render the React section.
	 *
	 * @param string $section The section to render.
	 */
	private function render_react_section( string $section ) {
		global $hide_save_button;
		$hide_save_button = true;
		echo '<div id="experimental_wc_settings_payments_' . esc_attr( $section ) . '"></div>';
	}

	/**
	 * Render the classic gateway settings page.
	 *
	 * @param array  $payment_gateways The payment gateways.
	 * @param string $current_section  The current section.
	 */
	private function render_classic_gateway_settings_page( array $payment_gateways, string $current_section ) {
		foreach ( $payment_gateways as $gateway ) {
			if ( in_array( $current_section, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
				if ( isset( $_GET['toggle_enabled'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
					$enabled = $gateway->get_option( 'enabled' );

					if ( $enabled ) {
						$gateway->settings['enabled'] = wc_string_to_bool( $enabled ) ? 'no' : 'yes';
					}
				}
				$this->run_gateway_admin_options( $gateway );
				break;
			}
		}
	}

	/**
	 * Run the 'admin_options' method on a given gateway.
	 *
	 * This method exists to help with unit testing.
	 *
	 * @param object $gateway The gateway object to run the method on.
	 */
	protected function run_gateway_admin_options( $gateway ) {
		$gateway->admin_options();
	}

	/**
	 * Get all sections for the current page.
	 *
	 * Reactified section pages won't have any sections.
	 * The rest of the settings pages will get the default/own section and those added via
	 * the `woocommerce_get_sections_checkout` filter.
	 *
	 * @return array The sections for this settings page.
	 */
	public function get_sections() {
		global $current_tab, $current_section;

		// We only want to prevent sections on the main WooCommerce Payments settings page and Reactified sections.
		if ( self::TAB_NAME === $current_tab && $this->should_render_react_section( $current_section ) ) {
			return array();
		}

		return parent::get_sections();
	}

	/**
	 * Save settings.
	 */
	public function save() {
		global $current_section;

		$standardized_section = $this->standardize_section_name( $current_section );

		$wc_payment_gateways = WC_Payment_Gateways::instance();

		$this->save_settings_for_current_section();

		if ( self::MAIN_SECTION_NAME === $standardized_section ) {
			// This makes sure 'gateway ordering' is saved.
			$wc_payment_gateways->process_admin_options();
			$wc_payment_gateways->init();
		} else {
			// This may be a gateway or some custom section.
			foreach ( $wc_payment_gateways->payment_gateways() as $gateway ) {
				// If the section is that of a gateway, we need to run the gateway actions and init.
				if ( in_array( $standardized_section, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
					/**
					 * Fires update actions for payment gateways.
					 *
					 * @since 3.4.0
					 *
					 * @param int $gateway->id Gateway ID.
					 */
					do_action( 'woocommerce_update_options_payment_gateways_' . $gateway->id );
					$wc_payment_gateways->init();

					// There is no need to run the action and gateways init again
					// since we can't be on the section page of multiple gateways at once.
					break;
				}
			}

			$this->do_update_options_action();
		}
	}

	/**
	 * Hide the help tabs.
	 */
	public function hide_help_tabs() {
		global $current_tab, $current_section;

		$screen = get_current_screen();
		if ( ! $screen instanceof WP_Screen || 'woocommerce_page_wc-settings' !== $screen->id ) {
			return;
		}

		// We only want to hide the help tabs on the main WooCommerce Payments settings page and Reactified sections.
		if ( self::TAB_NAME !== $current_tab ) {
			return;
		}
		if ( ! $this->should_render_react_section( $current_section ) ) {
			return;
		}

		$screen->remove_help_tabs();
	}

	/**
	 * Suppress WP admin notices on the WooCommerce Payments settings page.
	 */
	public function suppress_admin_notices() {
		global $wp_filter, $current_tab, $current_section;

		$screen = get_current_screen();
		if ( ! $screen instanceof WP_Screen || 'woocommerce_page_wc-settings' !== $screen->id ) {
			return;
		}

		// We only want to suppress notices on the main WooCommerce Payments settings page and Reactified sections.
		if ( self::TAB_NAME !== $current_tab ) {
			return;
		}
		if ( ! $this->should_render_react_section( $current_section ) ) {
			return;
		}

		// Generic admin notices are definitely not needed.
		remove_all_actions( 'all_admin_notices' );

		// WooCommerce uses the 'admin_notices' hook for its own notices.
		// We will only allow WooCommerce core notices to be displayed.
		$wp_admin_notices_hook = $wp_filter['admin_notices'] ?? null;
		if ( ! $wp_admin_notices_hook || ! $wp_admin_notices_hook->has_filters() ) {
			// Nothing to do if there are no actions hooked into `admin_notices`.
			return;
		}

		$wc_admin_notices = WC_Admin_Notices::get_notices();
		if ( empty( $wc_admin_notices ) ) {
			// If there are no WooCommerce core notices, we can remove all actions hooked into `admin_notices`.
			remove_all_actions( 'admin_notices' );
			return;
		}

		// Go through the callbacks hooked into `admin_notices` and
		// remove any that are NOT from the WooCommerce core (i.e. from the `WC_Admin_Notices` class).
		foreach ( $wp_admin_notices_hook->callbacks as $priority => $callbacks ) {
			if ( ! is_array( $callbacks ) ) {
				continue;
			}

			foreach ( $callbacks as $callback ) {
				// Ignore malformed callbacks.
				if ( ! is_array( $callback ) ) {
					continue;
				}
				// WooCommerce doesn't use closures to handle notices.
				// WooCommerce core notices are handled by `WC_Admin_Notices` class methods.
				// Remove plain functions or closures.
				if ( ! is_array( $callback['function'] ) ) {
					remove_action( 'admin_notices', $callback['function'], $priority );
					continue;
				}

				$class_or_object = $callback['function'][0] ?? null;
				// We need to allow Automattic\WooCommerce\Internal\Admin\Loader methods callbacks
				// because they are used to wrap notices.
				// @see Automattic\WooCommerce\Internal\Admin\Loader::inject_before_notices().
				// @see Automattic\WooCommerce\Internal\Admin\Loader::inject_after_notices().
				if (
					(
						// We have a class name.
						is_string( $class_or_object ) &&
						! ( WC_Admin_Notices::class === $class_or_object || Loader::class === $class_or_object )
					) ||
					(
						// We have a class instance.
						is_object( $class_or_object ) &&
						! ( $class_or_object instanceof WC_Admin_Notices || $class_or_object instanceof Loader )
					)
				) {
					remove_action( 'admin_notices', $callback['function'], $priority );
				}
			}
		}
	}

	/**
	 * Suppress the store-alerts WCAdmin feature on the WooCommerce Payments settings page and Reactified sections.
	 *
	 * @param mixed $features The WCAdmin features list.
	 *
	 * @return mixed The modified features list.
	 */
	public function suppress_store_alerts( $features ) {
		global $current_tab, $current_section;

		$feature_name = 'store-alerts';

		if ( is_array( $features ) &&
			in_array( $feature_name, $features, true ) &&
			self::TAB_NAME === $current_tab &&
			$this->should_render_react_section( $current_section ) ) {

			unset( $features[ array_search( $feature_name, $features, true ) ] );
		}

		return $features;
	}
}

return new WC_Settings_Payment_Gateways();
PK     tS\    5  settings/views/html-admin-page-shipping-providers.phpnu [        <?php
/**
 * Shipping providers admin
 *
 * @package WooCommerce\Admin\Shipping
 */

declare( strict_types = 1 );

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

?>

<h2 class="wc-shipping-zones-heading">
	<span><?php esc_html_e( 'Shipping providers', 'woocommerce' ); ?></span>
	<a class="page-title-action wc-shipping-provider-add-new" href="#"><?php esc_html_e( 'Add shipping provider', 'woocommerce' ); ?></a>
</h2>

<p class="wc-shipping-zone-help-text">
	<?php esc_html_e( 'Add custom shipping providers so they appear in the fulfillment form when creating shipments. Use the tracking URL template to auto-generate tracking links.', 'woocommerce' ); ?>
</p>

<table class="wc-shipping-classes widefat">
	<thead>
		<tr>
			<?php foreach ( $shipping_provider_columns as $class => $heading ) : // @phpstan-ignore variable.undefined ?>
				<th class="<?php echo esc_attr( $class ); ?>"><?php echo esc_html( $heading ); ?></th>
			<?php endforeach; ?>
			<th />
		</tr>
	</thead>
	<tbody class="wc-shipping-provider-rows wc-shipping-tables-tbody"></tbody>
</table>

<script type="text/html" id="tmpl-wc-shipping-provider-row-blank">
	<tr>
		<td class="wc-shipping-classes-blank-state" colspan="<?php echo absint( count( $shipping_provider_columns ) + 1 ); ?>"><p><?php esc_html_e( 'No custom shipping providers have been created.', 'woocommerce' ); ?></p></td>
	</tr>
</script>

<script type="text/html" id="tmpl-wc-shipping-provider-configure">
<div class="wc-backbone-modal wc-shipping-class-modal">
		<div class="wc-backbone-modal-content" data-id="{{ data.term_id }}">
			<section class="wc-backbone-modal-main" role="main">
				<header class="wc-backbone-modal-header">
					<h1><?php esc_html_e( 'Add shipping provider', 'woocommerce' ); ?></h1>
					<button class="modal-close modal-close-link dashicons dashicons-no-alt">
						<span class="screen-reader-text"><?php esc_html_e( 'Close modal panel', 'woocommerce' ); ?></span>
					</button>
				</header>
				<article>
				<form action="" method="post">
					<input type="hidden" name="term_id" value="{{{ data.term_id }}}" />
					<?php
					foreach ( $shipping_provider_columns as $class => $heading ) {
						echo '<div class="wc-shipping-class-modal-input ' . esc_attr( $class ) . '">';
						switch ( $class ) {
							case 'wc-shipping-provider-name':
								?>
								<div class="view">
									<?php echo esc_html( $heading ); ?> *
								</div>
								<div class="edit">
									<input type="text" name="name" data-attribute="name" value="{{ data.name }}" placeholder="<?php esc_attr_e( 'e.g. My Local Courier', 'woocommerce' ); ?>" />
								</div>
								<div class="wc-shipping-class-modal-help-text"><?php esc_html_e( 'The display name for this shipping provider.', 'woocommerce' ); ?></div>
								<?php
								break;
							case 'wc-shipping-provider-slug':
								?>
								<div class="view">
									<?php echo esc_html( $heading ); ?>
								</div>
								<div class="edit">
									<input type="text" name="slug" data-attribute="slug" value="{{ data.slug }}" placeholder="<?php esc_attr_e( 'e.g. my-local-courier', 'woocommerce' ); ?>" />
								</div>
								<div class="wc-shipping-class-modal-help-text"><?php esc_html_e( 'Unique identifier (auto-generated if left blank).', 'woocommerce' ); ?></div>
								<?php
								break;
							case 'wc-shipping-provider-tracking-url-template':
								?>
								<div class="view">
									<?php echo esc_html( $heading ); ?>
								</div>
								<div class="edit">
									<input type="text" name="tracking_url_template" data-attribute="tracking_url_template" value="{{ data.tracking_url_template }}" placeholder="<?php esc_attr_e( 'e.g. https://example.com/track?id=__PLACEHOLDER__', 'woocommerce' ); ?>" />
								</div>
								<div class="wc-shipping-class-modal-help-text"><?php esc_html_e( 'Use __PLACEHOLDER__ where the tracking number should appear in the URL.', 'woocommerce' ); ?></div>
								<?php
								break;
							case 'wc-shipping-provider-icon':
								?>
								<div class="view">
									<?php echo esc_html( $heading ); ?>
								</div>
								<div class="edit">
									<input type="text" name="icon" data-attribute="icon" value="{{ data.icon }}" placeholder="<?php esc_attr_e( 'e.g. https://example.com/icon.png', 'woocommerce' ); ?>" />
								</div>
								<div class="wc-shipping-class-modal-help-text"><?php esc_html_e( 'Optional URL for the provider icon.', 'woocommerce' ); ?></div>
								<?php
								break;
							default:
								?>
								<div class="view wc-shipping-class-hide-sibling-view">
									<?php echo esc_html( $heading ); ?>
								</div>
								<?php
								/**
								 * Fires for custom columns in the shipping providers configure modal.
								 *
								 * @since 10.7.0
								 */
								do_action( 'woocommerce_shipping_providers_column_' . $class );
								break;
						}
						echo '</div>';
					}
					?>
				</form>
				</article>
				<footer>
					<div class="inner">
						<button id="btn-ok" disabled class="button button-primary button-large disabled">
							<div class="wc-backbone-modal-action-{{ data.action === 'create' ? 'active' : 'inactive' }}"><?php esc_html_e( 'Create', 'woocommerce' ); ?></div>
							<div class="wc-backbone-modal-action-{{ data.action === 'edit' ? 'active' : 'inactive' }}"><?php esc_html_e( 'Save', 'woocommerce' ); ?></div>
						</button>
					</div>
				</footer>
			</section>
		</div>
	</div>
	<div class="wc-backbone-modal-backdrop modal-close"></div>
</script>

<script type="text/html" id="tmpl-wc-shipping-provider-row">
	<tr data-id="{{ data.term_id }}">
		<?php
		foreach ( $shipping_provider_columns as $class => $heading ) {
			echo '<td class="' . esc_attr( $class ) . '">';
			switch ( $class ) {
				case 'wc-shipping-provider-name':
					?>
					<div class="view">
						{{ data.name }}
					</div>
					<?php
					break;
				case 'wc-shipping-provider-slug':
					?>
					<div class="view">{{ data.slug }}</div>
					<?php
					break;
				case 'wc-shipping-provider-tracking-url-template':
					?>
					<div class="view">{{ data.tracking_url_template }}</div>
					<?php
					break;
				case 'wc-shipping-provider-icon':
					?>
					<div class="view">{{ data.icon }}</div>
					<?php
					break;
				default:
					/**
					 * Fires for custom columns in the shipping providers table row.
					 *
					 * @since 10.7.0
					 */
					do_action( 'woocommerce_shipping_providers_column_' . $class );
					break;
			}
			echo '</td>';
		}
		?>
		<td class="wc-shipping-zone-actions">
			<div>
				<a class="wc-shipping-provider-edit wc-shipping-zone-action-edit" href="#"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a> | <a href="#" class="wc-shipping-provider-delete wc-shipping-zone-actions"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a>
			</div>
		</td>
	</tr>
</script>
PK     tS\ю      $  settings/views/html-settings-tax.phpnu [        <?php
/**
 * Admin view: Settings tax
 *
 * @package WooCommerce\Admin\Settings
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>

<div class="wc-tax-rates-search" id="rates-search">
	<input type="search" class="wc-tax-rates-search-field" placeholder="<?php esc_attr_e( 'Search&hellip;', 'woocommerce' ); ?>" value="<?php echo isset( $_GET['s'] ) ? esc_attr( $_GET['s'] ) : ''; ?>" />
</div>

<div id="rates-pagination"></div>

<h3>
	<?php
	/* translators: %s: tax rate */
	printf(
		__( '"%s" tax rates', 'woocommerce' ),
		$current_class ? esc_html( $current_class ) : __( 'Standard', 'woocommerce' )
	);
	?>
</h3>

<table class="wc_tax_rates wc_input_table widefat">
	<thead>
		<tr>
			<th width="8%"><a href="https://en.wikipedia.org/wiki/ISO_3166-1#Current_codes" target="_blank"><?php _e( 'Country&nbsp;code', 'woocommerce' ); ?></a>&nbsp;<?php echo wc_help_tip( __( 'A 2 digit country code, e.g. US. Leave blank to apply to all.', 'woocommerce' ) ); ?></th>
			<th width="8%"><?php _e( 'State code', 'woocommerce' ); ?>&nbsp;<?php echo wc_help_tip( __( 'A 2 digit state code, e.g. AL. Leave blank to apply to all.', 'woocommerce' ) ); ?></th>
			<th><?php _e( 'Postcode / ZIP', 'woocommerce' ); ?>&nbsp;<?php echo wc_help_tip( __( 'Postcode for this rule. Semi-colon (;) separate multiple values. Leave blank to apply to all areas. Wildcards (*) and ranges for numeric postcodes (e.g. 12345...12350) can also be used.', 'woocommerce' ) ); ?></th>
			<th><?php _e( 'City', 'woocommerce' ); ?>&nbsp;<?php echo wc_help_tip( __( 'Cities for this rule. Semi-colon (;) separate multiple values. Leave blank to apply to all cities.', 'woocommerce' ) ); ?></th>
			<th width="8%"><?php _e( 'Rate&nbsp;%', 'woocommerce' ); ?>&nbsp;<?php echo wc_help_tip( __( 'Enter a tax rate (percentage) to 4 decimal places.', 'woocommerce' ) ); ?></th>
			<th width="8%"><?php _e( 'Tax name', 'woocommerce' ); ?>&nbsp;<?php echo wc_help_tip( __( 'Enter a name for this tax rate.', 'woocommerce' ) ); ?></th>
			<th width="8%"><?php _e( 'Priority', 'woocommerce' ); ?>&nbsp;<?php echo wc_help_tip( __( 'Choose a priority for this tax rate. Only 1 matching rate per priority will be used. To define multiple tax rates for a single area you need to specify a different priority per rate.', 'woocommerce' ) ); ?></th>
			<th width="8%"><?php _e( 'Compound', 'woocommerce' ); ?>&nbsp;<?php echo wc_help_tip( __( 'Choose whether or not this is a compound rate. Compound tax rates are applied on top of other tax rates.', 'woocommerce' ) ); ?></th>
			<th width="8%"><?php _e( 'Shipping', 'woocommerce' ); ?>&nbsp;<?php echo wc_help_tip( __( 'Choose whether or not this tax rate also gets applied to shipping.', 'woocommerce' ) ); ?></th>
		</tr>
	</thead>
	<tfoot>
		<tr>
			<th colspan="9">
				<a href="#" class="button plus insert"><?php _e( 'Insert row', 'woocommerce' ); ?></a>
				<a href="#" class="button minus remove_tax_rates"><?php _e( 'Remove selected row(s)', 'woocommerce' ); ?></a>
				<a href="#" download="tax_rates.csv" class="button export"><?php _e( 'Export CSV', 'woocommerce' ); ?></a>
				<a href="<?php echo admin_url( 'admin.php?import=woocommerce_tax_rate_csv' ); ?>" class="button import"><?php _e( 'Import CSV', 'woocommerce' ); ?></a>
			</th>
		</tr>
	</tfoot>
	<tbody id="rates">
		<tr>
			<th colspan="9" style="text-align: center;"><?php esc_html_e( 'Loading&hellip;', 'woocommerce' ); ?></th>
		</tr>
	</tbody>
</table>

<div id="rates-bottom-pagination"></div>

<script type="text/html" id="tmpl-wc-tax-table-row">
	<tr class="tips" data-tip="<?php printf( esc_attr__( 'Tax rate ID: %s', 'woocommerce' ), '{{ data.tax_rate_id }}' ); ?>" data-id="{{ data.tax_rate_id }}">
		<td class="country">
			<input type="text" value="{{ data.tax_rate_country }}" placeholder="*" name="tax_rate_country[{{ data.tax_rate_id }}]" class="wc_input_country_iso" data-attribute="tax_rate_country" style="text-transform:uppercase" />
		</td>

		<td class="state">
			<input type="text" value="{{ data.tax_rate_state }}" placeholder="*" name="tax_rate_state[{{ data.tax_rate_id }}]" data-attribute="tax_rate_state" />
		</td>

		<td class="postcode">
			<input type="text" value="<# if ( data.postcode ) print( _.escape( data.postcode.join( '; ' ) ) ); #>" placeholder="*" data-name="tax_rate_postcode[{{ data.tax_rate_id }}]" data-attribute="postcode" />
		</td>

		<td class="city">
			<input type="text" value="<# if ( data.city ) print( _.escape( data.city.join( '; ' ) ) ); #>" placeholder="*" data-name="tax_rate_city[{{ data.tax_rate_id }}]" data-attribute="city" />
		</td>

		<td class="rate">
			<input type="text" value="{{ data.tax_rate }}" placeholder="0" name="tax_rate[{{ data.tax_rate_id }}]" data-attribute="tax_rate" />
		</td>

		<td class="name">
			<input type="text" value="{{ data.tax_rate_name }}" name="tax_rate_name[{{ data.tax_rate_id }}]" data-attribute="tax_rate_name" />
		</td>

		<td class="priority">
			<input type="number" step="1" min="1" value="{{ data.tax_rate_priority }}" name="tax_rate_priority[{{ data.tax_rate_id }}]" data-attribute="tax_rate_priority" />
		</td>

		<td class="compound">
			<input type="checkbox" class="checkbox" name="tax_rate_compound[{{ data.tax_rate_id }}]" <# if ( parseInt( data.tax_rate_compound, 10 ) ) { #> checked="checked" <# } #> data-attribute="tax_rate_compound" />
		</td>

		<td class="apply_to_shipping">
			<input type="checkbox" class="checkbox" name="tax_rate_shipping[{{ data.tax_rate_id }}]" <# if ( parseInt( data.tax_rate_shipping, 10 ) ) { #> checked="checked" <# } #> data-attribute="tax_rate_shipping" />
		</td>
	</tr>
</script>

<script type="text/html" id="tmpl-wc-tax-table-row-empty">
	<tr>
		<th colspan="9" style="text-align:center"><?php esc_html_e( 'No matching tax rates found.', 'woocommerce' ); ?></th>
	</tr>
</script>

<script type="text/html" id="tmpl-wc-tax-table-pagination">
	<div class="tablenav">
		<div class="tablenav-pages">
			<span class="displaying-num">
				<?php
				/* translators: %s: number */
				printf(
					__( '%s items', 'woocommerce' ), // %s will be a number eventually, but must be a string for now.
					'{{ data.qty_rates }}'
				);
				?>
			</span>
			<span class="pagination-links">
				<# if ( data.current_page === 1 ) { #>
					<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&laquo;</span>
					<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&lsaquo;</span>
				<# } else { #>
					<a class="button" data-goto="1">
						<span class="screen-reader-text"><?php esc_html_e( 'First page', 'woocommerce' ); ?></span>
						<span aria-hidden="true">&laquo;</span>
					</a>
					<a class="button" data-goto="<# print( Math.max( 1, parseInt( data.current_page, 10 ) - 1 ) ) #>">
						<span class="screen-reader-text"><?php esc_html_e( 'Previous page', 'woocommerce' ); ?></span>
						<span aria-hidden="true">&lsaquo;</span>
					</a>
				<# } #>

				<span class="paging-input">
					<label for="current-page-selector" class="screen-reader-text"><?php esc_html_e( 'Current page', 'woocommerce' ); ?></label>
					<?php
						/* translators: 1: current page 2: total pages */
						printf(
							esc_html_x( '%1$s of %2$s', 'Pagination', 'woocommerce' ),
							'<input class="current-page" id="current-page-selector" type="text" name="paged" value="{{ data.current_page }}" size="<# print( data.qty_pages.toString().length ) #>" aria-describedby="table-paging">',
							'<span class="total-pages">{{ data.qty_pages }}</span>'
						);
					?>
				</span>

				<# if ( data.current_page === data.qty_pages ) { #>
					<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&rsaquo;</span>
					<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&raquo;</span>
				<# } else { #>
					<a class="button" data-goto="<# print( Math.min( data.qty_pages, parseInt( data.current_page, 10 ) + 1 ) ) #>">
						<span class="screen-reader-text"><?php esc_html_e( 'Next page', 'woocommerce' ); ?></span>
						<span aria-hidden="true">&rsaquo;</span>
					</a>
					<a class="button" data-goto="{{ data.qty_pages }}">
						<span class="screen-reader-text"><?php esc_html_e( 'Last page', 'woocommerce' ); ?></span>
						<span aria-hidden="true">&raquo;</span>
					</a>
				<# } #>

			</span>
		</div>
	</div>
</script>
PK     tS\<̟    !  settings/views/html-keys-edit.phpnu [        <?php
/**
 * Admin view: Edit API keys
 *
 * @package WooCommerce\Admin\Settings
 */

defined( 'ABSPATH' ) || exit;
?>

<div id="key-fields" class="settings-panel">
	<h2><?php esc_html_e( 'Key details', 'woocommerce' ); ?></h2>

	<div class="inline notice">
		<ul class="advice">
			<li><?php esc_html_e( 'API keys open up access to potentially sensitive information. Only share them with organizations you trust.', 'woocommerce' ); ?></li>
			<li><?php esc_html_e( 'Stick to one key per client: this makes it easier to revoke access in the future for a single client, without causing disruption for others.', 'woocommerce' ); ?></li>
		</ul>
	</div>

	<input type="hidden" id="key_id" value="<?php echo esc_attr( $key_id ); ?>" />

	<table id="api-keys-options" class="form-table">
		<tbody>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<label for="key_description">
						<?php esc_html_e( 'Description', 'woocommerce' ); ?>
						<?php echo wc_help_tip( __( 'Friendly name for identifying this key.', 'woocommerce' ) ); ?>
					</label>
				</th>
				<td class="forminp">
					<input maxlength="200" id="key_description" type="text" class="input-text regular-input" value="<?php echo esc_attr( $key_data['description'] ); ?>" />
					<p class="description">
						<?php esc_html_e( 'Add a meaningful description, including a note of the person, company or app you are sharing the key with.', 'woocommerce' ); ?>
					</p>
				</td>
			</tr>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<label for="key_user">
						<?php esc_html_e( 'User', 'woocommerce' ); ?>
						<?php echo wc_help_tip( __( 'Owner of these keys.', 'woocommerce' ) ); ?>
					</label>
				</th>
				<td class="forminp">
					<?php
					$current_user_id = get_current_user_id();
					$user_id        = ! empty( $key_data['user_id'] ) ? absint( $key_data['user_id'] ) : $current_user_id;
					$user           = get_user_by( 'id', $user_id );
					$user_string    = sprintf(
						/* translators: 1: user display name 2: user ID 3: user email */
						esc_html__( '%1$s (#%2$s &ndash; %3$s)', 'woocommerce' ),
						$user->display_name,
						absint( $user->ID ),
						$user->user_email
					);
					?>
					<select class="wc-customer-search" id="key_user" data-placeholder="<?php esc_attr_e( 'Search for a user&hellip;', 'woocommerce' ); ?>" data-allow_clear="true">
						<option value="<?php echo esc_attr( $user_id ); ?>" selected="selected"><?php echo htmlspecialchars( wp_kses_post( $user_string ) ); // htmlspecialchars to prevent XSS when rendered by selectWoo. ?></option>
					</select>
				</td>
			</tr>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<label for="key_permissions">
						<?php esc_html_e( 'Permissions', 'woocommerce' ); ?>
						<?php echo wc_help_tip( __( 'Select the access type of these keys.', 'woocommerce' ) ); ?>
					</label>
				</th>
				<td class="forminp">
					<select id="key_permissions" class="wc-enhanced-select">
						<?php
						$permissions = array(
							'read'       => __( 'Read', 'woocommerce' ),
							'write'      => __( 'Write', 'woocommerce' ),
							'read_write' => __( 'Read/Write', 'woocommerce' ),
						);

						foreach ( $permissions as $permission_id => $permission_name ) :
							?>
							<option value="<?php echo esc_attr( $permission_id ); ?>" <?php selected( $key_data['permissions'], $permission_id, true ); ?>><?php echo esc_html( $permission_name ); ?></option>
						<?php endforeach; ?>
					</select>
					<p class="conditional description" data-depends-on="#key_permissions" data-show-if-equals="write">
						<?php esc_html_e( 'Write-only keys do not prevent clients from seeing information about the entities they are updating.', 'woocommerce' ); ?>
					</p>
				</td>
			</tr>

			<?php if ( 0 !== $key_id ) : ?>
				<tr valign="top">
					<th scope="row" class="titledesc">
						<?php esc_html_e( 'Consumer key ending in', 'woocommerce' ); ?>
					</th>
					<td class="forminp">
						<code>&hellip;<?php echo esc_html( $key_data['truncated_key'] ); ?></code>
					</td>
				</tr>
				<tr valign="top">
					<th scope="row" class="titledesc">
						<?php esc_html_e( 'Last access', 'woocommerce' ); ?>
					</th>
					<td class="forminp">
						<span>
						<?php
						if ( ! empty( $key_data['last_access'] ) ) {
							/* translators: 1: last access date 2: last access time */
							$date = sprintf( __( '%1$s at %2$s', 'woocommerce' ), date_i18n( wc_date_format(), strtotime( $key_data['last_access'] ) ), date_i18n( wc_time_format(), strtotime( $key_data['last_access'] ) ) );

							echo esc_html( apply_filters( 'woocommerce_api_key_last_access_datetime', $date, $key_data['last_access'] ) );
						} else {
							esc_html_e( 'Unknown', 'woocommerce' );
						}
						?>
						</span>
					</td>
				</tr>
			<?php endif ?>
		</tbody>
	</table>

	<?php do_action( 'woocommerce_admin_key_fields', $key_data ); ?>

	<?php
	if ( 0 === intval( $key_id ) ) {
		submit_button( __( 'Generate API key', 'woocommerce' ), 'primary', 'update_api_key' );
	} else {
		?>
		<p class="submit">
			<?php submit_button( __( 'Save changes', 'woocommerce' ), 'primary', 'update_api_key', false ); ?>
			<a style="color: #a00; text-decoration: none; margin-left: 10px;" href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'revoke-key' => $key_id ), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys' ) ), 'revoke' ) ); ?>"><?php esc_html_e( 'Revoke key', 'woocommerce' ); ?></a>
		</p>
		<?php
	}
	?>
</div>

<script type="text/template" id="tmpl-api-keys-template">
	<p id="copy-error"></p>
	<table class="form-table">
		<tbody>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<?php esc_html_e( 'Consumer key', 'woocommerce' ); ?>
				</th>
				<td class="forminp">
					<input id="key_consumer_key" type="text" value="{{ data.consumer_key }}" size="55" readonly="readonly"> <button type="button" class="button-secondary copy-key" data-tip="<?php esc_attr_e( 'Copied!', 'woocommerce' ); ?>"><?php esc_html_e( 'Copy', 'woocommerce' ); ?></button>
				</td>
			</tr>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<?php esc_html_e( 'Consumer secret', 'woocommerce' ); ?>
				</th>
				<td class="forminp">
					<input id="key_consumer_secret" type="text" value="{{ data.consumer_secret }}" size="55" readonly="readonly"> <button type="button" class="button-secondary copy-secret" data-tip="<?php esc_attr_e( 'Copied!', 'woocommerce' ); ?>"><?php esc_html_e( 'Copy', 'woocommerce' ); ?></button>
				</td>
			</tr>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<?php esc_html_e( 'QRCode', 'woocommerce' ); ?>
				</th>
				<td class="forminp">
					<div id="keys-qrcode"></div>
				</td>
			</tr>
		</tbody>
	</table>
</script>
PK     tS\GU  U    settings/views/settings-tax.phpnu [        <?php
/**
 * Tax settings.
 *
 * @package WooCommerce\Admin\Settings.
 */

defined( 'ABSPATH' ) || exit;

$settings = array(

	array(
		'title' => __( 'Tax options', 'woocommerce' ),
		'type'  => 'title',
		'desc'  => '',
		'id'    => 'tax_options',
	),

	array(
		'title'    => __( 'Prices entered with tax', 'woocommerce' ),
		'id'       => 'woocommerce_prices_include_tax',
		'default'  => 'no',
		'type'     => 'radio',
		'desc_tip' => __( 'This option is important as it will affect how you input prices. If you select "Yes", enter prices including your base location\'s tax rate, the baseline for tax calculations. Changing this option will not update existing products.', 'woocommerce' ),
		'options'  => array(
			'yes' => __( 'Yes, I will enter prices inclusive of tax', 'woocommerce' ),
			'no'  => __( 'No, I will enter prices exclusive of tax', 'woocommerce' ),
		),
	),

	array(
		'title'    => __( 'Calculate tax based on', 'woocommerce' ),
		'id'       => 'woocommerce_tax_based_on',
		'desc_tip' => __( 'This option determines which address is used to calculate tax.', 'woocommerce' ),
		'default'  => 'shipping',
		'type'     => 'select',
		'class'    => 'wc-enhanced-select',
		'options'  => array(
			'shipping' => __( 'Customer shipping address', 'woocommerce' ),
			'billing'  => __( 'Customer billing address', 'woocommerce' ),
			'base'     => __( 'Shop base address', 'woocommerce' ),
		),
	),

	'shipping-tax-class' => array(
		'title'    => __( 'Shipping tax class', 'woocommerce' ),
		'desc'     => __( 'Optionally control which tax class shipping gets, or leave it so shipping tax is based on the cart items themselves.', 'woocommerce' ),
		'id'       => 'woocommerce_shipping_tax_class',
		'css'      => 'min-width:150px;',
		'default'  => 'inherit',
		'type'     => 'select',
		'class'    => 'wc-enhanced-select',
		'options'  => array( 'inherit' => __( 'Shipping tax class based on cart items', 'woocommerce' ) ) + wc_get_product_tax_class_options(),
		'desc_tip' => true,
	),

	array(
		'title'   => __( 'Rounding', 'woocommerce' ),
		'desc'    => __( 'Round tax at subtotal level, instead of rounding per line', 'woocommerce' ),
		'id'      => 'woocommerce_tax_round_at_subtotal',
		'default' => 'no',
		'type'    => 'checkbox',
	),

	array(
		'title'     => __( 'Additional tax classes', 'woocommerce' ),
		'desc_tip'  => __( 'List additional tax classes you need below (1 per line, e.g. Reduced Rates). These are in addition to "Standard rate" which exists by default.', 'woocommerce' ),
		'id'        => 'woocommerce_tax_classes',
		'css'       => 'height: 65px;',
		'type'      => 'textarea',
		'default'   => '',
		'is_option' => false,
		'value'     => implode( "\n", WC_Tax::get_tax_classes() ),
	),

	array(
		'title'   => __( 'Display prices in the shop', 'woocommerce' ),
		'id'      => 'woocommerce_tax_display_shop',
		'default' => 'excl',
		'type'    => 'select',
		'class'   => 'wc-enhanced-select',
		'options' => array(
			'incl' => __( 'Including tax', 'woocommerce' ),
			'excl' => __( 'Excluding tax', 'woocommerce' ),
		),
	),

	array(
		'title'   => __( 'Display prices during cart and checkout', 'woocommerce' ),
		'id'      => 'woocommerce_tax_display_cart',
		'default' => 'excl',
		'type'    => 'select',
		'class'   => 'wc-enhanced-select',
		'options' => array(
			'incl' => __( 'Including tax', 'woocommerce' ),
			'excl' => __( 'Excluding tax', 'woocommerce' ),
		),
	),

	array( 'type' => 'conflict_error' ), // React mount point for embedded banner slotfill.
	array( 'type' => 'add_settings_slot' ), // React mount point for settings slotfill.

	array(
		'title'       => __( 'Price display suffix', 'woocommerce' ),
		'id'          => 'woocommerce_price_display_suffix',
		'default'     => '',
		'placeholder' => __( 'N/A', 'woocommerce' ),
		'type'        => 'text',
		'desc_tip'    => __( 'Define text to show after your product prices. This could be, for example, "inc. Vat" to explain your pricing. You can also have prices substituted here using one of the following: {price_including_tax}, {price_excluding_tax}.', 'woocommerce' ),
	),

	array(
		'title'    => __( 'Display tax totals', 'woocommerce' ),
		'id'       => 'woocommerce_tax_total_display',
		'default'  => 'itemized',
		'type'     => 'select',
		'class'    => 'wc-enhanced-select',
		'options'  => array(
			'single'   => __( 'As a single total', 'woocommerce' ),
			'itemized' => __( 'Itemized', 'woocommerce' ),
		),
		'autoload' => false,
	),

	array(
		'type' => 'sectionend',
		'id'   => 'tax_options',
	),

);

if ( ! wc_shipping_enabled() ) {
	unset( $settings['shipping-tax-class'] );
}

return apply_filters( 'woocommerce_tax_settings', $settings );
PK     tS\ss  s  1  settings/views/html-admin-page-shipping-zones.phpnu [        <?php
/**
 * Shipping zones admin page.
 *
 * @package WooCommerce\Admin\Shipping
 */

use Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>

<h2 class="wc-shipping-zones-heading">
	<span><?php esc_html_e( 'Shipping zones', 'woocommerce' ); ?></span>
	<a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&zone_id=new' ) ); ?>" class="page-title-action"><?php esc_html_e( 'Add zone', 'woocommerce' ); ?></a>
</h2>
<p class="wc-shipping-zone-heading-help-text">
	<?php
	esc_html_e(
		"A shipping zone consists of the region(s) you'd like to ship to and the shipping method(s) offered. A shopper can only be matched to one zone, and we'll use their shipping address to show them the methods available in their area.",
		'woocommerce'
	);

	if ( CartCheckoutUtils::is_checkout_block_default() ) {
		echo ' ' . wp_kses_post(
			sprintf(
			/* translators: %s: URL to local pickup settings */
				__(
					"To offer local pickup, configure your pickup locations in the <a href='%s'>local pickup settings</a>.",
					'woocommerce'
				),
				esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&section=pickup_location' ) )
			)
		);
	}
	?>
</p>
<table class="wc-shipping-zones widefat">
	<thead>
		<tr>
			<th class="wc-shipping-zone-sort"><?php echo wc_help_tip( __( 'Drag and drop to re-order your custom zones. This is the order in which they will be matched against the customer address.', 'woocommerce' ) ); ?></th>
			<th class="wc-shipping-zone-name"><?php esc_html_e( 'Zone name', 'woocommerce' ); ?></th>
			<th class="wc-shipping-zone-region"><?php esc_html_e( 'Region(s)', 'woocommerce' ); ?></th>
			<th class="wc-shipping-zone-methods"><?php esc_html_e( 'Shipping method(s)', 'woocommerce' ); ?></th>
			<th></th>
		</tr>
	</thead>
	<tbody class="wc-shipping-zone-rows wc-shipping-tables-tbody"></tbody>

	<tfoot data-id="0" class="wc-shipping-zone-worldwide wc-shipping-zone-rows-tfoot">
		<td width="1%" class="wc-shipping-zone-worldwide"></td>
		<td class="wc-shipping-zone-name">
			<?php esc_html_e( 'Rest of the world', 'woocommerce' ); ?>
		</td>
		<td class="wc-shipping-zone-region"><?php esc_html_e( 'An optional zone you can use to set the shipping method(s) available to any regions that have not been listed above.', 'woocommerce' ); ?></td>
		<td class="wc-shipping-zone-methods">
			<ul>
				<?php
				$worldwide = new WC_Shipping_Zone( 0 );
				$methods   = $worldwide->get_shipping_methods();
				uasort( $methods, 'wc_shipping_zone_method_order_uasort_comparison' );

				if ( ! empty( $methods ) ) {
					foreach ( $methods as $method ) {
						$class_name = 'yes' === $method->enabled ? 'method_enabled' : 'method_disabled';
						echo '<li class="wc-shipping-zone-method ' . esc_attr( $class_name ) . '" data-id="' . esc_attr( $method->instance_id ) . '">' . esc_html( $method->get_title() ) . '</li>';
					}
				} else {
					echo '<li>' . esc_html__( 'No shipping methods offered to this zone.', 'woocommerce' ) . '</li>';
				}
				?>
			</ul>
		</td>
		<td class="wc-shipping-zone-actions">
			<a class="wc-shipping-zone-action-edit" href="admin.php?page=wc-settings&amp;tab=shipping&amp;zone_id=0"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a>
		</td>
	</tfoot>

</table>

<script type="text/html" id="tmpl-wc-shipping-zone-row-blank">
	<?php if ( 0 === $method_count ) : ?>
		<tr>
			<td class="wc-shipping-zones-blank-state" colspan="5">
				<p class="main"><?php esc_html_e( 'A shipping zone is a geographic region where a certain set of shipping methods and rates apply.', 'woocommerce' ); ?></p>
				<p><?php esc_html_e( 'For example:', 'woocommerce' ); ?></p>
				<ul>
					<li><?php esc_html_e( 'US domestic zone = All US states = Flat rate shipping', 'woocommerce' ); ?></li>
					<li><?php esc_html_e( 'Europe zone = Any country in Europe = Flat rate shipping', 'woocommerce' ); ?></li>
				</ul>
				<p><?php esc_html_e( 'Add as many zones as you need &ndash; customers will only see the methods available for their address.', 'woocommerce' ); ?></p>
				<a class="button button-primary wc-shipping-zone-add" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&zone_id=new' ) ); ?>"><?php _e( 'Add shipping zone', 'woocommerce' ); ?></a>
			</td>
		</tr>
	<?php endif; ?>
</script>

<script type="text/html" id="tmpl-wc-shipping-zone-row">
	<tr data-id="{{ data.zone_id }}">
		<td width="1%" class="wc-shipping-zone-sort"></td>
		<td class="wc-shipping-zone-name">
			{{ data.zone_name }}
		</td>
		<td class="wc-shipping-zone-region">
			{{ data.formatted_zone_location }}
		</td>
		<td class="wc-shipping-zone-methods">
			<div><ul></ul></div>
		</td>
		<td class="wc-shipping-zone-actions">
			<div>
				<a class="wc-shipping-zone-action-edit" href="admin.php?page=wc-settings&amp;tab=shipping&amp;zone_id={{ data.zone_id }}"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a> | <a href="#" class="wc-shipping-zone-delete wc-shipping-zone-actions"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a>
			</div>
		</td>
	</tr>
</script>

<script type="text/template" id="tmpl-wc-modal-add-shipping-method">
	<div class="wc-backbone-modal">
		<div class="wc-backbone-modal-content">
			<section class="wc-backbone-modal-main" role="main">
				<header class="wc-backbone-modal-header">
					<h1><?php esc_html_e( 'Add shipping method', 'woocommerce' ); ?></h1>
					<button class="modal-close modal-close-link dashicons dashicons-no-alt">
						<span class="screen-reader-text"><?php esc_html_e( 'Close modal panel', 'woocommerce' ); ?></span>
					</button>
				</header>
				<article>
					<form action="" method="post">
						<div class="wc-shipping-zone-method-selector">
							<p><?php esc_html_e( 'Choose the shipping method you wish to add. Only shipping methods which support zones are listed.', 'woocommerce' ); ?></p>

							<select name="add_method_id">
								<?php
								foreach ( WC()->shipping()->load_shipping_methods() as $method ) {
									if ( ! $method->supports( 'shipping-zones' ) ) {
										continue;
									}
									echo '<option data-description="' . esc_attr( wp_kses_post( wpautop( $method->get_method_description() ) ) ) . '" value="' . esc_attr( $method->id ) . '">' . esc_html( $method->get_method_title() ) . '</li>';
								}
								?>
							</select>
							<input type="hidden" name="zone_id" value="{{{ data.zone_id }}}" />
						</div>
					</form>
				</article>
				<footer>
					<div class="inner">
						<button id="btn-ok" class="button button-primary button-large"><?php _e( 'Add shipping method', 'woocommerce' ); ?></button>
					</div>
				</footer>
			</section>
		</div>
	</div>
	<div class="wc-backbone-modal-backdrop modal-close"></div>
</script>
PK     tS\sP?    :  settings/views/html-admin-page-shipping-zones-instance.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<h2>
	<a href="<?php echo admin_url( 'admin.php?page=wc-settings&tab=shipping' ); ?>"><?php _e( 'Shipping zones', 'woocommerce' ); ?></a> &gt;
	<a href="<?php echo admin_url( 'admin.php?page=wc-settings&tab=shipping&zone_id=' . absint( $zone->get_id() ) ); ?>"><?php echo esc_html( $zone->get_zone_name() ); ?></a> &gt;
	<?php echo esc_html( $shipping_method->get_method_title() ); ?>
</h2>

<?php $shipping_method->admin_options(); ?>
PK     tS\Z>M"      -  settings/views/class-wc-settings-rest-api.phpnu [        <?php // @codingStandardsIgnoreFile.
/**
 * Settings class file.
 *
 * @deprecated 3.4.0 Replaced with class-wc-settings-advanced.php.
 * @todo remove in 4.0.
 */

defined( 'ABSPATH' ) || exit;

return include __DIR__ . '/class-wc-settings-advanced.php';
PK     tS\EZ02  02  8  settings/views/html-admin-page-shipping-zone-methods.phpnu [        <?php
/**
 * Shipping zone admin
 *
 * @package WooCommerce\Admin\Shipping
 */

use Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils;
use Automattic\WooCommerce\Blocks\Shipping\ShippingController;
use Automattic\WooCommerce\StoreApi\Utilities\LocalPickupUtils;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>


<?php wc_back_header( $zone->get_zone_name() ? $zone->get_zone_name() : __( 'Add zone', 'woocommerce' ), __( 'Return to shipping', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ); ?>

<?php
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
do_action( 'woocommerce_shipping_zone_before_methods_table', $zone );
?>

<table class="form-table wc-shipping-zone-settings">
	<tbody>
		<?php if ( 0 !== $zone->get_id() ) : ?>
			<tr valign="top" class="">
				<th scope="row" class="titledesc">
					<label for="zone_name">
						<?php esc_html_e( 'Zone name', 'woocommerce' ); ?>
					</label>
					<p class="wc-shipping-zone-help-text">
						<?php esc_html_e( 'Give your zone a name! E.g. Local, or Worldwide.', 'woocommerce' ); ?>
					</p>
				</th>
				<td class="forminp">
					<input type="text" data-attribute="zone_name" name="zone_name" id="zone_name" value="<?php echo esc_attr( $zone->get_zone_name( 'edit' ) ); ?>" placeholder="<?php esc_attr_e( 'Zone name', 'woocommerce' ); ?>">
				</td>
			</tr>
			<tr valign="top" class="">
				<th scope="row" class="titledesc">
					<label for="zone_locations">
						<?php esc_html_e( 'Zone regions', 'woocommerce' ); ?>
					</label>
					<p class="wc-shipping-zone-help-text">
						<?php esc_html_e( 'List the regions you\'d like to include in your shipping zone. Customers will be matched against these regions.', 'woocommerce' ); ?>
					</p>
				</th>
				<td>
					<div>
						<div id="wc-shipping-zone-region-picker-root"/>
					</div>
					<?php if ( empty( $postcodes ) ) : ?>
						<a class="wc-shipping-zone-postcodes-toggle" href="#"><?php esc_html_e( 'Limit to specific ZIP/postcodes', 'woocommerce' ); ?></a>
					<?php endif; ?>
					<div class="wc-shipping-zone-postcodes">
						<textarea name="zone_postcodes" data-attribute="zone_postcodes" id="zone_postcodes" placeholder="<?php esc_attr_e( 'List 1 postcode per line', 'woocommerce' ); ?>" class="input-text large-text" cols="25" rows="5"><?php echo esc_textarea( implode( "\n", $postcodes ) ); ?></textarea>
						<?php /* translators: WooCommerce link to setting up shipping zones */ ?>
						<span class="description"><?php printf( __( 'Postcodes containing wildcards (e.g. CB23*) or fully numeric ranges (e.g. <code>90210...99000</code>) are also supported. Please see the shipping zones <a href="%s" target="_blank">documentation</a> for more information.', 'woocommerce' ), 'https://woocommerce.com/document/setting-up-shipping-zones/#section-3' ); ?></span><?php // @codingStandardsIgnoreLine. ?>
					</div>
				</td>
			</tr>
		<?php endif; ?>
		<tr valign="top" class="">
			<th scope="row" class="titledesc">
				<label>
					<?php esc_html_e( 'Shipping methods', 'woocommerce' ); ?>
				</label>
				<p class="wc-shipping-zone-help-text">
					<?php esc_html_e( 'Add the shipping methods you\'d like to make available to customers in this zone.', 'woocommerce' ); ?>
				</p>
			</th>
			<td class="">
				<table class="wc-shipping-zone-methods widefat">
					<thead>
						<tr>
							<th class="wc-shipping-zone-method-sort"></th>
							<th class="wc-shipping-zone-method-title"><?php esc_html_e( 'Title', 'woocommerce' ); ?></th>
							<th class="wc-shipping-zone-method-enabled"><?php esc_html_e( 'Enabled', 'woocommerce' ); ?></th>
							<th class="wc-shipping-zone-method-description"><?php esc_html_e( 'Description', 'woocommerce' ); ?></th>
							<th></th>
						</tr>
					</thead>
					<tbody class="wc-shipping-zone-method-rows wc-shipping-tables-tbody"></tbody>
				</table>
			</td>
		</tr>
		<tr>
			<th scope="row"></th>
			<td>
				<button type="submit" class="wc-shipping-zone-add-method components-button is-primary" value="<?php esc_attr_e( 'Add shipping method', 'woocommerce' ); ?>"><?php esc_html_e( 'Add shipping method', 'woocommerce' ); ?></button>
			</td>
		</tr>
	</tbody>
</table>

<?php
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
do_action( 'woocommerce_shipping_zone_after_methods_table', $zone );
?>

<p class="submit">
	<button type="submit" name="submit" id="submit" class="button-primary button-large wc-shipping-zone-method-save components-button is-primary" value="<?php esc_attr_e( 'Save changes', 'woocommerce' ); ?>" disabled><?php esc_html_e( 'Save changes', 'woocommerce' ); ?></button>
</p>

<script type="text/html" id="tmpl-wc-shipping-zone-method-row-blank">
	<tr>
		<td class="wc-shipping-zone-method-blank-state" colspan="5">
			<p><?php esc_html_e( 'You can add multiple shipping methods within this zone. Only customers within the zone will see them.', 'woocommerce' ); ?></p>
		</td>
	</tr>
</script>

<script type="text/html" id="tmpl-wc-shipping-zone-method-row">
	<tr data-id="{{ data.instance_id }}" data-enabled="{{ data.enabled }}">
		<td width="1%" class="wc-shipping-zone-method-sort"></td>
		<td class="wc-shipping-zone-method-title">
			{{{ data.title }}}
		</td>
		<td width="1%" class="wc-shipping-zone-method-enabled"><a href="#">{{{ data.enabled_icon }}}</a></td>
		<td class="wc-shipping-zone-method-description">
			{{{ data.method_description }}}
		</td>
		<td class="wc-shipping-zone-actions">
			<div>
				<a class="wc-shipping-zone-method-settings wc-shipping-zone-action-edit" href="admin.php?page=wc-settings&amp;tab=shipping&amp;instance_id={{ data.instance_id }}"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a> | <a href="#" class="wc-shipping-zone-method-delete wc-shipping-zone-actions"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a>
			</div>
		</td>
	</tr>
</script>

<script type="text/template" id="tmpl-wc-modal-shipping-method-settings">
	<div class="wc-backbone-modal wc-backbone-modal-shipping-method-settings">
		<div class="wc-backbone-modal-content">
			<section class="wc-backbone-modal-main" role="main">
				<header class="wc-backbone-modal-header">
					<h1>
						<?php
						printf(
							/* translators: %s: shipping method title */
							esc_html__( 'Set up %s', 'woocommerce' ),
							'{{{ data.method.method_title.toLowerCase() }}}'
						);
						?>
					</h1>
					<button class="modal-close modal-close-link dashicons dashicons-no-alt">
						<span class="screen-reader-text"><?php esc_html_e( 'Close modal panel', 'woocommerce' ); ?></span>
					</button>
				</header>
				<article class="wc-modal-shipping-method-settings" data-id="{{{ data.instance_id }}}" data-status="{{{ data.status }}}"  data-shipping-classes-count="<?php echo count( WC()->shipping()->get_shipping_classes() ); ?>">
					<form action="" method="post">
						{{{ data.method.settings_html }}}
						<input type="hidden" name="instance_id" value="{{{ data.instance_id }}}" />
					</form>
					<a class="wc-shipping-method-add-class-costs" style="display:none;" target="_blank" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&section=classes' ) ); ?>"><?php esc_html_e( 'Add shipping class costs', 'woocommerce' ); ?></a>
				</article>
				<footer>
					<div class="inner">
						<div>
							<button id="btn-back" class="button button-large wc-backbone-modal-back-{{ data.status === 'new' ? 'active' : 'inactive' }}"><?php esc_html_e( 'Back', 'woocommerce' ); ?></button>
							<button id="btn-ok" data-status='{{ data.status }}' class="button button-primary button-large">
								<div class="wc-backbone-modal-action-{{ data.status === 'new' ? 'active' : 'inactive' }}"><?php esc_html_e( 'Create and save', 'woocommerce' ); ?></div>
								<div class="wc-backbone-modal-action-{{ data.status === 'existing' ? 'active' : 'inactive' }}"><?php esc_html_e( 'Save', 'woocommerce' ); ?></div>
							</button>
						</div>
						<div class="wc-shipping-zone-method-modal-info wc-shipping-zone-method-modal-info-{{ data.status === 'existing' ? 'inactive' : 'active' }}"><?php esc_html_e( 'STEP 2 OF 2', 'woocommerce' ); ?></div>
					</div>
				</footer>
			</section>
		</div>
	</div>
	<div class="wc-backbone-modal-backdrop modal-close"></div>
</script>

<script type="text/template" id="tmpl-wc-modal-add-shipping-method">
	<div class="wc-backbone-modal wc-backbone-modal-add-shipping-method">
		<div class="wc-backbone-modal-content">
			<section class="wc-backbone-modal-main" role="main">
				<header class="wc-backbone-modal-header">
					<h1><?php esc_html_e( 'Create shipping method', 'woocommerce' ); ?></h1>
					<button class="modal-close modal-close-link dashicons dashicons-no-alt">
						<span class="screen-reader-text"><?php esc_html_e( 'Close modal panel', 'woocommerce' ); ?></span>
					</button>
				</header>
				<article>
					<form action="" method="post">
						<fieldset class="wc-shipping-zone-method-selector">
							<legend class="screen-reader-text"><?php esc_html_e( 'Choose the shipping method you wish to add. Only shipping methods which support zones are listed.', 'woocommerce' ); ?></legend>
							<?php
							$methods = WC()->shipping()->load_shipping_methods();

							$methods_placed_in_order = array();
							$first_methods_ids       = array( 'free_shipping', 'flat_rate', 'local_pickup' );

							foreach ( $first_methods_ids as $first_method_id ) {
								foreach ( $methods as $key => $obj ) {
									if ( $obj->id === $first_method_id ) {
										$methods_placed_in_order[] = $obj;
										unset( $methods[ $key ] );
										break;
									}
								}
							}

							$methods_placed_in_order = array_merge( $methods_placed_in_order, array_values( $methods ) );

							foreach ( $methods_placed_in_order as $method ) {
								if ( CartCheckoutUtils::is_checkout_block_default() && ! ShippingController::is_legacy_local_pickup_active() && 'local_pickup' === $method->id ) {
									continue;
								}

								if ( ! $method->supports( 'shipping-zones' ) ) {
									continue;
								}

								echo '<div class="wc-shipping-zone-method-input"><input type="radio" value="' . esc_attr( $method->id ) . '" id="' . esc_attr( $method->id ) . '" name="add_method_id"/><label for="' . esc_attr( $method->id ) . '">' . esc_html( $method->get_method_title() ) . '<span class="dashicons dashicons-yes"></span></label></div>';
							}

							echo '<div class="wc-shipping-zone-method-input-help-text-container">';

							foreach ( $methods_placed_in_order as $method ) {
								if ( ! $method->supports( 'shipping-zones' ) ) {
									continue;
								}

								echo '<div id=' . esc_attr( $method->id ) . '-description class="wc-shipping-zone-method-input-help-text"><span>' . wp_kses_post( wpautop( $method->get_method_description() ) ) . '</span></div>';
							}

							if ( CartCheckoutUtils::is_checkout_block_default() ) {
								echo '<p class="wc-shipping-legacy-local-pickup-help-text-container">';

								if ( ShippingController::is_legacy_local_pickup_active() ) {
									printf(
										wp_kses(
										/* translators: %s: Local pickup settings page URL. */
											__( 'Explore a new enhanced delivery method that allows you to easily offer one or more pickup locations to your customers in the <a href="%s">Local pickup settings page</a>.', 'woocommerce' ),
											array( 'a' => array( 'href' => array() ) )
										),
										esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&section=pickup_location' ) )
									);

								} else {
									/* translators: %s: Local pickup settings page URL. */
									$message = __( 'Local pickup: Set up pickup locations in the <a href="%s">Local pickup settings page</a>.', 'woocommerce' );
									if ( LocalPickupUtils::is_local_pickup_enabled() ) {
										/* translators: %s: Local pickup settings page URL. */
										$message = __( 'Local pickup: Manage existing pickup locations in the <a href="%s">Local pickup settings page</a>.', 'woocommerce' );
									}
									printf(
										wp_kses(
											$message,
											array( 'a' => array( 'href' => array() ) )
										),
										esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&section=pickup_location' ) )
									);
								}

								echo '</p>';
							}

							echo '</div>';

							?>
						</fieldset>
					</form>
				</article>
				<footer>
					<div class="inner">
						<button id="btn-next" disabled class="button button-primary button-large disabled"><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
						<div class="wc-shipping-zone-method-modal-info"><?php esc_html_e( 'STEP 1 OF 2', 'woocommerce' ); ?></div>
					</div>
				</footer>
			</section>
		</div>
	</div>
	<div class="wc-backbone-modal-backdrop modal-close"></div>
</script>
PK     tS\U    3  settings/views/html-admin-page-shipping-classes.phpnu [        <?php
/**
 * Shipping classes admin
 *
 * @package WooCommerce\Admin\Shipping
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

?>

<h2 class="wc-shipping-zones-heading">
	<span><?php esc_html_e( 'Shipping classes', 'woocommerce' ); ?></span>
	<a class="page-title-action wc-shipping-class-add-new" href="#"><?php esc_html_e( 'Add shipping class', 'woocommerce' ); ?></a>
</h2>

<p class="wc-shipping-zone-help-text">
	<?php esc_html_e( 'Use shipping classes to customize the shipping rates for different groups of products, such as heavy items that require higher postage fees.', 'woocommerce' ); ?> <a target="_blank" href="https://woocommerce.com/document/product-shipping-classes/"><?php esc_html_e( 'Learn more', 'woocommerce' ); ?></a>
</p>

<table class="wc-shipping-classes widefat">
	<thead>
		<tr>
			<?php foreach ( $shipping_class_columns as $class => $heading ) : ?>
				<th class="<?php echo esc_attr( $class ); ?>"><?php echo esc_html( $heading ); ?></th>
			<?php endforeach; ?>
			<th />
		</tr>
	</thead>
	<tbody class="wc-shipping-class-rows wc-shipping-tables-tbody"></tbody>
</table>

<script type="text/html" id="tmpl-wc-shipping-class-row-blank">
	<tr>
		<td class="wc-shipping-classes-blank-state" colspan="<?php echo absint( count( $shipping_class_columns ) + 1 ); ?>"><p><?php esc_html_e( 'No shipping classes have been created.', 'woocommerce' ); ?></p></td>
	</tr>
</script>

<!-- 1. Placeholder becomes the "label" in view class div -->
<!-- 1. Add labelFor or some kind of attribute for semantic HTML-->

<script type="text/html" id="tmpl-wc-shipping-class-configure">
<div class="wc-backbone-modal wc-shipping-class-modal">
		<div class="wc-backbone-modal-content" data-id="{{ data.term_id }}">
			<section class="wc-backbone-modal-main" role="main">
				<header class="wc-backbone-modal-header">
					<h1><?php esc_html_e( 'Add shipping class', 'woocommerce' ); ?></h1>
					<button class="modal-close modal-close-link dashicons dashicons-no-alt">
						<span class="screen-reader-text"><?php esc_html_e( 'Close modal panel', 'woocommerce' ); ?></span>
					</button>
				</header>
				<article>
				<form action="" method="post">
					<input type="hidden" name="term_id" value="{{{ data.term_id }}}" />
					<?php
					foreach ( $shipping_class_columns as $class => $heading ) {
						echo '<div class="wc-shipping-class-modal-input ' . esc_attr( $class ) . '">';
						switch ( $class ) {
							case 'wc-shipping-class-name':
								?>
								<div class="view">
									<?php echo esc_html( $heading ); ?> *
								</div>
								<div class="edit">
									<input type="text" name="name" data-attribute="name" value="{{ data.name }}" placeholder="<?php esc_attr_e( 'e.g. Heavy', 'woocommerce' ); ?>" />
								</div>
								<div class="wc-shipping-class-modal-help-text"><?php esc_html_e( 'Give your shipping class a name for easy identification', 'woocommerce' ); ?></div>
								<?php
								break;
							case 'wc-shipping-class-slug':
								?>
								<div class="view">
									<?php echo esc_html( $heading ); ?>
								</div>
								<div class="edit">
									<input type="text" name="slug" data-attribute="slug" value="{{ data.slug }}" placeholder="<?php esc_attr_e( 'e.g. heavy-packages', 'woocommerce' ); ?>" />
								</div>
								<div class="wc-shipping-class-modal-help-text"><?php esc_html_e( 'Slug (unique identifier) can be left blank and auto-generated, or you can enter one', 'woocommerce' ); ?></div>
								<?php
								break;
							case 'wc-shipping-class-description':
								?>
								<div class="view">
									<?php echo esc_html( $heading ); ?> *
								</div>
								<div class="edit">
									<input type="text" name="description" data-attribute="description" value="{{ data.description }}" placeholder="<?php esc_attr_e( 'e.g. For heavy items requiring higher postage', 'woocommerce' ); ?>" />
								</div>
								<?php
								break;
							case 'wc-shipping-class-count':
								break;
							default:
								?>
								<div class="view wc-shipping-class-hide-sibling-view">
									<?php echo esc_html( $heading ); ?>
								</div>
								<?php
								// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
								do_action( 'woocommerce_shipping_classes_column_' . $class );
								break;
						}
						echo '</div>';
					}
					?>
				</form>
				</article>
				<footer>
					<div class="inner">
						<button id="btn-ok" disabled class="button button-primary button-large disabled">
							<div class="wc-backbone-modal-action-{{ data.action === 'create' ? 'active' : 'inactive' }}"><?php esc_html_e( 'Create', 'woocommerce' ); ?></div>
							<div class="wc-backbone-modal-action-{{ data.action === 'edit' ? 'active' : 'inactive' }}"><?php esc_html_e( 'Save', 'woocommerce' ); ?></div>
						</button>
					</div>
				</footer>
			</section>
		</div>
	</div>
	<div class="wc-backbone-modal-backdrop modal-close"></div>
</script>

<script type="text/html" id="tmpl-wc-shipping-class-row">
	<tr data-id="{{ data.term_id }}">
		<?php
		foreach ( $shipping_class_columns as $class => $heading ) {
			echo '<td class="' . esc_attr( $class ) . '">';
			switch ( $class ) {
				case 'wc-shipping-class-name':
					?>
					<div class="view">
						{{ data.name }}
					</div>
					<?php
					break;
				case 'wc-shipping-class-slug':
					?>
					<div class="view">{{ data.slug }}</div>
					<?php
					break;
				case 'wc-shipping-class-description':
					?>
					<div class="view">{{ data.description }}</div>
					<?php
					break;
				case 'wc-shipping-class-count':
					?>
					<a href="<?php echo esc_url( admin_url( 'edit.php?post_type=product&product_shipping_class=' ) ); ?>{{data.slug}}">{{ data.count }}</a>
					<?php
					break;
				default:
					// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
					do_action( 'woocommerce_shipping_classes_column_' . $class );
					break;
			}
			echo '</td>';
		}
		?>
		<td class="wc-shipping-zone-actions">
			<div>
				<a class="wc-shipping-class-edit wc-shipping-zone-action-edit" href="#"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a> | <a href="#" class="wc-shipping-class-delete wc-shipping-zone-actions"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a>
			</div>
		</td>
	</tr>
</script>
PK     tS\&  &  %  settings/views/html-webhooks-edit.phpnu [        <?php
/**
 * Admin View: Edit Webhooks
 *
 * @package WooCommerce\Admin\Webhooks\Views
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>

<input type="hidden" name="webhook_id" value="<?php echo esc_attr( $webhook->get_id() ); ?>" />

<div id="webhook-options" class="settings-panel">
	<h2><?php esc_html_e( 'Webhook data', 'woocommerce' ); ?></h2>
	<table class="form-table">
		<tbody>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<label for="webhook_name">
						<?php esc_html_e( 'Name', 'woocommerce' ); ?>
						<?php
						/* translators: %s: date */
						echo wc_help_tip( sprintf( __( 'Friendly name for identifying this webhook, defaults to Webhook created on %s.', 'woocommerce' ), (new DateTime('now'))->format( _x( 'M d, Y @ h:i A', 'Webhook created on date parsed by DateTime::format', 'woocommerce' ) ) ) ); // @codingStandardsIgnoreLine
						?>
					</label>
				</th>
				<td class="forminp">
					<input name="webhook_name" id="webhook_name" type="text" class="input-text regular-input" value="<?php echo esc_attr( $webhook->get_name() ); ?>" />
				</td>
			</tr>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<label for="webhook_status">
						<?php esc_html_e( 'Status', 'woocommerce' ); ?>
						<?php echo wc_help_tip( __( 'The options are &quot;Active&quot; (delivers payload), &quot;Paused&quot; (does not deliver), or &quot;Disabled&quot; (does not deliver due delivery failures).', 'woocommerce' ) ); ?>
					</label>
				</th>
				<td class="forminp">
					<select name="webhook_status" id="webhook_status" class="wc-enhanced-select">
						<?php
						$statuses       = wc_get_webhook_statuses();
						$current_status = $webhook->get_status();

						foreach ( $statuses as $status_slug => $status_name ) :
							?>
							<option value="<?php echo esc_attr( $status_slug ); ?>" <?php selected( $current_status, $status_slug, true ); ?>><?php echo esc_html( $status_name ); ?></option>
						<?php endforeach; ?>
					</select>
				</td>
			</tr>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<label for="webhook_topic">
						<?php esc_html_e( 'Topic', 'woocommerce' ); ?>
						<?php echo wc_help_tip( __( 'Select when the webhook will fire.', 'woocommerce' ) ); ?>
					</label>
				</th>
				<td class="forminp">
					<select name="webhook_topic" id="webhook_topic" class="wc-enhanced-select">
						<?php
							$topic_data = WC_Admin_Webhooks::get_topic_data( $webhook );

							$topics = apply_filters(
								'woocommerce_webhook_topics',
								array(
									''                 => __( 'Select an option&hellip;', 'woocommerce' ),
									'coupon.created'   => __( 'Coupon created', 'woocommerce' ),
									'coupon.updated'   => __( 'Coupon updated', 'woocommerce' ),
									'coupon.deleted'   => __( 'Coupon deleted', 'woocommerce' ),
									'coupon.restored'  => __( 'Coupon restored', 'woocommerce' ),
									'customer.created' => __( 'Customer created', 'woocommerce' ),
									'customer.updated' => __( 'Customer updated', 'woocommerce' ),
									'customer.deleted' => __( 'Customer deleted', 'woocommerce' ),
									'order.created'    => __( 'Order created', 'woocommerce' ),
									'order.updated'    => __( 'Order updated', 'woocommerce' ),
									'order.deleted'    => __( 'Order deleted', 'woocommerce' ),
									'order.restored'   => __( 'Order restored', 'woocommerce' ),
									'product.created'  => __( 'Product created', 'woocommerce' ),
									'product.updated'  => __( 'Product updated', 'woocommerce' ),
									'product.deleted'  => __( 'Product deleted', 'woocommerce' ),
									'product.restored' => __( 'Product restored', 'woocommerce' ),
									'action'           => __( 'Action', 'woocommerce' ),
								)
							);

							foreach ( $topics as $topic_slug => $topic_name ) :

								$selected = $topic_slug === $topic_data['topic'] || $topic_slug === $topic_data['resource'] . '.' . $topic_data['event'];

								?>
								<option value="<?php echo esc_attr( $topic_slug ); ?>" <?php selected( $selected, true, true ); ?>><?php echo esc_html( $topic_name ); ?></option>
						<?php endforeach; ?>
					</select>
				</td>
			</tr>
			<tr valign="top" id="webhook-action-event-wrap">
				<th scope="row" class="titledesc">
					<label for="webhook_action_event">
						<?php esc_html_e( 'Action event', 'woocommerce' ); ?>
						<?php echo wc_help_tip( __( 'Enter the action that will trigger this webhook.', 'woocommerce' ) ); ?>
					</label>
				</th>
				<td class="forminp">
					<input name="webhook_action_event" id="webhook_action_event" type="text" class="input-text regular-input" value="<?php echo esc_attr( $topic_data['event'] ); ?>" />
				</td>
			</tr>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<label for="webhook_delivery_url">
						<?php esc_html_e( 'Delivery URL', 'woocommerce' ); ?>
						<?php echo wc_help_tip( __( 'URL where the webhook payload is delivered.', 'woocommerce' ) ); ?>
					</label>
				</th>
				<td class="forminp">
					<input name="webhook_delivery_url" id="webhook_delivery_url" type="text" class="input-text regular-input" value="<?php echo esc_attr( $webhook->get_delivery_url() ); ?>" />
				</td>
			</tr>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<label for="webhook_secret">
						<?php esc_html_e( 'Secret', 'woocommerce' ); ?>
						<?php echo wc_help_tip( __( 'The secret key is used to generate a hash of the delivered webhook and provided in the request headers.', 'woocommerce' ) ); ?>
					</label>
				</th>
				<td class="forminp">
					<input name="webhook_secret" id="webhook_secret" type="text" class="input-text regular-input" value="<?php echo esc_attr( $webhook->get_secret() ); ?>" />
				</td>
			</tr>
			<tr valign="top">
				<th scope="row" class="titledesc">
					<label for="webhook_api_version">
						<?php esc_html_e( 'API Version', 'woocommerce' ); ?>
						<?php echo wc_help_tip( __( 'REST API version used in the webhook deliveries.', 'woocommerce' ) ); ?>
					</label>
				</th>
				<td class="forminp">
					<select name="webhook_api_version" id="webhook_api_version">
						<?php foreach ( array_reverse( wc_get_webhook_rest_api_versions() ) as $version ) : ?>
							<option value="<?php echo esc_attr( $version ); ?>" <?php selected( $version, $webhook->get_api_version(), true ); ?>>
								<?php
									/* translators: %d: rest api version number */
									echo esc_html( sprintf( __( 'WP REST API Integration v%d', 'woocommerce' ), str_replace( 'wp_api_v', '', $version ) ) );
								?>
							</option>
						<?php endforeach; ?>
						<?php
						$legacy_api_option_name =
							WC()->legacy_rest_api_is_available() ?
							__( 'Legacy API v3 (deprecated)', 'woocommerce' ) :
							__( 'Legacy API v3 (⚠️ NOT AVAILABLE)', 'woocommerce' );
						?>
						<option value="legacy_v3" <?php selected( 'legacy_v3', $webhook->get_api_version(), true ); ?>><?php echo esc_html( $legacy_api_option_name ); ?></option>
					</select>
				</td>
			</tr>
		</tbody>
	</table>

	<?php
	/**
	 * Fires within the webhook editor, after the Webhook Data fields have rendered.
	 *
	 * @param WC_Webhook $webhook
	 */
	do_action( 'woocommerce_webhook_options', $webhook );
	?>
</div>

<div id="webhook-actions" class="settings-panel">
	<h2><?php esc_html_e( 'Webhook actions', 'woocommerce' ); ?></h2>
	<table class="form-table">
		<tbody>
			<?php if ( $webhook->get_date_created() && '0000-00-00 00:00:00' !== $webhook->get_date_created()->date( 'Y-m-d H:i:s' ) ) : ?>
				<?php if ( is_null( $webhook->get_date_modified() ) ) : ?>
					<tr valign="top">
						<th scope="row" class="titledesc">
							<?php esc_html_e( 'Created at', 'woocommerce' ); ?>
						</th>
						<td class="forminp">
							<?php echo esc_html( date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $webhook->get_date_created()->date( 'Y-m-d H:i:s' ) ) ) ); ?>
						</td>
					</tr>
				<?php else : ?>
				<tr valign="top">
						<th scope="row" class="titledesc">
							<?php esc_html_e( 'Created at', 'woocommerce' ); ?>
						</th>
						<td class="forminp">
							<?php echo esc_html( date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $webhook->get_date_created()->date( 'Y-m-d H:i:s' ) ) ) ); ?>
						</td>
					</tr>
				<tr valign="top">
						<th scope="row" class="titledesc">
							<?php esc_html_e( 'Updated at', 'woocommerce' ); ?>
						</th>
						<td class="forminp">
							<?php echo esc_html( date_i18n( __( 'M j, Y @ G:i', 'woocommerce' ), strtotime( $webhook->get_date_modified()->date( 'Y-m-d H:i:s' ) ) ) ); ?>
						</td>
					</tr>
				<?php endif; ?>
			<?php endif; ?>
			<tr valign="top">
				<td colspan="2" scope="row" style="padding-left: 0;">
					<p class="submit">
						<button type="submit" class="button button-primary button-large" name="save" id="publish" accesskey="p"><?php esc_html_e( 'Save webhook', 'woocommerce' ); ?></button>
						<?php
						if ( $webhook->get_id() ) :
							$delete_url = wp_nonce_url(
								add_query_arg(
									array(
										'delete' => $webhook->get_id(),
									),
									admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks' )
								),
								'delete-webhook'
							);
							?>
							<a style="color: #a00; text-decoration: none; margin-left: 10px;" href="<?php echo esc_url( $delete_url ); ?>"><?php esc_html_e( 'Delete permanently', 'woocommerce' ); ?></a>
						<?php endif; ?>
					</p>
				</td>
			</tr>
		</tbody>
	</table>
</div>

<script type="text/javascript">
	jQuery( function ( $ ) {
		$( '#webhook-options' ).find( '#webhook_topic' ).on( 'change', function() {
			var current            = $( this ).val(),
				action_event_field = $( '#webhook-options' ).find( '#webhook-action-event-wrap' );

			action_event_field.hide();

			if ( 'action' === current ) {
				action_event_field.show();
			}
		}).trigger( 'change' );
	});
</script>
PK     tS\ܡR  R  '  settings/class-wc-settings-advanced.phpnu [        <?php
/**
 * WooCommerce advanced settings
 *
 * @package  WooCommerce\Admin
 */

use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Utilities\FeaturesUtil;

defined( 'ABSPATH' ) || exit;

/**
 * Settings for API.
 */
if ( class_exists( 'WC_Settings_Advanced', false ) ) {
	return new WC_Settings_Advanced();
}

/**
 * WC_Settings_Advanced.
 */
class WC_Settings_Advanced extends WC_Settings_Page {

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id    = 'advanced';
		$this->label = __( 'Advanced', 'woocommerce' );

		parent::__construct();
		$this->notices();
	}

	/**
	 * Setting page icon.
	 *
	 * @var string
	 */
	public $icon = 'more';

	/**
	 * Get own sections.
	 *
	 * @return array
	 */
	protected function get_own_sections() {
		$sections = array(
			''     => __( 'Page setup', 'woocommerce' ),
			'keys' => __( 'REST API keys', 'woocommerce' ),
		);

		$features_controller = wc_get_container()->get( FeaturesController::class );
		if ( $features_controller->feature_is_enabled( 'rest_api_caching' ) ) {
			$sections['rest_api_caching'] = __( 'REST API caching', 'woocommerce' );
		}

		$sections['webhooks']        = __( 'Webhooks', 'woocommerce' );
		$sections['legacy_api']      = __( 'Legacy API', 'woocommerce' );
		$sections['woocommerce_com'] = __( 'WooCommerce.com', 'woocommerce' );

		if ( FeaturesUtil::feature_is_enabled( 'blueprint' ) ) {
			$sections['blueprint'] = __( 'Blueprint (beta)', 'woocommerce' );
		}

		return $sections;
	}

	/**
	 * Get settings for the default section.
	 *
	 * @return array
	 */
	protected function get_settings_for_default_section() {
		$settings =
			array(
				array(
					'title' => __( 'Page setup', 'woocommerce' ),
					'desc'  => __( 'These pages need to be set so that WooCommerce knows where to send users to checkout.', 'woocommerce' ),
					'type'  => 'title',
					'id'    => 'advanced_page_options',
				),

				array(
					'title'    => __( 'Cart page', 'woocommerce' ),
					/* Translators: %s Page contents. */
					'desc'     => __( 'Page where shoppers review their shopping cart', 'woocommerce' ),
					'id'       => 'woocommerce_cart_page_id',
					'type'     => 'single_select_page_with_search',
					'default'  => '',
					'class'    => 'wc-page-search',
					'css'      => 'min-width:300px;',
					'args'     => array(
						'exclude' =>
							array(
								wc_get_page_id( 'checkout' ),
								wc_get_page_id( 'myaccount' ),
							),
					),
					'desc_tip' => true,
					'autoload' => false,
				),

				array(
					'title'    => __( 'Checkout page', 'woocommerce' ),
					/* Translators: %s Page contents. */
					'desc'     => __( 'Page where shoppers go to finalize their purchase', 'woocommerce' ),
					'id'       => 'woocommerce_checkout_page_id',
					'type'     => 'single_select_page_with_search',
					'default'  => wc_get_page_id( 'checkout' ),
					'class'    => 'wc-page-search',
					'css'      => 'min-width:300px;',
					'args'     => array(
						'exclude' =>
							array(
								wc_get_page_id( 'cart' ),
								wc_get_page_id( 'myaccount' ),
							),
					),
					'desc_tip' => true,
					'autoload' => false,
				),

				array(
					'title'    => __( 'My account page', 'woocommerce' ),
					/* Translators: %s Page contents. */
					'desc'     => sprintf( __( 'Page contents: [%s]', 'woocommerce' ), apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) ),
					'id'       => 'woocommerce_myaccount_page_id',
					'type'     => 'single_select_page_with_search',
					'default'  => '',
					'class'    => 'wc-page-search',
					'css'      => 'min-width:300px;',
					'args'     => array(
						'exclude' =>
							array(
								wc_get_page_id( 'cart' ),
								wc_get_page_id( 'checkout' ),
							),
					),
					'desc_tip' => true,
					'autoload' => false,
				),

				array(
					'title'    => __( 'Terms and conditions', 'woocommerce' ),
					'desc'     => __( 'If you define a "Terms" page the customer will be asked if they accept them when checking out.', 'woocommerce' ),
					'id'       => 'woocommerce_terms_page_id',
					'default'  => '',
					'class'    => 'wc-page-search',
					'css'      => 'min-width:300px;',
					'type'     => 'single_select_page_with_search',
					'args'     => array( 'exclude' => wc_get_page_id( 'checkout' ) ),
					'desc_tip' => true,
					'autoload' => false,
				),

				array(
					'type' => 'sectionend',
					'id'   => 'advanced_page_options',
				),

				array(
					'title' => '',
					'type'  => 'title',
					'id'    => 'checkout_process_options',
				),

				'force_ssl_checkout'   => array(
					'title'           => __( 'Secure checkout', 'woocommerce' ),
					'desc'            => __( 'Force secure checkout', 'woocommerce' ),
					'id'              => 'woocommerce_force_ssl_checkout',
					'default'         => 'no',
					'type'            => 'checkbox',
					'checkboxgroup'   => 'start',
					'show_if_checked' => 'option',
					/* Translators: %s Docs URL. */
					'desc_tip'        => sprintf( __( 'Force SSL (HTTPS) on the checkout pages (<a href="%s" target="_blank">an SSL Certificate is required</a>).', 'woocommerce' ), 'https://woocommerce.com/document/ssl-and-https/#section-3' ),
				),

				'unforce_ssl_checkout' => array(
					'desc'            => __( 'Force HTTP when leaving the checkout', 'woocommerce' ),
					'id'              => 'woocommerce_unforce_ssl_checkout',
					'default'         => 'no',
					'type'            => 'checkbox',
					'checkboxgroup'   => 'end',
					'show_if_checked' => 'yes',
				),

				array(
					'type' => 'sectionend',
					'id'   => 'checkout_process_options',
				),

				array(
					'title' => __( 'Checkout endpoints', 'woocommerce' ),
					'type'  => 'title',
					'desc'  => __( 'Endpoints are appended to your page URLs to handle specific actions during the checkout process. They should be unique.', 'woocommerce' ),
					'id'    => 'checkout_endpoint_options',
				),

				array(
					'title'    => __( 'Pay', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the "Checkout &rarr; Pay" page.', 'woocommerce' ),
					'id'       => 'woocommerce_checkout_pay_endpoint',
					'type'     => 'text',
					'default'  => 'order-pay',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Order received', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the "Checkout &rarr; Order received" page.', 'woocommerce' ),
					'id'       => 'woocommerce_checkout_order_received_endpoint',
					'type'     => 'text',
					'default'  => 'order-received',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Add payment method', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the "Checkout &rarr; Add payment method" page.', 'woocommerce' ),
					'id'       => 'woocommerce_myaccount_add_payment_method_endpoint',
					'type'     => 'text',
					'default'  => 'add-payment-method',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Delete payment method', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the delete payment method page.', 'woocommerce' ),
					'id'       => 'woocommerce_myaccount_delete_payment_method_endpoint',
					'type'     => 'text',
					'default'  => 'delete-payment-method',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Set default payment method', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the setting a default payment method page.', 'woocommerce' ),
					'id'       => 'woocommerce_myaccount_set_default_payment_method_endpoint',
					'type'     => 'text',
					'default'  => 'set-default-payment-method',
					'desc_tip' => true,
				),

				array(
					'type' => 'sectionend',
					'id'   => 'checkout_endpoint_options',
				),

				array(
					'title' => __( 'Account endpoints', 'woocommerce' ),
					'type'  => 'title',
					'desc'  => __( 'Endpoints are appended to your page URLs to handle specific actions on the accounts pages. They should be unique and can be left blank to disable the endpoint.', 'woocommerce' ),
					'id'    => 'account_endpoint_options',
				),

				array(
					'title'    => __( 'Orders', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the "My account &rarr; Orders" page.', 'woocommerce' ),
					'id'       => 'woocommerce_myaccount_orders_endpoint',
					'type'     => 'text',
					'default'  => 'orders',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'View order', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the "My account &rarr; View order" page.', 'woocommerce' ),
					'id'       => 'woocommerce_myaccount_view_order_endpoint',
					'type'     => 'text',
					'default'  => 'view-order',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Downloads', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the "My account &rarr; Downloads" page.', 'woocommerce' ),
					'id'       => 'woocommerce_myaccount_downloads_endpoint',
					'type'     => 'text',
					'default'  => 'downloads',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Edit account', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the "My account &rarr; Edit account" page.', 'woocommerce' ),
					'id'       => 'woocommerce_myaccount_edit_account_endpoint',
					'type'     => 'text',
					'default'  => 'edit-account',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Addresses', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the "My account &rarr; Addresses" page.', 'woocommerce' ),
					'id'       => 'woocommerce_myaccount_edit_address_endpoint',
					'type'     => 'text',
					'default'  => 'edit-address',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Payment methods', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the "My account &rarr; Payment methods" page.', 'woocommerce' ),
					'id'       => 'woocommerce_myaccount_payment_methods_endpoint',
					'type'     => 'text',
					'default'  => 'payment-methods',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Lost password', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the "My account &rarr; Lost password" page.', 'woocommerce' ),
					'id'       => 'woocommerce_myaccount_lost_password_endpoint',
					'type'     => 'text',
					'default'  => 'lost-password',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Logout', 'woocommerce' ),
					'desc'     => __( 'Endpoint for the triggering logout. You can add this to your menus via a custom link: yoursite.com/?customer-logout=true', 'woocommerce' ),
					'id'       => 'woocommerce_logout_endpoint',
					'type'     => 'text',
					'default'  => 'customer-logout',
					'desc_tip' => true,
				),

				array(
					'type' => 'sectionend',
					'id'   => 'account_endpoint_options',
				),
			);

		$settings = apply_filters( 'woocommerce_settings_pages', $settings );

		if ( wc_site_is_https() ) {
			unset( $settings['unforce_ssl_checkout'], $settings['force_ssl_checkout'] );
		}

		return $settings;
	}

	/**
	 * Get settings for the WooCommerce.com section.
	 *
	 * @return array
	 */
	protected function get_settings_for_woocommerce_com_section() {
		$tracking_info_text = sprintf( '<a href="%s" target="_blank">%s</a>', 'https://woocommerce.com/usage-tracking', esc_html__( 'WooCommerce.com Usage Tracking Documentation', 'woocommerce' ) );

		$settings =
			array(
				array(
					'title' => esc_html__( 'Usage Tracking', 'woocommerce' ),
					'type'  => 'title',
					'id'    => 'tracking_options',
					'desc'  => __( 'Gathering usage data allows us to tailor your store setup experience, offer more relevant content, and help make WooCommerce better for everyone.', 'woocommerce' ),
				),
				array(
					'title'         => __( 'Enable tracking', 'woocommerce' ),
					'desc'          => __( 'Allow usage of WooCommerce to be tracked', 'woocommerce' ),
					/* Translators: %s URL to tracking info screen. */
					'desc_tip'      => sprintf( esc_html__( 'To opt out, leave this box unticked. Your store remains untracked, and no data will be collected. Read about what usage data is tracked at: %s.', 'woocommerce' ), $tracking_info_text ),
					'id'            => 'woocommerce_allow_tracking',
					'type'          => 'checkbox',
					'checkboxgroup' => 'start',
					'default'       => 'no',
					'autoload'      => true,
				),
				array(
					'type' => 'sectionend',
					'id'   => 'tracking_options',
				),
				array(
					'title' => esc_html__( 'Marketplace suggestions', 'woocommerce' ),
					'type'  => 'title',
					'id'    => 'marketplace_suggestions',
					'desc'  => __( 'We show contextual suggestions for official extensions that may be helpful to your store.', 'woocommerce' ),
				),
				array(
					'title'         => __( 'Show Suggestions', 'woocommerce' ),
					'desc'          => __( 'Display suggestions within WooCommerce', 'woocommerce' ),
					'desc_tip'      => esc_html__( 'Leave this box unchecked if you do not want to pull suggested extensions from WooCommerce.com.', 'woocommerce' ),
					'id'            => 'woocommerce_show_marketplace_suggestions',
					'type'          => 'checkbox',
					'checkboxgroup' => 'start',
					'default'       => 'yes',
					'autoload'      => false,
				),
				array(
					'type' => 'sectionend',
					'id'   => 'marketplace_suggestions',
				),
			);

		return apply_filters( 'woocommerce_com_integration_settings', $settings );
	}

	/**
	 * Get settings for the legacy API section.
	 *
	 * @return array
	 */
	protected function get_settings_for_legacy_api_section() {
		$legacy_api_setting_desc =
			'yes' === get_option( 'woocommerce_api_enabled' ) ?
			__( 'The legacy REST API is enabled', 'woocommerce' ) :
			__( 'The legacy REST API is NOT enabled', 'woocommerce' );

		$legacy_api_setting_tip =
			WC()->legacy_rest_api_is_available() ?
			__( 'ℹ️️ The WooCommerce Legacy REST API extension is installed and active.', 'woocommerce' ) :
			sprintf(
				/* translators: placeholders are URLs */
				__( '⚠️ The WooCommerce Legacy REST API has been moved to <a target=”_blank” href="%1$s">a dedicated extension</a>. <b><a target=”_blank” href="%2$s">Learn more about this change</a></b>', 'woocommerce' ),
				'https://wordpress.org/plugins/woocommerce-legacy-rest-api/',
				'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
			);

		$settings =
			array(
				array(
					'title' => '',
					'type'  => 'title',
					'desc'  => '',
					'id'    => 'legacy_api_options',
				),
				array(
					'title'    => __( 'Legacy API', 'woocommerce' ),
					'desc'     => $legacy_api_setting_desc,
					'id'       => 'woocommerce_api_enabled',
					'type'     => 'checkbox',
					'default'  => 'no',
					'disabled' => true,
					'desc_tip' => $legacy_api_setting_tip,
				),
				array(
					'type' => 'sectionend',
					'id'   => 'legacy_api_options',
				),
			);

		return apply_filters( 'woocommerce_settings_rest_api', $settings );
	}

	/**
	 * Get settings for the REST API caching section.
	 *
	 * @return array
	 */
	protected function get_settings_for_rest_api_caching_section() {
		$has_object_cache = wp_using_ext_object_cache();

		$settings = array(
			array(
				'title' => __( 'REST API response cache', 'woocommerce' ),
				'type'  => 'title',
				'desc'  => __( 'These settings control backend caching and cache control headers for REST API responses.', 'woocommerce' ),
				'id'    => 'rest_api_cache_options',
			),
		);

		if ( ! $has_object_cache ) {
			$settings[] = array(
				'type'        => 'notice',
				'id'          => 'rest_api_cache_warning',
				'notice_type' => 'warning',
				'text'        => sprintf(
					/* translators: %1$s and %2$s are opening and closing <a> tags */
					__( 'Backend caching requires a WordPress object cache plugin (Redis, Memcached, etc.) to be installed and active. %1$sLearn more about object caching%2$s.', 'woocommerce' ),
					'<a href="https://developer.wordpress.org/reference/classes/wp_object_cache/" target="_blank">',
					'</a>'
				),
			);
		}

		$backend_caching_setting = array(
			'title'       => __( 'Enable backend caching', 'woocommerce' ),
			'desc'        => __( 'Cache REST API responses on the server', 'woocommerce' ),
			'id'          => 'woocommerce_rest_api_enable_backend_caching',
			'type'        => 'checkbox',
			'default'     => 'no',
			'disabled'    => ! $has_object_cache,
			'fixed_value' => $has_object_cache ? null : 'no',
			'desc_tip'    => __( 'Enables responses for REST API endpoints configured as cacheable. Requires an external object cache.<br/>This setting should be enabled only if no other plugins that handle caching are active.', 'woocommerce' ),
		);

		$settings[] = $backend_caching_setting;

		$settings[] = array(
			'title'    => __( 'Enable cache control headers', 'woocommerce' ),
			'desc'     => __( 'Send cache control headers and support 304 Not Modified responses', 'woocommerce' ),
			'id'       => 'woocommerce_rest_api_enable_cache_headers',
			'type'     => 'checkbox',
			'default'  => 'yes',
			'desc_tip' => __( 'Enables including ETag and Cache-Control headers, and returning 304 Not Modified responses, for REST API endpoints configured as cacheable.', 'woocommerce' ),
		);

		$settings[] = array(
			'type' => 'sectionend',
			'id'   => 'rest_api_cache_options',
		);

		/**
		 * Filter REST API cache settings.
		 *
		 * @since 10.5.0
		 * @param array $settings REST API cache settings.
		 */
		return apply_filters( 'woocommerce_rest_api_cache_settings', $settings );
	}

	/**
	 * Get settings for the Blueprint section.
	 *
	 * @return array
	 */
	protected function get_settings_for_blueprint_section() {
		$settings =
			array(
				array(
					'id'   => 'wc_settings_blueprint_slotfill',
					'type' => 'slotfill_placeholder',
				),
			);

		return $settings;
	}

	/**
	 * Form method.
	 *
	 * @deprecated 3.4.4
	 *
	 * @param  string $method Method name.
	 *
	 * @return string
	 */
	public function form_method( $method ) {
		return 'post';
	}

	/**
	 * Notices.
	 */
	private function notices() {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		if ( isset( $_GET['section'] ) && 'webhooks' === $_GET['section'] ) {
			WC_Admin_Webhooks::notices();
		}
		if ( isset( $_GET['section'] ) && 'keys' === $_GET['section'] ) {
			WC_Admin_API_Keys::notices();
		}
		// phpcs:enable
	}

	/**
	 * Output the settings.
	 */
	public function output() {
		global $current_section, $hide_save_button;

		if ( 'blueprint' === $current_section ) {
			$hide_save_button = true;
		}

		if ( 'webhooks' === $current_section ) {
			WC_Admin_Webhooks::page_output();
		} elseif ( 'keys' === $current_section ) {
			WC_Admin_API_Keys::page_output();
		} else {
			parent::output();
		}
	}

	/**
	 * Save settings.
	 */
	public function save() {
		// phpcs:disable WordPress.Security.NonceVerification.Missing
		global $current_section;

		$prev_value = 'yes' === get_option( 'woocommerce_allow_tracking', 'no' ) ? 'yes' : 'no';
		$new_value  = isset( $_POST['woocommerce_allow_tracking'] ) && ( 'yes' === $_POST['woocommerce_allow_tracking'] || '1' === $_POST['woocommerce_allow_tracking'] ) ? 'yes' : 'no';

		if ( apply_filters( 'woocommerce_rest_api_valid_to_save', ! in_array( $current_section, array( 'keys', 'webhooks' ), true ) ) ) {
			// Prevent the T&Cs and checkout page from being set to the same page.
			if ( isset( $_POST['woocommerce_terms_page_id'], $_POST['woocommerce_checkout_page_id'] ) && $_POST['woocommerce_terms_page_id'] === $_POST['woocommerce_checkout_page_id'] ) {
				$_POST['woocommerce_terms_page_id'] = '';
			}

			// Prevent the Cart, checkout and my account page from being set to the same page.
			if ( isset( $_POST['woocommerce_cart_page_id'], $_POST['woocommerce_checkout_page_id'], $_POST['woocommerce_myaccount_page_id'] ) ) {
				if ( $_POST['woocommerce_cart_page_id'] === $_POST['woocommerce_checkout_page_id'] ) {
					$_POST['woocommerce_checkout_page_id'] = '';
				}
				if ( $_POST['woocommerce_cart_page_id'] === $_POST['woocommerce_myaccount_page_id'] ) {
					$_POST['woocommerce_myaccount_page_id'] = '';
				}
				if ( $_POST['woocommerce_checkout_page_id'] === $_POST['woocommerce_myaccount_page_id'] ) {
					$_POST['woocommerce_myaccount_page_id'] = '';
				}
			}

			if ( class_exists( 'WC_Tracks' ) && 'no' === $new_value && 'yes' === $prev_value ) {
				WC_Tracks::track_woocommerce_allow_tracking_toggled( $prev_value, $new_value, 'settings' );
			}

			$this->save_settings_for_current_section();
			$this->do_update_options_action();

			if ( class_exists( 'WC_Tracks' ) && 'yes' === $new_value && 'no' === $prev_value ) {
				WC_Tracks::track_woocommerce_allow_tracking_toggled( $prev_value, $new_value, 'settings' );
			}
		}
		// phpcs:enable
	}
}

// phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound, Generic.Commenting.Todo.CommentFound
/**
 * WC_Settings_Rest_API class.
 *
 * @deprecated 3.4 in favour of WC_Settings_Advanced.
 */
class WC_Settings_Rest_API extends WC_Settings_Advanced {
}

return new WC_Settings_Advanced();
// phpcs:enable
PK     tS\" F   F  '  settings/class-wc-settings-products.phpnu [        <?php
/**
 * WooCommerce Product Settings
 *
 * @package WooCommerce\Admin
 * @version 2.4.0
 */

use Automattic\WooCommerce\Utilities\I18nUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( class_exists( 'WC_Settings_Products', false ) ) {
	return new WC_Settings_Products();
}

/**
 * WC_Settings_Products.
 */
class WC_Settings_Products extends WC_Settings_Page {

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id    = 'products';
		$this->label = __( 'Products', 'woocommerce' );

		parent::__construct();
	}

	/**
	 * Setting page icon.
	 *
	 * @var string
	 */
	public $icon = 'box';

	/**
	 * Get own sections.
	 *
	 * @return array
	 */
	protected function get_own_sections() {
		return array(
			''             => __( 'General', 'woocommerce' ),
			'inventory'    => __( 'Inventory', 'woocommerce' ),
			'downloadable' => __( 'Downloadable products', 'woocommerce' ),
		);
	}

	/**
	 * Get settings for the default section.
	 *
	 * @return array
	 */
	protected function get_settings_for_default_section() {
		$locale_info            = include WC()->plugin_path() . '/i18n/locale-info.php';
		$default_weight_unit    = $locale_info['US']['weight_unit'];
		$default_dimension_unit = $locale_info['US']['dimension_unit'];

		$settings =
			array(
				array(
					'title' => __( 'Shop pages', 'woocommerce' ),
					'type'  => 'title',
					'desc'  => '',
					'id'    => 'catalog_options',
				),
				array(
					'title'    => __( 'Shop page', 'woocommerce' ),
					/* translators: %s: URL to settings. */
					'desc'     => sprintf( __( 'The base page can also be used in your <a href="%s">product permalinks</a>.', 'woocommerce' ), admin_url( 'options-permalink.php' ) ),
					'id'       => 'woocommerce_shop_page_id',
					'type'     => 'single_select_page',
					'default'  => '',
					'class'    => 'wc-enhanced-select-nostd',
					'css'      => 'min-width:300px;',
					'desc_tip' => __( 'This sets the base page of your shop - this is where your product archive will be.', 'woocommerce' ),
				),
				array(
					'title'         => __( 'Add to cart behaviour', 'woocommerce' ),
					'desc'          => __( 'Redirect to the cart page after successful addition', 'woocommerce' ),
					'id'            => 'woocommerce_cart_redirect_after_add',
					'default'       => 'no',
					'type'          => 'checkbox',
					'checkboxgroup' => 'start',
				),
				array(
					'desc'          => __( 'Enable AJAX add to cart buttons on archives', 'woocommerce' ),
					'id'            => 'woocommerce_enable_ajax_add_to_cart',
					'default'       => 'yes',
					'type'          => 'checkbox',
					'checkboxgroup' => 'end',
				),
				array(
					'title'       => __( 'Placeholder image', 'woocommerce' ),
					'id'          => 'woocommerce_placeholder_image',
					'type'        => 'text',
					'default'     => '',
					'class'       => '',
					'css'         => '',
					'placeholder' => __( 'Enter attachment ID or URL to an image', 'woocommerce' ),
					'desc_tip'    => __( 'This is the attachment ID, or image URL, used for placeholder images in the product catalog. Products with no image will use this.', 'woocommerce' ),
				),
				array(
					'type' => 'sectionend',
					'id'   => 'catalog_options',
				),

				array(
					'title' => __( 'Measurements', 'woocommerce' ),
					'type'  => 'title',
					'id'    => 'product_measurement_options',
				),

				array(
					'title'    => __( 'Weight unit', 'woocommerce' ),
					'desc'     => __( 'This controls what unit you will define weights in.', 'woocommerce' ),
					'id'       => 'woocommerce_weight_unit',
					'class'    => 'wc-enhanced-select',
					'css'      => 'min-width:300px;',
					'default'  => $default_weight_unit,
					'type'     => 'select',
					'options'  => array(
						'kg'  => I18nUtil::get_weight_unit_label( 'kg' ),
						'g'   => I18nUtil::get_weight_unit_label( 'g' ),
						'lbs' => I18nUtil::get_weight_unit_label( 'lbs' ),
						'oz'  => I18nUtil::get_weight_unit_label( 'oz' ),
					),
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Dimensions unit', 'woocommerce' ),
					'desc'     => __( 'This controls what unit you will define lengths in.', 'woocommerce' ),
					'id'       => 'woocommerce_dimension_unit',
					'class'    => 'wc-enhanced-select',
					'css'      => 'min-width:300px;',
					'default'  => $default_dimension_unit,
					'type'     => 'select',
					'options'  => array(
						'm'  => I18nUtil::get_dimensions_unit_label( 'm' ),
						'cm' => I18nUtil::get_dimensions_unit_label( 'cm' ),
						'mm' => I18nUtil::get_dimensions_unit_label( 'mm' ),
						'in' => I18nUtil::get_dimensions_unit_label( 'in' ),
						'yd' => I18nUtil::get_dimensions_unit_label( 'yd' ),
					),
					'desc_tip' => true,
				),

				array(
					'type' => 'sectionend',
					'id'   => 'product_measurement_options',
				),

				array(
					'title' => __( 'Reviews', 'woocommerce' ),
					'type'  => 'title',
					'desc'  => '',
					'id'    => 'product_rating_options',
				),

				array(
					'title'           => __( 'Enable reviews', 'woocommerce' ),
					'desc'            => __( 'Enable product reviews', 'woocommerce' ),
					'id'              => 'woocommerce_enable_reviews',
					'default'         => 'yes',
					'type'            => 'checkbox',
					'checkboxgroup'   => 'start',
					'show_if_checked' => 'option',
				),

				array(
					'desc'            => __( 'Show "verified owner" label on customer reviews', 'woocommerce' ),
					'id'              => 'woocommerce_review_rating_verification_label',
					'default'         => 'yes',
					'type'            => 'checkbox',
					'checkboxgroup'   => '',
					'show_if_checked' => 'yes',
					'autoload'        => false,
				),

				array(
					'desc'            => __( 'Reviews can only be left by "verified owners"', 'woocommerce' ),
					'id'              => 'woocommerce_review_rating_verification_required',
					'default'         => 'no',
					'type'            => 'checkbox',
					'checkboxgroup'   => 'end',
					'show_if_checked' => 'yes',
					'autoload'        => false,
				),

				array(
					'title'           => __( 'Product ratings', 'woocommerce' ),
					'desc'            => __( 'Enable star rating on reviews', 'woocommerce' ),
					'id'              => 'woocommerce_enable_review_rating',
					'default'         => 'yes',
					'type'            => 'checkbox',
					'checkboxgroup'   => 'start',
					'show_if_checked' => 'option',
				),

				array(
					'desc'            => __( 'Star ratings should be required, not optional', 'woocommerce' ),
					'id'              => 'woocommerce_review_rating_required',
					'default'         => 'yes',
					'type'            => 'checkbox',
					'checkboxgroup'   => 'end',
					'show_if_checked' => 'yes',
					'autoload'        => false,
				),

				array(
					'type' => 'sectionend',
					'id'   => 'product_rating_options',
				),
			);

		$settings = apply_filters( 'woocommerce_products_general_settings', $settings );
		return apply_filters( 'woocommerce_product_settings', $settings );
	}

	/**
	 * Get settings for the inventory section.
	 *
	 * @return array
	 */
	protected function get_settings_for_inventory_section() {
		$settings =
			array(
				array(
					'title' => __( 'Inventory', 'woocommerce' ),
					'type'  => 'title',
					'desc'  => '',
					'id'    => 'product_inventory_options',
				),

				array(
					'title'   => __( 'Manage stock', 'woocommerce' ),
					'desc'    => __( 'Enable stock management', 'woocommerce' ),
					'id'      => 'woocommerce_manage_stock',
					'default' => 'yes',
					'type'    => 'checkbox',
				),

				array(
					'title'             => __( 'Hold stock (minutes)', 'woocommerce' ),
					'desc'              => __( 'Hold stock (for unpaid orders) for x minutes. When this limit is reached, the pending order will be cancelled. Leave blank to disable.', 'woocommerce' ),
					'id'                => 'woocommerce_hold_stock_minutes',
					'type'              => 'number',
					'custom_attributes' => array(
						'min'  => 0,
						'step' => 1,
					),
					'css'               => 'width: 80px;',
					'default'           => '60',
					'autoload'          => false,
					'class'             => 'manage_stock_field',
				),

				array(
					'title'         => __( 'Notifications', 'woocommerce' ),
					'desc'          => __( 'Enable low stock notifications', 'woocommerce' ),
					'id'            => 'woocommerce_notify_low_stock',
					'default'       => 'yes',
					'type'          => 'checkbox',
					'checkboxgroup' => 'start',
					'autoload'      => false,
					'class'         => 'manage_stock_field',
				),

				array(
					'desc'          => __( 'Enable out of stock notifications', 'woocommerce' ),
					'id'            => 'woocommerce_notify_no_stock',
					'default'       => 'yes',
					'type'          => 'checkbox',
					'checkboxgroup' => 'end',
					'autoload'      => false,
					'class'         => 'manage_stock_field',
				),

				array(
					'title'    => __( 'Notification recipient(s)', 'woocommerce' ),
					'desc'     => __( 'Enter recipients (comma separated) that will receive this notification.', 'woocommerce' ),
					'id'       => 'woocommerce_stock_email_recipient',
					'type'     => 'text',
					'default'  => get_option( 'admin_email' ),
					'css'      => 'width: 250px;',
					'autoload' => false,
					'desc_tip' => true,
					'class'    => 'manage_stock_field',
				),

				array(
					'title'             => __( 'Low stock threshold', 'woocommerce' ),
					'desc'              => __( 'When product stock reaches this amount you will be notified via email.', 'woocommerce' ),
					'id'                => 'woocommerce_notify_low_stock_amount',
					'css'               => 'width:50px;',
					'type'              => 'number',
					'custom_attributes' => array(
						'min'  => 0,
						'step' => 1,
					),
					'default'           => '2',
					'autoload'          => false,
					'desc_tip'          => true,
					'class'             => 'manage_stock_field',
				),

				array(
					'title'             => __( 'Out of stock threshold', 'woocommerce' ),
					'desc'              => __( 'When product stock reaches this amount the stock status will change to "out of stock" and you will be notified via email. This setting does not affect existing "in stock" products.', 'woocommerce' ),
					'id'                => 'woocommerce_notify_no_stock_amount',
					'css'               => 'width:50px;',
					'type'              => 'number',
					'custom_attributes' => array(
						'min'  => 0,
						'step' => 1,
					),
					'default'           => '0',
					'desc_tip'          => true,
					'class'             => 'manage_stock_field',
				),

				array(
					'title'   => __( 'Out of stock visibility', 'woocommerce' ),
					'desc'    => __( 'Hide out of stock items from the catalog', 'woocommerce' ),
					'id'      => 'woocommerce_hide_out_of_stock_items',
					'default' => 'no',
					'type'    => 'checkbox',
				),

				array(
					'title'    => __( 'Stock display format', 'woocommerce' ),
					'desc'     => __( 'This controls how stock quantities are displayed on the frontend.', 'woocommerce' ),
					'id'       => 'woocommerce_stock_format',
					'css'      => 'min-width:150px;',
					'class'    => 'wc-enhanced-select',
					'default'  => '',
					'type'     => 'select',
					'options'  => array(
						''           => __( 'Always show quantity remaining in stock e.g. "12 in stock"', 'woocommerce' ),
						'low_amount' => __( 'Only show quantity remaining in stock when low e.g. "Only 2 left in stock"', 'woocommerce' ),
						'no_amount'  => __( 'Never show quantity remaining in stock', 'woocommerce' ),
					),
					'desc_tip' => true,
				),

				array(
					'type' => 'sectionend',
					'id'   => 'product_inventory_options',
				),
			);

		return apply_filters( 'woocommerce_inventory_settings', $settings );
	}

	/**
	 * Get settings for the downloadable section.
	 *
	 * @return array
	 */
	protected function get_settings_for_downloadable_section() {
		$settings =
			array(
				array(
					'title' => __( 'Downloadable products', 'woocommerce' ),
					'type'  => 'title',
					'id'    => 'digital_download_options',
				),

				array(
					'title'    => __( 'File download method', 'woocommerce' ),
					'desc_tip' => sprintf(
					/* translators: 1: X-Accel-Redirect 2: X-Sendfile 3: mod_xsendfile */
						__( 'Forcing downloads will keep URLs hidden, but some servers may serve large files unreliably. If supported, %1$s / %2$s can be used to serve downloads instead (server requires %3$s).', 'woocommerce' ),
						'<code>X-Accel-Redirect</code>',
						'<code>X-Sendfile</code>',
						'<code>mod_xsendfile</code>'
					),
					'id'       => 'woocommerce_file_download_method',
					'type'     => 'select',
					'class'    => 'wc-enhanced-select',
					'css'      => 'min-width:300px;',
					'default'  => 'force',
					'desc'     => sprintf(
					// translators: Link to WooCommerce Docs.
						__( "If you are using X-Accel-Redirect download method along with NGINX server, make sure that you have applied settings as described in <a href='%s'>Digital/Downloadable Product Handling</a> guide.", 'woocommerce' ),
						'https://woocommerce.com/document/digital-downloadable-product-handling#nginx-setting'
					),
					'options'  => array(
						'force'     => __( 'Force downloads', 'woocommerce' ),
						'xsendfile' => __( 'X-Accel-Redirect/X-Sendfile', 'woocommerce' ),
						'redirect'  => apply_filters( 'woocommerce_redirect_only_method_is_secure', false ) ? __( 'Redirect only', 'woocommerce' ) : __( 'Redirect only (Insecure)', 'woocommerce' ),
					),
					'autoload' => false,
				),

				array(
					'desc'          => __( 'Allow using redirect mode (insecure) as a last resort', 'woocommerce' ),
					'id'            => 'woocommerce_downloads_redirect_fallback_allowed',
					'type'          => 'checkbox',
					'default'       => 'no',
					'desc_tip'      => sprintf(
						/* translators: %1$s is a link to the WooCommerce documentation. */
						__( 'If the "Force Downloads" or "X-Accel-Redirect/X-Sendfile" download method is selected but does not work, the system will use the "Redirect" method as a last resort. <a href="%1$s">See this guide</a> for more details.', 'woocommerce' ),
						'https://woocommerce.com/document/digital-downloadable-product-handling/'
					),
					'checkboxgroup' => 'start',
					'autoload'      => false,
				),

				array(
					'title'         => __( 'Access restriction', 'woocommerce' ),
					'desc'          => __( 'Downloads require login', 'woocommerce' ),
					'id'            => 'woocommerce_downloads_require_login',
					'type'          => 'checkbox',
					'default'       => 'no',
					'desc_tip'      => __( 'This setting does not apply to guest purchases.', 'woocommerce' ),
					'checkboxgroup' => 'start',
					'autoload'      => false,
				),

				array(
					'desc'          => __( 'Grant access to downloadable products after payment', 'woocommerce' ),
					'id'            => 'woocommerce_downloads_grant_access_after_payment',
					'type'          => 'checkbox',
					'default'       => 'yes',
					'desc_tip'      => __( 'Enable this option to grant access to downloads when orders are "processing", rather than "completed".', 'woocommerce' ),
					'checkboxgroup' => 'end',
					'autoload'      => false,
				),

				array(
					'title'    => __( 'Open in browser', 'woocommerce' ),
					'desc'     => __( 'Open downloadable files in the browser, instead of saving them to the device.', 'woocommerce' ),
					'id'       => 'woocommerce_downloads_deliver_inline',
					'type'     => 'checkbox',
					'default'  => false,
					'desc_tip' => __( 'Customers can still save the file to their device, but by default file will be opened instead of being downloaded (does not work with redirects).', 'woocommerce' ),
					'autoload' => false,
				),

				array(
					'title'    => __( 'Filename', 'woocommerce' ),
					'desc'     => __( 'Append a unique string to filename for security', 'woocommerce' ),
					'id'       => 'woocommerce_downloads_add_hash_to_filename',
					'type'     => 'checkbox',
					'default'  => 'yes',
					'desc_tip' => sprintf(
					// translators: Link to WooCommerce Docs.
						__( "Not required if your download directory is protected. <a href='%s'>See this guide</a> for more details. Files already uploaded will not be affected.", 'woocommerce' ),
						'https://woocommerce.com/document/digital-downloadable-product-handling#unique-string'
					),
				),

				array(
					'title'    => __( 'Count partial downloads', 'woocommerce' ),
					'desc'     => __( 'Count downloads even if only part of a file is fetched.', 'woocommerce' ),
					'id'       => 'woocommerce_downloads_count_partial',
					'type'     => 'checkbox',
					'default'  => 'yes',
					'desc_tip' => sprintf(
						/* Translators: 1: opening link tag 2: closing link tag. */
						__( 'Repeat fetches made within a reasonable window of time (by default, 30 minutes) will not be counted twice. This is a generally reasonably way to enforce download limits in relation to ranged requests. %1$sLearn more.%2$s', 'woocommerce' ),
						'<a href="https://woocommerce.com/document/digital-downloadable-product-handling/">',
						'</a>'
					),
				),

				array(
					'type' => 'sectionend',
					'id'   => 'digital_download_options',
				),
			);

		return apply_filters( 'woocommerce_downloadable_products_settings', $settings );
	}

	/**
	 * Save settings and trigger the 'woocommerce_update_options_'.id action.
	 */
	public function save() {
		$this->save_settings_for_current_section();

		/*
		 * Product->Inventory has a setting `Out of stock visibility`.
		 * Because of this, we need to recount the terms to keep them in-sync.
		 */
		WC()->call_function( 'wc_recount_all_terms', false );

		$this->do_update_options_action();
	}
}

return new WC_Settings_Products();
PK     tS\D &    +  settings/class-wc-settings-integrations.phpnu [        <?php
/**
 * WooCommerce Integration Settings
 *
 * @package     WooCommerce\Admin
 * @version     2.1.0
 */

use Automattic\Jetpack\Constants;

defined( 'ABSPATH' ) || exit;

if ( ! class_exists( 'WC_Settings_Integrations', false ) ) :

	/**
	 * WC_Settings_Integrations.
	 */
	class WC_Settings_Integrations extends WC_Settings_Page {

		/**
		 * Constructor.
		 */
		public function __construct() {
			$this->id    = 'integration';
			$this->label = __( 'Integration', 'woocommerce' );

			if ( isset( WC()->integrations ) && WC()->integrations->get_integrations() ) {
				parent::__construct();
			}
		}

		/**
		 * Setting page icon.
		 *
		 * @var string
		 */
		public $icon = 'plugins';

		/**
		 * Get own sections.
		 *
		 * @return array
		 */
		protected function get_own_sections() {
			global $current_section;

			$sections = array();

			if ( ! $this->wc_is_installing() ) {
				$integrations = $this->get_integrations();

				if ( ! $current_section && ! empty( $integrations ) ) {
					$current_section = current( $integrations )->id;
				}

				if ( count( $integrations ) > 1 ) {
					foreach ( $integrations as $integration ) {
						$title                                      = empty( $integration->method_title ) ? ucfirst( $integration->id ) : $integration->method_title;
						$sections[ strtolower( $integration->id ) ] = esc_html( $title );
					}
				}
			}

			return $sections;
		}

		/**
		 * Is WC_INSTALLING constant defined?
		 * This method exists to ease unit testing.
		 *
		 * @return bool True is the WC_INSTALLING constant is defined.
		 */
		protected function wc_is_installing() {
			return Constants::is_defined( 'WC_INSTALLING' );
		}

		/**
		 * Get the currently available integrations.
		 * This method exists to ease unit testing.
		 *
		 * @return array Currently available integrations.
		 */
		protected function get_integrations() {
			return WC()->integrations->get_integrations();
		}

		/**
		 * Output the settings.
		 */
		public function output() {
			global $current_section;

			$integrations = $this->get_integrations();

			if ( isset( $integrations[ $current_section ] ) ) {
				$integrations[ $current_section ]->admin_options();
			}
		}
	}

endif;

return new WC_Settings_Integrations();
PK     tS\8\    '  settings/class-wc-settings-checkout.phpnu [        <?php // @codingStandardsIgnoreFile.
/**
 * Settings class file.
 *
 * @deprecated 3.4.0 Replaced with class-wc-settings-payment-gateways.php.
 * @todo remove in 4.0.
 */

defined( 'ABSPATH' ) || exit;

return include __DIR__ . '/class-wc-settings-payment-gateways.php';
PK     tS\FE  E  '  settings/class-wc-settings-accounts.phpnu [        <?php
/**
 * WooCommerce Account Settings.
 *
 * @package WooCommerce\Admin
 */

defined( 'ABSPATH' ) || exit;

if ( class_exists( 'WC_Settings_Accounts', false ) ) {
	return new WC_Settings_Accounts();
}

use Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils;
use Automattic\WooCommerce\Admin\Features\Features;

/**
 * WC_Settings_Accounts.
 */
class WC_Settings_Accounts extends WC_Settings_Page {

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id    = 'account';
		$this->label = __( 'Accounts &amp; Privacy', 'woocommerce' );
		parent::__construct();
	}

	/**
	 * Setting page icon.
	 *
	 * @var string
	 */
	public $icon = 'people';

	/**
	 * Get settings array.
	 *
	 * @return array
	 */
	protected function get_settings_for_default_section() {

		$erasure_text = esc_html__( 'account erasure request', 'woocommerce' );
		$privacy_text = esc_html__( 'privacy page', 'woocommerce' );
		if ( current_user_can( 'manage_privacy_options' ) ) {
			if ( version_compare( get_bloginfo( 'version' ), '5.3', '<' ) ) {
				$erasure_text = sprintf( '<a href="%s">%s</a>', esc_url( admin_url( 'tools.php?page=remove_personal_data' ) ), $erasure_text );
			} else {
				$erasure_text = sprintf( '<a href="%s">%s</a>', esc_url( admin_url( 'erase-personal-data.php' ) ), $erasure_text );
			}
			$privacy_text = sprintf( '<a href="%s">%s</a>', esc_url( admin_url( 'options-privacy.php' ) ), $privacy_text );
		}

		$account_settings = array(
			array(
				'title' => '',
				'type'  => 'title',
				'id'    => 'account_registration_options',
			),
			array(
				'title'         => __( 'Checkout', 'woocommerce' ),
				'desc'          => __( 'Enable guest checkout (recommended)', 'woocommerce' ),
				'desc_tip'      => __( 'Allows customers to checkout without an account.', 'woocommerce' ),
				'id'            => 'woocommerce_enable_guest_checkout',
				'default'       => 'yes',
				'type'          => 'checkbox',
				'checkboxgroup' => 'start',
				'autoload'      => false,
			),
			array(
				'title'         => __( 'Login', 'woocommerce' ),
				'desc'          => __( 'Enable log-in during checkout', 'woocommerce' ),
				'id'            => 'woocommerce_enable_checkout_login_reminder',
				'default'       => 'no',
				'type'          => 'checkbox',
				'checkboxgroup' => 'end',
				'autoload'      => false,
			),
			array(
				'title'             => __( 'Account creation', 'woocommerce' ),
				'desc'              => __( 'After checkout (recommended)', 'woocommerce' ),
				'desc_tip'          => sprintf(
					/* Translators: %1$s and %2$s are opening and closing <a> tags respectively. */
					__( 'Customers can create an account after their order is placed. Customize messaging %1$shere%2$s.', 'woocommerce' ),
					'<a target="_blank" class="delayed-account-creation-customize-link" href="' . esc_url( admin_url( 'site-editor.php?postId=woocommerce%2Fwoocommerce%2F%2Forder-confirmation&postType=wp_template&canvas=edit' ) ) . '">',
					'</a>'
				),
				'id'                => 'woocommerce_enable_delayed_account_creation',
				'default'           => 'no',
				'type'              => 'checkbox',
				'checkboxgroup'     => 'start',
				'autoload'          => false,
				'custom_attributes' => array(
					'disabled-tooltip' => __( 'Enable guest checkout to use this feature.', 'woocommerce' ),
				),
				'legend'            => __( 'Allow customers to create an account', 'woocommerce' ),
			),
			array(
				'title'         => __( 'Account creation', 'woocommerce' ),
				'desc'          => __( 'During checkout', 'woocommerce' ),
				'desc_tip'      => __( 'Customers can create an account before placing their order.', 'woocommerce' ),
				'id'            => 'woocommerce_enable_signup_and_login_from_checkout',
				'default'       => 'no',
				'type'          => 'checkbox',
				'checkboxgroup' => '',
				'autoload'      => false,
			),
			array(
				'title'         => __( 'Account creation', 'woocommerce' ),
				'desc'          => __( 'On "My account" page', 'woocommerce' ),
				'id'            => 'woocommerce_enable_myaccount_registration',
				'default'       => 'no',
				'type'          => 'checkbox',
				'checkboxgroup' => 'end',
				'autoload'      => false,
			),
			array(
				'title'             => __( 'Account creation options', 'woocommerce' ),
				'desc'              => __( 'Send password setup link (recommended)', 'woocommerce' ),
				'desc_tip'          => __( 'New users receive an email to set up their password.', 'woocommerce' ),
				'id'                => 'woocommerce_registration_generate_password',
				'default'           => 'yes',
				'type'              => 'checkbox',
				'checkboxgroup'     => 'start',
				'autoload'          => false,
				'custom_attributes' => array(
					'disabled-tooltip' => __( 'Enable an account creation method to use this feature.', 'woocommerce' ),
				),
			),
			array(
				'title'             => __( 'Account creation options', 'woocommerce' ),
				'desc'              => __( 'Generate account login (recommended)', 'woocommerce' ),
				'desc_tip'          => __( 'Generate a login for the account using first and/or last name. If neither is usable (e.g. invalid or missing) the email address will be used. If this option is unchecked, customers will need to set a username during account creation', 'woocommerce' ),
				'id'                => 'woocommerce_registration_generate_username',
				'default'           => 'yes',
				'type'              => 'checkbox',
				'checkboxgroup'     => 'end',
				'autoload'          => false,
				'custom_attributes' => array(
					'disabled-tooltip' => __( 'Enable an account creation method to use this feature.', 'woocommerce' ),
				),
			),
			array(
				'title'         => __( 'Account erasure requests', 'woocommerce' ),
				'desc'          => __( 'Remove personal data from orders on request', 'woocommerce' ),
				/* Translators: %s URL to erasure request screen. */
				'desc_tip'      => sprintf( esc_html__( 'When handling an %s, should personal data within orders be retained or removed?', 'woocommerce' ), $erasure_text ),
				'id'            => 'woocommerce_erasure_request_removes_order_data',
				'type'          => 'checkbox',
				'default'       => 'no',
				'checkboxgroup' => 'start',
				'autoload'      => false,
			),
			array(
				'desc'          => __( 'Remove access to downloads on request', 'woocommerce' ),
				/* Translators: %s URL to erasure request screen. */
				'desc_tip'      => sprintf( esc_html__( 'When handling an %s, should access to downloadable files be revoked and download logs cleared?', 'woocommerce' ), $erasure_text ),
				'id'            => 'woocommerce_erasure_request_removes_download_data',
				'type'          => 'checkbox',
				'default'       => 'no',
				'checkboxgroup' => '',
				'autoload'      => false,
			),
			array(
				'title'         => __( 'Personal data removal', 'woocommerce' ),
				'desc'          => __( 'Allow personal data to be removed in bulk from orders', 'woocommerce' ),
				'desc_tip'      => __( 'Adds an option to the orders screen for removing personal data in bulk. Note that removing personal data cannot be undone.', 'woocommerce' ),
				'id'            => 'woocommerce_allow_bulk_remove_personal_data',
				'type'          => 'checkbox',
				'checkboxgroup' => 'end',
				'default'       => 'no',
				'autoload'      => false,
			),
			array(
				'type' => 'sectionend',
				'id'   => 'account_registration_options',
			),
			array(
				'title' => __( 'Privacy policy', 'woocommerce' ),
				'type'  => 'title',
				'id'    => 'privacy_policy_options',
				/* translators: %s: privacy page link. */
				'desc'  => sprintf( esc_html__( 'This section controls the display of your website privacy policy. The privacy notices below will not show up unless a %s is set.', 'woocommerce' ), $privacy_text ),
			),

			array(
				'title'    => __( 'Registration privacy policy', 'woocommerce' ),
				'desc_tip' => __( 'Optionally add some text about your store privacy policy to show on account registration forms.', 'woocommerce' ),
				'id'       => 'woocommerce_registration_privacy_policy_text',
				/* translators: %s privacy policy page name and link */
				'default'  => sprintf( __( 'Your personal data will be used to support your experience throughout this website, to manage access to your account, and for other purposes described in our %s.', 'woocommerce' ), '[privacy_policy]' ),
				'type'     => 'textarea',
				'css'      => 'min-width: 50%; height: 75px;',
			),

			array(
				'title'    => __( 'Checkout privacy policy', 'woocommerce' ),
				'desc_tip' => __( 'Optionally add some text about your store privacy policy to show during checkout.', 'woocommerce' ),
				'id'       => 'woocommerce_checkout_privacy_policy_text',
				/* translators: %s privacy policy page name and link */
				'default'  => sprintf( __( 'Your personal data will be used to process your order, support your experience throughout this website, and for other purposes described in our %s.', 'woocommerce' ), '[privacy_policy]' ),
				'type'     => 'textarea',
				'css'      => 'min-width: 50%; height: 75px;',
			),
			array(
				'type' => 'sectionend',
				'id'   => 'privacy_policy_options',
			),
			array(
				'title' => __( 'Personal data retention', 'woocommerce' ),
				'desc'  => __( 'Choose how long to retain personal data when it\'s no longer needed for processing. Leave the following options blank to retain this data indefinitely.', 'woocommerce' ),
				'type'  => 'title',
				'id'    => 'personal_data_retention',
			),
			array(
				'title'       => __( 'Retain inactive accounts ', 'woocommerce' ),
				'desc_tip'    => __( 'Inactive accounts are those which have not logged in, or placed an order, for the specified duration. They will be deleted. Any orders will be converted into guest orders.', 'woocommerce' ),
				'id'          => 'woocommerce_delete_inactive_accounts',
				'type'        => 'relative_date_selector',
				'placeholder' => __( 'N/A', 'woocommerce' ),
				'default'     => array(
					'number' => '',
					'unit'   => 'months',
				),
				'autoload'    => false,
			),
			array(
				'title'       => __( 'Retain pending orders ', 'woocommerce' ),
				'desc_tip'    => __( 'Pending orders are unpaid and may have been abandoned by the customer. They will be trashed after the specified duration.', 'woocommerce' ),
				'id'          => 'woocommerce_trash_pending_orders',
				'type'        => 'relative_date_selector',
				'placeholder' => __( 'N/A', 'woocommerce' ),
				'default'     => '',
				'autoload'    => false,
			),
			array(
				'title'       => __( 'Retain failed orders', 'woocommerce' ),
				'desc_tip'    => __( 'Failed orders are unpaid and may have been abandoned by the customer. They will be trashed after the specified duration.', 'woocommerce' ),
				'id'          => 'woocommerce_trash_failed_orders',
				'type'        => 'relative_date_selector',
				'placeholder' => __( 'N/A', 'woocommerce' ),
				'default'     => '',
				'autoload'    => false,
			),
			array(
				'title'       => __( 'Retain cancelled orders', 'woocommerce' ),
				'desc_tip'    => __( 'Cancelled orders are unpaid and may have been cancelled by the store owner or customer. They will be trashed after the specified duration.', 'woocommerce' ),
				'id'          => 'woocommerce_trash_cancelled_orders',
				'type'        => 'relative_date_selector',
				'placeholder' => __( 'N/A', 'woocommerce' ),
				'default'     => '',
				'autoload'    => false,
			),
			array(
				'title'       => __( 'Retain refunded orders', 'woocommerce' ),
				'desc_tip'    => __( 'Retain refunded orders for a specified duration before anonymizing the personal data within them.', 'woocommerce' ),
				'id'          => 'woocommerce_anonymize_refunded_orders',
				'type'        => 'relative_date_selector',
				'placeholder' => __( 'N/A', 'woocommerce' ),
				'default'     => array(
					'number' => '',
					'unit'   => 'months',
				),
				'autoload'    => false,
			),
			array(
				'title'       => __( 'Retain completed orders', 'woocommerce' ),
				'desc_tip'    => __( 'Retain completed orders for a specified duration before anonymizing the personal data within them.', 'woocommerce' ),
				'id'          => 'woocommerce_anonymize_completed_orders',
				'type'        => 'relative_date_selector',
				'placeholder' => __( 'N/A', 'woocommerce' ),
				'default'     => array(
					'number' => '',
					'unit'   => 'months',
				),
				'autoload'    => false,
			),
			array(
				'type' => 'sectionend',
				'id'   => 'personal_data_retention',
			),
		);

		// Feature requires a block theme. Re-order settings if not using a block theme.
		if ( ! wp_is_block_theme() ) {
			$account_settings = array_map(
				function ( $setting ) {
					if ( 'woocommerce_enable_signup_and_login_from_checkout' === $setting['id'] ) {
						$setting['checkboxgroup'] = 'start';
						$setting['legend']        = __( 'Allow customers to create an account', 'woocommerce' );
					}
					return $setting;
				},
				$account_settings
			);
			$account_settings = array_filter(
				$account_settings,
				function ( $setting ) {
					return 'woocommerce_enable_delayed_account_creation' !== $setting['id'];
				},
			);
		}

		// Change settings when using the block based checkout.
		if ( CartCheckoutUtils::is_checkout_block_default() ) {
			$account_settings = array_filter(
				$account_settings,
				function ( $setting ) {
					return 'woocommerce_registration_generate_username' !== $setting['id'];
				},
			);
			$account_settings = array_map(
				function ( $setting ) {
					if ( 'woocommerce_registration_generate_password' === $setting['id'] ) {
						unset( $setting['checkboxgroup'] );
					}
					return $setting;
				},
				$account_settings
			);
		} else {
			$account_settings = array_map(
				function ( $setting ) {
					if ( 'woocommerce_enable_delayed_account_creation' === $setting['id'] ) {
						$setting['desc_tip'] = sprintf(
							/* Translators: %1$s and %2$s are opening and closing <a> tags respectively. */
							__( 'This feature is only available with the Cart & Checkout blocks. %1$sLearn more%2$s.', 'woocommerce' ),
							'<a href="https://woocommerce.com/document/woocommerce-store-editing/customizing-cart-and-checkout">',
							'</a>'
						);
						$setting['disabled']                              = true;
						$setting['value']                                 = 0;
						$setting['custom_attributes']['disabled-tooltip'] = __( 'Your store is using shortcode checkout. Use the Checkout blocks to activate this option.', 'woocommerce' );
					}
					return $setting;
				},
				$account_settings
			);
		}

		/**
		 * Filter account settings.
		 *
		 * @hook woocommerce_account_settings
		 * @since 3.5.0
		 * @param array $account_settings Account settings.
		 */
		return apply_filters( 'woocommerce_' . $this->id . '_settings', $account_settings );
	}

	/**
	 * Output the HTML for the settings.
	 */
	public function output() {
		parent::output();

		// The following code toggles disabled state on the account options based on other values.
		$script =
			'
			// Move tooltips to label element. This is not possible through the settings field API so this is a workaround
			// until said API is refactored.
			document.querySelectorAll("input[disabled-tooltip]").forEach(function(element) {
				const label = element.closest("label");
				label.setAttribute("disabled-tooltip", element.getAttribute("disabled-tooltip"));
			});

			// This handles settings that are enabled/disabled based on other settings.
			const checkboxes = [
				document.getElementById("woocommerce_enable_signup_and_login_from_checkout"),
				document.getElementById("woocommerce_enable_myaccount_registration"),
				document.getElementById("woocommerce_enable_delayed_account_creation"),
				document.getElementById("woocommerce_enable_signup_from_checkout_for_subscriptions")
			];
			const inputs = [
				document.getElementById("woocommerce_registration_generate_username"),
				document.getElementById("woocommerce_registration_generate_password")
			];
			checkboxes.forEach(cb => cb && cb.addEventListener("change", function() {
				const isChecked = checkboxes.some(cb => cb && cb.checked);
				inputs.forEach(input => {
					if ( ! input ) {
						return;
					}
					input.disabled = !isChecked;
				});
			}));
			checkboxes[0].dispatchEvent(new Event("change")); // Initial state

			// Tracks for customize link.
			if ( typeof window?.wcTracks?.recordEvent === "function" ) {
				const customizeLink = document.querySelector("a.delayed-account-creation-customize-link");
				if ( customizeLink ) {
					customizeLink.addEventListener("click", function() {
						window.wcTracks.recordEvent("delayed_account_creation_customize_link_clicked");
					});
				}
			}
		';

		// If the checkout block is not default, delayed account creation is always disabled. Otherwise its based on other settings.
		if ( CartCheckoutUtils::is_checkout_block_default() ) {
			$script .=
				'
				// Guest checkout should toggle off some options.
				const guestCheckout = document.getElementById("woocommerce_enable_guest_checkout");

				if ( guestCheckout ) {
					guestCheckout.addEventListener("change", function() {
						const isChecked = this.checked;
						const input = document.getElementById("woocommerce_enable_delayed_account_creation");
						if ( ! input ) {
							return;
						}
						input.disabled = !isChecked;
					});
					guestCheckout.dispatchEvent(new Event("change")); // Initial state
				}
			';
		}

		$handle = 'wc-admin-settings-accounts';
		wp_register_script( $handle, '', array(), WC_VERSION, array( 'in_footer' => true ) );
		wp_enqueue_script( $handle );
		wp_add_inline_script( $handle, $script );
	}
}

return new WC_Settings_Accounts();
PK     tS\KobC  C  #  settings/class-wc-settings-page.phpnu [        <?php
/**
 * WooCommerce Settings Page/Tab
 *
 * @package     WooCommerce\Admin
 * @version     2.1.0
 */

declare( strict_types = 1);

use Automattic\WooCommerce\Admin\Features\Features;


if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

if ( ! class_exists( 'WC_Settings_Page', false ) ) :

	/**
	 * WC_Settings_Page.
	 */
	abstract class WC_Settings_Page {

		/**
		 * Setting page id.
		 *
		 * @var string
		 */
		protected $id = '';

		/**
		 * Setting page icon.
		 *
		 * @var string
		 */
		public $icon = 'settings';

		/**
		 * Setting field types.
		 *
		 * @var string
		 */
		const TYPE_TITLE                          = 'title';
		const TYPE_INFO                           = 'info';
		const TYPE_SECTIONEND                     = 'sectionend';
		const TYPE_TEXT                           = 'text';
		const TYPE_PASSWORD                       = 'password';
		const TYPE_DATETIME                       = 'datetime';
		const TYPE_DATETIME_LOCAL                 = 'datetime-local';
		const TYPE_DATE                           = 'date';
		const TYPE_MONTH                          = 'month';
		const TYPE_TIME                           = 'time';
		const TYPE_WEEK                           = 'week';
		const TYPE_NUMBER                         = 'number';
		const TYPE_EMAIL                          = 'email';
		const TYPE_URL                            = 'url';
		const TYPE_TEL                            = 'tel';
		const TYPE_COLOR                          = 'color';
		const TYPE_TEXTAREA                       = 'textarea';
		const TYPE_SELECT                         = 'select';
		const TYPE_MULTISELECT                    = 'multiselect';
		const TYPE_RADIO                          = 'radio';
		const TYPE_CHECKBOX                       = 'checkbox';
		const TYPE_IMAGE_WIDTH                    = 'image_width';
		const TYPE_SINGLE_SELECT_PAGE             = 'single_select_page';
		const TYPE_SINGLE_SELECT_PAGE_WITH_SEARCH = 'single_select_page_with_search';
		const TYPE_SINGLE_SELECT_COUNTRY          = 'single_select_country';
		const TYPE_MULTI_SELECT_COUNTRIES         = 'multi_select_countries';
		const TYPE_RELATIVE_DATE_SELECTOR         = 'relative_date_selector';
		const TYPE_SLOTFILL_PLACEHOLDER           = 'slotfill_placeholder';

		/**
		 * Settings field types which are known.
		 *
		 * @var string[]
		 */
		protected $types = array(
			self::TYPE_TITLE,
			self::TYPE_INFO,
			self::TYPE_SECTIONEND,
			self::TYPE_TEXT,
			self::TYPE_PASSWORD,
			self::TYPE_DATETIME,
			self::TYPE_DATETIME_LOCAL,
			self::TYPE_DATE,
			self::TYPE_MONTH,
			self::TYPE_TIME,
			self::TYPE_WEEK,
			self::TYPE_NUMBER,
			self::TYPE_EMAIL,
			self::TYPE_URL,
			self::TYPE_TEL,
			self::TYPE_COLOR,
			self::TYPE_TEXTAREA,
			self::TYPE_SELECT,
			self::TYPE_MULTISELECT,
			self::TYPE_RADIO,
			self::TYPE_CHECKBOX,
			self::TYPE_IMAGE_WIDTH,
			self::TYPE_SINGLE_SELECT_PAGE,
			self::TYPE_SINGLE_SELECT_PAGE_WITH_SEARCH,
			self::TYPE_SINGLE_SELECT_COUNTRY,
			self::TYPE_MULTI_SELECT_COUNTRIES,
			self::TYPE_RELATIVE_DATE_SELECTOR,
			self::TYPE_SLOTFILL_PLACEHOLDER,
		);

		/**
		 * Setting page label.
		 *
		 * @var string
		 */
		protected $label = '';

		/**
		 * Setting page is modern.
		 *
		 * @var bool
		 */
		protected $is_modern = false;

		/**
		 * Whether the output method has been called.
		 *
		 * @var bool
		 */
		private $output_called = false;

		/**
		 * Constructor.
		 */
		public function __construct() {
			add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
			add_action( 'woocommerce_sections_' . $this->id, array( $this, 'output_sections' ) );
			add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
			add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
			add_action( 'woocommerce_admin_field_add_settings_slot', array( $this, 'add_settings_slot' ) );
		}

		/**
		 * Get settings page ID.
		 *
		 * @since 3.0.0
		 * @return string
		 */
		public function get_id() {
			return $this->id;
		}

		/**
		 * Get settings page label.
		 *
		 * @since 3.0.0
		 * @return string
		 */
		public function get_label() {
			return $this->label;
		}

		/**
		 * Creates the React mount point for settings slot.
		 */
		public function add_settings_slot() {
			?>
			<div id="wc_settings_slotfill"> </div>
			<?php
		}

		/**
		 * Add this page to settings.
		 *
		 * @param array $pages The settings array where we'll add ourselves.
		 *
		 * @return mixed
		 */
		public function add_settings_page( $pages ) {
			$pages[ $this->id ] = $this->label;

			return $pages;
		}

		/**
		 * Get page settings data to populate the settings editor.
		 *
		 * @param array $pages The settings array where we'll add data.
		 *
		 * @return array
		 */
		public function add_settings_page_data( $pages ) {
			global $current_section;

			$saved_current_section = $current_section;
			$sections              = $this->get_sections();
			$sections_data         = array();

			// Loop through each section and get the settings for that section.
			foreach ( $sections as $section_id => $section_label ) {
				$current_section       = $section_id;
				$section_settings_data = $this->get_section_settings_data( $section_id, $sections );

				// Replace empty string section ids with 'default'.
				$normalized_section_id                   = '' === $section_id ? 'default' : $section_id;
				$sections_data[ $normalized_section_id ] = array(
					'label'    => html_entity_decode( esc_html( $section_label ) ),
					'settings' => $section_settings_data,
				);
			}

			// Reset the current section to the saved current section.
			$current_section = $saved_current_section;

			$pages[ $this->id ] = array(
				'label'     => html_entity_decode( $this->label ),
				'slug'      => $this->id,
				'icon'      => $this->icon,
				'sections'  => $sections_data,
				'is_modern' => $this->is_modern,
			);

			$pages[ $this->id ]['start'] = $this->get_custom_view( 'woocommerce_before_settings_' . $this->id );
			$pages[ $this->id ]['end']   = $this->get_custom_view( 'woocommerce_after_settings_' . $this->id );

			return $pages;
		}

		/**
		 * Get settings data for a specific section.
		 *
		 * @param string $section_id The ID of the section.
		 * @param array  $sections   All sections available.
		 * @return array Settings data for the section.
		 */
		protected function get_section_settings_data( $section_id, $sections ) {
			$section_settings_data = array();

			$custom_view = $this->get_custom_view( 'woocommerce_settings_' . $this->id, $section_id );
			// We only want to loop through the settings object if the parent class's output method is being rendered during the get_custom_view call.
			if ( $this->output_called ) {
				$section_settings = count( $sections ) > 1
					? $this->get_settings_for_section( $section_id )
					: $this->get_settings();

				// Loop through each setting in the section and add the value to the settings data.
				foreach ( $section_settings as $section_setting ) {
					// Add custom views for sectionend.
					if ( 'sectionend' === $section_setting['type'] && ! empty( $section_setting['id'] ) ) {
						$section_settings_data[] = $this->get_custom_view( 'woocommerce_settings_' . $section_setting['id'] . '_end' );
						$section_settings_data[] = $this->get_custom_view( 'woocommerce_settings_' . $section_setting['id'] . '_after' );
					}

					$section_settings_data[] = $this->populate_setting_value( $section_setting );

					// Add custom views for title.
					if ( 'title' === $section_setting['type'] && ! empty( $section_setting['id'] ) ) {
						$section_settings_data[] = $this->get_custom_view( 'woocommerce_settings_' . $section_setting['id'] );
					}
				}
			}

			// If the custom view has output, add it to the settings data.
			if ( ! empty( $custom_view ) ) {
				$section_settings_data[] = $custom_view;
			}

			// Reset the output_called property.
			$this->output_called = false;

			return $section_settings_data;
		}

		/**
		 * Populate the value for a given section setting.
		 *
		 * @param array $section_setting The setting array to populate.
		 * @return array The setting array with populated value.
		 */
		protected function populate_setting_value( $section_setting ) {
			if ( isset( $section_setting['id'] ) ) {
				$section_setting['value'] = isset( $section_setting['default'] )
					// Fallback to the default value if it exists.
					? get_option( $section_setting['id'], $section_setting['default'] )
					// Otherwise, fallback to false.
					: get_option( $section_setting['id'] );
			}

			$type = $section_setting['type'];
			if ( ! in_array( $type, $this->types, true ) ) {
				$section_setting = $this->get_custom_type_field( 'woocommerce_admin_field_' . $type, $section_setting );
			}

			return $section_setting;
		}

		/**
		 * Get the custom view given the current tab and section.
		 *
		 * @param string $action The action to call.
		 * @param string $section_id The section id.
		 * @return string The custom view. HTML output.
		 */
		public function get_custom_view( $action, $section_id = false ) {
			global $current_section;

			if ( $section_id ) {
				// Make sure the current section is set to the sectionid here. Reset it at the end of the function.
				$saved_current_section = $current_section;
				// set global current_section to the section_id.
				$current_section = $section_id;
			}

			ob_start();
			/**
			 * Output the custom view given the current tab and section by calling the action.
			 *
			 * @since 2.1.0
			 */
			do_action( $action );
			$html = ob_get_contents();
			ob_end_clean();

			// Reset the global variable.
			if ( $section_id ) {
				$current_section = $saved_current_section;
			}

			$content = trim( $html );

			if ( empty( $content ) ) {
				return null;
			}

			return array(
				'id'      => wp_unique_prefixed_id( 'settings_custom_view' ),
				'type'    => 'custom',
				'content' => $content,
			);
		}

		/**
		 * Get the custom type field by calling the action and returning the setting with the content, id, and type.
		 *
		 * @param string $action  The action to call.
		 * @param array  $setting The setting to pass to the action.
		 * @return array The setting with the content, id, and type.
		 */
		public function get_custom_type_field( $action, $setting ) {
			ob_start();
			/**
			 * Output the custom type field by calling the action.
			 *
			 * @since 3.3.0
			 */
			do_action( $action, $setting );
			$html = ob_get_contents();
			ob_end_clean();
			$setting['content'] = trim( $html );
			$setting['id']      = isset( $setting['id'] ) ? $setting['id'] : wp_unique_prefixed_id( 'settings_custom_view' );
			$setting['type']    = 'custom';

			return $setting;
		}

		/**
		 * Get settings array for the default section.
		 *
		 * External settings classes (registered via 'woocommerce_get_settings_pages' filter)
		 * might have redefined this method as "get_settings($section_id='')", thus we need
		 * to use this method internally instead of 'get_settings_for_section' to register settings
		 * and render settings pages.
		 *
		 * *But* we can't just redefine the method as "get_settings($section_id='')" here, since this
		 * will break on PHP 8 if any external setting class have it as 'get_settings()'.
		 *
		 * Thus we leave the method signature as is and use 'func_get_arg' to get the setting id
		 * if it's supplied, and we use this method internally; but it's deprecated and should
		 * otherwise never be used.
		 *
		 * @deprecated 5.4.0 Use 'get_settings_for_section' (passing an empty string for default section)
		 *
		 * @return array Settings array, each item being an associative array representing a setting.
		 */
		public function get_settings() {
			$section_id = 0 === func_num_args() ? '' : func_get_arg( 0 );
			return $this->get_settings_for_section( $section_id );
		}

		/**
		 * Get settings array.
		 *
		 * The strategy for getting the settings is as follows:
		 *
		 * - If a method named 'get_settings_for_{section_id}_section' exists in the class
		 *   it will be invoked (for the default '' section, the method name is 'get_settings_for_default_section').
		 *   Derived classes can implement these methods as required.
		 *
		 * - Otherwise, 'get_settings_for_section_core' will be invoked. Derived classes can override it
		 *   as an alternative to implementing 'get_settings_for_{section_id}_section' methods.
		 *
		 * @param string $section_id The id of the section to return settings for, an empty string for the default section.
		 *
		 * @return array Settings array, each item being an associative array representing a setting.
		 */
		final public function get_settings_for_section( $section_id ) {
			if ( '' === $section_id ) {
				$method_name = 'get_settings_for_default_section';
			} else {
				$method_name = "get_settings_for_{$section_id}_section";
			}

			if ( method_exists( $this, $method_name ) ) {
				$settings = $this->$method_name();
			} else {
				$settings = $this->get_settings_for_section_core( $section_id );
			}

			return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $section_id );
		}

		/**
		 * Get the settings for a given section.
		 * This method is invoked from 'get_settings_for_section' when no 'get_settings_for_{current_section}_section'
		 * method exists in the class.
		 *
		 * When overriding, note that the 'woocommerce_get_settings_' filter must NOT be triggered,
		 * as this is already done by 'get_settings_for_section'.
		 *
		 * @param string $section_id The section name to get the settings for.
		 *
		 * @return array Settings array, each item being an associative array representing a setting.
		 */
		protected function get_settings_for_section_core( $section_id ) {
			return array();
		}

		/**
		 * Get all sections for this page, both the own ones and the ones defined via filters.
		 *
		 * @return array
		 */
		public function get_sections() {
			$sections = $this->get_own_sections();
			/**
			 * Filters the sections for this settings page.
			 *
			 * @since 2.2.0
			 * @param array $sections The sections for this settings page.
			 */
			return (array) apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
		}

		/**
		 * Get own sections for this page.
		 * Derived classes should override this method if they define sections.
		 * There should always be one default section with an empty string as identifier.
		 *
		 * Example:
		 * return array(
		 *   ''        => __( 'General', 'woocommerce' ),
		 *   'foobars' => __( 'Foos & Bars', 'woocommerce' ),
		 * );
		 *
		 * @return array An associative array where keys are section identifiers and the values are translated section names.
		 */
		protected function get_own_sections() {
			return array( '' => __( 'General', 'woocommerce' ) );
		}

		/**
		 * Output sections.
		 */
		public function output_sections() {
			global $current_section;

			$sections = $this->get_sections();

			if ( empty( $sections ) || 1 === count( $sections ) ) {
				return;
			}

			echo '<ul class="subsubsub">';

			$array_keys = array_keys( $sections );

			foreach ( $sections as $id => $label ) {
				$url       = admin_url( 'admin.php?page=wc-settings&tab=' . $this->id . '&section=' . sanitize_title( $id ) );
				$class     = ( $current_section === $id ? 'current' : '' );
				$separator = ( end( $array_keys ) === $id ? '' : '|' );
				$text      = esc_html( $label );
				echo "<li><a href='$url' class='$class'>$text</a> $separator </li>"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			}

			echo '</ul><br class="clear" />';
		}

		/**
		 * Output the HTML for the settings.
		 */
		public function output() {
			$this->output_called = true;

			if ( Features::is_enabled( 'settings' ) ) {
				return;
			}

			global $current_section;

			// We can't use "get_settings_for_section" here
			// for compatibility with derived classes overriding "get_settings".
			$settings = $this->get_settings( $current_section );

			WC_Admin_Settings::output_fields( $settings );
		}

		/**
		 * Save settings and trigger the 'woocommerce_update_options_'.id action.
		 */
		public function save() {
			$this->save_settings_for_current_section();
			$this->do_update_options_action();
		}

		/**
		 * Save settings for current section.
		 */
		protected function save_settings_for_current_section() {
			global $current_section;

			// We can't use "get_settings_for_section" here
			// for compatibility with derived classes overriding "get_settings".
			$settings = $this->get_settings( $current_section );
			WC_Admin_Settings::save_fields( $settings );
		}

		/**
		 * Trigger the 'woocommerce_update_options_'.id action.
		 *
		 * @param string $section_id Section to trigger the action for, or null for current section.
		 */
		protected function do_update_options_action( $section_id = null ) {
			global $current_section;

			if ( is_null( $section_id ) ) {
				$section_id = $current_section;
			}

			if ( $section_id ) {
				do_action( 'woocommerce_update_options_' . $this->id . '_' . $section_id );
			}
		}
	}

endif;
PK     tS\`=E  =E  '  settings/class-wc-settings-shipping.phpnu [        <?php
/**
 * WooCommerce Shipping Settings
 *
 * @package     WooCommerce\Admin
 * @version     2.6.0
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;
use Automattic\WooCommerce\Utilities\FeaturesUtil;

defined( 'ABSPATH' ) || exit;

if ( class_exists( 'WC_Settings_Shipping', false ) ) {
	return new WC_Settings_Shipping();
}

/**
 * WC_Settings_Shipping.
 */
class WC_Settings_Shipping extends WC_Settings_Page {

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id    = 'shipping';
		$this->label = __( 'Shipping', 'woocommerce' );

		parent::__construct();
	}

	/**
	 * Setting page icon.
	 *
	 * @var string
	 */
	public $icon = 'shipping';

	/**
	 * Add this page to settings.
	 *
	 * @param array $pages Current pages.
	 * @return array|mixed
	 */
	public function add_settings_page( $pages ) {
		return wc_shipping_enabled() ? parent::add_settings_page( $pages ) : $pages;
	}

	/**
	 * Get own sections.
	 *
	 * @return array
	 */
	protected function get_own_sections() {
		$sections = array(
			''        => __( 'Shipping zones', 'woocommerce' ),
			'options' => __( 'Shipping settings', 'woocommerce' ),
			'classes' => __( 'Classes', 'woocommerce' ),
		);

		if ( FeaturesUtil::feature_is_enabled( 'fulfillments' ) ) {
			$sections['fulfillment-providers'] = __( 'Shipping providers', 'woocommerce' );
		}

		if ( ! $this->wc_is_installing() ) {
			// Load shipping methods so we can show any global options they may have.
			$shipping_methods = $this->get_shipping_methods();

			foreach ( $shipping_methods as $method ) {
				if ( ! $method->has_settings() ) {
					continue;
				}
				$title                                 = empty( $method->method_title ) ? ucfirst( $method->id ) : $method->method_title;
				$sections[ strtolower( $method->id ) ] = esc_html( $title );
			}
		}

		return $sections;
	}

	/**
	 * Is WC_INSTALLING constant defined?
	 * This method exists to ease unit testing.
	 *
	 * @return bool True is the WC_INSTALLING constant is defined.
	 */
	protected function wc_is_installing() {
		return Constants::is_defined( 'WC_INSTALLING' );
	}

	/**
	 * Get the currently available shipping methods.
	 * This method exists to ease unit testing.
	 *
	 * @return array Currently available shipping methods.
	 */
	protected function get_shipping_methods() {
		return WC()->shipping()->get_shipping_methods();
	}

	/**
	 * Get settings for the options section.
	 *
	 * @return array
	 */
	protected function get_settings_for_options_section() {
		$settings =
			array(
				array(
					'title' => __( 'Shipping settings', 'woocommerce' ),
					'type'  => 'title',
					'id'    => 'shipping_options',
				),

				array(
					'title'         => __( 'Calculations', 'woocommerce' ),
					'desc'          => __( 'Enable the shipping calculator on the cart page', 'woocommerce' ),
					'id'            => 'woocommerce_enable_shipping_calc',
					'default'       => 'yes',
					'type'          => 'checkbox',
					'checkboxgroup' => 'start',
					'autoload'      => false,
				),

				array(
					'desc'          => __( 'Hide shipping costs until an address is entered', 'woocommerce' ),
					'id'            => 'woocommerce_shipping_cost_requires_address',
					'default'       => 'no',
					'type'          => 'checkbox',
					'checkboxgroup' => '',
				),

				array(
					'desc'          => __( 'Hide shipping rates when free shipping is available', 'woocommerce' ),
					'id'            => 'woocommerce_shipping_hide_rates_when_free',
					'default'       => 'no',
					'type'          => 'checkbox',
					'autoload'      => false,
					'checkboxgroup' => 'end',
				),

				array(
					'title'           => __( 'Shipping destination', 'woocommerce' ),
					'desc'            => __( 'This controls which shipping address is used by default.', 'woocommerce' ),
					'id'              => 'woocommerce_ship_to_destination',
					'default'         => 'billing',
					'type'            => 'radio',
					'options'         => array(
						'shipping'     => __( 'Default to customer shipping address', 'woocommerce' ),
						'billing'      => __( 'Default to customer billing address', 'woocommerce' ),
						'billing_only' => __( 'Force shipping to the customer billing address', 'woocommerce' ),
					),
					'autoload'        => false,
					'desc_tip'        => true,
					'show_if_checked' => 'option',
				),

				array(
					'title'    => __( 'Debug mode', 'woocommerce' ),
					'desc'     => __( 'Enable debug mode', 'woocommerce' ),
					'desc_tip' => __( 'Enable shipping debug mode to show matching shipping zones and to bypass shipping rate cache.', 'woocommerce' ),
					'id'       => 'woocommerce_shipping_debug_mode',
					'default'  => 'no',
					'type'     => 'checkbox',
				),

				array(
					'type' => 'sectionend',
					'id'   => 'shipping_options',
				),
			);

		return apply_filters( 'woocommerce_shipping_settings', $settings );
	}

	/**
	 * Output the settings.
	 */
	public function output() {
		global $current_section, $hide_save_button;

		// Load shipping methods so we can show any global options they may have.
		$shipping_methods = $this->get_shipping_methods();

		if ( '' === $current_section ) {
			$this->output_zones_screen();
		} elseif ( 'classes' === $current_section ) {
			$hide_save_button = true;
			$this->output_shipping_class_screen();
		} elseif ( 'fulfillment-providers' === $current_section && FeaturesUtil::feature_is_enabled( 'fulfillments' ) ) {
			$hide_save_button = true;
			$this->output_shipping_providers_screen();
		} else {
			$is_shipping_method = false;
			foreach ( $shipping_methods as $method ) {
				if ( in_array( $current_section, array( $method->id, sanitize_title( get_class( $method ) ) ), true ) && $method->has_settings() ) {
					$is_shipping_method = true;
					$method->admin_options();
				}
			}
			if ( ! $is_shipping_method ) {
				parent::output();
			}
		}
	}

	/**
	 * Save settings.
	 */
	public function save() {
		global $current_section;

		switch ( $current_section ) {
			case 'options':
				$this->save_settings_for_current_section();
				$this->do_update_options_action();
				break;
			case 'classes':
				$this->do_update_options_action();
				break;
			case 'fulfillment-providers':
				if ( FeaturesUtil::feature_is_enabled( 'fulfillments' ) ) {
					$this->do_update_options_action();
				}
				break;
			case '':
				break;
			default:
				$is_shipping_method = false;

				foreach ( $this->get_shipping_methods() as $method_id => $method ) {
					if ( in_array( $current_section, array( $method->id, sanitize_title( get_class( $method ) ) ), true ) ) {
						$is_shipping_method = true;
						$this->do_update_options_action( $method->id );
					}
				}
				if ( ! $is_shipping_method ) {
					$this->save_settings_for_current_section();
				}
				break;
		}

		// Increments the transient version to invalidate cache.
		WC_Cache_Helper::get_transient_version( 'shipping', true );
	}

	/**
	 * Handles output of the shipping zones page in admin.
	 */
	protected function output_zones_screen() {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		global $hide_save_button;

		if ( isset( $_REQUEST['zone_id'] ) ) {
			$hide_save_button = true;
			$this->zone_methods_screen( wc_clean( wp_unslash( $_REQUEST['zone_id'] ) ) );
		} elseif ( isset( $_REQUEST['instance_id'] ) ) {
			$this->instance_settings_screen( absint( wp_unslash( $_REQUEST['instance_id'] ) ) );
		} else {
			$hide_save_button = true;
			$this->zones_screen();
		}
		// phpcs:enable WordPress.Security.NonceVerification.Recommended
	}

	/**
	 * Get all available regions.
	 *
	 * @param int $allowed_countries Zone ID.
	 * @param int $shipping_continents Zone ID.
	 */
	protected function get_region_options( $allowed_countries, $shipping_continents ) {
		$options = array();
		foreach ( $shipping_continents as $continent_code => $continent ) {
			$continent_data = array(
				'value'    => 'continent:' . esc_attr( $continent_code ),
				'label'    => esc_html( $continent['name'] ),
				'children' => array(),
			);

			$countries = array_intersect( array_keys( $allowed_countries ), $continent['countries'] );

			foreach ( $countries as $country_code ) {
				$country_data = array(
					'value'    => 'country:' . esc_attr( $country_code ),
					'label'    => esc_html( $allowed_countries[ $country_code ] ),
					'children' => array(),
				);

				$states = WC()->countries->get_states( $country_code );

				if ( $states ) {
					foreach ( $states as $state_code => $state_name ) {
						$country_data['children'][] = array(
							'value' => 'state:' . esc_attr( $country_code . ':' . $state_code ),
							'label' => esc_html( $state_name . ', ' . $allowed_countries[ $country_code ] ),
						);
					}
				}
				$continent_data['children'][] = $country_data;
			}
			$options[] = $continent_data;
		}

		return $options;
	}

	/**
	 * Show method for a zone
	 *
	 * @param int $zone_id Zone ID.
	 */
	protected function zone_methods_screen( $zone_id ) {
		if ( 'new' === $zone_id ) {
			$zone = new WC_Shipping_Zone();
		} else {
			$zone = WC_Shipping_Zones::get_zone( absint( $zone_id ) );
		}

		if ( ! $zone ) {
			wp_die( esc_html__( 'Zone does not exist!', 'woocommerce' ) );
		}

		$allowed_countries   = WC()->countries->get_shipping_countries();
		$shipping_continents = WC()->countries->get_shipping_continents();

		// Prepare locations.
		$locations = array();
		$postcodes = array();

		foreach ( $zone->get_zone_locations() as $location ) {
			if ( 'postcode' === $location->type ) {
				$postcodes[] = $location->code;
			} else {
				$locations[] = $location->type . ':' . $location->code;
			}
		}

		$localized_object = array(
			'methods'                 => $zone->get_shipping_methods( false, 'json' ),
			'zone_name'               => $zone->get_zone_name(),
			'zone_id'                 => $zone->get_id(),
			'locations'               => $locations,
			'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ),
			'strings'                 => array(
				'unload_confirmation_msg'             => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
				'save_changes_prompt'                 => __( 'Do you wish to save your changes first? Your changed data will be discarded if you choose to cancel.', 'woocommerce' ),
				'save_failed'                         => __( 'Your changes were not saved. Please retry.', 'woocommerce' ),
				'add_method_failed'                   => __( 'Shipping method could not be added. Please retry.', 'woocommerce' ),
				'remove_method_failed'                => __( 'Shipping method could not be removed. Please retry.', 'woocommerce' ),
				'yes'                                 => __( 'Yes', 'woocommerce' ),
				'no'                                  => __( 'No', 'woocommerce' ),
				'default_zone_name'                   => __( 'Zone', 'woocommerce' ),
				'delete_shipping_method_confirmation' => __( 'Are you sure you want to delete this shipping method?', 'woocommerce' ),
				'invalid_number_format'               => __( 'Please enter a valid number.', 'woocommerce' ),
			),
		);

		if ( 0 !== $zone->get_id() ) {
			WCAdminAssets::register_script( 'wp-admin-scripts', 'shipping-settings-region-picker', true, array( 'wc-shipping-zone-methods' ) );
			$localized_object['region_options'] = $this->get_region_options( $allowed_countries, $shipping_continents );
		}

		wp_localize_script(
			'wc-shipping-zone-methods',
			'shippingZoneMethodsLocalizeScript',
			$localized_object,
		);
		wp_enqueue_script( 'wc-shipping-zone-methods' );

		include_once __DIR__ . '/views/html-admin-page-shipping-zone-methods.php';
	}

	/**
	 * Show zones
	 */
	protected function zones_screen() {
		$method_count = wc_get_shipping_method_count( false, true );

		wp_localize_script(
			'wc-shipping-zones',
			'shippingZonesLocalizeScript',
			array(
				'zones'                   => WC_Shipping_Zones::get_zones( 'json' ),
				'default_zone'            => array(
					'zone_id'    => 0,
					'zone_name'  => '',
					'zone_order' => null,
				),
				'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ),
				'strings'                 => array(
					'unload_confirmation_msg'     => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
					'delete_confirmation_msg'     => __( 'Are you sure you want to delete this zone? This action cannot be undone.', 'woocommerce' ),
					'save_failed'                 => __( 'Your changes were not saved. Please retry.', 'woocommerce' ),
					'no_shipping_methods_offered' => __( 'No shipping methods offered to this zone.', 'woocommerce' ),
				),
			)
		);
		wp_enqueue_script( 'wc-shipping-zones' );

		include_once __DIR__ . '/views/html-admin-page-shipping-zones.php';
	}

	/**
	 * Show instance settings
	 *
	 * @param int $instance_id Shipping instance ID.
	 */
	protected function instance_settings_screen( $instance_id ) {
		$zone            = WC_Shipping_Zones::get_zone_by( 'instance_id', $instance_id );
		$shipping_method = WC_Shipping_Zones::get_shipping_method( $instance_id );

		if ( ! $shipping_method ) {
			wp_die( esc_html__( 'Invalid shipping method!', 'woocommerce' ) );
		}
		if ( ! $zone ) {
			wp_die( esc_html__( 'Zone does not exist!', 'woocommerce' ) );
		}
		if ( ! $shipping_method->has_settings() ) {
			wp_die( esc_html__( 'This shipping method does not have any settings to configure.', 'woocommerce' ) );
		}

		if ( ! empty( $_POST['save'] ) ) {

			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( wp_unslash( $_REQUEST['_wpnonce'] ), 'woocommerce-settings' ) ) {
				echo '<div class="updated error"><p>' . esc_html__( 'Edit failed. Please try again.', 'woocommerce' ) . '</p></div>';
			}

			$shipping_method->process_admin_options();
			$shipping_method->display_errors();
		}

		include_once __DIR__ . '/views/html-admin-page-shipping-zones-instance.php';
	}

	/**
	 * Handles output of the shipping class settings screen.
	 */
	protected function output_shipping_class_screen() {
		$wc_shipping = WC_Shipping::instance();
		wp_localize_script(
			'wc-shipping-classes',
			'shippingClassesLocalizeScript',
			array(
				'classes'                   => $wc_shipping->get_shipping_classes(),
				'default_shipping_class'    => array(
					'term_id'     => 0,
					'name'        => '',
					'description' => '',
				),
				'wc_shipping_classes_nonce' => wp_create_nonce( 'wc_shipping_classes_nonce' ),
				'strings'                   => array(
					'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
					'save_failed'             => __( 'Your changes were not saved. Please retry.', 'woocommerce' ),
				),
			)
		);
		wp_enqueue_script( 'wc-shipping-classes' );

		// Extendable columns to show on the shipping classes screen.
		$shipping_class_columns = apply_filters(
			'woocommerce_shipping_classes_columns',
			array(
				'wc-shipping-class-name'        => __( 'Shipping class', 'woocommerce' ),
				'wc-shipping-class-slug'        => __( 'Slug', 'woocommerce' ),
				'wc-shipping-class-description' => __( 'Description', 'woocommerce' ),
				'wc-shipping-class-count'       => __( 'Product count', 'woocommerce' ),
			)
		);

		include_once __DIR__ . '/views/html-admin-page-shipping-classes.php';
	}

	/**
	 * Handles output of the shipping providers settings screen.
	 *
	 * @since 10.7.0
	 */
	protected function output_shipping_providers_screen(): void {
		$providers = get_terms(
			array(
				'taxonomy'   => 'wc_fulfillment_shipping_provider',
				'hide_empty' => false,
			)
		);

		if ( is_wp_error( $providers ) ) {
			$providers = array();
		}

		$shipping_providers = array();
		foreach ( $providers as $provider ) {
			$shipping_providers[] = array(
				'term_id'               => $provider->term_id,
				'name'                  => $provider->name,
				'slug'                  => $provider->slug,
				'tracking_url_template' => get_term_meta( $provider->term_id, 'tracking_url_template', true ),
				'icon'                  => get_term_meta( $provider->term_id, 'icon', true ),
			);
		}

		wp_localize_script(
			'wc-shipping-providers',
			'shippingProvidersLocalizeScript',
			array(
				'providers'                   => $shipping_providers,
				'default_shipping_provider'   => array(
					'term_id'               => 0,
					'name'                  => '',
					'slug'                  => '',
					'tracking_url_template' => '',
					'icon'                  => '',
				),
				'wc_shipping_providers_nonce' => wp_create_nonce( 'wc_shipping_providers_nonce' ),
				'strings'                     => array(
					'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
					'save_failed'             => __( 'Your changes were not saved. Please retry.', 'woocommerce' ),
					'delete_confirmation'     => __( 'Are you sure you want to delete this shipping provider?', 'woocommerce' ),
				),
			)
		);
		wp_enqueue_script( 'wc-shipping-providers' );

		$shipping_provider_columns = array(
			'wc-shipping-provider-name'                  => __( 'Name', 'woocommerce' ),
			'wc-shipping-provider-slug'                  => __( 'Slug', 'woocommerce' ),
			'wc-shipping-provider-tracking-url-template' => __( 'Tracking URL template', 'woocommerce' ),
			'wc-shipping-provider-icon'                  => __( 'Icon URL', 'woocommerce' ),
		);

		include_once __DIR__ . '/views/html-admin-page-shipping-providers.php';
	}
}

return new WC_Settings_Shipping();
PK     tS\u<  <  &  settings/class-wc-settings-general.phpnu [        <?php
/**
 * WooCommerce General Settings
 *
 * @package WooCommerce\Admin
 */

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Internal\AddressProvider\AddressProviderController;

defined( 'ABSPATH' ) || exit;

if ( class_exists( 'WC_Settings_General', false ) ) {
	return new WC_Settings_General();
}

/**
 * WC_Admin_Settings_General.
 */
class WC_Settings_General extends WC_Settings_Page {

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id    = 'general';
		$this->label = __( 'General', 'woocommerce' );

		parent::__construct();
	}

	/**
	 * Setting page icon.
	 *
	 * @var string
	 */
	public $icon = 'cog';

	/**
	 * Get settings or the default section.
	 *
	 * @return array
	 */
	protected function get_settings_for_default_section() {

		$currency_code_options = get_woocommerce_currencies();

		foreach ( $currency_code_options as $code => $name ) {
			$currency_code_options[ $code ] = $name . ' (' . get_woocommerce_currency_symbol( $code ) . ') — ' . esc_html( $code );
		}

		$address_autocomplete_preferred_provider_setting = array();
		$address_autocomplete_setting_desc_tip           = __( 'Suggest full addresses to customers as they type.', 'woocommerce' );

		// This is in a try because getting the class from the container may fail if the class is not available.
		// If it fails, these settings should not be shown as the feature is not available.
		try {
			$address_provider_class         = wc_get_container()->get( AddressProviderController::class );
			$address_autocomplete_providers = $address_provider_class->get_providers();
			$address_autocomplete_available = ! empty( $address_autocomplete_providers );

			if ( ! $address_autocomplete_available ) {
				// translators: %s: WooPayments URL.
				$address_autocomplete_setting_desc_tip .= ' ' . sprintf( __( 'Requires a plugin with predictive address search support (e.g. <a href="%s" target="_blank">WooPayments</a>).', 'woocommerce' ), 'https://woocommerce.com/products/woocommerce-payments/' );
			}

			$enable_address_autocomplete_setting = array(
				'id'       => 'woocommerce_address_autocomplete_enabled',
				'desc'     => __( 'Enable predictive address search', 'woocommerce' ),
				'name'     => __( 'Address autocomplete', 'woocommerce' ),
				'type'     => 'checkbox',
				'disabled' => ! $address_autocomplete_available,
				'desc_tip' => $address_autocomplete_setting_desc_tip,
				'default'  => 'no',
			);

			// If no providers are available, make sure the checkbox is unchecked.
			if ( ! $address_autocomplete_available ) {
				$enable_address_autocomplete_setting['value'] = false;
			}

			if ( count( $address_autocomplete_providers ) > 1 ) {
				$address_provider_options = array();
				foreach ( $address_autocomplete_providers as $address_provider ) {
					$address_provider_options[ $address_provider->id ] = sanitize_text_field( $address_provider->name );
				}
				$address_autocomplete_preferred_provider_setting = array(
					'id'      => 'woocommerce_address_autocomplete_provider',
					'name'    => __( 'Preferred address autocomplete provider', 'woocommerce' ),
					'type'    => 'select',
					'class'   => 'wc-enhanced-select',
					'default' => $address_autocomplete_providers[0]->id ?? '',
					'options' => $address_provider_options,
				);
			}
		} catch ( \Exception $e ) {
			// If the class is not available, we don't want to show the setting.
			wc_get_logger()->log( 'error', 'Error getting address provider class: ' . $e->getMessage() );
			$enable_address_autocomplete_setting             = array();
			$address_autocomplete_preferred_provider_setting = array();
		}

		$settings =
			array(

				array(
					'title' => __( 'Store Address', 'woocommerce' ),
					'type'  => 'title',
					'desc'  => __( 'This is where your business is located. Tax rates and shipping rates will use this address.', 'woocommerce' ),
					'id'    => 'store_address',
					'order' => 10,
				),

				array(
					'title'    => __( 'Address line 1', 'woocommerce' ),
					'desc'     => __( 'The street address for your business location.', 'woocommerce' ),
					'id'       => 'woocommerce_store_address',
					'default'  => '',
					'type'     => 'text',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Address line 2', 'woocommerce' ),
					'desc'     => __( 'An additional, optional address line for your business location.', 'woocommerce' ),
					'id'       => 'woocommerce_store_address_2',
					'default'  => '',
					'type'     => 'text',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'City', 'woocommerce' ),
					'desc'     => __( 'The city in which your business is located.', 'woocommerce' ),
					'id'       => 'woocommerce_store_city',
					'default'  => '',
					'type'     => 'text',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Country / State', 'woocommerce' ),
					'desc'     => __( 'The country and state or province, if any, in which your business is located.', 'woocommerce' ),
					'id'       => 'woocommerce_default_country',
					'default'  => 'US:CA',
					'type'     => 'single_select_country',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Postcode / ZIP', 'woocommerce' ),
					'desc'     => __( 'The postal code, if any, in which your business is located.', 'woocommerce' ),
					'id'       => 'woocommerce_store_postcode',
					'css'      => 'min-width:50px;',
					'default'  => '',
					'type'     => 'text',
					'desc_tip' => true,
				),

				array(
					'type' => 'sectionend',
					'id'   => 'store_address',
				),

				array(
					'title' => __( 'General options', 'woocommerce' ),
					'type'  => 'title',
					'desc'  => '',
					'id'    => 'general_options',
					'order' => 20,
				),

				array(
					'title'    => __( 'Selling location(s)', 'woocommerce' ),
					'desc'     => __( 'This option lets you limit which countries you are willing to sell to.', 'woocommerce' ),
					'id'       => 'woocommerce_allowed_countries',
					'default'  => 'all',
					'type'     => 'select',
					'class'    => 'wc-enhanced-select',
					'css'      => 'min-width: 350px;',
					'desc_tip' => true,
					'options'  => array(
						'all'        => __( 'Sell to all countries', 'woocommerce' ),
						'all_except' => __( 'Sell to all countries, except for&hellip;', 'woocommerce' ),
						'specific'   => __( 'Sell to specific countries', 'woocommerce' ),
					),
				),

				array(
					'title'   => __( 'Sell to all countries, except for&hellip;', 'woocommerce' ),
					'desc'    => '',
					'id'      => 'woocommerce_all_except_countries',
					'css'     => 'min-width: 350px;',
					'default' => '',
					'type'    => 'multi_select_countries',
				),

				array(
					'title'   => __( 'Sell to specific countries', 'woocommerce' ),
					'desc'    => '',
					'id'      => 'woocommerce_specific_allowed_countries',
					'css'     => 'min-width: 350px;',
					'default' => '',
					'type'    => 'multi_select_countries',
				),

				array(
					'title'    => __( 'Shipping location(s)', 'woocommerce' ),
					'desc'     => __( 'Choose which countries you want to ship to, or choose to ship to all locations you sell to.', 'woocommerce' ),
					'id'       => 'woocommerce_ship_to_countries',
					'default'  => '',
					'type'     => 'select',
					'class'    => 'wc-enhanced-select',
					'desc_tip' => true,
					'options'  => array(
						''         => __( 'Ship to all countries you sell to', 'woocommerce' ),
						'all'      => __( 'Ship to all countries', 'woocommerce' ),
						'specific' => __( 'Ship to specific countries only', 'woocommerce' ),
						'disabled' => __( 'Disable shipping &amp; shipping calculations', 'woocommerce' ),
					),
				),

				array(
					'title'   => __( 'Ship to specific countries', 'woocommerce' ),
					'desc'    => '',
					'id'      => 'woocommerce_specific_ship_to_countries',
					'css'     => '',
					'default' => '',
					'type'    => 'multi_select_countries',
				),

				array(
					'title'    => __( 'Default customer location', 'woocommerce' ),
					'id'       => 'woocommerce_default_customer_address',
					'desc_tip' => __( 'This option determines a customers default location. The MaxMind GeoLite Database will be periodically downloaded to your wp-content directory if using geolocation.', 'woocommerce' ),
					'default'  => 'base',
					'type'     => 'select',
					'class'    => 'wc-enhanced-select',
					'options'  => array(
						''                 => __( 'No location by default', 'woocommerce' ),
						'base'             => __( 'Shop country/region', 'woocommerce' ),
						'geolocation'      => __( 'Geolocate', 'woocommerce' ),
						'geolocation_ajax' => __( 'Geolocate (with page caching support)', 'woocommerce' ),
					),
				),

				$enable_address_autocomplete_setting,

				$address_autocomplete_preferred_provider_setting,

				array(
					'type' => 'sectionend',
					'id'   => 'general_options',
				),

				array(
					'title' => __( 'Taxes and coupons', 'woocommerce' ),
					'type'  => 'title',
					'desc'  => __( 'Enable taxes and coupons and configure how they are calculated.', 'woocommerce' ),
					'id'    => 'taxes_and_coupons_options',
					'order' => 30,
				),

				array(
					'title'    => __( 'Enable taxes', 'woocommerce' ),
					'desc'     => __( 'Enable tax rates and calculations', 'woocommerce' ),
					'id'       => 'woocommerce_calc_taxes',
					'default'  => 'no',
					'type'     => 'checkbox',
					'desc_tip' => __( 'Rates will be configurable and taxes will be calculated during checkout.', 'woocommerce' ),
				),

				array(
					'title'           => __( 'Enable coupons', 'woocommerce' ),
					'desc'            => __( 'Enable the use of coupon codes', 'woocommerce' ),
					'id'              => 'woocommerce_enable_coupons',
					'default'         => 'yes',
					'type'            => 'checkbox',
					'checkboxgroup'   => 'start',
					'show_if_checked' => 'option',
					'desc_tip'        => __( 'Coupons can be applied from the cart and checkout pages.', 'woocommerce' ),
				),

				array(
					'desc'            => __( 'Calculate coupon discounts sequentially', 'woocommerce' ),
					'id'              => 'woocommerce_calc_discounts_sequentially',
					'default'         => 'no',
					'type'            => 'checkbox',
					'desc_tip'        => __( 'When applying multiple coupons, apply the first coupon to the full price and the second coupon to the discounted price and so on.', 'woocommerce' ),
					'show_if_checked' => 'yes',
					'checkboxgroup'   => 'end',
					'autoload'        => false,
				),

				array(
					'type' => 'sectionend',
					'id'   => 'taxes_and_coupons_options',
				),

				array(
					'title' => __( 'Currency options', 'woocommerce' ),
					'type'  => 'title',
					'desc'  => __( 'The following options affect how prices are displayed on the frontend.', 'woocommerce' ),
					'id'    => 'pricing_options',
					'order' => 40,
				),

				array(
					'title'    => __( 'Currency', 'woocommerce' ),
					'desc'     => __( 'This controls what currency prices are listed at in the catalog and which currency gateways will take payments in.', 'woocommerce' ),
					'id'       => 'woocommerce_currency',
					'default'  => 'USD',
					'type'     => 'select',
					'class'    => 'wc-enhanced-select',
					'desc_tip' => true,
					'options'  => $currency_code_options,
				),

				array(
					'title'    => __( 'Currency position', 'woocommerce' ),
					'desc'     => __( 'This controls the position of the currency symbol.', 'woocommerce' ),
					'id'       => 'woocommerce_currency_pos',
					'class'    => 'wc-enhanced-select',
					'default'  => 'left',
					'type'     => 'select',
					'options'  => array(
						'left'        => __( 'Left', 'woocommerce' ),
						'right'       => __( 'Right', 'woocommerce' ),
						'left_space'  => __( 'Left with space', 'woocommerce' ),
						'right_space' => __( 'Right with space', 'woocommerce' ),
					),
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Thousand separator', 'woocommerce' ),
					'desc'     => __( 'This sets the thousand separator of displayed prices.', 'woocommerce' ),
					'id'       => 'woocommerce_price_thousand_sep',
					'css'      => 'width:50px;',
					'default'  => ',',
					'type'     => 'text',
					'desc_tip' => true,
				),

				array(
					'title'    => __( 'Decimal separator', 'woocommerce' ),
					'desc'     => __( 'This sets the decimal separator of displayed prices.', 'woocommerce' ),
					'id'       => 'woocommerce_price_decimal_sep',
					'css'      => 'width:50px;',
					'default'  => '.',
					'type'     => 'text',
					'desc_tip' => true,
				),

				array(
					'title'             => __( 'Number of decimals', 'woocommerce' ),
					'desc'              => __( 'This sets the number of decimal points shown in displayed prices.', 'woocommerce' ),
					'id'                => 'woocommerce_price_num_decimals',
					'css'               => 'width:50px;',
					'default'           => '2',
					'desc_tip'          => true,
					'type'              => 'number',
					'custom_attributes' => array(
						'min'  => 0,
						'step' => 1,
					),
				),

				array(
					'type' => 'sectionend',
					'id'   => 'pricing_options',
				),
			);

		// Remove any empty items from settings array.
		// e.g. The preferred autocomplete provider setting would be empty if <=1 providers are registered.
		$settings = array_filter(
			$settings,
			function ( $setting ) {
				return ! empty( $setting );
			}
		);
		return apply_filters( 'woocommerce_general_settings', $settings );
	}

	/**
	 * Output a color picker input box.
	 *
	 * @param mixed  $name Name of input.
	 * @param string $id ID of input.
	 * @param mixed  $value Value of input.
	 * @param string $desc (default: '') Description for input.
	 */
	public function color_picker( $name, $id, $value, $desc = '' ) {
		echo '<div class="color_box">' . wc_help_tip( $desc ) . '
			<input name="' . esc_attr( $id ) . '" id="' . esc_attr( $id ) . '" type="text" value="' . esc_attr( $value ) . '" class="colorpick" /> <div id="colorPickerDiv_' . esc_attr( $id ) . '" class="colorpickdiv"></div>
		</div>';
	}

	/**
	 * Output settings with additional JS to hide preferred provider if autocomplete is disabled.
	 *
	 * @return void
	 */
	public function output() {
		parent::output();

		$handle = 'wc-admin-settings-general';
		wp_register_script( $handle, '', array(), WC_VERSION, array( 'in_footer' => true ) );
		wp_enqueue_script( $handle );
		wp_add_inline_script(
			$handle,
			"
			const preferredProviderInput = document.querySelector( '#woocommerce_address_autocomplete_provider' );
			const autocompleteEnabledInput = document.querySelector( '#woocommerce_address_autocomplete_enabled' );
			let preferredProviderRow = null;
			if ( preferredProviderInput ) {
				preferredProviderRow = preferredProviderInput.closest( 'tr' );
			}
			if ( autocompleteEnabledInput && preferredProviderRow ) {
				if ( ! autocompleteEnabledInput.checked ) {
					preferredProviderRow.style.display = 'none';
				}
				autocompleteEnabledInput.addEventListener( 'change', function( e ) {
					if ( e.target.checked ) {
						preferredProviderRow.style.display = 'table-row';
					} else {
						preferredProviderRow.style.display = 'none';
					}
				} );
			}
			"
		);
	}
}

return new WC_Settings_General();
PK     tS\Z(    %  settings/class-wc-settings-emails.phpnu [        <?php
/**
 * WooCommerce Email Settings
 *
 * @package WooCommerce\Admin
 * @version 2.1.0
 */

use Automattic\WooCommerce\Internal\Admin\EmailPreview\EmailPreview;
use Automattic\WooCommerce\Internal\Email\EmailColors;
use Automattic\WooCommerce\Internal\Email\EmailFont;
use Automattic\WooCommerce\Internal\Email\EmailStyleSync;
use Automattic\WooCommerce\Internal\EmailEditor\EmailTemplates\WooEmailTemplate;
use Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails\WCTransactionalEmailPostsManager;
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Utilities\FeaturesUtil;

defined( 'ABSPATH' ) || exit;

if ( class_exists( 'WC_Settings_Emails', false ) ) {
	return new WC_Settings_Emails();
}

/**
 * WC_Settings_Emails.
 */
class WC_Settings_Emails extends WC_Settings_Page {

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id    = 'email';
		$this->label = __( 'Emails', 'woocommerce' );

		add_action( 'woocommerce_admin_field_email_notification', array( $this, 'email_notification_setting' ) );
		add_action( 'woocommerce_admin_field_email_notification_block_emails', array( $this, 'email_notification_setting_block_emails' ) );
		add_action( 'woocommerce_admin_field_email_preview', array( $this, 'email_preview' ) );
		add_action( 'woocommerce_admin_field_email_image_url', array( $this, 'email_image_url' ) );
		add_action( 'woocommerce_admin_field_email_font_family', array( $this, 'email_font_family' ) );
		add_action( 'woocommerce_admin_field_email_color_palette', array( $this, 'email_color_palette' ) );
		add_action( 'woocommerce_admin_field_previewing_new_templates', array( $this, 'previewing_new_templates' ) );
		add_action( 'woocommerce_admin_field_email_improvements_button', array( $this, 'email_improvements_button' ) );
		add_action( 'woocommerce_email_settings_after', array( $this, 'email_preview_single' ) );
		add_action( 'woocommerce_settings_saved', array( $this, 'enable_email_improvements_when_trying_new_templates' ), 999 );
		add_filter( 'woocommerce_admin_settings_sanitize_option_woocommerce_email_header_image', array( $this, 'sanitize_email_header_image' ), 10, 3 );
		add_filter( 'woocommerce_tracks_event_properties', array( $this, 'append_feature_email_improvements_to_tracks' ) );
		add_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $this, 'track_email_improvements_feature_change' ), 10, 2 );
		parent::__construct();
	}

	/**
	 * Setting page icon.
	 *
	 * @var string
	 */
	public $icon = 'atSymbol';

	/**
	 * Get own sections.
	 *
	 * @return array
	 */
	protected function get_own_sections() {
		return array(
			'' => __( 'Email options', 'woocommerce' ),
		);
	}

	/**
	 * Get settings array.
	 *
	 * @return array
	 */
	protected function get_settings_for_default_section() {
		$desc_help_text = sprintf(
		/* translators: %1$s: Link to WP Mail Logging plugin, %2$s: Link to Email FAQ support page. */
			__( 'To ensure your store&rsquo;s notifications arrive in your and your customers&rsquo; inboxes, we recommend connecting your email address to your domain and setting up a dedicated SMTP server. If something doesn&rsquo;t seem to be sending correctly, install the <a href="%1$s">WP Mail Logging Plugin</a> or check the <a href="%2$s">Email FAQ page</a>.', 'woocommerce' ),
			'https://wordpress.org/plugins/wp-mail-logging/',
			'https://woocommerce.com/document/email-faq'
		);

		$block_email_editor_enabled = FeaturesUtil::feature_is_enabled( 'block_email_editor' );
		$email_improvements_enabled = $this->get_email_improvements_enabled();

		// These defaults should be chosen by the same logic as the other color option properties.
		$default_colors = EmailColors::get_default_colors( $email_improvements_enabled );

		if ( $block_email_editor_enabled ) {
			$email_notifications_field = 'email_notification_block_emails';
			$email_notifications_desc  = null;
		} else {
			$email_notifications_field = 'email_notification';
			/* translators: %s: help description with link to WP Mail logging and support page. */
			$email_notifications_desc = sprintf( __( 'Email notifications sent from WooCommerce are listed below. Click on an email to configure it.<br>%s', 'woocommerce' ), $desc_help_text );
		}

		$settings =
			array(
				array(
					'title' => __( 'Email notifications', 'woocommerce' ),
					'desc'  => $email_notifications_desc,
					'type'  => 'title',
					'id'    => 'email_notification_settings',
				),

				array( 'type' => $email_notifications_field ),

				array(
					'type' => 'sectionend',
					'id'   => 'email_notification_settings',
				),

				array(
					'type' => 'sectionend',
					'id'   => 'email_recipient_options',
				),
				array(
					'title' => __( 'Email sender options', 'woocommerce' ),
					'type'  => 'title',
					'desc'  => __( "Set the name and email address you'd like your outgoing emails to use.", 'woocommerce' ),
					'id'    => 'email_options',
				),

				array(
					'title'             => __( '"From" name', 'woocommerce' ),
					'desc'              => '',
					'id'                => 'woocommerce_email_from_name',
					'type'              => 'text',
					'css'               => 'min-width:400px;',
					'default'           => esc_attr( get_bloginfo( 'name', 'display' ) ),
					'autoload'          => false,
					'desc_tip'          => true,
					'skip_initial_save' => true,
				),

				array(
					'title'             => __( '"From" address', 'woocommerce' ),
					'desc'              => '',
					'id'                => 'woocommerce_email_from_address',
					'type'              => 'email',
					'custom_attributes' => array(
						'multiple' => 'multiple',
					),
					'css'               => 'min-width:400px;',
					'default'           => get_option( 'admin_email' ),
					'autoload'          => false,
					'desc_tip'          => true,
				),
			);

		// Add reply-to fields when block email editor is enabled.
		if ( $block_email_editor_enabled ) {
			$settings = array_merge(
				$settings,
				array(
					array(
						'title'    => __( 'Add "Reply-to" email', 'woocommerce' ),
						'desc'     => __( 'Add a different email address to receive replies.', 'woocommerce' ),
						'id'       => 'woocommerce_email_reply_to_enabled',
						'type'     => 'checkbox',
						'default'  => 'no',
						'autoload' => false,
					),

					array(
						'title'    => __( '"Reply-to" name', 'woocommerce' ),
						'desc'     => '',
						'id'       => 'woocommerce_email_reply_to_name',
						'type'     => 'text',
						'css'      => 'min-width:400px;',
						'default'  => '',
						'autoload' => false,
						'desc_tip' => true,
					),

					array(
						'title'    => __( '"Reply-to" address', 'woocommerce' ),
						'desc'     => '',
						'id'       => 'woocommerce_email_reply_to_address',
						'type'     => 'email',
						'css'      => 'min-width:400px;',
						'default'  => '',
						'autoload' => false,
						'desc_tip' => true,
					),
				)
			);
		}

		$settings = array_merge(
			$settings,
			array(
				array(
					'type' => 'sectionend',
					'id'   => 'email_options',
				),
			)
		);

		// If the email editor is enabled the design is handled by the email editor.
		if ( ! $block_email_editor_enabled ) {
			$settings = array_merge(
				$settings,
				array(
					array(
						'title' => __( 'Email template', 'woocommerce' ),
						'type'  => 'title',
						'desc'  => __( 'Customize your WooCommerce email template and preview it below.', 'woocommerce' ),
						'id'    => 'email_template_options',
					),

					array(
						'title' => __( 'Try new templates', 'woocommerce' ),
						'type'  => 'previewing_new_templates',
						'id'    => 'previewing_new_templates',
					),

					array(
						'title'       => __( 'Logo', 'woocommerce' ),
						'desc'        => __( 'Add your logo to each of your WooCommerce emails. If no logo is uploaded, your site title will be used instead.', 'woocommerce' ),
						'id'          => 'woocommerce_email_header_image',
						'type'        => 'email_image_url',
						'css'         => 'min-width:400px;',
						'placeholder' => __( 'N/A', 'woocommerce' ),
						'default'     => '',
						'autoload'    => false,
						'desc_tip'    => true,
					),

					array(
						'title'     => __( 'Logo width (px)', 'woocommerce' ),
						'id'        => 'woocommerce_email_header_image_width',
						'desc_tip'  => '',
						'default'   => '120',
						'type'      => 'number',
						'row_class' => $email_improvements_enabled ? '' : 'disabled',
					),

					array(
						'title'     => __( 'Header alignment', 'woocommerce' ),
						'id'        => 'woocommerce_email_header_alignment',
						'desc_tip'  => '',
						'default'   => 'left',
						'type'      => 'select',
						'class'     => 'wc-enhanced-select',
						'options'   => array(
							'left'   => __( 'Left', 'woocommerce' ),
							'center' => __( 'Center', 'woocommerce' ),
							'right'  => __( 'Right', 'woocommerce' ),
						),
						'row_class' => $email_improvements_enabled ? '' : 'disabled',
					),

					array(
						'title'     => __( 'Font family', 'woocommerce' ),
						'id'        => 'woocommerce_email_font_family',
						'default'   => 'Helvetica',
						'type'      => 'email_font_family',
						'row_class' => $email_improvements_enabled ? '' : 'disabled',
					),

					array(
						'title'       => __( 'Footer text', 'woocommerce' ),
						/* translators: %s: Available placeholders for use */
						'desc'        => __( 'This text will appear in the footer of all of your WooCommerce emails.', 'woocommerce' ) . ' ' . sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '{site_title} {site_url} {store_address} {store_email}' ),
						'id'          => 'woocommerce_email_footer_text',
						'css'         => 'width:400px; height: 75px;',
						'placeholder' => __( 'N/A', 'woocommerce' ),
						'type'        => 'textarea',
						'default'     => '{site_title}<br />{store_address}',
						'autoload'    => false,
						'desc_tip'    => true,
					),

					array(
						'type' => 'sectionend',
						'id'   => 'email_template_options',
					),

					array(
						'title' => __( 'Color palette', 'woocommerce' ),
						'type'  => 'email_color_palette',
						'id'    => 'email_color_palette',
					),

					array(
						'title'    => __( 'Accent', 'woocommerce' ),
						/* translators: %s: default color */
						'desc'     => sprintf( __( 'Customize the color of your buttons and links. Default %s.', 'woocommerce' ), '<code>' . $default_colors['base'] . '</code>' ),
						'id'       => 'woocommerce_email_base_color',
						'type'     => 'color',
						'css'      => 'width:6em;',
						'default'  => $default_colors['base'],
						'autoload' => false,
						'desc_tip' => true,
					),

					array(
						'title'    => __( 'Email background', 'woocommerce' ),
						/* translators: %s: default color */
						'desc'     => sprintf( __( 'Select a color for the background of your emails. Default %s.', 'woocommerce' ), '<code>' . $default_colors['bg'] . '</code>' ),
						'id'       => 'woocommerce_email_background_color',
						'type'     => 'color',
						'css'      => 'width:6em;',
						'default'  => $default_colors['bg'],
						'autoload' => false,
						'desc_tip' => true,
					),

					array(
						'title'    => __( 'Content background', 'woocommerce' ),
						/* translators: %s: default color */
						'desc'     => sprintf( __( 'Choose a background color for the content area of your emails. Default %s.', 'woocommerce' ), '<code>' . $default_colors['body_bg'] . '</code>' ),
						'id'       => 'woocommerce_email_body_background_color',
						'type'     => 'color',
						'css'      => 'width:6em;',
						'default'  => $default_colors['body_bg'],
						'autoload' => false,
						'desc_tip' => true,
					),

					array(
						'title'    => __( 'Heading & text', 'woocommerce' ),
						/* translators: %s: default color */
						'desc'     => sprintf( __( 'Set the color of your headings and text. Default %s.', 'woocommerce' ), '<code>' . $default_colors['body_text'] . '</code>' ),
						'id'       => 'woocommerce_email_text_color',
						'type'     => 'color',
						'css'      => 'width:6em;',
						'default'  => $default_colors['body_text'],
						'autoload' => false,
						'desc_tip' => true,
					),

					array(
						'title'    => __( 'Secondary text', 'woocommerce' ),
						/* translators: %s: footer default color */
						'desc'     => sprintf( __( 'Choose a color for your secondary text, such as your footer content. Default %s.', 'woocommerce' ), '<code>' . $default_colors['footer_text'] . '</code>' ),
						'id'       => 'woocommerce_email_footer_text_color',
						'type'     => 'color',
						'css'      => 'width:6em;',
						'default'  => $default_colors['footer_text'],
						'autoload' => false,
						'desc_tip' => true,
					),

					array(
						'title'    => __( 'Auto-sync with theme', 'woocommerce' ),
						'desc'     => __( 'Automatically update email styles when theme styles change', 'woocommerce' ),
						'id'       => 'woocommerce_email_auto_sync_with_theme',
						'type'     => 'hidden',
						'default'  => 'no',
						'autoload' => false,
					),

					array(
						'type' => 'sectionend',
						'id'   => 'email_color_palette',
					),

					array(
						'title' => __( 'Email improvements button', 'woocommerce' ),
						'type'  => 'email_improvements_button',
						'id'    => 'email_improvements_button',
					),

					array( 'type' => 'email_preview' ),
				)
			);
		}

		// Remove empty elements that depend on the email_improvements feature flag.
		$settings = array_filter( $settings );

		/**
		 * Filters the email settings array.
		 *
		 * @since 2.1.0
		 *
		 * @param array $settings Array of email settings.
		 */
		return apply_filters( 'woocommerce_email_settings', $settings );
	}

	/**
	 * Get custom fonts for emails.
	 */
	public function get_custom_fonts() {
		$custom_fonts = array();
		if ( wp_is_block_theme() && class_exists( 'WP_Font_Face_Resolver' ) ) {
			$theme_fonts = WP_Font_Face_Resolver::get_fonts_from_theme_json();
			if ( count( $theme_fonts ) > 0 ) {
				foreach ( $theme_fonts as $font ) {
					if ( ! empty( $font[0]['font-family'] ) ) {
						$custom_fonts[ $font[0]['font-family'] ] = $font[0]['font-family'];
					}
				}
			}
		}
		ksort( $custom_fonts );

		return $custom_fonts;
	}

	/**
	 * Output the settings.
	 */
	public function output() {
		global $current_section;

		// Define emails that can be customised here.
		$mailer          = WC()->mailer();
		$email_templates = $mailer->get_emails();

		if ( $current_section ) {
			foreach ( $email_templates as $email_key => $email ) {
				if ( strtolower( $email_key ) === $current_section ) {
					$this->run_email_admin_options( $email );
					break;
				}
			}
		}

		parent::output();
	}

	/**
	 * Run the 'admin_options' method on a given email.
	 * This method exists to easy unit testing.
	 *
	 * @param object $email The email object to run the method on.
	 */
	protected function run_email_admin_options( $email ) {
		$email->admin_options();
	}

	/**
	 * Save settings.
	 */
	public function save() {
		global $current_section;

		if ( ! $current_section ) {
			$this->save_settings_for_current_section();
			$this->do_update_options_action();
		} else {
			$wc_emails = WC_Emails::instance();

			if ( in_array( $current_section, array_map( 'sanitize_title', array_keys( $wc_emails->get_emails() ) ), true ) ) {
				foreach ( $wc_emails->get_emails() as $email_id => $email ) {
					if ( sanitize_title( $email_id ) === $current_section ) {
						$this->do_update_options_action( $email->id );
					}
				}
			} else {
				$this->save_settings_for_current_section();
				$this->do_update_options_action();
			}
		}
	}

	/**
	 * Output email notification settings.
	 */
	public function email_notification_setting() {
		// Define emails that can be customised here.
		$mailer          = WC()->mailer();
		$email_templates = $mailer->get_emails();

		?>
		<tr valign="top">
		<td class="wc_emails_wrapper" colspan="2">
			<table class="wc_emails widefat" cellspacing="0">
				<thead>
					<tr>
						<?php
						/**
						 * Filters the columns displayed in the email settings table.
						 *
						 * @since 2.1.0
						 *
						 * @param array $columns Array of column keys and labels.
						 */
						$columns = apply_filters(
							'woocommerce_email_setting_columns',
							array(
								'status'     => '',
								'name'       => __( 'Email', 'woocommerce' ),
								'email_type' => __( 'Content type', 'woocommerce' ),
								'recipient'  => __( 'Recipient(s)', 'woocommerce' ),
								'actions'    => '',
							)
						);
						foreach ( $columns as $key => $column ) {
							echo '<th class="wc-email-settings-table-' . esc_attr( $key ) . '">' . esc_html( $column ) . '</th>';
						}
						?>
						</tr>
					</thead>
					<tbody>
						<?php
						foreach ( $email_templates as $email_key => $email ) {
							echo '<tr>';

							foreach ( $columns as $key => $column ) {

								switch ( $key ) {
									case 'name':
										echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
										<a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=email&section=' . strtolower( $email_key ) ) ) . '">' . esc_html( $email->get_title() ) . '</a>
										' . wc_help_tip( $email->get_description() ) . '
										</td>';
										break;
									case 'recipient':
										$to  = $email->is_customer_email() ? __( 'Customer', 'woocommerce' ) : $email->get_recipient();
										$cc  = false;
										$bcc = false;
										if ( FeaturesUtil::feature_is_enabled( 'email_improvements' ) ) {
											$ccs  = $email->get_cc_recipient();
											$bccs = $email->get_bcc_recipient();
											// Translators: %s: comma-separated email addresses to which the email is cc-ed.
											$cc = $ccs ? sprintf( __( '<b>Cc</b>: %s', 'woocommerce' ), $ccs ) : false;
											// Translators: %s: comma-separated email addresses to which the email is bcc-ed.
											$bcc = $bccs ? sprintf( __( '<b>Bcc</b>: %s', 'woocommerce' ), $bccs ) : false;
											if ( $cc || $bcc ) {
												// Translators: %s: comma-separated email addresses to which the email is sent.
												$to = sprintf( __( '<b>To</b>: %s', 'woocommerce' ), $to );
											}
										}
										$allowed_tags = array( 'b' => array() );

										echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">';
										echo wp_kses( $to, $allowed_tags );
										if ( $cc ) {
											echo '<br>' . wp_kses( $cc, $allowed_tags );
										}
										if ( $bcc ) {
											echo '<br>' . wp_kses( $bcc, $allowed_tags );
										}
										echo '</td>';
										break;
									case 'status':
										echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">';

										if ( $email->is_manual() ) {
											echo '<span class="status-manual tips" data-tip="' . esc_attr__( 'Manually sent', 'woocommerce' ) . '">' . esc_html__( 'Manual', 'woocommerce' ) . '</span>';
										} elseif ( $email->is_enabled() ) {
											echo '<span class="status-enabled tips" data-tip="' . esc_attr__( 'Enabled', 'woocommerce' ) . '">' . esc_html__( 'Yes', 'woocommerce' ) . '</span>';
										} else {
											echo '<span class="status-disabled tips" data-tip="' . esc_attr__( 'Disabled', 'woocommerce' ) . '">-</span>';
										}

										echo '</td>';
										break;
									case 'email_type':
										echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
										' . esc_html( $email->get_content_type() ) . '
										</td>';
										break;
									case 'actions':
										echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
										<a class="button alignright" href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=email&section=' . strtolower( $email_key ) ) ) . '">' . esc_html__( 'Manage', 'woocommerce' ) . '</a>
										</td>';
										break;
									default:
										/**
										 * Fires when rendering a custom column in the email settings table.
										 *
										 * @since 2.1.0
										 *
										 * @param WC_Email $email The email object.
										 */
										do_action( 'woocommerce_email_setting_column_' . $key, $email );
										break;
								}
							}

							echo '</tr>';
						}
						?>
					</tbody>
				</table>
			</td>
		</tr>
		<?php
	}

	/**
	 * Creates the React mount point for listing of block based emails.
	 */
	public function email_notification_setting_block_emails() {
		$desc_help_text = sprintf(
			/* translators: %1$s: Link to WP Mail Logging plugin, %2$s: Link to Email FAQ support page. */
			__( 'To ensure your store&rsquo;s notifications arrive in your and your customers&rsquo; inboxes, we recommend connecting your email address to your domain and setting up a dedicated SMTP server. If something doesn&rsquo;t seem to be sending correctly, install the <a href="%1$s">WP Mail Logging Plugin</a> or check the <a href="%2$s">Email FAQ page</a>.', 'woocommerce' ),
			'https://wordpress.org/plugins/wp-mail-logging/',
			'https://woocommerce.com/document/email-faq'
		);
		$email_post_manager   = WCTransactionalEmailPostsManager::get_instance();
		$emails               = WC()->mailer()->get_emails();
		$email_types          = array();
		$post_id_for_template = null;
		foreach ( $emails as $email_key => $email ) {
			$post_id       = $email_post_manager->get_email_template_post_id( $email->id );
			$email_types[] = array(
				'title'       => $email->get_title(),
				'description' => $email->get_description(),
				'id'          => $email->id,
				'email_key'   => strtolower( $email_key ),
				'post_id'     => $post_id,
				'enabled'     => $email->is_enabled(),
				'manual'      => $email->is_manual(),
				'recipients'  => array(
					'to'  => $email->is_customer_email() ? __( 'Customers', 'woocommerce' ) : $email->get_recipient(),
					'cc'  => $email->get_cc_recipient(),
					'bcc' => $email->get_bcc_recipient(),
				),
			);

			// Store the first valid post ID we find.
			if ( ! $post_id_for_template && $post_id ) {
				$post_id_for_template = $post_id;
			}
		}
		// Create URL for email editor template mode.
		$edit_template_url = null;
		if ( $post_id_for_template ) {
			$email_template_id = get_stylesheet() . '//' . WooEmailTemplate::TEMPLATE_SLUG;
			$edit_template_url = admin_url( 'post.php?post=' . $post_id_for_template . '&action=edit&template=' . $email_template_id );
		}

		?>
		<div
			id="wc_settings_email_listing_slotfill" class="wc-settings-prevent-change-event woocommerce-email-listing-listview"
			data-email-types="<?php echo esc_attr( wp_json_encode( $email_types ) ); ?>"
			data-edit-template-url="<?php echo esc_attr( $edit_template_url ); ?>"
		>
			<div style="
			display: flex;
			align-items: center;
			justify-content: center;
			padding: 12px;
			height: 40px;
			width: 100%;
			">
				<h3> <?php esc_html_e( 'Loading&hellip;', 'woocommerce' ); ?>  </h3>
			</div>
		</div>
		<div>
			<p><?php echo wp_kses_post( wpautop( wptexturize( $desc_help_text ) ) ); ?></p>
		</div>
		<?php
	}

	/**
	 * Creates the React mount point for the email preview.
	 */
	public function email_preview() {
		$this->delete_transient_email_settings();
		$emails      = WC()->mailer()->get_emails();
		$email_types = array();
		foreach ( $emails as $email ) {
			$email_types[] = array(
				'label' => $email->get_title(),
				'value' => get_class( $email ),
			);
		}
		?>
		<div
			id="wc_settings_email_preview_slotfill"
			data-preview-url="<?php echo esc_url( wp_nonce_url( admin_url( '?preview_woocommerce_mail=true' ), 'preview-mail' ) ); ?>"
			data-email-types="<?php echo esc_attr( wp_json_encode( $email_types ) ); ?>"
			data-email-setting-ids="<?php echo esc_attr( wp_json_encode( EmailPreview::get_email_style_setting_ids() ) ); ?>"
		></div>
		<?php
	}

	/**
	 * Creates the React mount point for the single email preview.
	 *
	 * @param object $email The email object to run the method on.
	 */
	public function email_preview_single( $email ) {
		$this->delete_transient_email_settings();
		// Email types array should have a single entry for current email.
		$email_types = array(
			array(
				'label' => $email->get_title(),
				'value' => get_class( $email ),
			),
		);
		?>
		<h2><?php echo esc_html( __( 'Email preview', 'woocommerce' ) ); ?></h2>

		<p><?php echo esc_html( __( 'Preview your email template. You can also test on different devices and send yourself a test email.', 'woocommerce' ) ); ?></p>
		<div>
			<div
				id="wc_settings_email_preview_slotfill"
				data-preview-url="<?php echo esc_url( wp_nonce_url( admin_url( '?preview_woocommerce_mail=true' ), 'preview-mail' ) ); ?>"
				data-email-types="<?php echo esc_attr( wp_json_encode( $email_types ) ); ?>"
				data-email-setting-ids="<?php echo esc_attr( wp_json_encode( EmailPreview::get_email_content_setting_ids( $email->id ) ) ); ?>"
			></div>
			<input type="hidden" id="woocommerce_email_from_name" value="<?php echo esc_attr( get_option( 'woocommerce_email_from_name' ) ); ?>" />
			<input type="hidden" id="woocommerce_email_from_address" value="<?php echo esc_attr( get_option( 'woocommerce_email_from_address' ) ); ?>" />
		</div>
		<?php
	}

	/**
	 * Deletes transient with email settings used for live preview. This is to
	 * prevent conflicts where the preview would show values from previous session.
	 */
	private function delete_transient_email_settings() {
		$setting_ids = EmailPreview::get_all_email_setting_ids();
		foreach ( $setting_ids as $id ) {
			delete_transient( $id );
		}
	}

	/**
	 * Creates the React mount point for the email image url.
	 *
	 * @param array $value Field value array.
	 */
	public function email_image_url( $value ) {
		$option_value = $value['value'];
		if ( ! isset( $value['field_name'] ) ) {
			$value['field_name'] = $value['id'];
		}
		?>
		<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
			<th scope="row" class="titledesc">
				<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?> <?php echo wc_help_tip( $value['desc'] ); // WPCS: XSS ok. ?></label>
			</th>
			<td class="forminp forminp-<?php echo esc_attr( sanitize_title( $value['type'] ) ); ?>">
				<input
					name="<?php echo esc_attr( $value['field_name'] ); ?>"
					id="<?php echo esc_attr( $value['id'] ); ?>"
					type="hidden"
					value="<?php echo esc_attr( $option_value ); ?>"
				/>
				<div
					id="wc_settings_email_image_url_slotfill"
					data-id="<?php echo esc_attr( $value['id'] ); ?>"
					data-image-url="<?php echo esc_attr( $option_value ); ?>"
				></div>
			</td>
		</tr>
		<?php
	}

	/**
	 * Sanitize email image URL.
	 *
	 * @param  string $value     Option value.
	 * @param  array  $option    Option name.
	 * @param  string $raw_value Raw value.
	 * @return string
	 */
	public function sanitize_email_header_image( $value, $option, $raw_value ) {
		return sanitize_url( $raw_value );
	}

	/**
	 * Creates the email font family field with custom font family applied to each option.
	 *
	 * @param array $value Field value array.
	 */
	public function email_font_family( $value ) {
		$option_value = $value['value'];
		// This is a temporary fix to prevent using custom fonts without fallback.
		$custom_fonts = null;

		?>
		<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
			<th scope="row" class="titledesc">
				<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
			</th>
			<td class="forminp forminp-<?php echo esc_attr( sanitize_title( $value['type'] ) ); ?>">
			<script type="text/javascript">
				function renderWithFont( node ) {
					if ( ! node.element || ! node.element.value ) return node.text;
					var $wrapper = jQuery( '<span></span>' );
					$wrapper.css( {'font-family': node.element.dataset['font-family'] || node.element.value} );
					$wrapper.text( node.text );
					return $wrapper;
				}
				function fontsSelect( selector ) {
					jQuery( selector ).selectWoo( {
						minimumResultsForSearch: Infinity,
						templateResult: renderWithFont
					} );
				}
				jQuery( document.body )
					.on( 'wc-enhanced-select-init', function() {
						fontsSelect( '#<?php echo esc_js( $value['id'] ); ?>' );
					} );
				</script>
				<select
					name="<?php echo esc_attr( $value['field_name'] ); ?>"
					id="<?php echo esc_attr( $value['id'] ); ?>"
					>
					<optgroup label="<?php echo esc_attr__( 'Standard fonts', 'woocommerce' ); ?>">
						<?php
						foreach ( EmailFont::$font as $key => $font_family ) {
							?>
							<option
								value="<?php echo esc_attr( $key ); ?>"
								data-font-family="<?php echo esc_attr( $font_family ); ?>"
								<?php selected( $option_value, (string) $key ); ?>
							><?php echo esc_html( $key ); ?></option>
							<?php
						}
						?>
					</optgroup>
					<?php if ( $custom_fonts ) : ?>
						<optgroup label="<?php echo esc_attr__( 'Custom fonts', 'woocommerce' ); ?>">
							<?php
							foreach ( $custom_fonts as $key => $val ) {
								?>
							<option
								value="<?php echo esc_attr( $key ); ?>"
								<?php selected( $option_value, (string) $key ); ?>
							><?php echo esc_html( $val ); ?></option>
								<?php
							}
							?>
						</optgroup>
					<?php endif; ?>
				</select>
			</td>
		</tr>
		<?php
	}

	/**
	 * Creates the React mount point for the email color palette title.
	 *
	 * @param array $value Field value array.
	 */
	public function email_color_palette( $value ) {
		$email_improvements_enabled = $this->get_email_improvements_enabled();
		$default_colors             = EmailColors::get_default_colors( $email_improvements_enabled );
		$auto_sync                  = get_option( EmailStyleSync::AUTO_SYNC_OPTION, 'no' );

		?>
		<hr class="wc-settings-email-color-palette-separator" />
		<div class="wc-settings-email-color-palette-header">
			<h2 class="wc-settings-email-color-palette-title"><?php echo esc_html( $value['title'] ); ?></h2>
			<?php if ( $email_improvements_enabled ) : ?>
				<div
					class="wc-settings-email-color-palette-buttons"
					id="wc_settings_email_color_palette_slotfill"
					data-default-colors="<?php echo esc_attr( wp_json_encode( $default_colors ) ); ?>"
					<?php echo wp_theme_has_theme_json() ? 'data-has-theme-json' : ''; ?>
				></div>
				<input
					type="hidden"
					name="woocommerce_email_auto_sync_with_theme"
					id="woocommerce_email_auto_sync_with_theme"
					value="<?php echo esc_attr( $auto_sync ); ?>"
				/>
			<?php else : ?>
				<div class="wc-settings-email-color-palette-buttons">
					<button disabled type="button" class="components-button is-secondary"><?php esc_html_e( 'Sync with theme', 'woocommerce' ); ?></button>
				</div>
			<?php endif; ?>
		</div>
		<table class="form-table">
		<?php
	}

	/**
	 * Show a notice to the user when they are trying out the new email templates.
	 */
	public function previewing_new_templates(): void {
		if ( ! $this->is_trying_new_templates() ) {
			return;
		}
		if ( FeaturesUtil::feature_is_enabled( 'email_improvements' ) ) {
			return;
		}
		update_option( 'woocommerce_admin_dismissed_try_email_improvements_modal', 'yes' );
		?>
		<div class="wc-settings-email-color-palette-header submit">
			<div class="notice notice-info inline">
				<p><?php esc_html_e( 'Previewing new template designs. You can customize and test your emails and switch to the new template whenever you are ready.', 'woocommerce' ); ?></p>
				<p>
					<button name="save" type="submit" class="components-button is-secondary" value="<?php esc_attr_e( 'Save changes', 'woocommerce' ); ?>">
						<?php esc_html_e( 'Switch to new template', 'woocommerce' ); ?>
					</button>
					<a href="?page=wc-settings&tab=email" class="components-button is-tertiary">
						<?php esc_html_e( 'Keep legacy template', 'woocommerce' ); ?>
					</a>
				</p>
			</div>
		</div>
		<?php
	}

	/**
	 * Show a button to revert or enable email improvements.
	 */
	public function email_improvements_button(): void {
		if ( 'yes' === get_transient( 'wc_settings_email_improvements_reverted' ) ) {
			?>
			<div id="wc_settings_features_email_feedback_slotfill"></div>
			<?php
		}
		$is_feature_enabled   = FeaturesUtil::feature_is_enabled( 'email_improvements' );
		$trying_new_templates = $this->is_trying_new_templates();
		if ( ! $is_feature_enabled && ! $trying_new_templates ) {
			?>
			<hr class="wc-settings-email-color-palette-separator" />
			<a href="?page=wc-settings&tab=email&try-new-templates" class="components-button is-link">
				<?php esc_html_e( 'Try our new email templates!', 'woocommerce' ); ?>
			</a>
			<?php
			return;
		}

		$has_feature_enabled_since_installation = 'yes' === get_option( 'woocommerce_email_improvements_default_enabled', 'no' );
		if ( $is_feature_enabled && ! $has_feature_enabled_since_installation ) {
			$disable_feature_args = array(
				'email_improvements' => '0',
				'_feature_nonce'     => wp_create_nonce( 'change_feature_enable' ),
			);
			?>
			<hr class="wc-settings-email-color-palette-separator" />
			<a href="<?php echo esc_url( add_query_arg( $disable_feature_args ) ); ?>"
				class="components-button is-link"
				onclick="return confirm('<?php esc_attr_e( 'Are you sure want to revert to legacy? Doing so will erase any changes you’ve made to your new email templates, and will restore your previous email designs.', 'woocommerce' ); ?>');"
			>
				<?php esc_html_e( 'Revert to legacy template', 'woocommerce' ); ?>
			</a>
			<?php
			return;
		}
		?>
		<?php
	}

	/**
	 * Append email improvements prop to Tracks globally.
	 *
	 * @param array $event_properties Event properties array.
	 *
	 * @return array
	 */
	public function append_feature_email_improvements_to_tracks( $event_properties ) {
		if ( is_array( $event_properties ) ) {
			$is_email_improvements_enabled                  = FeaturesUtil::feature_is_enabled( 'email_improvements' );
			$event_properties['feature_email_improvements'] = $is_email_improvements_enabled ? 'enabled' : 'disabled';
		}
		return $event_properties;
	}

	/**
	 * Track email improvements feature change.
	 *
	 * @param string $feature_id The feature ID.
	 * @param bool   $enabled True if the feature is enabled, false if it is disabled.
	 */
	public function track_email_improvements_feature_change( $feature_id, $enabled ) {
		if ( 'email_improvements' === $feature_id ) {
			$current_date = gmdate( 'Y-m-d H:i:s' );
			if ( $enabled ) {
				$enabled_count = get_option( 'woocommerce_email_improvements_enabled_count', 0 );
				update_option( 'woocommerce_email_improvements_enabled_count', $enabled_count + 1 );
				add_option( 'woocommerce_email_improvements_first_enabled_at', $current_date );
				update_option( 'woocommerce_email_improvements_last_enabled_at', $current_date );
			} else {
				$disabled_count = get_option( 'woocommerce_email_improvements_disabled_count', 0 );
				update_option( 'woocommerce_email_improvements_disabled_count', $disabled_count + 1 );
				add_option( 'woocommerce_email_improvements_first_disabled_at', $current_date );
				update_option( 'woocommerce_email_improvements_last_disabled_at', $current_date );
			}
		}
	}

	/**
	 * When the email settings are saved, if the user is trying out the new email templates, enable the email improvements feature.
	 */
	public function enable_email_improvements_when_trying_new_templates() {
		if ( $this->is_trying_new_templates() ) {
			$feature_controller = wc_get_container()->get( FeaturesController::class );
			$feature_controller->change_feature_enable( 'email_improvements', true );

			// Remove the try-new-templates parameter from the URL.
			wp_safe_redirect( remove_query_arg( 'try-new-templates' ) );
			exit;
		}
	}

	/**
	 * Get "email improvements" feature status or force it when enabled via URL parameter.
	 * Transient is used to force the email improvements feature in email preview, which
	 * is rendered in iframe.
	 *
	 * @return bool
	 */
	private function get_email_improvements_enabled() {
		$email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improvements' );
		// Check for try-new-templates URL parameter, which is used to force the email improvements feature in preview mode.
		if ( $this->is_trying_new_templates() ) {
			$email_improvements_enabled = true;
			set_transient( EmailPreview::TRANSIENT_PREVIEW_EMAIL_IMPROVEMENTS, 'yes' );
		} else {
			delete_transient( EmailPreview::TRANSIENT_PREVIEW_EMAIL_IMPROVEMENTS );
		}
		return $email_improvements_enabled;
	}

	/**
	 * Check if the user is trying out the new email templates.
	 *
	 * @return bool
	 */
	private function is_trying_new_templates() {
		global $current_tab;
		if ( 'email' !== $current_tab ) {
			return false;
		}
		if ( isset( $_GET['section'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return false;
		}
		return isset( $_GET['try-new-templates'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
	}
}

return new WC_Settings_Emails();
PK     tS\Z    8  marketplace-suggestions/class-wc-marketplace-updater.phpnu [        <?php
/**
 * Marketplace suggestions updater
 *
 * Uses WC_Queue to ensure marketplace suggestions data is up to date and cached locally.
 *
 * @package WooCommerce\Classes
 * @since   3.6.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Marketplace Suggestions Updater
 */
class WC_Marketplace_Updater {

	/**
	 * Setup.
	 */
	public static function load() {
		add_action( 'init', array( __CLASS__, 'init' ) );
	}

	/**
	 * Schedule events and hook appropriate actions.
	 */
	public static function init() {
		add_action( 'woocommerce_update_marketplace_suggestions', array( __CLASS__, 'update_marketplace_suggestions' ) );
	}

	/**
	 * Fetches new marketplace data, updates wc_marketplace_suggestions.
	 */
	public static function update_marketplace_suggestions() {
		$data = get_option(
			'woocommerce_marketplace_suggestions',
			array(
				'suggestions' => array(),
				'updated'     => time(),
			)
		);

		$data['updated'] = time();

		$request_data = array();

		$allow_tracking = 'yes' === get_option( 'woocommerce_allow_tracking', 'no' );
		if ( class_exists( 'WC_Marketplace_Suggestions' ) && WC_Marketplace_Suggestions::allow_suggestions() && $allow_tracking ) {
			$request_data = self::add_personalization_data( $request_data );
		}

		$url = 'https://woocommerce.com/wp-json/wccom/marketplace-suggestions/2.0/suggestions.json';

		// Add request data as query parameters if it exists.
		if ( ! empty( $request_data ) ) {
			$url = add_query_arg( $request_data, $url );
		}

		$request = wp_safe_remote_get(
			$url,
			array(
				'user-agent' => 'WooCommerce/' . WC()->version . '; ' . get_bloginfo( 'url' ),
			)
		);

		if ( is_wp_error( $request ) ) {
			self::retry();
			return update_option( 'woocommerce_marketplace_suggestions', $data, false );
		}

		$body = wp_remote_retrieve_body( $request );
		if ( empty( $body ) ) {
			self::retry();
			return update_option( 'woocommerce_marketplace_suggestions', $data, false );
		}

		$body = json_decode( $body, true );
		if ( empty( $body ) || ! is_array( $body ) ) {
			self::retry();
			return update_option( 'woocommerce_marketplace_suggestions', $data, false );
		}

		$data['suggestions'] = $body;
		return update_option( 'woocommerce_marketplace_suggestions', $data, false );
	}

	/**
	 * Used when an error has occurred when fetching suggestions.
	 * Re-schedules the job earlier than the main weekly one.
	 */
	public static function retry() {
		WC()->queue()->cancel_all( 'woocommerce_update_marketplace_suggestions' );
		WC()->queue()->schedule_single( time() + DAY_IN_SECONDS, 'woocommerce_update_marketplace_suggestions' );
	}

	/**
	 * Add additional data to the request for personalized suggestions.
	 *
	 * @param array $request_params The data to include in the request.
	 * @return array
	 */
	public static function add_personalization_data( $request_params ) {
		$request_params['country'] = wc_get_base_location()['country'];

		return $request_params;
	}
}

WC_Marketplace_Updater::load();
PK     tS\}'    +  marketplace-suggestions/views/container.phpnu [        <?php
/**
 * Marketplace suggestions container
 *
 * @package  WooCommerce\Templates
 * @version  3.6.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

?>
<div class="marketplace-suggestions-container"
	data-marketplace-suggestions-context="<?php echo esc_attr( $context ); ?>"
	>
</div>
PK     tS\\U&  &  B  marketplace-suggestions/templates/html-product-data-extensions.phpnu [        <?php
/**
 * The marketplace suggestions tab HTML in the product tabs
 *
 * @package WooCommerce\Classes
 * @since   3.6.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

?>
<div id="marketplace_suggestions" class="panel woocommerce_options_panel hidden">
	<?php
		WC_Marketplace_Suggestions::render_suggestions_container( 'product-edit-meta-tab-header' );
		WC_Marketplace_Suggestions::render_suggestions_container( 'product-edit-meta-tab-body' );
		WC_Marketplace_Suggestions::render_suggestions_container( 'product-edit-meta-tab-footer' );
	?>
	<div class="marketplace-suggestions-metabox-nosuggestions-placeholder hidden">
		<img src="https://woocommerce.com/wp-content/plugins/wccom-plugins/marketplace-suggestions/icons/get_more_options.svg" class="marketplace-suggestion-icon">
		<div class="marketplace-suggestion-placeholder-content">
			<h4><?php esc_html_e( 'Enhance your products', 'woocommerce' ); ?></h4>
			<p><?php esc_html_e( 'Extensions can add new functionality to your product pages that make your store stand out', 'woocommerce' ); ?></p>
		</div>
		<a href="https://woocommerce.com/product-category/woocommerce-extensions/?utm_source=editproduct&amp;utm_campaign=marketplacesuggestions&amp;utm_medium=product" target="blank" class="button"><?php esc_html_e( 'Browse the Marketplace', 'woocommerce' ); ?></a><br />
		<a class="marketplace-suggestion-manage-link" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=woocommerce_com' ) ); ?>"><?php esc_html_e( 'Manage suggestions', 'woocommerce' ); ?></a>
	</div>
</div>
PK     tS\    <  marketplace-suggestions/class-wc-marketplace-suggestions.phpnu [        <?php
/**
 * Marketplace suggestions
 *
 * Behaviour for displaying in-context suggestions for marketplace extensions.
 *
 * @package WooCommerce\Classes
 * @since   3.6.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Marketplace suggestions core behaviour.
 */
class WC_Marketplace_Suggestions {

	/**
	 * Initialise.
	 */
	public static function init() {
		if ( ! self::allow_suggestions() ) {
			return;
		}

		// Add suggestions to the product tabs.
		add_action( 'woocommerce_product_data_tabs', array( __CLASS__, 'product_data_tabs' ) );
		add_action( 'woocommerce_product_data_panels', array( __CLASS__, 'product_data_panels' ) );

		// Register ajax api handlers.
		add_action( 'wp_ajax_woocommerce_add_dismissed_marketplace_suggestion', array( __CLASS__, 'post_add_dismissed_suggestion_handler' ) );

		// Register hooks for rendering suggestions container markup.
		add_action( 'wc_marketplace_suggestions_orders_empty_state', array( __CLASS__, 'render_orders_list_empty_state' ) );

		// Trigger suggestions fetch on wc-admin dashboard.
		add_action( 'current_screen', array( __CLASS__, 'maybe_trigger_suggestions_fetch' ) );
	}

	/**
	 * Product data tabs filter
	 *
	 * Adds a new Extensions tab to the product data meta box.
	 *
	 * @param array $tabs Existing tabs.
	 *
	 * @return array
	 */
	public static function product_data_tabs( $tabs ) {
		$tabs['marketplace-suggestions'] = array(
			'label'    => _x( 'Get more options', 'Marketplace suggestions', 'woocommerce' ),
			'target'   => 'marketplace_suggestions',
			'class'    => array(),
			'priority' => 1000,
		);

		return $tabs;
	}

	/**
	 * Render additional panels in the product data metabox.
	 */
	public static function product_data_panels() {
		include dirname( __FILE__ ) . '/templates/html-product-data-extensions.php';
	}

	/**
	 * Return an array of suggestions the user has dismissed.
	 */
	public static function get_dismissed_suggestions() {
		$dismissed_suggestions = array();

		$dismissed_suggestions_data = get_user_meta( get_current_user_id(), 'wc_marketplace_suggestions_dismissed_suggestions', true );
		if ( $dismissed_suggestions_data ) {
			$dismissed_suggestions = $dismissed_suggestions_data;
			if ( ! is_array( $dismissed_suggestions ) ) {
				$dismissed_suggestions = array();
			}
		}

		return $dismissed_suggestions;
	}

	/**
	 * POST handler for adding a dismissed suggestion.
	 */
	public static function post_add_dismissed_suggestion_handler() {
		if ( ! check_ajax_referer( 'add_dismissed_marketplace_suggestion' ) ) {
			wp_die();
		}

		$post_data       = wp_unslash( $_POST );
		$suggestion_slug = sanitize_text_field( $post_data['slug'] );
		if ( ! $suggestion_slug ) {
			wp_die();
		}

		$dismissed_suggestions = self::get_dismissed_suggestions();

		if ( in_array( $suggestion_slug, $dismissed_suggestions, true ) ) {
			wp_die();
		}

		$dismissed_suggestions[] = $suggestion_slug;
		update_user_meta(
			get_current_user_id(),
			'wc_marketplace_suggestions_dismissed_suggestions',
			$dismissed_suggestions
		);

		wp_die();
	}

	/**
	 * Render suggestions containers in orders list empty state.
	 */
	public static function render_orders_list_empty_state() {
		self::render_suggestions_container( 'orders-list-empty-header' );
		self::render_suggestions_container( 'orders-list-empty-body' );
		self::render_suggestions_container( 'orders-list-empty-footer' );
	}

	/**
	 * Render a suggestions container element, with the specified context.
	 *
	 * @param string $context Suggestion context name (rendered as a css class).
	 */
	public static function render_suggestions_container( $context ) {
		include dirname( __FILE__ ) . '/views/container.php';
	}

	/**
	 * Should suggestions be displayed?
	 *
	 * @param string $screen_id The current admin screen.
	 *
	 * @return bool
	 */
	public static function show_suggestions_for_screen( $screen_id ) {
		// We only show suggestions on certain admin screens.
		if ( ! in_array( $screen_id, array( 'edit-product', 'edit-shop_order', 'product', wc_get_page_screen_id( 'shop-order' ) ), true ) ) {
			return false;
		}

		return self::allow_suggestions();
	}

	/**
	 * Trigger suggestion fetch for wc-admin dashboard.
	 */
	public static function maybe_trigger_suggestions_fetch() {
		$screen    = get_current_screen();
		$screen_id = $screen ? $screen->id : '';

		if ( 'woocommerce_page_wc-admin' === $screen_id && self::allow_suggestions() ) {
			self::get_suggestions_api_data();
		}
	}

	/**
	 * Should suggestions be displayed?
	 *
	 * @return bool
	 */
	public static function allow_suggestions() {
		// We currently only support English suggestions.
		$locale             = get_locale();
		$suggestion_locales = array(
			'en_AU',
			'en_CA',
			'en_GB',
			'en_NZ',
			'en_US',
			'en_ZA',
		);
		if ( ! in_array( $locale, $suggestion_locales, true ) ) {
			return false;
		}

		// Suggestions are only displayed if user can install plugins.
		if ( ! current_user_can( 'install_plugins' ) ) {
			return false;
		}

		// Suggestions may be disabled via a setting under Accounts & Privacy.
		if ( 'no' === get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) ) {
			return false;
		}

		// User can disabled all suggestions via filter.
		return apply_filters( 'woocommerce_allow_marketplace_suggestions', true );
	}

	/**
	 * Pull suggestion data from options. This is retrieved from a remote endpoint.
	 *
	 * @return array of json API data
	 */
	public static function get_suggestions_api_data() {
		$data = get_option( 'woocommerce_marketplace_suggestions', array() );

		// If the options have never been updated, or were updated over a week ago, queue update.
		if ( empty( $data['updated'] ) || ( time() - WEEK_IN_SECONDS ) > $data['updated'] ) {
			$next = WC()->queue()->get_next( 'woocommerce_update_marketplace_suggestions' );
			if ( ! $next ) {
				WC()->queue()->cancel_all( 'woocommerce_update_marketplace_suggestions' );
				WC()->queue()->schedule_single( time(), 'woocommerce_update_marketplace_suggestions' );
			}
		}

		return ! empty( $data['suggestions'] ) ? $data['suggestions'] : array();
	}
}

WC_Marketplace_Suggestions::init();

PK     tS\Lh؟  ؟    class-wc-admin-settings.phpnu [        <?php
/**
 * WooCommerce Admin Settings Class
 *
 * @package  WooCommerce\Admin
 * @version  3.4.0
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Utilities\FeaturesUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'WC_Admin_Settings', false ) ) :

	/**
	 * WC_Admin_Settings Class.
	 */
	class WC_Admin_Settings {

		/**
		 * Setting pages.
		 *
		 * @var array
		 */
		private static $settings = array();

		/**
		 * Error messages.
		 *
		 * @var array
		 */
		private static $errors = array();

		/**
		 * Update messages.
		 *
		 * @var array
		 */
		private static $messages = array();

		/**
		 * Include the settings page classes.
		 */
		public static function get_settings_pages() {
			if ( empty( self::$settings ) ) {
				$settings = array();

				include_once __DIR__ . '/settings/class-wc-settings-page.php';

				$settings[] = include_once __DIR__ . '/settings/class-wc-settings-general.php';
				$settings[] = include_once __DIR__ . '/settings/class-wc-settings-products.php';
				$settings[] = include_once __DIR__ . '/settings/class-wc-settings-tax.php';
				$settings[] = include_once __DIR__ . '/settings/class-wc-settings-shipping.php';
				$settings[] = include_once __DIR__ . '/settings/class-wc-settings-payment-gateways.php';
				$settings[] = include_once __DIR__ . '/settings/class-wc-settings-accounts.php';
				$settings[] = include_once __DIR__ . '/settings/class-wc-settings-emails.php';
				$settings[] = include_once __DIR__ . '/settings/class-wc-settings-integrations.php';
				if ( \Automattic\WooCommerce\Admin\Features\Features::is_enabled( 'launch-your-store' ) ) {
					$settings[] = include_once __DIR__ . '/settings/class-wc-settings-site-visibility.php';
				}
				if ( FeaturesUtil::feature_is_enabled( 'point_of_sale' ) ) {
					$settings[] = include_once __DIR__ . '/settings/class-wc-settings-point-of-sale.php';
				}
				$settings[] = include_once __DIR__ . '/settings/class-wc-settings-advanced.php';

				self::$settings = apply_filters( 'woocommerce_get_settings_pages', $settings );
				add_action(
					'admin_head',
					function () {
						if ( function_exists( 'get_current_screen' ) ) {
							$screen = get_current_screen();
							if ( 'woocommerce_page_wc-settings' === $screen->id ) {
								$screen->remove_help_tabs();
							}
						}
					}
				);

				// Reset settings when features that affect settings are toggled.
				add_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( __CLASS__, 'reset_settings_pages_on_feature_change' ), 10, 2 );
			}

			return self::$settings;
		}

		/**
		 * Reset settings when features that affect settings are toggled.
		 *
		 * @param string $feature_id The feature ID.
		 * @param bool   $is_enabled Whether the feature is enabled.
		 *
		 * @internal For exclusive usage within this class, backwards compatibility not guaranteed.
		 */
		public static function reset_settings_pages_on_feature_change( $feature_id, $is_enabled ) {
			if ( 'point_of_sale' === $feature_id && $is_enabled ) {
				self::$settings = array();
				self::get_settings_pages();
			}
		}

		/**
		 * Save the settings.
		 */
		public static function save() {
			global $current_tab;

			if ( ! current_user_can( 'manage_woocommerce' ) ) {
				wp_die( esc_html__( 'You do not have permission to save settings.', 'woocommerce' ), 403 );
			}

			check_admin_referer( 'woocommerce-settings' );

			// Trigger actions.
			do_action( 'woocommerce_settings_save_' . $current_tab );
			do_action( 'woocommerce_update_options_' . $current_tab );
			do_action( 'woocommerce_update_options' );

			self::add_message( __( 'Your settings have been saved.', 'woocommerce' ) );
			self::check_download_folder_protection();

			// Clear any unwanted data and flush rules.
			update_option( 'woocommerce_queue_flush_rewrite_rules', 'yes' );
			WC()->query->init_query_vars();
			WC()->query->add_endpoints();

			do_action( 'woocommerce_settings_saved' );
		}

		/**
		 * Add a message.
		 *
		 * @param string $text Message.
		 */
		public static function add_message( $text ) {
			self::$messages[] = $text;
		}

		/**
		 * Add an error.
		 *
		 * @param string $text Message.
		 */
		public static function add_error( $text ) {
			self::$errors[] = $text;
		}

		/**
		 * Output messages + errors.
		 */
		public static function show_messages() {
			if ( count( self::$errors ) > 0 ) {
				foreach ( self::$errors as $error ) {
					echo '<div id="message" class="error inline"><p><strong>' . esc_html( $error ) . '</strong></p></div>';
				}
			} elseif ( count( self::$messages ) > 0 ) {
				foreach ( self::$messages as $message ) {
					echo '<div id="message" class="updated inline"><p><strong>' . esc_html( $message ) . '</strong></p></div>';
				}
			}
		}

		/**
		 * Settings page.
		 *
		 * Handles the display of the main woocommerce settings page in admin.
		 */
		public static function output() {
			global $current_section, $current_tab;

			$suffix = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';

			do_action( 'woocommerce_settings_start' );

			wp_enqueue_script( 'woocommerce_settings', WC()->plugin_url() . '/assets/js/admin/settings' . $suffix . '.js', array( 'jquery', 'wp-util', 'jquery-ui-datepicker', 'jquery-ui-sortable', 'iris', 'selectWoo' ), WC()->version, true );

			wp_localize_script(
				'woocommerce_settings',
				'woocommerce_settings_params',
				array(
					'i18n_nav_warning'                    => __( 'The changes you made will be lost if you navigate away from this page.', 'woocommerce' ),
					'i18n_moved_up'                       => __( 'Item moved up', 'woocommerce' ),
					'i18n_moved_down'                     => __( 'Item moved down', 'woocommerce' ),
					'i18n_no_specific_countries_selected' => __( 'Selecting no country / region to sell to prevents from completing the checkout. Continue anyway?', 'woocommerce' ),
				)
			);

			// Get tabs for the settings page.
			$tabs = apply_filters( 'woocommerce_settings_tabs_array', array() );

			include __DIR__ . '/views/html-admin-settings.php';
		}

		/**
		 * Get a setting from the settings API.
		 *
		 * @param string $option_name Option name.
		 * @param mixed  $default     Default value.
		 * @return mixed
		 */
		public static function get_option( $option_name, $default = '' ) {
			if ( ! $option_name ) {
				return $default;
			}

			// Array value.
			if ( strstr( $option_name, '[' ) ) {

				parse_str( $option_name, $option_array );

				// Option name is first key.
				$option_name = current( array_keys( $option_array ) );

				// Get value.
				$option_values = get_option( $option_name, '' );

				$key = key( $option_array[ $option_name ] );

				if ( isset( $option_values[ $key ] ) ) {
					$option_value = $option_values[ $key ];
				} else {
					$option_value = null;
				}
			} else {
				// Single value.
				$option_value = get_option( $option_name, null );
			}

			if ( is_array( $option_value ) ) {
				$option_value = wp_unslash( $option_value );
			} elseif ( ! is_null( $option_value ) ) {
				$option_value = stripslashes( $option_value );
			}

			return ( null === $option_value ) ? $default : $option_value;
		}

		/**
		 * Output admin fields.
		 *
		 * Loops through the woocommerce options array and outputs each field.
		 *
		 * @param array[] $options Opens array to output.
		 */
		public static function output_fields( $options ) {
			foreach ( $options as $value ) {
				if ( ! isset( $value['type'] ) ) {
					continue;
				}
				if ( ! isset( $value['id'] ) ) {
					$value['id'] = '';
				}

				// The 'field_name' key can be used when it is useful to specify an input field name that is different
				// from the input field ID. We use the key 'field_name' because 'name' is already in use for a different
				// purpose.
				if ( ! isset( $value['field_name'] ) ) {
					$value['field_name'] = $value['id'];
				}
				if ( ! isset( $value['title'] ) ) {
					$value['title'] = isset( $value['name'] ) ? $value['name'] : '';
				}
				if ( ! isset( $value['class'] ) ) {
					$value['class'] = '';
				}
				if ( ! isset( $value['css'] ) ) {
					$value['css'] = '';
				}
				if ( ! isset( $value['default'] ) ) {
					$value['default'] = '';
				}
				if ( ! isset( $value['desc'] ) ) {
					$value['desc'] = '';
				}
				if ( ! isset( $value['desc_tip'] ) ) {
					$value['desc_tip'] = false;
				}
				if ( ! isset( $value['placeholder'] ) ) {
					$value['placeholder'] = '';
				}
				if ( ! isset( $value['row_class'] ) ) {
					$value['row_class'] = '';
				}
				if ( ! empty( $value['row_class'] ) && substr( $value['row_class'], 0, 16 ) !== 'wc-settings-row-' ) {
					$value['row_class'] = 'wc-settings-row-' . $value['row_class'];
				}
				if ( ! isset( $value['suffix'] ) ) {
					$value['suffix'] = '';
				}
				if ( ! isset( $value['value'] ) ) {
					$value['value'] = self::get_option( $value['id'], $value['default'] );
				}

				if ( ! is_null( $value['fixed_value'] ?? null ) ) {
					$value['value'] = $value['fixed_value'];
				}

				// Custom attribute handling.
				$custom_attributes = array();

				if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
					foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
						$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
					}
				}

				// Description handling.
				$field_description = self::get_field_description( $value );
				$description       = $field_description['description'];
				$tooltip_html      = $field_description['tooltip_html'];

				// Switch based on type.
				switch ( $value['type'] ) {

					// Section Titles.
					case 'title':
						if ( ! empty( $value['title'] ) ) {
							echo '<h2>' . esc_html( $value['title'] ) . '</h2>';
						}
						if ( ! empty( $value['desc'] ) ) {
							echo '<div id="' . esc_attr( sanitize_title( $value['id'] ) ) . '-description">';
							echo wp_kses_post( wpautop( wptexturize( $value['desc'] ) ) );
							echo '</div>';
						}
						echo '<table class="form-table">' . "\n\n";
						if ( ! empty( $value['id'] ) ) {
							do_action( 'woocommerce_settings_' . sanitize_title( $value['id'] ) );
						}
						break;

					case 'info':
						?><tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc"><?php echo esc_html( $value['title'] ); ?></th>
							<td style="<?php echo esc_attr( $value['css'] ); ?>">
						<?php
						echo wp_kses_post( wpautop( wptexturize( $value['text'] ) ) );
						echo '</td></tr>';
						break;

					// Notice.
					case 'notice':
						$notice_type = $value['notice_type'] ?? 'info';
						$notice_text = $value['text'] ?? '';

						?>
						</table>
						<div class="notice notice-<?php echo esc_attr( $notice_type ); ?> inline">
							<p><?php echo wp_kses_post( $notice_text ); ?></p>
						</div>
						<table class="form-table" role="presentation">
						<?php
						break;

					// Section Ends.
					case 'sectionend':
						if ( ! empty( $value['id'] ) ) {
							do_action( 'woocommerce_settings_' . sanitize_title( $value['id'] ) . '_end' );
						}
						echo '</table>';
						if ( ! empty( $value['id'] ) ) {
							do_action( 'woocommerce_settings_' . sanitize_title( $value['id'] ) . '_after' );
						}
						break;

					// Standard text inputs and subtypes like 'number'.
					case 'text':
					case 'password':
					case 'datetime':
					case 'datetime-local':
					case 'date':
					case 'month':
					case 'time':
					case 'week':
					case 'number':
					case 'email':
					case 'url':
					case 'tel':
						$option_value = $value['value'];

						?>
						<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
								<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html; // WPCS: XSS ok. ?></label>
							</th>
							<td class="forminp forminp-<?php echo esc_attr( sanitize_title( $value['type'] ) ); ?>">
								<input
									name="<?php echo esc_attr( $value['field_name'] ); ?>"
									id="<?php echo esc_attr( $value['id'] ); ?>"
									type="<?php echo esc_attr( $value['type'] ); ?>"
									style="<?php echo esc_attr( $value['css'] ); ?>"
									value="<?php echo esc_attr( $option_value ); ?>"
									class="<?php echo esc_attr( $value['class'] ); ?>"
									placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
									<?php echo implode( ' ', $custom_attributes ); // WPCS: XSS ok. ?>
									/><?php echo esc_html( $value['suffix'] ); ?> <?php echo $description; // WPCS: XSS ok. ?>
							</td>
						</tr>
						<?php
						break;

					// Color picker.
					case 'color':
						$option_value = $value['value'];

						?>
						<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
								<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html; // WPCS: XSS ok. ?></label>
							</th>
							<td class="forminp forminp-<?php echo esc_attr( sanitize_title( $value['type'] ) ); ?>">&lrm;
								<span class="colorpickpreview" style="background: <?php echo esc_attr( $option_value ); ?>">&nbsp;</span>
								<input
									name="<?php echo esc_attr( $value['field_name'] ); ?>"
									id="<?php echo esc_attr( $value['id'] ); ?>"
									type="text"
									dir="ltr"
									style="<?php echo esc_attr( $value['css'] ); ?>"
									value="<?php echo esc_attr( $option_value ); ?>"
									class="<?php echo esc_attr( $value['class'] ); ?>colorpick"
									placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
									<?php echo implode( ' ', $custom_attributes ); // WPCS: XSS ok. ?>
									/>&lrm; <?php echo $description; // WPCS: XSS ok. ?>
									<div id="colorPickerDiv_<?php echo esc_attr( $value['id'] ); ?>" class="colorpickdiv" style="z-index: 100;background:#eee;border:1px solid #ccc;position:absolute;display:none;"></div>
							</td>
						</tr>
						<?php
						break;

					// Textarea.
					case 'textarea':
						$option_value     = $value['value'];
						$show_desc_at_end = $value['desc_at_end'] ?? false;

						?>
						<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
								<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html; // WPCS: XSS ok. ?></label>
							</th>
							<td class="forminp forminp-<?php echo esc_attr( sanitize_title( $value['type'] ) ); ?>">
								<?php
								if ( ! $show_desc_at_end ) {
									echo wp_kses_post( $description );
								}
								?>
								<textarea
									name="<?php echo esc_attr( $value['field_name'] ); ?>"
									id="<?php echo esc_attr( $value['id'] ); ?>"
									style="<?php echo esc_attr( $value['css'] ); ?>"
									class="<?php echo esc_attr( $value['class'] ); ?>"
									placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
									<?php echo implode( ' ', $custom_attributes ); // WPCS: XSS ok. ?>
									><?php echo esc_textarea( $option_value ); // WPCS: XSS ok. ?></textarea>
								<?php
								if ( $show_desc_at_end ) {
									echo wp_kses_post( $description );
								}
								?>
							</td>
						</tr>
						<?php
						break;

					// Select boxes.
					case 'select':
					case 'multiselect':
						$option_value = $value['value'];

						?>
						<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
								<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html; // WPCS: XSS ok. ?></label>
							</th>
							<td class="forminp forminp-<?php echo esc_attr( sanitize_title( $value['type'] ) ); ?>">
								<select
									name="<?php echo esc_attr( $value['field_name'] ); ?><?php echo ( 'multiselect' === $value['type'] ) ? '[]' : ''; ?>"
									id="<?php echo esc_attr( $value['id'] ); ?>"
									style="<?php echo esc_attr( $value['css'] ); ?>"
									class="<?php echo esc_attr( $value['class'] ); ?>"
									<?php echo implode( ' ', $custom_attributes ); // WPCS: XSS ok. ?>
									<?php echo 'multiselect' === $value['type'] ? 'multiple="multiple"' : ''; ?>
									>
									<?php
									foreach ( $value['options'] as $key => $val ) {
										?>
										<option value="<?php echo esc_attr( $key ); ?>"
											<?php

											if ( is_array( $option_value ) ) {
												selected( in_array( (string) $key, $option_value, true ), true );
											} else {
												selected( $option_value, (string) $key );
											}

											?>
										><?php echo esc_html( $val ); ?></option>
										<?php
									}
									?>
								</select> <?php echo $description; // WPCS: XSS ok. ?>
							</td>
						</tr>
						<?php
						break;

					// Radio inputs.
					case 'radio':
						$option_value     = $value['value'];
						$disabled_values  = $value['disabled'] ?? array();
						$show_desc_at_end = $value['desc_at_end'] ?? false;

						?>
						<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
								<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html; // WPCS: XSS ok. ?></label>
							</th>
							<td class="forminp forminp-<?php echo esc_attr( sanitize_title( $value['type'] ) ); ?>">
								<fieldset>
									<?php
									if ( ! $show_desc_at_end ) {
										echo wp_kses_post( $description );
									}
									?>
									<ul>
									<?php
									foreach ( $value['options'] as $key => $val ) {
										?>
										<li>
											<label><input
												name="<?php echo esc_attr( $value['field_name'] ); ?>"
												value="<?php echo esc_attr( $key ); ?>"
												type="radio"
												<?php
												if ( in_array( $key, $disabled_values, true ) ) {
													echo 'disabled'; }
												?>
												style="<?php echo esc_attr( $value['css'] ); ?>"
												class="<?php echo esc_attr( $value['class'] ); ?>"
												<?php echo implode( ' ', $custom_attributes ); // WPCS: XSS ok. ?>
												<?php checked( $key, $option_value ); ?>
												/> <?php echo esc_html( $val ); ?></label>
										</li>
										<?php
									}
									if ( $show_desc_at_end ) {
										echo wp_kses_post( "<p class='description description-thin'>{$description}</p>" );
									}
									?>
									</ul>
								</fieldset>
							</td>
						</tr>
						<?php
						break;

					// Checkbox input.
					case 'checkbox':
						$option_value     = $value['value'];
						$visibility_class = array();

						if ( ! isset( $value['hide_if_checked'] ) ) {
							$value['hide_if_checked'] = false;
						}
						if ( ! isset( $value['show_if_checked'] ) ) {
							$value['show_if_checked'] = false;
						}
						if ( 'yes' === $value['hide_if_checked'] || 'yes' === $value['show_if_checked'] ) {
							$visibility_class[] = 'hidden_option';
						}
						if ( 'option' === $value['hide_if_checked'] ) {
							$visibility_class[] = 'hide_options_if_checked';
						}
						if ( 'option' === $value['show_if_checked'] ) {
							$visibility_class[] = 'show_options_if_checked';
						}
						if ( $value['row_class'] ) {
							$visibility_class[] = $value['row_class'];
						}

						$must_disable = $value['disabled'] ?? false;

						if ( $must_disable ) {
							$visibility_class[] = 'disabled';
						}

						$container_class = implode( ' ', $visibility_class );
						$has_title       = isset( $value['title'] ) && '' !== $value['title'];
						$has_legend      = isset( $value['legend'] ) && '' !== $value['legend'];

						if ( ! isset( $value['checkboxgroup'] ) || 'start' === $value['checkboxgroup'] ) {
							$has_tooltip = isset( $value['tooltip'] ) && '' !== $value['tooltip'];

							$tooltip_container_class = $has_tooltip ? 'with-tooltip' : '';
							?>
								<tr class="<?php echo esc_attr( $container_class ); ?>">
									<th scope="row" class="titledesc"><?php echo esc_html( $value['title'] ); ?></th>
									<td class="forminp forminp-checkbox <?php echo esc_html( $tooltip_container_class ); ?>">
										<?php if ( $has_tooltip ) : ?>
											<span class="help-tooltip"><?php echo wc_help_tip( esc_html( $value['tooltip'] ) ); ?></span>
										<?php endif; ?>
										<fieldset>
							<?php
						} else {
							?>
								<fieldset class="<?php echo esc_attr( $container_class ); ?>">
							<?php
						}

						if ( $has_title || $has_legend ) {
							?>
								<legend class="<?php echo $has_legend ? '' : 'screen-reader-text'; ?>"><span><?php echo esc_html( $has_legend ? $value['legend'] : $value['title'] ); ?></span></legend>
							<?php
						}

						?>
							<label for="<?php echo esc_attr( $value['id'] ); ?>">
								<input
									<?php echo $must_disable ? 'disabled' : ''; ?>
									name="<?php echo esc_attr( $value['field_name'] ); ?>"
									id="<?php echo esc_attr( $value['id'] ); ?>"
									type="checkbox"
									class="<?php echo esc_attr( isset( $value['class'] ) ? $value['class'] : '' ); ?>"
									value="1"
									<?php checked( $option_value, 'yes' ); ?>
									<?php echo implode( ' ', $custom_attributes ); // WPCS: XSS ok. ?>
								/> <?php echo $description; // WPCS: XSS ok. ?>
							</label> <?php echo $tooltip_html; // WPCS: XSS ok. ?>
						<?php

						if ( ! isset( $value['checkboxgroup'] ) || 'end' === $value['checkboxgroup'] ) {
							?>
										</fieldset>
									</td>
								</tr>
							<?php
						} else {
							?>
								</fieldset>
							<?php
						}
						break;

					// Image width settings. @todo deprecate and remove in 4.0. No longer needed by core.
					case 'image_width':
						$image_size       = str_replace( '_image_size', '', $value['id'] );
						$size             = wc_get_image_size( $image_size );
						$width            = isset( $size['width'] ) ? $size['width'] : $value['default']['width'];
						$height           = isset( $size['height'] ) ? $size['height'] : $value['default']['height'];
						$crop             = isset( $size['crop'] ) ? $size['crop'] : $value['default']['crop'];
						$disabled_attr    = '';
						$disabled_message = '';

						if ( has_filter( 'woocommerce_get_image_size_' . $image_size ) ) {
							$disabled_attr    = 'disabled="disabled"';
							$disabled_message = '<p><small>' . esc_html__( 'The settings of this image size have been disabled because its values are being overwritten by a filter.', 'woocommerce' ) . '</small></p>';
						}

						?>
						<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
							<label><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html . $disabled_message; // WPCS: XSS ok. ?></label>
						</th>
							<td class="forminp image_width_settings">

								<input name="<?php echo esc_attr( $value['field_name'] ); ?>[width]" <?php echo $disabled_attr; // WPCS: XSS ok. ?> id="<?php echo esc_attr( $value['id'] ); ?>-width" type="text" size="3" value="<?php echo esc_attr( $width ); ?>" /> &times; <input name="<?php echo esc_attr( $value['id'] ); ?>[height]" <?php echo $disabled_attr; // WPCS: XSS ok. ?> id="<?php echo esc_attr( $value['id'] ); ?>-height" type="text" size="3" value="<?php echo esc_attr( $height ); ?>" />px

								<label><input name="<?php echo esc_attr( $value['field_name'] ); ?>[crop]" <?php echo $disabled_attr; // WPCS: XSS ok. ?> id="<?php echo esc_attr( $value['id'] ); ?>-crop" type="checkbox" value="1" <?php checked( 1, $crop ); ?> /> <?php esc_html_e( 'Hard crop?', 'woocommerce' ); ?></label>

								</td>
						</tr>
						<?php
						break;

					// Single page selects.
					case 'single_select_page':
						$args = array(
							'name'             => $value['field_name'],
							'id'               => $value['id'],
							'sort_column'      => 'menu_order',
							'sort_order'       => 'ASC',
							'show_option_none' => ' ',
							'class'            => $value['class'],
							'echo'             => false,
							'selected'         => absint( $value['value'] ),
							'post_status'      => 'publish,private,draft',
						);

						if ( isset( $value['args'] ) ) {
							$args = wp_parse_args( $value['args'], $args );
						}

						?>
						<tr class="single_select_page <?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
								<label><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html; // WPCS: XSS ok. ?></label>
							</th>
							<td class="forminp">
								<?php echo str_replace( ' id=', " data-placeholder='" . esc_attr__( 'Select a page&hellip;', 'woocommerce' ) . "' style='" . $value['css'] . "' class='" . $value['class'] . "' id=", wp_dropdown_pages( $args ) ); // WPCS: XSS ok. ?> <?php echo $description; // WPCS: XSS ok. ?>
							</td>
						</tr>
						<?php
						break;

					case 'single_select_page_with_search':
						$option_value = $value['value'];
						$page         = get_post( $option_value );

						if ( ! is_null( $page ) ) {
							$page                = get_post( $option_value );
							$option_display_name = sprintf(
								/* translators: 1: page name 2: page ID */
								__( '%1$s (ID: %2$s)', 'woocommerce' ),
								$page->post_title,
								$option_value
							);
						}
						?>
						<tr class="single_select_page <?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
								<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></label>
							</th>
							<td class="forminp forminp-<?php echo esc_attr( sanitize_title( $value['type'] ) ); ?>">
								<select
									name="<?php echo esc_attr( $value['field_name'] ); ?>"
									id="<?php echo esc_attr( $value['id'] ); ?>"
									style="<?php echo esc_attr( $value['css'] ); ?>"
									class="<?php echo esc_attr( $value['class'] ); ?>"
									<?php echo implode( ' ', $custom_attributes ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
									data-placeholder="<?php esc_attr_e( 'Search for a page&hellip;', 'woocommerce' ); ?>"
									data-allow_clear="true"
									data-exclude="<?php echo wc_esc_json( wp_json_encode( $value['args']['exclude'] ) ); ?>"
									>
									<option value=""></option>
									<?php if ( ! is_null( $page ) ) { ?>
										<option value="<?php echo esc_attr( $option_value ); ?>" selected="selected">
										<?php echo wp_strip_all_tags( $option_display_name ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
										</option>
									<?php } ?>
								</select> <?php echo $description; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
							</td>
						</tr>
						<?php
						break;

					// Single country selects.
					case 'single_select_country':
						$country_setting = (string) $value['value'];

						if ( strstr( $country_setting, ':' ) ) {
							$country_setting = explode( ':', $country_setting );
							$country         = current( $country_setting );
							$state           = end( $country_setting );
						} else {
							$country = $country_setting;
							$state   = '*';
						}
						?>
						<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
								<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html; // WPCS: XSS ok. ?></label>
							</th>
							<td class="forminp"><select name="<?php echo esc_attr( $value['field_name'] ); ?>" id="<?php echo esc_attr( $value['id'] ); ?>" style="<?php echo esc_attr( $value['css'] ); ?>" data-placeholder="<?php esc_attr_e( 'Choose a country / region&hellip;', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'Country / Region', 'woocommerce' ); ?>" class="wc-enhanced-select">
								<?php WC()->countries->country_dropdown_options( $country, $state ); ?>
							</select> <?php echo $description; // WPCS: XSS ok. ?>
							</td>
						</tr>
						<?php
						break;

					// Country multiselects.
					case 'multi_select_countries':
						$selections = (array) $value['value'];

						if ( ! empty( $value['options'] ) ) {
							$countries = $value['options'];
						} else {
							$countries = WC()->countries->countries;
						}

						asort( $countries );
						?>
						<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
								<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html; // WPCS: XSS ok. ?></label>
							</th>
							<td class="forminp">
								<select
									multiple="multiple"
									name="<?php echo esc_attr( $value['field_name'] ); ?>[]"
									id="<?php echo esc_attr( $value['id'] ); ?>"
									style="width:350px"
									data-placeholder="<?php esc_attr_e( 'Choose countries / regions&hellip;', 'woocommerce' ); ?>"
									aria-label="<?php esc_attr_e( 'Country / Region', 'woocommerce' ); ?>"
									class="wc-enhanced-select">
									<?php
									if ( ! empty( $countries ) ) {
										foreach ( $countries as $key => $val ) {
											echo '<option value="' . esc_attr( $key ) . '"' . wc_selected( $key, $selections ) . '>' . esc_html( $val ) . '</option>'; // WPCS: XSS ok.
										}
									}
									?>
								</select> <?php echo ( $description ) ? $description : ''; // WPCS: XSS ok. ?> <br /><a class="select_all button" href="#"><?php esc_html_e( 'Select all', 'woocommerce' ); ?></a> <a class="select_none button" href="#"><?php esc_html_e( 'Select none', 'woocommerce' ); ?></a>
							</td>
						</tr>
						<?php
						break;

					// Days/months/years selector.
					case 'relative_date_selector':
						$periods      = array(
							'days'   => __( 'Day(s)', 'woocommerce' ),
							'weeks'  => __( 'Week(s)', 'woocommerce' ),
							'months' => __( 'Month(s)', 'woocommerce' ),
							'years'  => __( 'Year(s)', 'woocommerce' ),
						);
						$option_value = wc_parse_relative_date_option( $value['value'] );
						?>
						<tr class="<?php echo esc_attr( $value['row_class'] ); ?>">
							<th scope="row" class="titledesc">
								<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?> <?php echo $tooltip_html; // WPCS: XSS ok. ?></label>
							</th>
							<td class="forminp">
							<input
									name="<?php echo esc_attr( $value['field_name'] ); ?>[number]"
									id="<?php echo esc_attr( $value['id'] ); ?>"
									type="number"
									style="width: 80px;"
									value="<?php echo esc_attr( $option_value['number'] ); ?>"
									class="<?php echo esc_attr( $value['class'] ); ?>"
									placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
									step="1"
									min="1"
									<?php echo implode( ' ', $custom_attributes ); // WPCS: XSS ok. ?>
								/>&nbsp;
								<select name="<?php echo esc_attr( $value['field_name'] ); ?>[unit]" style="width: auto;">
									<?php
									foreach ( $periods as $value => $label ) {
										echo '<option value="' . esc_attr( $value ) . '"' . selected( $option_value['unit'], $value, false ) . '>' . esc_html( $label ) . '</option>';
									}
									?>
								</select> <?php echo ( $description ) ? $description : ''; // WPCS: XSS ok. ?>
							</td>
						</tr>
						<?php
						break;

					case 'slotfill_placeholder':
						?>
						<div
							id="<?php echo esc_attr( $value['id'] ); ?>"
							class="<?php echo esc_attr( $value['class'] ); ?>"
						>
						</div>
						<?php
						break;
					// Default: run an action.
					default:
						do_action( 'woocommerce_admin_field_' . $value['type'], $value );
						break;
				}
			}
		}

		/**
		 * Helper function to get the formatted description and tip HTML for a
		 * given form field. Plugins can call this when implementing their own custom
		 * settings types.
		 *
		 * @param  array $value The form field value array.
		 * @return array The description and tip as a 2 element array.
		 */
		public static function get_field_description( $value ) {
			$description  = '';
			$tooltip_html = '';

			if ( true === $value['desc_tip'] ) {
				$tooltip_html = $value['desc'];
			} elseif ( ! empty( $value['desc_tip'] ) ) {
				$description  = $value['desc'];
				$tooltip_html = $value['desc_tip'];
			} elseif ( ! empty( $value['desc'] ) ) {
				$description = $value['desc'];
			}

			$desc_at_end = ( isset( $value['desc_at_end'] ) ? $value['desc_at_end'] : false );
			$error_class = ( ! empty( $value['description_is_error'] ) ) ? 'is-error' : '';

			if ( $description && in_array( $value['type'], array( 'textarea' ), true ) && true !== $desc_at_end ) {
				$description = '<p class="description ' . $error_class . '" style="margin-top:0;">' . wp_kses_post( $description ) . '</p>';
			} elseif ( $description && in_array( $value['type'], array( 'radio' ), true ) ) {
				$description = '<p style="margin-top:0">' . wp_kses_post( $description ) . '</p>';
			} elseif ( $description && in_array( $value['type'], array( 'checkbox' ), true ) ) {
				$description = wp_kses_post( $description );
			} elseif ( $description ) {
				$description = '<p class="description ' . $error_class . '">' . wp_kses_post( $description ) . '</p>';
			}

			if ( $tooltip_html && in_array( $value['type'], array( 'checkbox' ), true ) ) {
				$tooltip_html = '<p class="description ' . $error_class . '">' . $tooltip_html . '</p>';
			} elseif ( $tooltip_html ) {
				$tooltip_html = wc_help_tip( $tooltip_html );
			}

			return array(
				'description'  => $description,
				'tooltip_html' => $tooltip_html,
			);
		}

		/**
		 * Save admin fields.
		 *
		 * Loops through the woocommerce options array and outputs each field.
		 *
		 * @param array $options Options array to output.
		 * @param array $data    Optional. Data to use for saving. Defaults to $_POST.
		 * @return bool
		 */
		public static function save_fields( $options, $data = null ) {
			if ( is_null( $data ) ) {
				$data = $_POST; // WPCS: input var okay, CSRF ok.
			}
			if ( empty( $data ) ) {
				return false;
			}

			// Options to update will be stored here and saved later.
			$update_options   = array();
			$autoload_options = array();

			// Loop options and get values to save.
			foreach ( $options as $option ) {
				if ( ! isset( $option['id'] ) || ! isset( $option['type'] ) || ( isset( $option['is_option'] ) && false === $option['is_option'] ) ) {
					continue;
				}

				$option_name = $option['field_name'] ?? $option['id'];

				// Get posted value.
				if ( strstr( $option_name, '[' ) ) {
					parse_str( $option_name, $option_name_array );
					$option_name  = current( array_keys( $option_name_array ) );
					$setting_name = key( $option_name_array[ $option_name ] );
					$raw_value    = isset( $data[ $option_name ][ $setting_name ] ) ? wp_unslash( $data[ $option_name ][ $setting_name ] ) : null;
				} else {
					$setting_name = '';
					$raw_value    = isset( $data[ $option_name ] ) ? wp_unslash( $data[ $option_name ] ) : null;
				}

				// Format the value based on option type.
				switch ( $option['type'] ) {
					case 'checkbox':
						$value = '1' === $raw_value || 'yes' === $raw_value ? 'yes' : 'no';
						break;
					case 'textarea':
						$value = wp_kses_post( trim( $raw_value ) );
						break;
					case 'multiselect':
					case 'multi_select_countries':
						$value = array_filter( array_map( 'wc_clean', (array) $raw_value ) );
						break;
					case 'image_width':
						$value = array();
						if ( isset( $raw_value['width'] ) ) {
							$value['width']  = wc_clean( $raw_value['width'] );
							$value['height'] = wc_clean( $raw_value['height'] );
							$value['crop']   = isset( $raw_value['crop'] ) ? 1 : 0;
						} else {
							$value['width']  = $option['default']['width'];
							$value['height'] = $option['default']['height'];
							$value['crop']   = $option['default']['crop'];
						}
						break;
					case 'select':
						$allowed_values = empty( $option['options'] ) ? array() : array_map( 'strval', array_keys( $option['options'] ) );
						if ( empty( $option['default'] ) && empty( $allowed_values ) ) {
							$value = null;
							break;
						}
						$default = ( empty( $option['default'] ) ? $allowed_values[0] : $option['default'] );
						$value   = in_array( $raw_value, $allowed_values, true ) ? $raw_value : $default;
						break;
					case 'relative_date_selector':
						$value = wc_parse_relative_date_option( $raw_value );
						break;
					case 'password':
						// Non-string or absent → null so the option is skipped, not overwritten.
						// Only trim — no wp_strip_all_tags() or wc_clean() which would corrupt
						// passwords containing '<' or percent-like sequences.
						// $raw_value is already wp_unslash()ed upstream, so no stripslashes() needed.
						// Matches WC_Settings_API::validate_password_field() behavior.
						$value = is_string( $raw_value ) ? trim( $raw_value ) : null;
						break;
					default:
						$value = wc_clean( $raw_value );
						break;
				}

				/**
				 * Fire an action when a certain 'type' of field is being saved.
				 *
				 * @deprecated 2.4.0 - doesn't allow manipulation of values!
				 */
				if ( has_action( 'woocommerce_update_option_' . sanitize_title( $option['type'] ) ) ) {
					wc_deprecated_function( 'The woocommerce_update_option_X action', '2.4.0', 'woocommerce_admin_settings_sanitize_option filter' );
					do_action( 'woocommerce_update_option_' . sanitize_title( $option['type'] ), $option );
					continue;
				}

				/**
				 * Sanitize the value of an option.
				 *
				 * @since 2.4.0
				 */
				$value = apply_filters( 'woocommerce_admin_settings_sanitize_option', $value, $option, $raw_value );

				/**
				 * Sanitize the value of an option by option name.
				 *
				 * @since 2.4.0
				 */
				$value = apply_filters( "woocommerce_admin_settings_sanitize_option_$option_name", $value, $option, $raw_value );

				if ( is_null( $value ) ) {
					continue;
				}

				// Check if option is an array and handle that differently to single values.
				if ( $option_name && $setting_name ) {
					if ( ! isset( $update_options[ $option_name ] ) ) {
						$update_options[ $option_name ] = get_option( $option_name, array() );
					}
					if ( ! is_array( $update_options[ $option_name ] ) ) {
						$update_options[ $option_name ] = array();
					}
					$update_options[ $option_name ][ $setting_name ] = $value;
				} else {
					$update_options[ $option_name ] = $value;
				}

				$autoload_options[ $option_name ] = isset( $option['autoload'] ) ? (bool) $option['autoload'] : true;

				/**
				 * Fire an action before saved.
				 *
				 * @deprecated 2.4.0 - doesn't allow manipulation of values!
				 */
				do_action( 'woocommerce_update_option', $option );
			}

			// Save all options in our array.
			foreach ( $update_options as $name => $value ) {
				update_option( $name, $value, $autoload_options[ $name ] ? 'yes' : 'no' );
			}

			return true;
		}

		/**
		 * Checks which method we're using to serve downloads.
		 *
		 * If using force or x-sendfile, this ensures the .htaccess is in place.
		 */
		public static function check_download_folder_protection() {
			$upload_dir      = wp_get_upload_dir();
			$downloads_path  = $upload_dir['basedir'] . '/woocommerce_uploads';
			$download_method = get_option( 'woocommerce_file_download_method' );
			$file_path       = $downloads_path . '/.htaccess';
			$file_content    = 'redirect' === $download_method ? 'Options -Indexes' : 'deny from all';
			$create          = false;

			if ( wp_mkdir_p( $downloads_path ) && ! file_exists( $file_path ) ) {
				$create = true;
			} else {
				$current_content = @file_get_contents( $file_path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents

				if ( $current_content !== $file_content ) {
					unlink( $file_path );
					$create = true;
				}
			}

			if ( $create ) {
				$file_handle = @fopen( $file_path, 'wb' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen
				if ( $file_handle ) {
					fwrite( $file_handle, $file_content ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fwrite
					fclose( $file_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose
				}
			}
		}
	}

endif;
PK     tS\dd  dd    class-wc-admin-notices.phpnu [        <?php
/**
 * Display notices in admin
 *
 * @package WooCommerce\Admin
 * @version 3.4.0
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Internal\Utilities\Users;
use Automattic\WooCommerce\Internal\Utilities\WebhookUtil;

defined( 'ABSPATH' ) || exit;

/**
 * WC_Admin_Notices Class.
 */
class WC_Admin_Notices {

	/**
	 * Local notices cache.
	 *
	 * DON'T manipulate this field directly!
	 * Always use get_notices and set_notices instead.
	 *
	 * @var array
	 */
	private static $notices = array();

	/**
	 * Array of notices - name => callback.
	 *
	 * @var array
	 */
	private static $core_notices = array(
		'update'                             => 'update_notice',
		'template_files'                     => 'template_file_check_notice',
		'legacy_shipping'                    => 'legacy_shipping_notice',
		'no_shipping_methods'                => 'no_shipping_methods_notice',
		'regenerating_thumbnails'            => 'regenerating_thumbnails_notice',
		'regenerating_lookup_table'          => 'regenerating_lookup_table_notice',
		'no_secure_connection'               => 'secure_connection_notice',
		'maxmind_license_key'                => 'maxmind_missing_license_key_notice',
		'redirect_download_method'           => 'redirect_download_method_notice',
		'uploads_directory_is_unprotected'   => 'uploads_directory_is_unprotected_notice',
		'base_tables_missing'                => 'base_tables_missing_notice',
		'download_directories_sync_complete' => 'download_directories_sync_complete',
		'hpos_sync_on_read_disabled'         => 'sync_on_read_disabled_notice',
	);

	/**
	 * Stores a flag indicating if the code is running in a multisite setup.
	 *
	 * @var bool
	 */
	private static bool $is_multisite;

	/**
	 * Initializes the class.
	 *
	 * @return void
	 */
	public static function init() {
		self::$is_multisite = is_multisite();
		self::set_notices( get_option( 'woocommerce_admin_notices', array() ) );

		add_action( 'switch_theme', array( __CLASS__, 'reset_admin_notices' ) );
		add_action( 'woocommerce_installed', array( __CLASS__, 'reset_admin_notices' ) );
		add_action( 'update_option_woocommerce_file_download_method', array( __CLASS__, 'add_redirect_download_method_notice' ) );
		add_action( 'admin_init', array( __CLASS__, 'hide_notices' ), 20 );
		add_action( 'admin_init', array( __CLASS__, 'maybe_remove_legacy_api_removal_notice' ), 20 );

		// @TODO: This prevents Action Scheduler async jobs from storing empty list of notices during WC installation.
		// That could lead to OBW not starting and 'Run setup wizard' notice not appearing in WP admin, which we want
		// to avoid.
		if ( ! WC_Install::is_new_install() || ! wc_is_running_from_async_action_scheduler() ) {
			add_action( 'shutdown', array( __CLASS__, 'store_notices' ) );
		}

		if ( current_user_can( 'manage_woocommerce' ) ) {
			add_action( 'admin_print_styles', array( __CLASS__, 'add_notices' ) );
		}
	}

	/**
	 * Parses query to create nonces when available.
	 *
	 * @deprecated 5.4.0
	 * @param object $response The WP_REST_Response we're working with.
	 * @return object $response The prepared WP_REST_Response object.
	 */
	public static function prepare_note_with_nonce( $response ) {
		wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '5.4.0' );

		return $response;
	}

	/**
	 * Store the locally cached notices to DB.
	 *
	 * @return void
	 */
	public static function store_notices() {
		$current_notices = self::get_notices();
		$prev_notices    = get_option( 'woocommerce_admin_notices', array() );

		// Store notices.
		update_option( 'woocommerce_admin_notices', $current_notices );

		// Clean up removed notices.
		foreach ( array_diff( $prev_notices, $current_notices ) as $notice ) {
			if ( isset( self::$core_notices[ $notice ] ) ) {
				continue;
			}

			delete_option( 'woocommerce_admin_notice_' . $notice );
		}
	}

	/**
	 * Get the value of the locally cached notices array for the current site.
	 *
	 * @return array
	 */
	public static function get_notices() {
		if ( ! self::$is_multisite ) {
			return self::$notices;
		}

		$blog_id = get_current_blog_id();
		$notices = self::$notices[ $blog_id ] ?? null;
		if ( ! is_null( $notices ) ) {
			return $notices;
		}

		self::$notices[ $blog_id ] = get_option( 'woocommerce_admin_notices', array() );
		return self::$notices[ $blog_id ];
	}

	/**
	 * Set the locally cached notices array for the current site.
	 *
	 * @param array $notices New value for the locally cached notices array.
	 * @return void
	 */
	private static function set_notices( array $notices ) {
		if ( self::$is_multisite ) {
			self::$notices[ get_current_blog_id() ] = $notices;
		} else {
			self::$notices = $notices;
		}
	}

	/**
	 * Remove all notices from the locally cached notices array.
	 *
	 * @return void
	 */
	public static function remove_all_notices() {
		self::set_notices( array() );
	}

	/**
	 * Reset notices for themes when switched or a new version of WC is installed.
	 *
	 * @return void
	 */
	public static function reset_admin_notices() {
		if ( ! self::is_ssl() ) {
			self::add_notice( 'no_secure_connection' );
		}
		if ( ! self::is_uploads_directory_protected() ) {
			self::add_notice( 'uploads_directory_is_unprotected' );
		}
		self::add_notice( 'template_files' );
		self::add_min_version_notice();
		self::add_maxmind_missing_license_key_notice();
		self::maybe_add_legacy_api_removal_notice();
	}

	/**
	 * Add an admin notice about unsupported webhooks with Legacy API payload if at least one of these exist
	 * and the Legacy REST API plugin is not installed.
	 *
	 * @return void
	 */
	private static function maybe_add_legacy_api_removal_notice() {
		if ( wc_get_container()->get( WebhookUtil::class )->get_legacy_webhooks_count() > 0 && ! WC()->legacy_rest_api_is_available() ) {
			self::add_custom_notice(
				'legacy_webhooks_unsupported_in_woo_90',
				sprintf(
					'%s%s',
					sprintf(
						'<h4>%s</h4>',
						esc_html__( 'WooCommerce webhooks that use the Legacy REST API are unsupported', 'woocommerce' )
					),
					sprintf(
					// translators: Placeholders are URLs.
						wpautop( __( '⚠️ The WooCommerce Legacy REST API has been removed from WooCommerce, this will cause <a href="%1$s">webhooks on this site that are configured to use the Legacy REST API</a> to stop working. <a target="_blank" href="%2$s">A separate WooCommerce extension is available</a> to allow these webhooks to keep using the Legacy REST API without interruption. You can also edit these webhooks to use the current REST API version to generate the payload instead. <b><a target="_blank" href="%3$s">Learn more about this change.</a></b>', 'woocommerce' ) ),
						admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&legacy=true' ),
						'https://wordpress.org/plugins/woocommerce-legacy-rest-api/',
						'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
					)
				)
			);
		}
	}

	/**
	 * Remove the admin notice about the unsupported webhooks if the Legacy REST API plugin is installed.
	 *
	 * @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
	 * @return void
	 */
	public static function maybe_remove_legacy_api_removal_notice() {
		if ( self::has_notice( 'legacy_webhooks_unsupported_in_woo_90' ) && ( WC()->legacy_rest_api_is_available() || 0 === wc_get_container()->get( WebhookUtil::class )->get_legacy_webhooks_count() ) ) {
			self::remove_notice( 'legacy_webhooks_unsupported_in_woo_90' );
		}
	}

	/**
	 * Show a notice.
	 *
	 * @param string $name Notice name.
	 * @param bool   $force_save Force saving inside this method instead of at the 'shutdown'.
	 * @return void
	 */
	public static function add_notice( $name, $force_save = false ) {
		self::set_notices( array_unique( array_merge( self::get_notices(), array( $name ) ) ) );

		if ( $force_save ) {
			// Adding early save to prevent more race conditions with notices.
			self::store_notices();
		}
	}

	/**
	 * Remove a notice from being displayed.
	 *
	 * @param string $name Notice name.
	 * @param bool   $force_save Force saving inside this method instead of at the 'shutdown'.
	 * @return void
	 */
	public static function remove_notice( $name, $force_save = false ) {
		if ( self::has_notice( $name ) ) {
			self::set_notices( array_diff( self::get_notices(), array( $name ) ) );
		}

		if ( $force_save ) {
			// Adding early save to prevent more race conditions with notices.
			self::store_notices();
		}
	}

	/**
	 * Remove a given set of notices.
	 *
	 * An array of notice names or a regular expression string can be passed, in the later case
	 * all the notices whose name matches the regular expression will be removed.
	 *
	 * @param array|string $names_array_or_regex An array of notice names, or a string representing a regular expression.
	 * @param bool         $force_save Force saving inside this method instead of at the 'shutdown'.
	 * @return void
	 */
	public static function remove_notices( $names_array_or_regex, $force_save = false ) {
		if ( ! is_array( $names_array_or_regex ) ) {
			$names_array_or_regex = array_filter( self::get_notices(), fn( $notice_name ) => 1 === preg_match( $names_array_or_regex, $notice_name ) );
		}
		self::set_notices( array_diff( self::get_notices(), $names_array_or_regex ) );

		if ( $force_save ) {
			// Adding early save to prevent more race conditions with notices.
			self::store_notices();
		}
	}

	/**
	 * See if a notice is being shown.
	 *
	 * @param string $name Notice name.
	 *
	 * @return boolean
	 */
	public static function has_notice( $name ) {
		return in_array( $name, self::get_notices(), true );
	}

	/**
	 * Hide a notice if the GET variable is set.
	 *
	 * @return void
	 */
	public static function hide_notices() {
		if ( isset( $_GET['wc-hide-notice'] ) && isset( $_GET['_wc_notice_nonce'] ) ) {
			if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_GET['_wc_notice_nonce'] ) ), 'woocommerce_hide_notices_nonce' ) ) {
				wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
			}

			$notice_name = sanitize_text_field( wp_unslash( $_GET['wc-hide-notice'] ) );

			/**
			 * Filter the capability required to dismiss a given notice.
			 *
			 * @since 6.7.0
			 *
			 * @param string $default_capability The default required capability.
			 * @param string $notice_name The notice name.
			 */
			$required_capability = apply_filters( 'woocommerce_dismiss_admin_notice_capability', 'manage_woocommerce', $notice_name );

			if ( ! current_user_can( $required_capability ) ) {
				wp_die( esc_html__( 'You don&#8217;t have permission to do this.', 'woocommerce' ) );
			}

			self::hide_notice( $notice_name );
		}
	}

	/**
	 * Hide a single notice.
	 *
	 * @param string $name Notice name.
	 * @return void
	 */
	private static function hide_notice( $name ) {
		self::remove_notice( $name );

		update_user_meta( get_current_user_id(), 'dismissed_' . $name . '_notice', true );

		do_action( 'woocommerce_hide_' . $name . '_notice' );
	}

	/**
	 * Check if a given user has dismissed a given admin notice.
	 *
	 * @since 8.5.0
	 *
	 * @param string   $name The name of the admin notice to check.
	 * @param int|null $user_id User id, or null for the current user.
	 * @return bool True if the user has dismissed the notice.
	 */
	public static function user_has_dismissed_notice( string $name, ?int $user_id = null ): bool {
		return (bool) get_user_meta( $user_id ?? get_current_user_id(), "dismissed_{$name}_notice", true );
	}

	/**
	 * Add notices + styles if needed.
	 *
	 * @return void
	 */
	public static function add_notices() {
		$notices = self::get_notices();

		if ( empty( $notices ) ) {
			return;
		}

		require_once WC_ABSPATH . 'includes/admin/wc-admin-functions.php';

		$screen          = get_current_screen();
		$screen_id       = $screen ? $screen->id : '';
		$show_on_screens = array(
			'dashboard',
			'plugins',
		);

		// Notices should only show on WooCommerce screens, the main dashboard, and on the plugins screen.
		if ( ! in_array( $screen_id, wc_get_screen_ids(), true ) && ! in_array( $screen_id, $show_on_screens, true ) ) {
			return;
		}

		wp_enqueue_style( 'woocommerce-activation', plugins_url( '/assets/css/activation.css', WC_PLUGIN_FILE ), array(), Constants::get_constant( 'WC_VERSION' ) );

		// Add RTL support.
		wp_style_add_data( 'woocommerce-activation', 'rtl', 'replace' );

		foreach ( $notices as $notice ) {
			if ( ! empty( self::$core_notices[ $notice ] ) && apply_filters( 'woocommerce_show_admin_notice', true, $notice ) ) {
				add_action( 'admin_notices', array( __CLASS__, self::$core_notices[ $notice ] ) );
			} else {
				add_action( 'admin_notices', array( __CLASS__, 'output_custom_notices' ) );
			}
		}
	}

	/**
	 * Add a custom notice.
	 *
	 * @param string $name        Notice name.
	 * @param string $notice_html Notice HTML.
	 * @return void
	 */
	public static function add_custom_notice( $name, $notice_html ) {
		self::add_notice( $name );
		update_option( 'woocommerce_admin_notice_' . $name, wp_kses_post( $notice_html ) );
	}

	/**
	 * Output any stored custom notices.
	 *
	 * @return void
	 */
	public static function output_custom_notices() {
		$notices = self::get_notices();

		if ( ! empty( $notices ) ) {
			foreach ( $notices as $notice ) {
				if ( empty( self::$core_notices[ $notice ] ) ) {
					$notice_html = get_option( 'woocommerce_admin_notice_' . $notice );

					if ( $notice_html ) {
						include __DIR__ . '/views/html-notice-custom.php';
					}
				}
			}
		}
	}

	/**
	 * If we need to update the database, include a message with the DB update button.
	 *
	 * @return void
	 */
	public static function update_notice() {
		$screen    = get_current_screen();
		$screen_id = $screen ? $screen->id : '';
		if ( WC()->is_wc_admin_active() && in_array( $screen_id, wc_get_screen_ids(), true ) ) {
			return;
		}

		if ( WC_Install::needs_db_update() ) {
			$next_scheduled_date = WC()->queue()->get_next( 'woocommerce_run_update_callback', null, 'woocommerce-db-updates' );

            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			if ( $next_scheduled_date || ! empty( $_GET['do_update_woocommerce'] ) ) {
				include __DIR__ . '/views/html-notice-updating.php';
			} else {
				include __DIR__ . '/views/html-notice-update.php';
			}
		} else {
			include __DIR__ . '/views/html-notice-updated.php';
		}
	}

	/**
	 * If we have just installed, show a message with the install pages button.
	 *
	 * @deprecated 4.6.0
	 * @return void
	 */
	public static function install_notice() {
		_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', esc_html__( 'Onboarding is maintained in WooCommerce Admin.', 'woocommerce' ) );
	}

	/**
	 * Show a notice highlighting bad template files.
	 *
	 * @return void
	 */
	public static function template_file_check_notice() {
		$core_templates = WC_Admin_Status::scan_template_files( WC()->plugin_path() . '/templates' );
		$outdated       = false;

		foreach ( $core_templates as $file ) {

			$theme_file = false;
			if ( file_exists( get_stylesheet_directory() . '/' . $file ) ) {
				$theme_file = get_stylesheet_directory() . '/' . $file;
			} elseif ( file_exists( get_stylesheet_directory() . '/' . WC()->template_path() . $file ) ) {
				$theme_file = get_stylesheet_directory() . '/' . WC()->template_path() . $file;
			} elseif ( file_exists( get_template_directory() . '/' . $file ) ) {
				$theme_file = get_template_directory() . '/' . $file;
			} elseif ( file_exists( get_template_directory() . '/' . WC()->template_path() . $file ) ) {
				$theme_file = get_template_directory() . '/' . WC()->template_path() . $file;
			}

			if ( false !== $theme_file ) {
				$core_version  = WC_Admin_Status::get_file_version( WC()->plugin_path() . '/templates/' . $file );
				$theme_version = WC_Admin_Status::get_file_version( $theme_file );

				if ( $core_version && $theme_version && version_compare( $theme_version, $core_version, '<' ) ) {
					$outdated = true;
					break;
				}
			}
		}

		if ( $outdated ) {
			include __DIR__ . '/views/html-notice-template-check.php';
		} else {
			self::remove_notice( 'template_files' );
		}
	}

	/**
	 * Show a notice asking users to convert to shipping zones.
	 *
	 * @todo remove in 4.0.0
	 * @return void
	 */
	public static function legacy_shipping_notice() {
		$maybe_load_legacy_methods = array( 'flat_rate', 'free_shipping', 'international_delivery', 'local_delivery', 'local_pickup' );
		$enabled                   = false;

		foreach ( $maybe_load_legacy_methods as $method ) {
			$options = get_option( 'woocommerce_' . $method . '_settings' );
			if ( $options && isset( $options['enabled'] ) && 'yes' === $options['enabled'] ) {
				$enabled = true;
			}
		}

		if ( $enabled ) {
			include __DIR__ . '/views/html-notice-legacy-shipping.php';
		} else {
			self::remove_notice( 'legacy_shipping' );
		}
	}

	/**
	 * No shipping methods.
	 *
	 * @return void
	 */
	public static function no_shipping_methods_notice() {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( wc_shipping_enabled() && ( ! is_wc_admin_settings_page() || empty( $_GET['tab'] ) || 'shipping' !== $_GET['tab'] ) ) {
			$product_count = wp_count_posts( 'product' );
			$method_count  = wc_get_shipping_method_count();

			if ( $product_count->publish > 0 && 0 === $method_count ) {
				include __DIR__ . '/views/html-notice-no-shipping-methods.php';
			}

			if ( $method_count > 0 ) {
				self::remove_notice( 'no_shipping_methods' );
			}
		}
	}

	/**
	 * Notice shown when regenerating thumbnails background process is running.
	 *
	 * @return void
	 */
	public static function regenerating_thumbnails_notice() {
		include __DIR__ . '/views/html-notice-regenerating-thumbnails.php';
	}

	/**
	 * Notice about secure connection.
	 *
	 * @return void
	 */
	public static function secure_connection_notice() {
		if ( self::is_ssl() || get_user_meta( get_current_user_id(), 'dismissed_no_secure_connection_notice', true ) ) {
			return;
		}

		include __DIR__ . '/views/html-notice-secure-connection.php';
	}

	/**
	 * Notice shown when regenerating thumbnails background process is running.
	 *
	 * @since 3.6.0
	 * @return void
	 */
	public static function regenerating_lookup_table_notice() {
		// See if this is still relevant.
		if ( ! wc_update_product_lookup_tables_is_running() ) {
			self::remove_notice( 'regenerating_lookup_table' );
			return;
		}

		include __DIR__ . '/views/html-notice-regenerating-lookup-table.php';
	}

	/**
	 * Add notice about minimum PHP and WordPress requirement.
	 *
	 * @since 3.6.5
	 * @return void
	 */
	public static function add_min_version_notice() {
		if ( version_compare( phpversion(), WC_NOTICE_MIN_PHP_VERSION, '<' ) || version_compare( get_bloginfo( 'version' ), WC_NOTICE_MIN_WP_VERSION, '<' ) ) {
			self::add_notice( WC_PHP_MIN_REQUIREMENTS_NOTICE );
		}
	}

	/**
	 * Notice about WordPress and PHP minimum requirements.
	 *
	 * @deprecated 8.2.0 WordPress and PHP minimum requirements notices are no longer shown.
	 *
	 * @since 3.6.5
	 * @return void
	 */
	public static function wp_php_min_requirements_notice() {
	}

	/**
	 * Add MaxMind missing license key notice.
	 *
	 * @since 3.9.0
	 * @return void
	 */
	public static function add_maxmind_missing_license_key_notice() {
		$default_address = get_option( 'woocommerce_default_customer_address' );

		if ( ! in_array( $default_address, array( 'geolocation', 'geolocation_ajax' ), true ) ) {
			return;
		}

		$integration_options = get_option( 'woocommerce_maxmind_geolocation_settings' );
		if ( empty( $integration_options['license_key'] ) ) {
			self::add_notice( 'maxmind_license_key' );

		}
	}

	/**
	 *  Add notice about Redirect-only download method, nudging user to switch to a different method instead.
	 *
	 * @return void
	 */
	public static function add_redirect_download_method_notice() {
		if ( 'redirect' === get_option( 'woocommerce_file_download_method' ) ) {
			self::add_notice( 'redirect_download_method' );
		} else {
			self::remove_notice( 'redirect_download_method' );
		}
	}

	/**
	 * Notice about the completion of the product downloads sync, with further advice for the site operator.
	 *
	 * @return void
	 */
	public static function download_directories_sync_complete() {
		$notice_dismissed = apply_filters(
			'woocommerce_hide_download_directories_sync_complete',
			get_user_meta( get_current_user_id(), 'download_directories_sync_complete', true )
		);

		if ( $notice_dismissed ) {
			self::remove_notice( 'download_directories_sync_complete' );
		}

		if ( Users::is_site_administrator() ) {
			include __DIR__ . '/views/html-notice-download-dir-sync-complete.php';
		}
	}

	/**
	 * Display MaxMind missing license key notice.
	 *
	 * @since 3.9.0
	 * @return void
	 */
	public static function maxmind_missing_license_key_notice() {
		$user_dismissed_notice   = get_user_meta( get_current_user_id(), 'dismissed_maxmind_license_key_notice', true );
		$filter_dismissed_notice = ! apply_filters( 'woocommerce_maxmind_geolocation_display_notices', true );

		if ( $user_dismissed_notice || $filter_dismissed_notice ) {
			self::remove_notice( 'maxmind_license_key' );
			return;
		}

		include __DIR__ . '/views/html-notice-maxmind-license-key.php';
	}

	/**
	 * Notice about Redirect-Only download method.
	 *
	 * @since 4.0
	 * @return void
	 */
	public static function redirect_download_method_notice() {
		if ( apply_filters( 'woocommerce_hide_redirect_method_nag', get_user_meta( get_current_user_id(), 'dismissed_redirect_download_method_notice', true ) ) ) {
			self::remove_notice( 'redirect_download_method' );
			return;
		}

		include __DIR__ . '/views/html-notice-redirect-only-download.php';
	}

	/**
	 * Notice about uploads directory begin unprotected.
	 *
	 * @since 4.2.0
	 * @return void
	 */
	public static function uploads_directory_is_unprotected_notice() {
		if ( get_user_meta( get_current_user_id(), 'dismissed_uploads_directory_is_unprotected_notice', true ) || self::is_uploads_directory_protected() ) {
			self::remove_notice( 'uploads_directory_is_unprotected' );
			return;
		}

		include __DIR__ . '/views/html-notice-uploads-directory-is-unprotected.php';
	}

	/**
	 * Notice about base tables missing.
	 *
	 * @return void
	 */
	public static function base_tables_missing_notice() {
		$notice_dismissed = apply_filters(
			'woocommerce_hide_base_tables_missing_nag',
			get_user_meta( get_current_user_id(), 'dismissed_base_tables_missing_notice', true )
		);
		if ( $notice_dismissed ) {
			self::remove_notice( 'base_tables_missing' );
		}

		include __DIR__ . '/views/html-notice-base-table-missing.php';
	}

	/**
	 * Notice about HPOS sync-on-read being disabled by default.
	 *
	 * @since 10.7.0
	 * @return void
	 */
	public static function sync_on_read_disabled_notice() {
		$dismiss =
			! \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled()
			|| ! wc_get_container()->get( \Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::class )->data_sync_is_enabled()
			|| get_user_meta( get_current_user_id(), 'dismissed_hpos_sync_on_read_disabled_notice', true );

		if ( $dismiss ) {
			self::remove_notice( 'hpos_sync_on_read_disabled' );
			return;
		}

		include __DIR__ . '/views/html-notice-sync-on-read-disabled.php';
	}

	/**
	 * Determine if the store is running SSL.
	 *
	 * @return bool Flag SSL enabled.
	 * @since  3.5.1
	 */
	protected static function is_ssl() {
		$shop_page = wc_get_page_permalink( 'shop' );

		return ( is_ssl() && 'https' === substr( $shop_page, 0, 5 ) );
	}

	/**
	 * Wrapper for is_plugin_active.
	 *
	 * @param string $plugin Plugin to check.
	 * @return boolean
	 */
	protected static function is_plugin_active( $plugin ) {
		if ( ! function_exists( 'is_plugin_active' ) ) {
			include_once ABSPATH . 'wp-admin/includes/plugin.php';
		}
		return is_plugin_active( $plugin );
	}

	/**
	 * Simplify Commerce is no longer in core.
	 *
	 * @deprecated 3.6.0 No longer shown.
	 * @return void
	 */
	public static function simplify_commerce_notice() {
		wc_deprecated_function( 'WC_Admin_Notices::simplify_commerce_notice', '3.6.0' );
	}

	/**
	 * Show the Theme Check notice.
	 *
	 * @deprecated 3.3.0 No longer shown.
	 * @return void
	 */
	public static function theme_check_notice() {
		wc_deprecated_function( 'WC_Admin_Notices::theme_check_notice', '3.3.0' );
	}

	/**
	 * Check if uploads directory is protected.
	 *
	 * @since 4.2.0
	 * @return bool
	 */
	protected static function is_uploads_directory_protected() {
		$cache_key = '_woocommerce_upload_directory_status';
		$status    = get_transient( $cache_key );

		// Check for cache.
		if ( false !== $status ) {
			return 'protected' === $status;
		}

		// Get only data from the uploads directory.
		$uploads = wp_get_upload_dir();

		// Check for the "uploads/woocommerce_uploads" directory.
		$response         = wp_safe_remote_get(
			esc_url_raw( $uploads['baseurl'] . '/woocommerce_uploads/' ),
			array(
				'redirection' => 0,
			)
		);
		$response_code    = intval( wp_remote_retrieve_response_code( $response ) );
		$response_content = wp_remote_retrieve_body( $response );

		// Check if returns 200 with empty content in case can open an index.html file,
		// and check for non-200 codes in case the directory is protected.
		$is_protected = ( 200 === $response_code && empty( $response_content ) ) || ( 200 !== $response_code );
		set_transient( $cache_key, $is_protected ? 'protected' : 'unprotected', 1 * DAY_IN_SECONDS );

		return $is_protected;
	}
}

WC_Admin_Notices::init();
PK     tS\1  1    importers/mappings/generic.phpnu [        <?php
/**
 * Generic mappings
 *
 * @package WooCommerce\Admin\Importers
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Add generic mappings.
 *
 * @since 3.1.0
 * @param array $mappings Importer columns mappings.
 * @return array
 */
function wc_importer_generic_mappings( $mappings ) {
	$generic_mappings = array(
		__( 'Title', 'woocommerce' )         => 'name',
		__( 'Product Title', 'woocommerce' ) => 'name',
		__( 'Price', 'woocommerce' )         => 'regular_price',
		__( 'Parent SKU', 'woocommerce' )    => 'parent_id',
		__( 'Quantity', 'woocommerce' )      => 'stock_quantity',
		__( 'Menu order', 'woocommerce' )    => 'menu_order',
	);

	return array_merge( $mappings, $generic_mappings );
}
add_filter( 'woocommerce_csv_product_import_mapping_default_columns', 'wc_importer_generic_mappings' );
PK     tS\:MMW  W    importers/mappings/default.phpnu [        <?php
/**
 * Default mappings
 *
 * @package WooCommerce\Admin\Importers
 */

use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Importer current locale.
 *
 * @since 3.1.0
 * @return string
 */
function wc_importer_current_locale() {
	$locale = get_locale();
	if ( function_exists( 'get_user_locale' ) ) {
		$locale = get_user_locale();
	}

	return $locale;
}

/**
 * Add English mapping placeholders when not using English as current language.
 *
 * @since 3.1.0
 * @param array $mappings Importer columns mappings.
 * @return array
 */
function wc_importer_default_english_mappings( $mappings ) {
	if ( 'en_US' === wc_importer_current_locale() && is_array( $mappings ) && count( $mappings ) > 0 ) {
		return $mappings;
	}

	$weight_unit    = get_option( 'woocommerce_weight_unit' );
	$dimension_unit = get_option( 'woocommerce_dimension_unit' );
	$new_mappings   = array(
		'ID'                                      => 'id',
		'Type'                                    => 'type',
		'SKU'                                     => 'sku',
		'Name'                                    => 'name',
		'Published'                               => 'published',
		'Is featured?'                            => 'featured',
		'Visibility in catalog'                   => 'catalog_visibility',
		'Short description'                       => 'short_description',
		'Description'                             => 'description',
		'Date sale price starts'                  => 'date_on_sale_from',
		'Date sale price ends'                    => 'date_on_sale_to',
		'Tax status'                              => 'tax_status',
		'Tax class'                               => 'tax_class',
		'In stock?'                               => 'stock_status',
		'Stock'                                   => 'stock_quantity',
		'Backorders allowed?'                     => 'backorders',
		'Low stock amount'                        => 'low_stock_amount',
		'Sold individually?'                      => 'sold_individually',
		sprintf( 'Weight (%s)', $weight_unit )    => 'weight',
		sprintf( 'Length (%s)', $dimension_unit ) => 'length',
		sprintf( 'Width (%s)', $dimension_unit )  => 'width',
		sprintf( 'Height (%s)', $dimension_unit ) => 'height',
		'Allow customer reviews?'                 => 'reviews_allowed',
		'Purchase note'                           => 'purchase_note',
		'Sale price'                              => 'sale_price',
		'Regular price'                           => 'regular_price',
		'Categories'                              => 'category_ids',
		'Tags'                                    => 'tag_ids',
		'Shipping class'                          => 'shipping_class_id',
		'Images'                                  => 'images',
		'Download limit'                          => 'download_limit',
		'Download expiry days'                    => 'download_expiry',
		'Parent'                                  => 'parent_id',
		'Upsells'                                 => 'upsell_ids',
		'Cross-sells'                             => 'cross_sell_ids',
		'Grouped products'                        => 'grouped_products',
		'External URL'                            => 'product_url',
		'Button text'                             => 'button_text',
		'Position'                                => 'menu_order',
	);

	if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() ) {
		$new_mappings['Cost of goods'] = 'cogs_value';
	}

	return array_merge( $mappings, $new_mappings );
}
add_filter( 'woocommerce_csv_product_import_mapping_default_columns', 'wc_importer_default_english_mappings', 100 );

/**
 * Add English special mapping placeholders when not using English as current language.
 *
 * @since 3.1.0
 * @param array $mappings Importer columns mappings.
 * @return array
 */
function wc_importer_default_special_english_mappings( $mappings ) {
	if ( 'en_US' === wc_importer_current_locale() && is_array( $mappings ) && count( $mappings ) > 0 ) {
		return $mappings;
	}

	$new_mappings = array(
		'Attribute %d name'     => 'attributes:name',
		'Attribute %d value(s)' => 'attributes:value',
		'Attribute %d visible'  => 'attributes:visible',
		'Attribute %d global'   => 'attributes:taxonomy',
		'Attribute %d default'  => 'attributes:default',
		'Download %d ID'        => 'downloads:id',
		'Download %d name'      => 'downloads:name',
		'Download %d URL'       => 'downloads:url',
		'Meta: %s'              => 'meta:',
	);

	return array_merge( $mappings, $new_mappings );
}
add_filter( 'woocommerce_csv_product_import_mapping_special_columns', 'wc_importer_default_special_english_mappings', 100 );
PK     tS\7       importers/mappings/wordpress.phpnu [        <?php
/**
 * WordPress mappings
 *
 * @package WooCommerce\Admin\Importers
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Add mappings for WordPress tables.
 *
 * @since 3.1.0
 * @param array $mappings Importer columns mappings.
 * @return array
 */
function wc_importer_wordpress_mappings( $mappings ) {

	$wp_mappings = array(
		'post_id'      => 'id',
		'post_title'   => 'name',
		'post_content' => 'description',
		'post_excerpt' => 'short_description',
		'post_parent'  => 'parent_id',
	);

	return array_merge( $mappings, $wp_mappings );
}
add_filter( 'woocommerce_csv_product_import_mapping_default_columns', 'wc_importer_wordpress_mappings' );
PK     tS\X  X    importers/mappings/mappings.phpnu [        <?php
/**
 * Load up extra automatic mappings for the CSV importer.
 *
 * @package WooCommerce\Admin\Importers
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

require dirname( __FILE__ ) . '/default.php';
require dirname( __FILE__ ) . '/generic.php';
require dirname( __FILE__ ) . '/shopify.php';
require dirname( __FILE__ ) . '/wordpress.php';
PK     tS\f	V  V    importers/mappings/shopify.phpnu [        <?php
/**
 * Shopify mappings
 *
 * @package WooCommerce\Admin\Importers
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Add Shopify mappings.
 *
 * @since 3.7.0
 * @param array $mappings    Importer columns mappings.
 * @param array $raw_headers Raw headers from CSV being imported.
 * @return array
 */
function wc_importer_shopify_mappings( $mappings, $raw_headers ) {
	// Only map if this is looks like a Shopify export.
	if ( 0 !== count( array_diff( array( 'Title', 'Body (HTML)', 'Type', 'Variant SKU' ), $raw_headers ) ) ) {
		return $mappings;
	}
	$shopify_mappings = array(
		'Variant SKU'               => 'sku',
		'Title'                     => 'name',
		'Body (HTML)'               => 'description',
		'Quantity'                  => 'stock_quantity',
		'Variant Inventory Qty'     => 'stock_quantity',
		'Image Src'                 => 'images',
		'Variant Image'             => 'images',
		'Variant SKU'               => 'sku',
		'Variant Price'             => 'sale_price',
		'Variant Compare At Price'  => 'regular_price',
		'Type'                      => 'category_ids',
		'Tags'                      => 'tag_ids_spaces',
		'Variant Grams'             => 'weight',
		'Variant Requires Shipping' => 'meta:shopify_requires_shipping',
		'Variant Taxable'           => 'tax_status',
	);
	return array_merge( $mappings, $shopify_mappings );
}
add_filter( 'woocommerce_csv_product_import_mapping_default_columns', 'wc_importer_shopify_mappings', 10, 2 );

/**
 * Add special wildcard Shopify mappings.
 *
 * @since 3.7.0
 * @param array $mappings    Importer columns mappings.
 * @param array $raw_headers Raw headers from CSV being imported.
 * @return array
 */
function wc_importer_shopify_special_mappings( $mappings, $raw_headers ) {
	// Only map if this is looks like a Shopify export.
	if ( 0 !== count( array_diff( array( 'Title', 'Body (HTML)', 'Type', 'Variant SKU' ), $raw_headers ) ) ) {
		return $mappings;
	}
	$shopify_mappings = array(
		'Option%d Name'  => 'attributes:name',
		'Option%d Value' => 'attributes:value',
	);
	return array_merge( $mappings, $shopify_mappings );
}
add_filter( 'woocommerce_csv_product_import_mapping_special_columns', 'wc_importer_shopify_special_mappings', 10, 2 );

/**
 * Expand special Shopify columns to WC format.
 *
 * @since 3.7.0
 * @param  array $data Array of data.
 * @return array Expanded data.
 */
function wc_importer_shopify_expand_data( $data ) {
	if ( isset( $data['meta:shopify_requires_shipping'] ) ) {
		$requires_shipping = wc_string_to_bool( $data['meta:shopify_requires_shipping'] );

		if ( ! $requires_shipping ) {
			if ( isset( $data['type'] ) ) {
				$data['type'][] = 'virtual';
			} else {
				$data['type'] = array( 'virtual' );
			}
		}

		unset( $data['meta:shopify_requires_shipping'] );
	}
	return $data;
}
add_filter( 'woocommerce_product_importer_pre_expand_data', 'wc_importer_shopify_expand_data' );
PK     tS\b3!    *  importers/views/html-csv-import-header.phpnu [        <?php
/**
 * Admin View: Header
 *
 * @package WooCommerce\Admin\Importers
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div class="wrap woocommerce">
	<h1><?php esc_html_e( 'Import Products', 'woocommerce' ); ?></h1>

	<div class="woocommerce-progress-form-wrapper">
PK     tS\d{    +  importers/views/html-csv-import-mapping.phpnu [        <?php
/**
 * Admin View: Importer - CSV mapping
 *
 * @package WooCommerce\Admin\Importers
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<form class="wc-progress-form-content woocommerce-importer" method="post" action="<?php echo esc_url( $this->get_next_step_link() ); ?>">
	<header>
		<h2><?php esc_html_e( 'Map CSV fields to products', 'woocommerce' ); ?></h2>
		<p><?php esc_html_e( 'Select fields from your CSV file to map against products fields, or to ignore during import.', 'woocommerce' ); ?></p>
	</header>
	<section class="wc-importer-mapping-table-wrapper">
		<table class="widefat wc-importer-mapping-table">
			<thead>
				<tr>
					<th><?php esc_html_e( 'Column name', 'woocommerce' ); ?></th>
					<th><?php esc_html_e( 'Map to field', 'woocommerce' ); ?></th>
				</tr>
			</thead>
			<tbody>
				<?php foreach ( $headers as $index => $name ) : ?>
					<?php $mapped_value = $mapped_items[ $index ]; ?>
					<tr>
						<td class="wc-importer-mapping-table-name">
							<?php echo esc_html( $name ); ?>
							<?php if ( ! empty( $sample[ $index ] ) ) : ?>
								<span class="description"><?php esc_html_e( 'Sample:', 'woocommerce' ); ?> <code><?php echo esc_html( $sample[ $index ] ); ?></code></span>
							<?php endif; ?>
						</td>
						<td class="wc-importer-mapping-table-field">
							<input type="hidden" name="map_from[<?php echo esc_attr( $index ); ?>]" value="<?php echo esc_attr( $name ); ?>" />
							<select name="map_to[<?php echo esc_attr( $index ); ?>]">
								<option value=""><?php esc_html_e( 'Do not import', 'woocommerce' ); ?></option>
								<option value="">--------------</option>
								<?php foreach ( $this->get_mapping_options( $mapped_value ) as $key => $value ) : ?>
									<?php if ( is_array( $value ) ) : ?>
										<optgroup label="<?php echo esc_attr( $value['name'] ); ?>">
											<?php foreach ( $value['options'] as $sub_key => $sub_value ) : ?>
												<option value="<?php echo esc_attr( $sub_key ); ?>" <?php selected( $mapped_value, $sub_key ); ?>><?php echo esc_html( $sub_value ); ?></option>
											<?php endforeach ?>
										</optgroup>
									<?php else : ?>
										<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $mapped_value, $key ); ?>><?php echo esc_html( $value ); ?></option>
									<?php endif; ?>
								<?php endforeach ?>
							</select>
						</td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
	</section>
	<div class="wc-actions">
		<button type="submit" class="button button-primary button-next" value="<?php esc_attr_e( 'Run the importer', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Run the importer', 'woocommerce' ); ?></button>
		<input type="hidden" name="file" value="<?php echo esc_attr( $this->file ); ?>" />
		<input type="hidden" name="delimiter" value="<?php echo esc_attr( $this->delimiter ); ?>" />
		<input type="hidden" name="update_existing" value="<?php echo (int) $this->update_existing; ?>" />
		<?php if ( $args['character_encoding'] ) { ?>
			<input type="hidden" name="character_encoding" value="<?php echo esc_html( $args['character_encoding'] ); ?>" />
		<?php } ?>
		<?php wp_nonce_field( 'woocommerce-csv-importer' ); ?>
	</div>
</form>
PK     tS\S7  7  ,  importers/views/html-csv-import-progress.phpnu [        <?php
/**
 * Admin View: Importer - CSV import progress
 *
 * @package WooCommerce\Admin\Importers
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div class="wc-progress-form-content woocommerce-importer woocommerce-importer__importing">
	<header>
		<span class="spinner is-active"></span>
		<h2><?php esc_html_e( 'Importing', 'woocommerce' ); ?></h2>
		<p><?php esc_html_e( 'Your products are now being imported...', 'woocommerce' ); ?></p>
	</header>
	<section>
		<progress class="woocommerce-importer-progress" max="100" value="0"></progress>
	</section>
</div>
PK     tS\f  f  )  importers/views/html-csv-import-steps.phpnu [        <?php
/**
 * Admin View: Steps
 *
 * @package WooCommerce\Admin\Importers
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<ol class="wc-progress-steps">
	<?php foreach ( $this->steps as $step_key => $step ) : ?>
		<?php
		$step_class = '';
		if ( $step_key === $this->step ) {
			$step_class = 'active';
		} elseif ( array_search( $this->step, array_keys( $this->steps ), true ) > array_search( $step_key, array_keys( $this->steps ), true ) ) {
			$step_class = 'done';
		}
		?>
		<li class="<?php echo esc_attr( $step_class ); ?>">
			<?php echo esc_html( $step['name'] ); ?>
		</li>
	<?php endforeach; ?>
</ol>
PK     tS\Uً      *  importers/views/html-csv-import-footer.phpnu [        <?php
/**
 * Admin View: Header
 *
 * @package WooCommerce\Admin\Importers
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
	</div>
</div>
PK     tS\T  T  0  importers/views/html-product-csv-import-form.phpnu [        <?php
/**
 * Admin View: Product import form
 *
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<form class="wc-progress-form-content woocommerce-importer" enctype="multipart/form-data" method="post">
	<header>
		<h2><?php esc_html_e( 'Import products from a CSV file', 'woocommerce' ); ?></h2>
		<p><?php esc_html_e( 'This tool allows you to import (or merge) product data to your store from a CSV or TXT file.', 'woocommerce' ); ?></p>
	</header>
	<section>
		<table class="form-table woocommerce-importer-options">
			<tbody>
				<tr>
					<th scope="row">
						<label for="upload">
							<?php esc_html_e( 'Choose a CSV file from your computer:', 'woocommerce' ); ?>
						</label>
					</th>
					<td>
						<?php
						if ( ! empty( $upload_dir['error'] ) ) {
							?>
							<div class="inline error">
								<p><?php esc_html_e( 'Before you can upload your import file, you will need to fix the following error:', 'woocommerce' ); ?></p>
								<p><strong><?php echo esc_html( $upload_dir['error'] ); ?></strong></p>
							</div>
							<?php
						} else {
							?>
							<input type="file" id="upload" name="import" size="25" />
							<input type="hidden" name="action" value="save" />
							<input type="hidden" name="max_file_size" value="<?php echo esc_attr( $bytes ); ?>" />
							<br>
							<small>
								<?php
								printf(
									/* translators: %s: maximum upload size */
									esc_html__( 'Maximum size: %s', 'woocommerce' ),
									esc_html( $size )
								);
								?>
							</small>
							<?php
						}
						?>
					</td>
				</tr>
				<tr>
					<th><label for="woocommerce-importer-update-existing"><?php esc_html_e( 'Update existing products', 'woocommerce' ); ?></label><br/></th>
					<td>
						<input type="hidden" name="update_existing" value="0" />
						<input type="checkbox" id="woocommerce-importer-update-existing" name="update_existing" value="1" />
						<label for="woocommerce-importer-update-existing"><?php esc_html_e( 'Existing products that match by ID or SKU will be updated. Products that do not exist will be skipped.', 'woocommerce' ); ?></label>
					</td>
				</tr>
				<tr class="woocommerce-importer-advanced hidden">
					<th>
						<label for="woocommerce-importer-file-url"><?php esc_html_e( 'Alternatively, enter the path to a CSV file on your server:', 'woocommerce' ); ?></label>
					</th>
					<td>
						<label for="woocommerce-importer-file-url" class="woocommerce-importer-file-url-field-wrapper">
							<code><?php echo esc_html( ABSPATH ) . ' '; ?></code><input type="text" id="woocommerce-importer-file-url" name="file_url" />
						</label>
					</td>
				</tr>
				<tr class="woocommerce-importer-advanced hidden">
					<th><label><?php esc_html_e( 'CSV Delimiter', 'woocommerce' ); ?></label><br/></th>
					<td><input type="text" name="delimiter" placeholder="," size="2" /></td>
				</tr>
				<tr class="woocommerce-importer-advanced hidden">
					<th><label><?php esc_html_e( 'Use previous column mapping preferences?', 'woocommerce' ); ?></label><br/></th>
					<td><input type="checkbox" id="woocommerce-importer-map-preferences" name="map_preferences" value="1" /></td>
				</tr>
				<tr class="woocommerce-importer-advanced hidden">
					<th><label><?php esc_html_e( 'Character encoding of the file', 'woocommerce' ); ?></label><br/></th>
					<td><select id="woocommerce-importer-character-encoding" name="character_encoding">
							<option value="" selected><?php esc_html_e( 'Autodetect', 'woocommerce' ); ?></option>
							<?php
							$encodings = mb_list_encodings();
							sort( $encodings, SORT_NATURAL );
							foreach ( $encodings as $encoding ) {
								echo '<option>' . esc_html( $encoding ) . '</option>';
							}
							?>
						</select>
					</td>
				</tr>
			</tbody>
		</table>
	</section>
	<script type="text/javascript">
		jQuery(function() {
			jQuery( '.woocommerce-importer-toggle-advanced-options' ).on( 'click', function() {
				var elements = jQuery( '.woocommerce-importer-advanced' );
				if ( elements.is( '.hidden' ) ) {
					elements.removeClass( 'hidden' );
					jQuery( this ).text( jQuery( this ).data( 'hidetext' ) );
				} else {
					elements.addClass( 'hidden' );
					jQuery( this ).text( jQuery( this ).data( 'showtext' ) );
				}
				return false;
			} );
		});
	</script>
	<div class="wc-actions">
		<a href="#" class="woocommerce-importer-toggle-advanced-options" data-hidetext="<?php esc_attr_e( 'Hide advanced options', 'woocommerce' ); ?>" data-showtext="<?php esc_attr_e( 'Show advanced options', 'woocommerce' ); ?>"><?php esc_html_e( 'Show advanced options', 'woocommerce' ); ?></a>
		<button type="submit" class="button button-primary button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
		<?php wp_nonce_field( 'woocommerce-csv-importer' ); ?>
	</div>
</form>
PK     tS\z jE    (  importers/views/html-csv-import-done.phpnu [        <?php
/**
 * Admin View: Importer - Done!
 *
 * @package WooCommerce\Admin\Importers
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
?>
<div class="wc-progress-form-content woocommerce-importer">
	<section class="woocommerce-importer-done">
		<?php
		$results = array();

		if ( 0 < $imported ) {
			$results[] = sprintf(
				/* translators: %d: products count */
				_n( '%s product imported', '%s products imported', $imported, 'woocommerce' ),
				'<strong>' . number_format_i18n( $imported ) . '</strong>'
			);
		}

		if ( 0 < $updated ) {
			$results[] = sprintf(
				/* translators: %d: products count */
				_n( '%s product updated', '%s products updated', $updated, 'woocommerce' ),
				'<strong>' . number_format_i18n( $updated ) . '</strong>'
			);
		}

		if ( 0 < $imported_variations ) {
			$results[] = sprintf(
				/* translators: %d: products count */
				_n( '%s variations imported', '%s variations imported', $imported_variations, 'woocommerce' ),
				'<strong>' . number_format_i18n( $imported_variations ) . '</strong>'
			);
		}

		if ( 0 < $skipped ) {
			$results[] = sprintf(
				/* translators: %d: products count */
				_n( '%s product was skipped', '%s products were skipped', $skipped, 'woocommerce' ),
				'<strong>' . number_format_i18n( $skipped ) . '</strong>'
			);
		}

		if ( 0 < $failed ) {
			$results [] = sprintf(
				/* translators: %d: products count */
				_n( 'Failed to import %s product', 'Failed to import %s products', $failed, 'woocommerce' ),
				'<strong>' . number_format_i18n( $failed ) . '</strong>'
			);
		}

		if ( 0 < $failed || 0 < $skipped ) {
			$results[] = '<a href="#" class="woocommerce-importer-done-view-errors">' . __( 'View import log', 'woocommerce' ) . '</a>';
		}

		if ( ! empty( $file_name ) ) {
			$results[] = sprintf(
				/* translators: %s: File name */
				__( 'File uploaded: %s', 'woocommerce' ),
				'<strong>' . $file_name . '</strong>'
			);
		}

		/* translators: %d: import results */
		echo wp_kses_post( __( 'Import complete!', 'woocommerce' ) . ' ' . implode( '. ', $results ) );
		?>
	</section>
	<section class="wc-importer-error-log" style="display:none">
		<table class="widefat wc-importer-error-log-table">
			<thead>
				<tr>
					<th><?php esc_html_e( 'Product', 'woocommerce' ); ?></th>
					<th><?php esc_html_e( 'Reason for failure', 'woocommerce' ); ?></th>
				</tr>
			</thead>
			<tbody>
				<?php
				if ( is_array( $errors ) && count( $errors ) ) {
					foreach ( $errors as $error ) {
						if ( ! is_wp_error( $error ) ) {
							continue;
						}
						$error_data = $error->get_error_data();
						?>
						<tr>
							<th><code><?php echo esc_html( $error_data['row'] ); ?></code></th>
							<td><?php echo wp_kses_post( $error->get_error_message() ); ?></td>
						</tr>
						<?php
					}
				}
				?>
			</tbody>
		</table>
	</section>
	<script type="text/javascript">
		jQuery(function() {
			jQuery( '.woocommerce-importer-done-view-errors' ).on( 'click', function() {
				jQuery( '.wc-importer-error-log' ).slideToggle();
				return false;
			} );
		} );
	</script>
	<div class="wc-actions">
		<a class="button button-primary" href="<?php echo esc_url( admin_url( 'edit.php?post_type=product' ) ); ?>"><?php esc_html_e( 'View products', 'woocommerce' ); ?></a>
	</div>
</div>
PK     tS\6>%  %  (  importers/class-wc-tax-rate-importer.phpnu [        <?php
/**
 * Tax importer class file
 *
 * @version 2.3.0
 * @package WooCommerce\Admin
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'WP_Importer' ) ) {
	return;
}

/**
 * Tax Rates importer - import tax rates and local tax rates into WooCommerce.
 *
 * @package     WooCommerce\Admin\Importers
 * @version     2.3.0
 */
class WC_Tax_Rate_Importer extends WP_Importer {

	/**
	 * The current file id.
	 *
	 * @var int
	 */
	public $id;

	/**
	 * The current file url.
	 *
	 * @var string
	 */
	public $file_url;

	/**
	 * The current import page.
	 *
	 * @var string
	 */
	public $import_page;

	/**
	 * The current delimiter.
	 *
	 * @var string
	 */
	public $delimiter;

	/**
	 * Error message for import.
	 *
	 * @var string
	 */
	public $import_error_message;

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->import_page = 'woocommerce_tax_rate_csv';
		$this->delimiter   = empty( $_POST['delimiter'] ) ? ',' : (string) wc_clean( wp_unslash( $_POST['delimiter'] ) ); // WPCS: CSRF ok.
	}

	/**
	 * Registered callback function for the WordPress Importer.
	 *
	 * Manages the three separate stages of the CSV import process.
	 */
	public function dispatch() {

		$this->header();

		$step = empty( $_GET['step'] ) ? 0 : (int) $_GET['step'];

		switch ( $step ) {

			case 0:
				$this->greet();
				break;

			case 1:
				check_admin_referer( 'import-upload' );

				if ( $this->handle_upload() ) {

					if ( $this->id ) {
						$file = get_attached_file( $this->id );
					} else {
						$file = ABSPATH . $this->file_url;
					}

					add_filter( 'http_request_timeout', array( $this, 'bump_request_timeout' ) );

					$this->import( $file );
				} else {
					$this->import_error( $this->import_error_message );
				}
				break;
		}

		$this->footer();
	}

	/**
	 * Import is starting.
	 */
	private function import_start() {
		if ( function_exists( 'gc_enable' ) ) {
			gc_enable(); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.gc_enableFound
		}
		wc_set_time_limit( 0 );
		@ob_flush();
		@flush();
	}

	/**
	 * UTF-8 encode the data if `$enc` value isn't UTF-8.
	 *
	 * @param mixed  $data Data.
	 * @param string $enc Encoding.
	 * @return string
	 */
	public function format_data_from_csv( $data, $enc ) {
		return ( 'UTF-8' === $enc ) ? $data : utf8_encode( $data );
	}

	/**
	 * Import the file if it exists and is valid.
	 *
	 * @param mixed $file File.
	 */
	public function import( $file ) {
		if ( ! is_file( $file ) ) {
			$this->import_error( __( 'The file does not exist, please try again.', 'woocommerce' ) );
		}

		$this->import_start();

		$loop   = 0;
		$handle = fopen( $file, 'r' );

		if ( false !== $handle ) {

			$header = fgetcsv( $handle, 0, $this->delimiter );
			$count  = is_countable( $header ) ? count( $header ) : 0;
			if ( 10 === $count ) {

				$row = fgetcsv( $handle, 0, $this->delimiter );

				while ( false !== $row ) {

					list( $country, $state, $postcode, $city, $rate, $name, $priority, $compound, $shipping, $class ) = $row;

					$tax_rate = array(
						'tax_rate_country'  => $country,
						'tax_rate_state'    => $state,
						'tax_rate'          => $rate,
						'tax_rate_name'     => $name,
						'tax_rate_priority' => $priority,
						'tax_rate_compound' => $compound ? 1 : 0,
						'tax_rate_shipping' => $shipping ? 1 : 0,
						'tax_rate_order'    => $loop ++,
						'tax_rate_class'    => $class,
					);

					$tax_rate_id = WC_Tax::_insert_tax_rate( $tax_rate );
					WC_Tax::_update_tax_rate_postcodes( $tax_rate_id, wc_clean( $postcode ) );
					WC_Tax::_update_tax_rate_cities( $tax_rate_id, wc_clean( $city ) );

					$row = fgetcsv( $handle, 0, $this->delimiter );
				}
			} else {
				$this->import_error( __( 'The CSV is invalid.', 'woocommerce' ) );
			}

			fclose( $handle );
		}

		// Show Result.
		echo '<div class="updated settings-error"><p>';
		printf(
			/* translators: %s: tax rates count */
			esc_html__( 'Import complete - imported %s tax rates.', 'woocommerce' ),
			'<strong>' . absint( $loop ) . '</strong>'
		);
		echo '</p></div>';

		$this->import_end();
	}

	/**
	 * Performs post-import cleanup of files and the cache.
	 */
	public function import_end() {
		echo '<p>' . esc_html__( 'All done!', 'woocommerce' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=tax' ) ) . '">' . esc_html__( 'View tax rates', 'woocommerce' ) . '</a></p>';

		do_action( 'import_end' );
	}

	/**
	 * Set the import error message.
	 *
	 * @param string $message Error message.
	 */
	protected function set_import_error_message( $message ) {
		$this->import_error_message = $message;
	}

	/**
	 * Handles the CSV upload and initial parsing of the file to prepare for.
	 * displaying author import options.
	 *
	 * @return bool False if error uploading or invalid file, true otherwise
	 */
	public function handle_upload() {
		$file_url = isset( $_POST['file_url'] ) ? wc_clean( wp_unslash( $_POST['file_url'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce already verified in WC_Tax_Rate_Importer::dispatch()

		if ( empty( $file_url ) ) {
			$file = wp_import_handle_upload();

			if ( isset( $file['error'] ) ) {
				$this->set_import_error_message( $file['error'] );

				return false;
			}

			if ( ! wc_is_file_valid_csv( $file['file'], false ) ) {
				// Remove file if not valid.
				wp_delete_attachment( $file['id'], true );

				$this->set_import_error_message( __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );

				return false;
			}

			$this->id = absint( $file['id'] );
		} elseif (
			( 0 === stripos( realpath( ABSPATH . $file_url ), ABSPATH ) ) &&
			file_exists( ABSPATH . $file_url )
		) {
			if ( ! wc_is_file_valid_csv( ABSPATH . $file_url ) ) {
				$this->set_import_error_message( __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );

				return false;
			}

			$this->file_url = esc_attr( $file_url );
		} else {
			return false;
		}

		return true;
	}

	/**
	 * Output header html.
	 */
	public function header() {
		echo '<div class="wrap">';
		echo '<h1>' . esc_html__( 'Import tax rates', 'woocommerce' ) . '</h1>';
	}

	/**
	 * Output footer html.
	 */
	public function footer() {
		echo '</div>';
	}

	/**
	 * Output information about the uploading process.
	 */
	public function greet() {

		echo '<div class="narrow">';
		echo '<p>' . esc_html__( 'Hi there! Upload a CSV file containing tax rates to import the contents into your shop. Choose a .csv file to upload, then click "Upload file and import".', 'woocommerce' ) . '</p>';

		/* translators: 1: Link to tax rates sample file 2: Closing link. */
		echo '<p>' . sprintf( esc_html__( 'Your CSV needs to include columns in a specific order. %1$sClick here to download a sample%2$s.', 'woocommerce' ), '<a href="' . esc_url( WC()->plugin_url() ) . '/sample-data/sample_tax_rates.csv">', '</a>' ) . '</p>';

		$action = 'admin.php?import=woocommerce_tax_rate_csv&step=1';

		$bytes      = apply_filters( 'import_upload_size_limit', wp_max_upload_size() );
		$size       = size_format( $bytes );
		$upload_dir = wp_upload_dir();
		if ( ! empty( $upload_dir['error'] ) ) :
			?>
			<div class="error">
				<p><?php esc_html_e( 'Before you can upload your import file, you will need to fix the following error:', 'woocommerce' ); ?></p>
				<p><strong><?php echo esc_html( $upload_dir['error'] ); ?></strong></p>
			</div>
		<?php else : ?>
			<form enctype="multipart/form-data" id="import-upload-form" method="post" action="<?php echo esc_attr( wp_nonce_url( $action, 'import-upload' ) ); ?>">
				<table class="form-table">
					<tbody>
						<tr>
							<th>
								<label for="upload"><?php esc_html_e( 'Choose a file from your computer:', 'woocommerce' ); ?></label>
							</th>
							<td>
								<input type="file" id="upload" name="import" size="25" />
								<input type="hidden" name="action" value="save" />
								<input type="hidden" name="max_file_size" value="<?php echo absint( $bytes ); ?>" />
								<small>
									<?php
									printf(
										/* translators: %s: maximum upload size */
										esc_html__( 'Maximum size: %s', 'woocommerce' ),
										esc_attr( $size )
									);
									?>
								</small>
							</td>
						</tr>
						<tr>
							<th>
								<label for="file_url"><?php esc_html_e( 'OR enter path to file:', 'woocommerce' ); ?></label>
							</th>
							<td>
								<?php echo ' ' . esc_html( ABSPATH ) . ' '; ?><input type="text" id="file_url" name="file_url" size="25" />
							</td>
						</tr>
						<tr>
							<th><label><?php esc_html_e( 'Delimiter', 'woocommerce' ); ?></label><br/></th>
							<td><input type="text" name="delimiter" placeholder="," size="2" /></td>
						</tr>
					</tbody>
				</table>
				<p class="submit">
					<button type="submit" class="button" value="<?php esc_attr_e( 'Upload file and import', 'woocommerce' ); ?>"><?php esc_html_e( 'Upload file and import', 'woocommerce' ); ?></button>
				</p>
			</form>
			<?php
		endif;

		echo '</div>';
	}

	/**
	 * Show import error and quit.
	 *
	 * @param  string $message Error message.
	 */
	private function import_error( $message = '' ) {
		echo '<p><strong>' . esc_html__( 'Sorry, there has been an error.', 'woocommerce' ) . '</strong><br />';
		if ( $message ) {
			echo esc_html( $message );
		}
		echo '</p>';
		$this->footer();
		die();
	}

	/**
	 * Added to http_request_timeout filter to force timeout at 60 seconds during import.
	 *
	 * @param  int $val Value.
	 * @return int 60
	 */
	public function bump_request_timeout( $val ) {
		return 60;
	}
}
PK     tS\o0ix  ix  6  importers/class-wc-product-csv-importer-controller.phpnu [        <?php
/**
 * Class WC_Product_CSV_Importer_Controller file.
 *
 * @package WooCommerce\Admin\Importers
 */

use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;
use Automattic\WooCommerce\Internal\Utilities\FilesystemUtil;
use Automattic\WooCommerce\Internal\Utilities\URL;
use Automattic\WooCommerce\Utilities\I18nUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'WP_Importer' ) ) {
	return;
}

/**
 * Product importer controller - handles file upload and forms in admin.
 *
 * @package     WooCommerce\Admin\Importers
 * @version     3.1.0
 */
class WC_Product_CSV_Importer_Controller {

	/**
	 * The path to the current file.
	 *
	 * @var string
	 */
	protected $file = '';

	/**
	 * The current import step.
	 *
	 * @var string
	 */
	protected $step = '';

	/**
	 * Progress steps.
	 *
	 * @var array
	 */
	protected $steps = array();

	/**
	 * Errors.
	 *
	 * @var array
	 */
	protected $errors = array();

	/**
	 * The current delimiter for the file being read.
	 *
	 * @var string
	 */
	protected $delimiter = ',';

	/**
	 * Whether to use previous mapping selections.
	 *
	 * @var bool
	 */
	protected $map_preferences = false;

	/**
	 * Whether to skip existing products.
	 *
	 * @var bool
	 */
	protected $update_existing = false;

	/**
	 * The character encoding to use to interpret the input file, or empty string for autodetect.
	 *
	 * @var string
	 */
	protected $character_encoding = 'UTF-8';

	/**
	 * Get importer instance.
	 *
	 * @param  string $file File to import.
	 * @param  array  $args Importer arguments.
	 * @return WC_Product_CSV_Importer
	 */
	public static function get_importer( $file, $args = array() ) {
		$importer_class = apply_filters( 'woocommerce_product_csv_importer_class', 'WC_Product_CSV_Importer' );
		$args           = apply_filters( 'woocommerce_product_csv_importer_args', $args, $importer_class );
		return new $importer_class( $file, $args );
	}

	/**
	 * Check whether a file is a valid CSV file.
	 *
	 * @param string $file File path.
	 * @param bool   $check_path Whether to also check the file is located in a valid location (Default: true).
	 * @return bool
	 */
	public static function is_file_valid_csv( $file, $check_path = true ) {
		return wc_is_file_valid_csv( $file, $check_path );
	}

	/**
	 * Runs before controller actions to check that the file used during the import is valid.
	 *
	 * @since 9.3.0
	 *
	 * @param string $path Path to test.
	 *
	 * @throws \Exception When file validation fails.
	 */
	protected static function validate_file_path( string $path ): void {
		try {
			FilesystemUtil::validate_upload_file_path( $path );
		} catch ( \Exception $e ) {
			throw new \Exception( esc_html__( 'File path provided for import is invalid.', 'woocommerce' ) );
		}

		if ( ! self::is_file_valid_csv( $path ) ) {
			throw new \Exception( esc_html__( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
		}
	}

	/**
	 * Get all the valid filetypes for a CSV file.
	 *
	 * @return array
	 */
	protected static function get_valid_csv_filetypes() {
		return apply_filters(
			'woocommerce_csv_product_import_valid_filetypes',
			array(
				'csv' => 'text/csv',
				'txt' => 'text/plain',
			)
		);
	}

	/**
	 * Constructor.
	 */
	public function __construct() {
		$default_steps = array(
			'upload'  => array(
				'name'    => __( 'Upload CSV file', 'woocommerce' ),
				'view'    => array( $this, 'upload_form' ),
				'handler' => array( $this, 'upload_form_handler' ),
			),
			'mapping' => array(
				'name'    => __( 'Column mapping', 'woocommerce' ),
				'view'    => array( $this, 'mapping_form' ),
				'handler' => '',
			),
			'import'  => array(
				'name'    => __( 'Import', 'woocommerce' ),
				'view'    => array( $this, 'import' ),
				'handler' => '',
			),
			'done'    => array(
				'name'    => __( 'Done!', 'woocommerce' ),
				'view'    => array( $this, 'done' ),
				'handler' => '',
			),
		);

		$this->steps = apply_filters( 'woocommerce_product_csv_importer_steps', $default_steps );

		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		$this->step               = isset( $_REQUEST['step'] ) ? sanitize_key( $_REQUEST['step'] ) : current( array_keys( $this->steps ) );
		$this->file               = isset( $_REQUEST['file'] ) ? wc_clean( wp_unslash( $_REQUEST['file'] ) ) : '';
		$this->update_existing    = isset( $_REQUEST['update_existing'] ) ? (bool) $_REQUEST['update_existing'] : false;
		$this->delimiter          = ! empty( $_REQUEST['delimiter'] ) ? wc_clean( wp_unslash( $_REQUEST['delimiter'] ) ) : ',';
		$this->map_preferences    = isset( $_REQUEST['map_preferences'] ) ? (bool) $_REQUEST['map_preferences'] : false;
		$this->character_encoding = isset( $_REQUEST['character_encoding'] ) ? wc_clean( wp_unslash( $_REQUEST['character_encoding'] ) ) : 'UTF-8';
		// phpcs:enable

		// Import mappings for CSV data.
		include_once __DIR__ . '/mappings/mappings.php';

		if ( $this->map_preferences ) {
			add_filter( 'woocommerce_csv_product_import_mapped_columns', array( $this, 'auto_map_user_preferences' ), 9999 );
		}
	}

	/**
	 * Get the URL for the next step's screen.
	 *
	 * @param string $step  slug (default: current step).
	 * @return string       URL for next step if a next step exists.
	 *                      Admin URL if it's the last step.
	 *                      Empty string on failure.
	 */
	public function get_next_step_link( $step = '' ) {
		if ( ! $step ) {
			$step = $this->step;
		}

		$keys = array_keys( $this->steps );

		if ( end( $keys ) === $step ) {
			return admin_url();
		}

		$step_index = array_search( $step, $keys, true );

		if ( false === $step_index ) {
			return '';
		}

		$params = array(
			'step'               => $keys[ $step_index + 1 ],
			'file'               => str_replace( DIRECTORY_SEPARATOR, '/', $this->file ),
			'delimiter'          => $this->delimiter,
			'update_existing'    => $this->update_existing,
			'map_preferences'    => $this->map_preferences,
			'character_encoding' => $this->character_encoding,
			'_wpnonce'           => wp_create_nonce( 'woocommerce-csv-importer' ), // wp_nonce_url() escapes & to &amp; breaking redirects.
		);

		return add_query_arg( $params );
	}

	/**
	 * Output header view.
	 */
	protected function output_header() {
		include __DIR__ . '/views/html-csv-import-header.php';
	}

	/**
	 * Output steps view.
	 */
	protected function output_steps() {
		include __DIR__ . '/views/html-csv-import-steps.php';
	}

	/**
	 * Output footer view.
	 */
	protected function output_footer() {
		include __DIR__ . '/views/html-csv-import-footer.php';
	}

	/**
	 * Add error message.
	 *
	 * @param string $message Error message.
	 * @param array  $actions List of actions with 'url' and 'label'.
	 */
	protected function add_error( $message, $actions = array() ) {
		$this->errors[] = array(
			'message' => $message,
			'actions' => $actions,
		);
	}

	/**
	 * Add error message.
	 */
	protected function output_errors() {
		if ( ! $this->errors ) {
			return;
		}

		foreach ( $this->errors as $error ) {
			echo '<div class="error inline">';
			echo '<p>' . esc_html( $error['message'] ) . '</p>';

			if ( ! empty( $error['actions'] ) ) {
				echo '<p>';
				foreach ( $error['actions'] as $action ) {
					echo '<a class="button button-primary" href="' . esc_url( $action['url'] ) . '">' . esc_html( $action['label'] ) . '</a> ';
				}
				echo '</p>';
			}
			echo '</div>';
		}
	}

	/**
	 * Dispatch current step and show correct view.
	 */
	public function dispatch() {
		$output = '';

		try {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing
			if ( ! empty( $_POST['save_step'] ) && ! empty( $this->steps[ $this->step ]['handler'] ) ) {
				if ( is_callable( $this->steps[ $this->step ]['handler'] ) ) {
					call_user_func( $this->steps[ $this->step ]['handler'], $this );
				}
			}

			ob_start();

			if ( is_callable( $this->steps[ $this->step ]['view'] ) ) {
				call_user_func( $this->steps[ $this->step ]['view'], $this );
			}

			$output = ob_get_clean();
		} catch ( \Exception $e ) {
			$this->add_error( $e->getMessage() );
		}

		$this->output_header();
		$this->output_steps();
		$this->output_errors();
		echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output is HTML we've generated ourselves.
		$this->output_footer();
	}

	/**
	 * Processes AJAX requests related to a product CSV import.
	 *
	 * @since 9.3.0
	 */
	public static function dispatch_ajax() {
		global $wpdb;

		check_ajax_referer( 'wc-product-import', 'security' );

		try {
			$file = wc_clean( wp_unslash( $_POST['file'] ?? '' ) ); // PHPCS: input var ok.
			self::validate_file_path( $file );

			$params = array(
				'delimiter'          => ! empty( $_POST['delimiter'] ) ? wc_clean( wp_unslash( $_POST['delimiter'] ) ) : ',', // PHPCS: input var ok.
				'start_pos'          => isset( $_POST['position'] ) ? absint( $_POST['position'] ) : 0, // PHPCS: input var ok.
				'mapping'            => isset( $_POST['mapping'] ) ? (array) wc_clean( wp_unslash( $_POST['mapping'] ) ) : array(), // PHPCS: input var ok.
				'update_existing'    => isset( $_POST['update_existing'] ) ? (bool) $_POST['update_existing'] : false, // PHPCS: input var ok.
				'character_encoding' => isset( $_POST['character_encoding'] ) ? wc_clean( wp_unslash( $_POST['character_encoding'] ) ) : '',

				/**
				 * Batch size for the product import process.
				 *
				 * @param int $size Batch size.
				 *
				 * @since 3.1.0
				 */
				'lines'              => apply_filters( 'woocommerce_product_import_batch_size', 30 ),
				'parse'              => true,
			);

			// Log failures.
			if ( 0 !== $params['start_pos'] ) {
				$error_log = array_filter( (array) get_user_option( 'product_import_error_log' ) );
			} else {
				$error_log = array();
			}

			include_once WC_ABSPATH . 'includes/import/class-wc-product-csv-importer.php';

			$importer         = self::get_importer( $file, $params );
			$results          = $importer->import();
			$percent_complete = $importer->get_percent_complete();
			$error_log        = array_merge( $error_log, $results['failed'], $results['skipped'] );

			update_user_option( get_current_user_id(), 'product_import_error_log', $error_log );

			if ( 100 === $percent_complete ) {
				// @codingStandardsIgnoreStart.
				$wpdb->delete( $wpdb->postmeta, array( 'meta_key' => '_original_id' ) );
				$wpdb->delete( $wpdb->posts, array(
					'post_type'   => 'product',
					'post_status' => 'importing',
				) );
				$wpdb->delete( $wpdb->posts, array(
					'post_type'   => 'product_variation',
					'post_status' => 'importing',
				) );
				// @codingStandardsIgnoreEnd.

				// Clean up orphaned data.
				$wpdb->query(
					"
					DELETE {$wpdb->posts}.* FROM {$wpdb->posts}
					LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->posts}.post_parent
					WHERE wp.ID IS NULL AND {$wpdb->posts}.post_type = 'product_variation'
				"
				);
				$wpdb->query(
					"
					DELETE {$wpdb->postmeta}.* FROM {$wpdb->postmeta}
					LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->postmeta}.post_id
					WHERE wp.ID IS NULL
				"
				);
				// @codingStandardsIgnoreStart.
				$wpdb->query( "
					DELETE tr.* FROM {$wpdb->term_relationships} tr
					LEFT JOIN {$wpdb->posts} wp ON wp.ID = tr.object_id
					LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
					WHERE wp.ID IS NULL
					AND tt.taxonomy IN ( '" . implode( "','", array_map( 'esc_sql', get_object_taxonomies( 'product' ) ) ) . "' )
				" );
				// @codingStandardsIgnoreEnd.

				// Send success.
				wp_send_json_success(
					array(
						'position'            => 'done',
						'percentage'          => 100,
						'url'                 => add_query_arg( array( '_wpnonce' => wp_create_nonce( 'woocommerce-csv-importer' ) ), admin_url( 'edit.php?post_type=product&page=product_importer&step=done' ) ),
						'imported'            => is_countable( $results['imported'] ) ? count( $results['imported'] ) : 0,
						'imported_variations' => is_countable( $results['imported_variations'] ) ? count( $results['imported_variations'] ) : 0,
						'failed'              => is_countable( $results['failed'] ) ? count( $results['failed'] ) : 0,
						'updated'             => is_countable( $results['updated'] ) ? count( $results['updated'] ) : 0,
						'skipped'             => is_countable( $results['skipped'] ) ? count( $results['skipped'] ) : 0,
					)
				);
			} else {
				wp_send_json_success(
					array(
						'position'            => $importer->get_file_position(),
						'percentage'          => $percent_complete,
						'imported'            => is_countable( $results['imported'] ) ? count( $results['imported'] ) : 0,
						'imported_variations' => is_countable( $results['imported_variations'] ) ? count( $results['imported_variations'] ) : 0,
						'failed'              => is_countable( $results['failed'] ) ? count( $results['failed'] ) : 0,
						'updated'             => is_countable( $results['updated'] ) ? count( $results['updated'] ) : 0,
						'skipped'             => is_countable( $results['skipped'] ) ? count( $results['skipped'] ) : 0,
					)
				);
			}
		} catch ( \Exception $e ) {
			wp_send_json_error( array( 'message' => $e->getMessage() ) );
		}
	}

	/**
	 * Output information about the uploading process.
	 */
	protected function upload_form() {
		$bytes      = apply_filters( 'import_upload_size_limit', wp_max_upload_size() );
		$size       = size_format( $bytes );
		$upload_dir = wp_upload_dir();

		include __DIR__ . '/views/html-product-csv-import-form.php';
	}

	/**
	 * Handle the upload form and store options.
	 */
	public function upload_form_handler() {
		check_admin_referer( 'woocommerce-csv-importer' );

		$file = $this->handle_upload();

		if ( is_wp_error( $file ) ) {
			$this->add_error( $file->get_error_message() );
			return;
		} else {
			$this->file = $file;
		}

		wp_redirect( esc_url_raw( $this->get_next_step_link() ) );
		exit;
	}

	/**
	 * Handles the CSV upload and initial parsing of the file to prepare for
	 * displaying author import options.
	 *
	 * @return string|WP_Error
	 */
	public function handle_upload() {
		// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce already verified in WC_Product_CSV_Importer_Controller::upload_form_handler()
		$file_url = isset( $_POST['file_url'] ) ? wc_clean( wp_unslash( $_POST['file_url'] ) ) : '';

		try {
			if ( ! empty( $file_url ) ) {
				$path = ABSPATH . $file_url;
				self::validate_file_path( $path );
			} else {
				$csv_import_util = wc_get_container()->get( Automattic\WooCommerce\Internal\Admin\ImportExport\CSVUploadHelper::class );
				$upload          = $csv_import_util->handle_csv_upload( 'product', 'import', self::get_valid_csv_filetypes() );
				$path            = $upload['file'];
			}

			return $path;
		} catch ( \Exception $e ) {
			return new \WP_Error( 'woocommerce_product_csv_importer_upload_invalid_file', $e->getMessage() );
		}
	}

	/**
	 * Mapping step.
	 */
	protected function mapping_form() {
		check_admin_referer( 'woocommerce-csv-importer' );
		self::validate_file_path( $this->file );

		$args = array(
			'lines'              => 1,
			'delimiter'          => $this->delimiter,
			'character_encoding' => $this->character_encoding,
		);

		$importer     = self::get_importer( $this->file, $args );
		$headers      = $importer->get_raw_keys();
		$mapped_items = $this->auto_map_columns( $headers );
		$sample       = current( $importer->get_raw_data() );

		if ( empty( $sample ) ) {
			$this->add_error(
				__( 'The file is empty or using a different encoding than UTF-8, please try again with a new file.', 'woocommerce' ),
				array(
					array(
						'url'   => admin_url( 'edit.php?post_type=product&page=product_importer' ),
						'label' => __( 'Upload a new file', 'woocommerce' ),
					),
				)
			);

			// Force output the errors in the same page.
			$this->output_errors();
			return;
		}

		include_once __DIR__ . '/views/html-csv-import-mapping.php';
	}

	/**
	 * Import the file if it exists and is valid.
	 */
	public function import() {
		// Displaying this page triggers Ajax action to run the import with a valid nonce,
		// therefore this page needs to be nonce protected as well.
		check_admin_referer( 'woocommerce-csv-importer' );
		self::validate_file_path( $this->file );

		if ( ! empty( $_POST['map_from'] ) && ! empty( $_POST['map_to'] ) ) {
			$mapping_from = wc_clean( wp_unslash( $_POST['map_from'] ) );
			$mapping_to   = wc_clean( wp_unslash( $_POST['map_to'] ) );

			// Save mapping preferences for future imports.
			update_user_option( get_current_user_id(), 'woocommerce_product_import_mapping', $mapping_to );
		} else {
			wp_redirect( esc_url_raw( $this->get_next_step_link( 'upload' ) ) );
			exit;
		}

		wp_localize_script(
			'wc-product-import',
			'wc_product_import_params',
			array(
				'import_nonce'       => wp_create_nonce( 'wc-product-import' ),
				'mapping'            => array(
					'from' => $mapping_from,
					'to'   => $mapping_to,
				),
				'file'               => $this->file,
				'update_existing'    => $this->update_existing,
				'delimiter'          => $this->delimiter,
				'character_encoding' => $this->character_encoding,
			)
		);
		wp_enqueue_script( 'wc-product-import' );

		include_once __DIR__ . '/views/html-csv-import-progress.php';
	}

	/**
	 * Done step.
	 */
	protected function done() {
		check_admin_referer( 'woocommerce-csv-importer' );
		$imported            = isset( $_GET['products-imported'] ) ? absint( $_GET['products-imported'] ) : 0;
		$imported_variations = isset( $_GET['products-imported-variations'] ) ? absint( $_GET['products-imported-variations'] ) : 0;
		$updated             = isset( $_GET['products-updated'] ) ? absint( $_GET['products-updated'] ) : 0;
		$failed              = isset( $_GET['products-failed'] ) ? absint( $_GET['products-failed'] ) : 0;
		$skipped             = isset( $_GET['products-skipped'] ) ? absint( $_GET['products-skipped'] ) : 0;
		$file_name           = isset( $_GET['file-name'] ) ? sanitize_text_field( wp_unslash( $_GET['file-name'] ) ) : '';
		$errors              = array_filter( (array) get_user_option( 'product_import_error_log' ) );

		include_once __DIR__ . '/views/html-csv-import-done.php';
	}

	/**
	 * Columns to normalize.
	 *
	 * @param  array $columns List of columns names and keys.
	 * @return array
	 */
	protected function normalize_columns_names( $columns ) {
		$normalized = array();

		foreach ( $columns as $key => $value ) {
			$normalized[ strtolower( $key ) ] = $value;
		}

		return $normalized;
	}

	/**
	 * Auto map column names.
	 *
	 * @param  array $raw_headers Raw header columns.
	 * @param  bool  $num_indexes If should use numbers or raw header columns as indexes.
	 * @return array
	 */
	protected function auto_map_columns( $raw_headers, $num_indexes = true ) {
		$weight_unit_label    = I18nUtil::get_weight_unit_label( get_option( 'woocommerce_weight_unit', 'kg' ) );
		$dimension_unit_label = I18nUtil::get_dimensions_unit_label( get_option( 'woocommerce_dimension_unit', 'cm' ) );

		$default_columns = array(
			__( 'ID', 'woocommerce' )                      => 'id',
			__( 'Type', 'woocommerce' )                    => 'type',
			__( 'SKU', 'woocommerce' )                     => 'sku',
			__( 'Name', 'woocommerce' )                    => 'name',
			__( 'Published', 'woocommerce' )               => 'published',
			__( 'Is featured?', 'woocommerce' )            => 'featured',
			__( 'Visibility in catalog', 'woocommerce' )   => 'catalog_visibility',
			__( 'Short description', 'woocommerce' )       => 'short_description',
			__( 'Description', 'woocommerce' )             => 'description',
			__( 'Date sale price starts', 'woocommerce' )  => 'date_on_sale_from',
			__( 'Date sale price ends', 'woocommerce' )    => 'date_on_sale_to',
			__( 'Tax status', 'woocommerce' )              => 'tax_status',
			__( 'Tax class', 'woocommerce' )               => 'tax_class',
			__( 'In stock?', 'woocommerce' )               => 'stock_status',
			__( 'Stock', 'woocommerce' )                   => 'stock_quantity',
			__( 'Backorders allowed?', 'woocommerce' )     => 'backorders',
			__( 'Low stock amount', 'woocommerce' )        => 'low_stock_amount',
			__( 'Sold individually?', 'woocommerce' )      => 'sold_individually',
			/* translators: %s: Weight unit */
			sprintf( __( 'Weight (%s)', 'woocommerce' ), $weight_unit_label ) => 'weight',
			/* translators: %s: Length unit */
			sprintf( __( 'Length (%s)', 'woocommerce' ), $dimension_unit_label ) => 'length',
			/* translators: %s: Width unit */
			sprintf( __( 'Width (%s)', 'woocommerce' ), $dimension_unit_label ) => 'width',
			/* translators: %s: Height unit */
			sprintf( __( 'Height (%s)', 'woocommerce' ), $dimension_unit_label ) => 'height',
			__( 'Allow customer reviews?', 'woocommerce' ) => 'reviews_allowed',
			__( 'Purchase note', 'woocommerce' )           => 'purchase_note',
			__( 'Sale price', 'woocommerce' )              => 'sale_price',
			__( 'Regular price', 'woocommerce' )           => 'regular_price',
			__( 'Categories', 'woocommerce' )              => 'category_ids',
			__( 'Tags', 'woocommerce' )                    => 'tag_ids',
			__( 'Shipping class', 'woocommerce' )          => 'shipping_class_id',
			__( 'Images', 'woocommerce' )                  => 'images',
			__( 'Download limit', 'woocommerce' )          => 'download_limit',
			__( 'Download expiry days', 'woocommerce' )    => 'download_expiry',
			__( 'Parent', 'woocommerce' )                  => 'parent_id',
			__( 'Upsells', 'woocommerce' )                 => 'upsell_ids',
			__( 'Cross-sells', 'woocommerce' )             => 'cross_sell_ids',
			__( 'Grouped products', 'woocommerce' )        => 'grouped_products',
			__( 'External URL', 'woocommerce' )            => 'product_url',
			__( 'Button text', 'woocommerce' )             => 'button_text',
			__( 'Position', 'woocommerce' )                => 'menu_order',
		);

		if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() ) {
			$default_columns[ __( 'Cost of goods', 'woocommerce' ) ] = 'cogs_value';
		}

		/*
		 * @hooked wc_importer_generic_mappings - 10
		 * @hooked wc_importer_wordpress_mappings - 10
		 * @hooked wc_importer_default_english_mappings - 100
		 */
		$default_columns = $this->normalize_columns_names(
			apply_filters(
				'woocommerce_csv_product_import_mapping_default_columns',
				$default_columns,
				$raw_headers
			)
		);

		$special_columns = $this->get_special_columns(
			$this->normalize_columns_names(
				apply_filters(
					'woocommerce_csv_product_import_mapping_special_columns',
					array(
						/* translators: %d: Attribute number */
						__( 'Attribute %d name', 'woocommerce' ) => 'attributes:name',
						/* translators: %d: Attribute number */
						__( 'Attribute %d value(s)', 'woocommerce' ) => 'attributes:value',
						/* translators: %d: Attribute number */
						__( 'Attribute %d visible', 'woocommerce' ) => 'attributes:visible',
						/* translators: %d: Attribute number */
						__( 'Attribute %d global', 'woocommerce' ) => 'attributes:taxonomy',
						/* translators: %d: Attribute number */
						__( 'Attribute %d default', 'woocommerce' ) => 'attributes:default',
						/* translators: %d: Download number */
						__( 'Download %d ID', 'woocommerce' ) => 'downloads:id',
						/* translators: %d: Download number */
						__( 'Download %d name', 'woocommerce' ) => 'downloads:name',
						/* translators: %d: Download number */
						__( 'Download %d URL', 'woocommerce' ) => 'downloads:url',
						/* translators: %d: Meta number */
						__( 'Meta: %s', 'woocommerce' ) => 'meta:',
					),
					$raw_headers
				)
			)
		);

		$headers = array();
		foreach ( $raw_headers as $key => $field ) {
			$normalized_field  = strtolower( $field );
			$index             = $num_indexes ? $key : $field;
			$headers[ $index ] = $normalized_field;

			if ( isset( $default_columns[ $normalized_field ] ) ) {
				$headers[ $index ] = $default_columns[ $normalized_field ];
			} else {
				foreach ( $special_columns as $regex => $special_key ) {
					// Don't use the normalized field in the regex since meta might be case-sensitive.
					if ( preg_match( $regex, $field, $matches ) ) {
						$headers[ $index ] = $special_key . $matches[1];
						break;
					}
				}
			}
		}

		return apply_filters( 'woocommerce_csv_product_import_mapped_columns', $headers, $raw_headers );
	}

	/**
	 * Map columns using the user's latest import mappings.
	 *
	 * @param  array $headers Header columns.
	 * @return array
	 */
	public function auto_map_user_preferences( $headers ) {
		$mapping_preferences = get_user_option( 'woocommerce_product_import_mapping' );

		if ( ! empty( $mapping_preferences ) && is_array( $mapping_preferences ) ) {
			return $mapping_preferences;
		}

		return $headers;
	}

	/**
	 * Sanitize special column name regex.
	 *
	 * @param  string $value Raw special column name.
	 * @return string
	 */
	protected function sanitize_special_column_name_regex( $value ) {
		return '/' . str_replace( array( '%d', '%s' ), '(.*)', trim( quotemeta( $value ) ) ) . '/i';
	}

	/**
	 * Get special columns.
	 *
	 * @param  array $columns Raw special columns.
	 * @return array
	 */
	protected function get_special_columns( $columns ) {
		$formatted = array();

		foreach ( $columns as $key => $value ) {
			$regex = $this->sanitize_special_column_name_regex( $key );

			$formatted[ $regex ] = $value;
		}

		return $formatted;
	}

	/**
	 * Get mapping options.
	 *
	 * @param  string $item Item name.
	 * @return array
	 */
	protected function get_mapping_options( $item = '' ) {
		// Get index for special column names.
		$index = $item;

		if ( preg_match( '/\d+/', $item, $matches ) ) {
			$index = $matches[0];
		}

		// Properly format for meta field.
		$meta = str_replace( 'meta:', '', $item );

		// Available options.
		$weight_unit_label    = I18nUtil::get_weight_unit_label( get_option( 'woocommerce_weight_unit', 'kg' ) );
		$dimension_unit_label = I18nUtil::get_dimensions_unit_label( get_option( 'woocommerce_dimension_unit', 'cm' ) );
		$options              = array(
			'id'                 => __( 'ID', 'woocommerce' ),
			'type'               => __( 'Type', 'woocommerce' ),
			'sku'                => __( 'SKU', 'woocommerce' ),
			'global_unique_id'   => __( 'GTIN, UPC, EAN, or ISBN', 'woocommerce' ),
			'name'               => __( 'Name', 'woocommerce' ),
			'published'          => __( 'Published', 'woocommerce' ),
			'featured'           => __( 'Is featured?', 'woocommerce' ),
			'catalog_visibility' => __( 'Visibility in catalog', 'woocommerce' ),
			'short_description'  => __( 'Short description', 'woocommerce' ),
			'description'        => __( 'Description', 'woocommerce' ),
			'price'              => array(
				'name'    => __( 'Price', 'woocommerce' ),
				'options' => array(
					'regular_price'     => __( 'Regular price', 'woocommerce' ),
					'sale_price'        => __( 'Sale price', 'woocommerce' ),
					'date_on_sale_from' => __( 'Date sale price starts', 'woocommerce' ),
					'date_on_sale_to'   => __( 'Date sale price ends', 'woocommerce' ),
				),
			),
			'tax_status'         => __( 'Tax status', 'woocommerce' ),
			'tax_class'          => __( 'Tax class', 'woocommerce' ),
			'stock_status'       => __( 'In stock?', 'woocommerce' ),
			'stock_quantity'     => _x( 'Stock', 'Quantity in stock', 'woocommerce' ),
			'backorders'         => __( 'Backorders allowed?', 'woocommerce' ),
			'low_stock_amount'   => __( 'Low stock amount', 'woocommerce' ),
			'sold_individually'  => __( 'Sold individually?', 'woocommerce' ),
			/* translators: %s: weight unit */
			'weight'             => sprintf( __( 'Weight (%s)', 'woocommerce' ), $weight_unit_label ),
			'dimensions'         => array(
				'name'    => __( 'Dimensions', 'woocommerce' ),
				'options' => array(
					/* translators: %s: dimension unit */
					'length' => sprintf( __( 'Length (%s)', 'woocommerce' ), $dimension_unit_label ),
					/* translators: %s: dimension unit */
					'width'  => sprintf( __( 'Width (%s)', 'woocommerce' ), $dimension_unit_label ),
					/* translators: %s: dimension unit */
					'height' => sprintf( __( 'Height (%s)', 'woocommerce' ), $dimension_unit_label ),
				),
			),
			'category_ids'       => __( 'Categories', 'woocommerce' ),
			'tag_ids'            => __( 'Tags (comma separated)', 'woocommerce' ),
			'tag_ids_spaces'     => __( 'Tags (space separated)', 'woocommerce' ),
			'shipping_class_id'  => __( 'Shipping class', 'woocommerce' ),
			'images'             => __( 'Images', 'woocommerce' ),
			'parent_id'          => __( 'Parent', 'woocommerce' ),
			'upsell_ids'         => __( 'Upsells', 'woocommerce' ),
			'cross_sell_ids'     => __( 'Cross-sells', 'woocommerce' ),
			'grouped_products'   => __( 'Grouped products', 'woocommerce' ),
			'external'           => array(
				'name'    => __( 'External product', 'woocommerce' ),
				'options' => array(
					'product_url' => __( 'External URL', 'woocommerce' ),
					'button_text' => __( 'Button text', 'woocommerce' ),
				),
			),
			'downloads'          => array(
				'name'    => __( 'Downloads', 'woocommerce' ),
				'options' => array(
					'downloads:id' . $index   => __( 'Download ID', 'woocommerce' ),
					'downloads:name' . $index => __( 'Download name', 'woocommerce' ),
					'downloads:url' . $index  => __( 'Download URL', 'woocommerce' ),
					'download_limit'          => __( 'Download limit', 'woocommerce' ),
					'download_expiry'         => __( 'Download expiry days', 'woocommerce' ),
				),
			),
			'attributes'         => array(
				'name'    => __( 'Attributes', 'woocommerce' ),
				'options' => array(
					'attributes:name' . $index     => __( 'Attribute name', 'woocommerce' ),
					'attributes:value' . $index    => __( 'Attribute value(s)', 'woocommerce' ),
					'attributes:taxonomy' . $index => __( 'Is a global attribute?', 'woocommerce' ),
					'attributes:visible' . $index  => __( 'Attribute visibility', 'woocommerce' ),
					'attributes:default' . $index  => __( 'Default attribute', 'woocommerce' ),
				),
			),
			'reviews_allowed'    => __( 'Allow customer reviews?', 'woocommerce' ),
			'purchase_note'      => __( 'Purchase note', 'woocommerce' ),
			'meta:' . $meta      => __( 'Import as meta data', 'woocommerce' ),
			'menu_order'         => __( 'Position', 'woocommerce' ),
		);

		if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() ) {
			$options['cogs_value'] = __( 'Cost of goods', 'woocommerce' );
		}

		return apply_filters( 'woocommerce_csv_product_import_mapping_options', $options, $item );
	}
}
PK     Td\r7  7    reports.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class WOOMULTI_CURRENCY_Admin_Reports
 */
class WOOMULTI_CURRENCY_F_Admin_Reports {
	protected $settings;
	protected $currencies;
	protected $currency;
	protected $results;
	protected $chart_interval;
	protected $where_meta;
	protected $total_sales;
	protected $order_items;
	protected $current_range;
	protected $default_currency;
	protected $is_dashboard;

	function __construct() {
		$this->settings     = WOOMULTI_CURRENCY_F_Data::get_ins();
		$this->is_dashboard = false;
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
		add_filter( 'woocommerce_reports_get_order_report_data_args', array( $this, 'report_by_currency' ) );
		add_filter( 'woocommerce_reports_get_order_report_data', array(
			$this,
			'woocommerce_reports_get_order_report_data_for_dashboard'
		), 10, 2 );
		add_filter( 'woocommerce_currency', array( $this, 'woocommerce_currency' ), 99 );
		add_filter( 'wc_get_price_decimals', array( $this, 'wc_get_price_decimals' ), 99 );
		$this->default_currency = $this->settings->get_default_currency();
		$this->currencies       = $this->settings->get_list_currencies();
	}

	/**Get current range to recalculate report data
	 * @return string
	 */
	public function get_current_range() {
		if ( isset( $_REQUEST['_woo_multi_currency_nonce'] ) && ! wp_verify_nonce( sanitize_text_field( $_REQUEST['_woo_multi_currency_nonce'] ), 'woo_multi_currency_reports' ) ) {
			return '7day';
		}
		if ( $this->current_range === null ) {
			$this->current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day';
			if ( ! in_array( $this->current_range, array(
				'custom',
				'year',
				'last_month',
				'month',
				'7day'
			), true ) ) {
				$this->current_range = '7day';
			}
		}

		return $this->current_range;
	}

	public function admin_enqueue_scripts() {
		if ( isset( $_REQUEST['_woo_multi_currency_nonce'] ) && ! wp_verify_nonce( sanitize_text_field( $_REQUEST['_woo_multi_currency_nonce'] ), 'woo_multi_currency_reports' ) ) {
			return;
		}
		$screen    = get_current_screen();
		$screen_id = $screen ? $screen->id : '';
		if ( 'woocommerce_page_wc-reports' == $screen_id ) {
			$tab          = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'orders';
			$report       = isset( $_GET['report'] ) ? sanitize_text_field( wp_unslash( $_GET['report'] ) ) : '';
			$currency     = isset( $_GET['wmc-currency'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_GET['wmc-currency'] ) ) ) : '';
			$view_default = isset( $_GET['wmc-view-default-currency'] ) ? sanitize_text_field( wp_unslash( $_GET['wmc-view-default-currency'] ) ) : '';
			if ( ( $tab === 'orders' && $report !== 'coupon_usage' ) || ( $tab === 'customers' && $report === 'customers' ) ) {
				$src_min = WP_DEBUG ? '' : '.min';
				wp_enqueue_style( 'woocommerce-multi-currency-admin-reports', WOOMULTI_CURRENCY_F_CSS . 'reports' . $src_min . '.css', '', WOOMULTI_CURRENCY_F_VERSION );
				wp_enqueue_script( 'woocommerce-multi-currency-admin-reports', WOOMULTI_CURRENCY_F_JS . 'reports' . $src_min . '.js', array( 'jquery' ), WOOMULTI_CURRENCY_F_VERSION, false );
				wp_localize_script( 'woocommerce-multi-currency-admin-reports', 'woocommerce_multi_currency_admin_reports', array(
					'currency' => $currency ? $currency : 'all-currencies'
				) );
				add_action( 'admin_footer', array( $this, 'admin_footer' ) );
			}
			if ( ! $currency ) {
				if ( $tab === 'orders' ) {
					if ( ! $report || $report === 'sales_by_date' ) {
						add_filter( 'woocommerce_reports_get_order_report_data_args', array(
							$this,
							'add_return_order_id'
						) );
						add_filter( 'woocommerce_reports_get_order_report_data', array(
							$this,
							'woocommerce_reports_get_order_report_data_1'
						), 10, 2 );
					} elseif ( $report === 'sales_by_product' && ! empty( $_REQUEST['product_ids'] ) ) {
						include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-admin-report.php' );
						include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-report-sales-by-product.php' );
						$current_range = $this->get_current_range();
						$results       = array();
						if ( count( $this->currencies ) ) {
							foreach ( $this->currencies as $currency_code => $currency_data ) {
								$this->currency = $currency_code;
								add_filter( 'woocommerce_reports_get_order_report_data_args', array(
									$this,
									'report_by_currency_for_all'
								) );
								$report = new WC_Report_Sales_By_Product();
								$report->check_current_range_nonce( $current_range );
								$report->calculate_current_range( $current_range );
								$total_sales = $report->get_order_report_data(
									array(
										'data'         => array(
											'_line_total' => array(
												'type'            => 'order_item_meta',
												'order_item_type' => 'line_item',
												'function'        => 'SUM',
												'name'            => 'order_item_amount',
											),
										),
										'where_meta'   => array(
											'relation' => 'OR',
											array(
												'type'       => 'order_item_meta',
												'meta_key'   => array( '_product_id', '_variation_id' ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
												'meta_value' => $report->product_ids, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
												'operator'   => 'IN',
											),
										),
										'query_type'   => 'get_var',
										'filter_range' => true,
										'order_status' => array( 'completed', 'processing', 'on-hold', 'refunded' ),
									)
								);

								$results[] = self::convert_to_default_currency( $total_sales, $currency_data['rate'] );
								remove_filter( 'woocommerce_reports_get_order_report_data_args', array(
									$this,
									'report_by_currency_for_all'
								) );
							}
						}
						add_filter( 'woocommerce_reports_get_order_report_data', array(
							$this,
							'woocommerce_reports_get_order_report_data'
						), 10, 2 );
						$this->total_sales = array_sum( $results );
					} elseif ( $report === 'sales_by_category' && ! empty( $_GET['show_categories'] ) ) {
						include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-admin-report.php' );
						include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-report-sales-by-category.php' );
						$current_range = $this->get_current_range();
						$results       = array();
						if ( count( $this->currencies ) ) {
							foreach ( $this->currencies as $currency_code => $currency_data ) {
								$this->currency = $currency_code;
								add_filter( 'woocommerce_reports_get_order_report_data_args', array(
									$this,
									'report_by_currency_for_all'
								) );
								$report = new WC_Report_Sales_By_Category();
								$report->check_current_range_nonce( $current_range );
								$report->calculate_current_range( $current_range );
								$order_items = $report->get_order_report_data(
									array(
										'data'         => array(
											'_product_id' => array(
												'type'            => 'order_item_meta',
												'order_item_type' => 'line_item',
												'function'        => '',
												'name'            => 'product_id',
											),
											'_line_total' => array(
												'type'            => 'order_item_meta',
												'order_item_type' => 'line_item',
												'function'        => 'SUM',
												'name'            => 'order_item_amount',
											),
											'post_date'   => array(
												'type'     => 'post_data',
												'function' => '',
												'name'     => 'post_date',
											),
										),
										'group_by'     => 'ID, product_id, post_date',
										'query_type'   => 'get_results',
										'filter_range' => true,
									)
								);
								if ( is_array( $order_items ) && count( $order_items ) ) {
									foreach ( $order_items as $order_item ) {
										$order_item->order_item_amount = self::convert_to_default_currency( $order_item->order_item_amount, $currency_data['rate'] );
									}
								}
								$results = array_merge( $results, $order_items );
								remove_filter( 'woocommerce_reports_get_order_report_data_args', array(
									$this,
									'report_by_currency_for_all'
								) );
							}
						}
						add_filter( 'woocommerce_reports_get_order_report_data', array(
							$this,
							'woocommerce_reports_get_order_report_data'
						), 10, 2 );
						$this->order_items = $results;
					}
				}
			} elseif ( $view_default === 'yes' && $this->default_currency !== $currency ) {
				if ( ! $report || $report === 'sales_by_date' ) {
					$this->currency = $currency;
					if ( isset( $this->currencies[ $this->currency ] ) ) {
						include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-admin-report.php' );
						include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-report-sales-by-date.php' );
						$current_range = $this->get_current_range();
						$results       = array();
						add_filter( 'woocommerce_reports_get_order_report_data_args', array(
							$this,
							'report_by_currency_for_all'
						) );
						$report = new WC_Report_Sales_By_Date();
						$report->check_current_range_nonce( $current_range );
						$report->calculate_current_range( $current_range );
						$result               = $report->get_report_data();
						$this->chart_interval = $report->chart_interval;
						if ( isset( $result->orders ) && is_array( $result->orders ) && count( $result->orders ) ) {
							foreach ( $result->orders as $order ) {
								$order->total_sales        = self::convert_to_default_currency( $order->total_sales, $this->currencies[ $this->currency ]['rate'] );
								$order->total_shipping     = self::convert_to_default_currency( $order->total_shipping, $this->currencies[ $this->currency ]['rate'] );
								$order->total_tax          = self::convert_to_default_currency( $order->total_tax, $this->currencies[ $this->currency ]['rate'] );
								$order->total_shipping_tax = self::convert_to_default_currency( $order->total_shipping_tax, $this->currencies[ $this->currency ]['rate'] );
							}
						}
						if ( isset( $result->refunded_orders ) && is_array( $result->refunded_orders ) && count( $result->refunded_orders ) ) {
							foreach ( $result->refunded_orders as $refunded_orders ) {
								$refunded_orders->total_refund       = self::convert_to_default_currency( $refunded_orders->total_refund, $this->currencies[ $this->currency ]['rate'] );
								$refunded_orders->total_shipping     = self::convert_to_default_currency( $refunded_orders->total_shipping, $this->currencies[ $this->currency ]['rate'] );
								$refunded_orders->total_tax          = self::convert_to_default_currency( $refunded_orders->total_tax, $this->currencies[ $this->currency ]['rate'] );
								$refunded_orders->total_shipping_tax = self::convert_to_default_currency( $refunded_orders->total_shipping_tax, $this->currencies[ $this->currency ]['rate'] );
								$refunded_orders->net_refund         = self::convert_to_default_currency( $refunded_orders->net_refund, $this->currencies[ $this->currency ]['rate'] );
							}
						}
						if ( isset( $result->refund_lines ) && is_array( $result->refund_lines ) && count( $result->refund_lines ) ) {
							foreach ( $result->refund_lines as $refund_lines ) {
								$refund_lines->total_refund       = self::convert_to_default_currency( $refund_lines->total_refund, $this->currencies[ $this->currency ]['rate'] );
								$refund_lines->total_shipping     = self::convert_to_default_currency( $refund_lines->total_shipping, $this->currencies[ $this->currency ]['rate'] );
								$refund_lines->total_tax          = self::convert_to_default_currency( $refund_lines->total_tax, $this->currencies[ $this->currency ]['rate'] );
								$refund_lines->total_shipping_tax = self::convert_to_default_currency( $refund_lines->total_shipping_tax, $this->currencies[ $this->currency ]['rate'] );
								$refund_lines->total_sales        = self::convert_to_default_currency( $refund_lines->total_sales, $this->currencies[ $this->currency ]['rate'] );
							}
						}
						$result->total_tax                   = self::convert_to_default_currency( $result->total_tax, $this->currencies[ $this->currency ]['rate'] );
						$result->total_shipping              = self::convert_to_default_currency( $result->total_shipping, $this->currencies[ $this->currency ]['rate'] );
						$result->total_shipping_tax          = self::convert_to_default_currency( $result->total_shipping_tax, $this->currencies[ $this->currency ]['rate'] );
						$result->total_sales                 = self::convert_to_default_currency( $result->total_sales, $this->currencies[ $this->currency ]['rate'] );
						$result->net_sales                   = self::convert_to_default_currency( $result->net_sales, $this->currencies[ $this->currency ]['rate'] );
						$result->total_tax_refunded          = self::convert_to_default_currency( $result->total_tax_refunded, $this->currencies[ $this->currency ]['rate'] );
						$result->total_shipping_refunded     = self::convert_to_default_currency( $result->total_shipping_refunded, $this->currencies[ $this->currency ]['rate'] );
						$result->total_shipping_tax_refunded = self::convert_to_default_currency( $result->total_shipping_tax_refunded, $this->currencies[ $this->currency ]['rate'] );
						$result->total_refunds               = self::convert_to_default_currency( $result->total_refunds, $this->currencies[ $this->currency ]['rate'] );
						$results[]                           = $result;
						remove_filter( 'woocommerce_reports_get_order_report_data_args', array(
							$this,
							'report_by_currency_for_all'
						) );
						add_filter( 'woocommerce_admin_report_data', array( $this, 'woocommerce_admin_report_data' ) );
						$this->results = $results;
					}
				} elseif ( $report === 'sales_by_product' && ! empty( $_REQUEST['product_ids'] ) ) {
					$this->currency = $currency;
					if ( isset( $this->currencies[ $this->currency ] ) ) {
						include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-admin-report.php' );
						include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-report-sales-by-product.php' );
						$current_range = $this->get_current_range();
						add_filter( 'woocommerce_reports_get_order_report_data_args', array(
							$this,
							'report_by_currency_for_all'
						) );
						$report = new WC_Report_Sales_By_Product();
						$report->check_current_range_nonce( $current_range );
						$report->calculate_current_range( $current_range );
						$total_sales = $report->get_order_report_data(
							array(
								'data'         => array(
									'_line_total' => array(
										'type'            => 'order_item_meta',
										'order_item_type' => 'line_item',
										'function'        => 'SUM',
										'name'            => 'order_item_amount',
									),
								),
								'where_meta'   => array(
									'relation' => 'OR',
									array(
										'type'       => 'order_item_meta',
										'meta_key'   => array( '_product_id', '_variation_id' ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
										'meta_value' => $report->product_ids, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
										'operator'   => 'IN',
									),
								),
								'query_type'   => 'get_var',
								'filter_range' => true,
								'order_status' => array( 'completed', 'processing', 'on-hold', 'refunded' ),
							)
						);
						remove_filter( 'woocommerce_reports_get_order_report_data_args', array(
							$this,
							'report_by_currency_for_all'
						) );
						add_filter( 'woocommerce_reports_get_order_report_data', array(
							$this,
							'woocommerce_reports_get_order_report_data'
						), 10, 2 );
						$this->total_sales = self::convert_to_default_currency( $total_sales, $this->currencies[ $this->currency ]['rate'] );
					}
				} elseif ( $report === 'sales_by_category' && ! empty( $_GET['show_categories'] ) ) {
					$this->currency = $currency;
					if ( isset( $this->currencies[ $this->currency ] ) ) {
						include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-admin-report.php' );
						include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-report-sales-by-category.php' );
						$current_range = $this->get_current_range();
						add_filter( 'woocommerce_reports_get_order_report_data_args', array(
							$this,
							'report_by_currency_for_all'
						) );
						$report = new WC_Report_Sales_By_Category();
						$report->check_current_range_nonce( $current_range );
						$report->calculate_current_range( $current_range );
						$order_items = $report->get_order_report_data(
							array(
								'data'         => array(
									'_product_id' => array(
										'type'            => 'order_item_meta',
										'order_item_type' => 'line_item',
										'function'        => '',
										'name'            => 'product_id',
									),
									'_line_total' => array(
										'type'            => 'order_item_meta',
										'order_item_type' => 'line_item',
										'function'        => 'SUM',
										'name'            => 'order_item_amount',
									),
									'post_date'   => array(
										'type'     => 'post_data',
										'function' => '',
										'name'     => 'post_date',
									),
								),
								'group_by'     => 'ID, product_id, post_date',
								'query_type'   => 'get_results',
								'filter_range' => true,
							)
						);

						if ( is_array( $order_items ) && count( $order_items ) ) {
							foreach ( $order_items as $order_item ) {
								$order_item->order_item_amount = self::convert_to_default_currency( $order_item->order_item_amount, $this->currencies[ $this->currency ]['rate'] );
							}

							$this->order_items = $order_items;
							add_filter( 'woocommerce_reports_get_order_report_data', array(
								$this,
								'woocommerce_reports_get_order_report_data'
							), 10, 2 );
						}
						remove_filter( 'woocommerce_reports_get_order_report_data_args', array(
							$this,
							'report_by_currency_for_all'
						) );
					}
				}
			}
		}
	}

	/**
	 * @param $price
	 * @param $rate
	 *
	 * @return float|int
	 */
	public static function convert_to_default_currency( $price, $rate ) {
		return floatval( $price ) / floatval( $rate );
	}

	/**
	 *
	 */
	public function admin_footer() {
		if ( isset( $_REQUEST['_woo_multi_currency_nonce'] ) && ! wp_verify_nonce( sanitize_text_field( $_REQUEST['_woo_multi_currency_nonce'] ), 'woo_multi_currency_reports' ) ) {
			return;
		}
		$currency          = isset( $_GET['wmc-currency'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_GET['wmc-currency'] ) ) ) : '';
		$view_default      = isset( $_GET['wmc-view-default-currency'] ) ? sanitize_text_field( wp_unslash( $_GET['wmc-view-default-currency'] ) ) : '';
		$request_uri       = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
		$view_default_link = $view_default === 'yes' ? remove_query_arg( 'wmc-view-default-currency', $request_uri ) : add_query_arg( array( 'wmc-view-default-currency' => 'yes' ), $request_uri );
		$links             = $this->settings->get_links();
		$currency_name     = get_woocommerce_currencies();
		?>
        <li class="wmc-reports-currency-selector">
            <div class="woocommerce-multi-currency shortcode">
                <div class="wmc-currency">
                    <select class="wmc-nav"
                            onchange="this.options[this.selectedIndex].value && (window.location = this.options[this.selectedIndex].value);">
                        <option value="<?php echo esc_url( remove_query_arg( 'wmc-currency', $request_uri ) ) ?>"><?php esc_html_e( 'All currencies', 'woo-multi-currency' ) ?></option>
						<?php
						foreach ( $links as $code => $link ) {
							?>
                            <option <?php selected( $currency, $code ) ?>
                                    value="<?php echo esc_url( $link ) ?>"><?php echo esc_html( $currency_name[ $code ] ) ?></option>
							<?php
						}
						?>
                    </select>
                </div>
            </div>
        </li>
		<?php
		if ( $currency && $currency !== $this->default_currency ) {
			?>
            <li class="wmc-view-default-currency-container">
                <input id="wmc-view-default-currency" type="checkbox"
                       value="yes" <?php checked( $view_default, 'yes' ) ?>
                       data-report_link="<?php echo esc_url( $view_default_link ) ?>"><label
                        for="wmc-view-default-currency"><?php esc_html_e( 'View in default currency', 'woo-multi-currency' ) ?></label>
            </li>
			<?php
		}
	}

	/**Filter orders by each currency
	 *
	 * @param $args
	 *
	 * @return mixed
	 */
	public function report_by_currency_for_all( $args ) {
		$args['where_meta'][]           = array(
			'meta_key'   => '_order_currency',// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
			'meta_value' => $this->currency,// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
			'operator'   => '=',
		);
		$args['where_meta']['relation'] = 'AND';

		$args['nocache'] = true;

		return $args;
	}

	public function add_return_order_id( $args ) {
		if ( ! isset( $args['data']['ID'] ) ) {
			if ( ! empty( $args['data']['_order_total'] ) ) {
				$args['data']['ID']                       = array(
					'type'     => 'post_data',
					'function' => '',
					'name'     => 'order_id',
				);
				$args['group_by']                         = 'order_id';
				$args['data']['_order_total']['function'] = '';
			} elseif ( ! empty( $args['data']['_line_total'] ) ) {
				$args['data']['ID']                      = array(
					'type'     => 'post_data',
					'function' => '',
					'name'     => 'order_id',
				);
				$args['group_by']                        = 'order_id';
				$args['data']['_line_total']['function'] = '';
			}

		}
		$args['nocache'] = true;

		return $args;
	}

	/**Convert to default currency for WooCommerce Status in WP dashboard
	 *
	 * @param $result
	 * @param $data
	 *
	 * @return mixed
	 */
	public function woocommerce_reports_get_order_report_data_for_dashboard( $result, $data ) {
		if ( $this->is_dashboard ) {
			if ( count( array_keys( $data ) ) === 3 && count( array_intersect( array_keys( $data ), array(
					'_order_total',
					'post_date',
					'ID'
				) ) ) === 3 ) {
				if ( is_array( $result ) && count( $result ) ) {
					foreach ( $result as $key => $value ) {
						$order_id        = $value->order_id;
						$line_product    = wc_get_order( $order_id );
						$_order_currency = $line_product->get_meta('_order_currency', true );
						$wmc_order_info  = $line_product->get_meta('wmc_order_info', true );
						$rate            = 0;
						if ( isset( $wmc_order_info[ $this->default_currency ] ) && isset( $wmc_order_info[ $this->default_currency ]['is_main'] ) && $wmc_order_info[ $this->default_currency ]['is_main'] == 1 ) {
							if ( isset( $wmc_order_info[ $_order_currency ] ) ) {
								$rate = $wmc_order_info[ $_order_currency ]['rate'];
							}
							if ( isset( $this->currencies[ $_order_currency ] ) ) {
								$rate = $this->currencies[ $_order_currency ]['rate'];
							}

						} elseif ( isset( $this->currencies[ $_order_currency ] ) ) {
							$rate = $this->currencies[ $_order_currency ]['rate'];
						}
						if ( $rate > 0 ) {
							$value->sparkline_value = self::convert_to_default_currency( $value->sparkline_value, $rate );
						}
					}
				}
			} else {
				$result = $this->woocommerce_reports_get_order_report_data_1( $result, $data );
			}
			$this->is_dashboard = false;
		}

		return $result;
	}

	/**
	 * @param $result
	 * @param $data
	 *
	 * @return mixed
	 */
	public function woocommerce_reports_get_order_report_data_1( $result, $data ) {
		if ( isset( $data['ID'] ) && ( ! empty( $data['_order_total'] ) || ! empty( $data['_line_total'] ) ) ) {
			foreach ( $result as $data_k => $data_obj ) {
				$order_id = isset( $data_obj->order_id ) ? $data_obj->order_id : ( isset( $data_obj->refund_id ) ? $data_obj->refund_id : '' );
				if ( $order_id ) {
				    $line_order = wc_get_order( $order_id );
					$_order_currency = $line_order->get_meta('_order_currency', true );
					if ( $this->default_currency !== $_order_currency ) {
						$wmc_order_info = $line_order->get_meta('wmc_order_info', true );
						$rate           = 0;
						if ( isset( $wmc_order_info[ $this->default_currency ] ) && isset( $wmc_order_info[ $this->default_currency ]['is_main'] ) && $wmc_order_info[ $this->default_currency ]['is_main'] == 1 ) {
							if ( isset( $wmc_order_info[ $_order_currency ] ) ) {
								$rate = $wmc_order_info[ $_order_currency ]['rate'];
							}
							if ( isset( $this->currencies[ $_order_currency ] ) ) {
								$rate = $this->currencies[ $_order_currency ]['rate'];
							}

						} elseif ( isset( $this->currencies[ $_order_currency ] ) ) {
							$rate = $this->currencies[ $_order_currency ]['rate'];
						}
						if ( $rate > 0 ) {
							foreach ( $data_obj as $data_obj_k => $data_obj_v ) {
								if ( ! in_array( $data_obj_k, array( 'post_date', 'order_id', 'refund_id' ) ) ) {
									$data_obj->{$data_obj_k} = self::convert_to_default_currency( $data_obj_v, $rate );
								}
							}
						}
					}
				}
			}
		}

		return $result;
	}

	/**
	 * @param $result
	 * @param $data
	 *
	 * @return mixed
	 */
	public function woocommerce_reports_get_order_report_data( $result, $data ) {
		if ( isset( $data['_line_total'] ) ) {
			if ( $this->total_sales !== null && ! is_array( $result ) ) {
				$result = $this->total_sales;
			} elseif ( $this->order_items !== null && is_array( $result ) ) {
				$result = $this->order_items;
			}
		}

		return $result;
	}

	/**Recalculate report data after converting all to default currency
	 *
	 * @param $report_data
	 *
	 * @return mixed
	 */
	public function woocommerce_admin_report_data( $report_data ) {
		if ( is_array( $this->results ) && count( $this->results ) ) {
			$report_data->orders          = array();
			$report_data->refund_lines    = array();
			$report_data->refunded_orders = array();
			$report_data->full_refunds    = array();
			foreach ( $this->results as $result ) {
				if ( isset( $result->orders ) && is_array( $result->orders ) && count( $result->orders ) ) {
					$report_data->orders = array_merge( $report_data->orders, $result->orders );
				}
				if ( isset( $result->refund_lines ) && is_array( $result->refund_lines ) && count( $result->refund_lines ) ) {
					$report_data->refund_lines = array_merge( $report_data->refund_lines, $result->refund_lines );
				}
				if ( isset( $result->refunded_orders ) && is_array( $result->refunded_orders ) && count( $result->refunded_orders ) ) {
					$report_data->refunded_orders = array_merge( $report_data->refunded_orders, $result->refunded_orders );
				}
				if ( isset( $result->full_refunds ) && is_array( $result->full_refunds ) && count( $result->full_refunds ) ) {
					$report_data->full_refunds = array_merge( $report_data->full_refunds, $result->full_refunds );
				}
			}
			$report_data->total_tax_refunded          = 0;
			$report_data->total_shipping_refunded     = 0;
			$report_data->total_shipping_tax_refunded = 0;
			$report_data->total_refunds               = 0;

			$report_data->refunded_orders = array_merge( $report_data->partial_refunds, $report_data->full_refunds );

			foreach ( $report_data->refunded_orders as $key => $value ) {
				$report_data->total_tax_refunded          += floatval( $value->total_tax < 0 ? $value->total_tax * - 1 : $value->total_tax );
				$report_data->total_refunds               += floatval( $value->total_refund );
				$report_data->total_shipping_tax_refunded += floatval( $value->total_shipping_tax < 0 ? $value->total_shipping_tax * - 1 : $value->total_shipping_tax );
				$report_data->total_shipping_refunded     += floatval( $value->total_shipping < 0 ? $value->total_shipping * - 1 : $value->total_shipping );

				// Only applies to parial.
				if ( isset( $value->order_item_count ) ) {
					$report_data->refunded_order_items += floatval( $value->order_item_count < 0 ? $value->order_item_count * - 1 : $value->order_item_count );
				}
			}
			// Totals from all orders - including those refunded. Subtract refunded amounts.
			$report_data->total_tax          = wc_format_decimal( array_sum( wp_list_pluck( $report_data->orders, 'total_tax' ) ) - $report_data->total_tax_refunded, 2 );
			$report_data->total_shipping     = wc_format_decimal( array_sum( wp_list_pluck( $report_data->orders, 'total_shipping' ) ) - $report_data->total_shipping_refunded, 2 );
			$report_data->total_shipping_tax = wc_format_decimal( array_sum( wp_list_pluck( $report_data->orders, 'total_shipping_tax' ) ) - $report_data->total_shipping_tax_refunded, 2 );

			// Total the refunds and sales amounts. Sales subract refunds. Note - total_sales also includes shipping costs.
			$report_data->total_sales = wc_format_decimal( array_sum( wp_list_pluck( $report_data->orders, 'total_sales' ) ) - $report_data->total_refunds, 2 );
			$report_data->net_sales   = wc_format_decimal( $report_data->total_sales - $report_data->total_shipping - max( 0, $report_data->total_tax ) - max( 0, $report_data->total_shipping_tax ), 2 );

			// Calculate average based on net.
			$report_data->average_sales       = wc_format_decimal( $report_data->net_sales / ( $this->chart_interval + 1 ), 2 );
			$report_data->average_total_sales = wc_format_decimal( $report_data->total_sales / ( $this->chart_interval + 1 ), 2 );

			// Total orders and discounts also includes those which have been refunded at some point.
			$report_data->total_coupons         = number_format( array_sum( wp_list_pluck( $report_data->coupons, 'discount_amount' ) ), 2, '.', '' );
			$report_data->total_refunded_orders = absint( count( $report_data->full_refunds ) );

			// Total orders in this period, even if refunded.
			$report_data->total_orders = absint( array_sum( wp_list_pluck( $report_data->order_counts, 'count' ) ) );

			// Item items ordered in this period, even if refunded.
			$report_data->total_items = absint( array_sum( wp_list_pluck( $report_data->order_items, 'order_item_count' ) ) );
			$this->results            = array();
		}

		return $report_data;
	}

	/**Set price decimal for each currency for report
	 *
	 * @param $decimal
	 *
	 * @return int
	 */
	public function wc_get_price_decimals( $decimal ) {
		if ( isset( $_REQUEST['_woo_multi_currency_nonce'] ) && ! wp_verify_nonce( sanitize_text_field( $_REQUEST['_woo_multi_currency_nonce'] ), 'woo_multi_currency_reports' ) ) {
			return $decimal;
		}
		$view_default = isset( $_GET['wmc-view-default-currency'] ) ? sanitize_text_field( wp_unslash( $_GET['wmc-view-default-currency'] ) ) : '';
		if ( is_admin() && ! empty( $_GET['wmc-currency'] ) && $view_default !== 'yes' ) {
			$currency = strtoupper( sanitize_text_field( wp_unslash( $_GET['wmc-currency'] ) ) );
			if ( $currency !== $this->default_currency ) {
				$decimal = isset( $this->currencies[ $currency ]['decimals'] ) ? $this->currencies[ $currency ]['decimals'] : 0;
			}
		}

		return (int) $decimal;
	}

	/**Set currency for report
	 *
	 * @param $woocommerce_currency
	 *
	 * @return string
	 */
	public function woocommerce_currency( $woocommerce_currency ) {
		if ( isset( $_REQUEST['_woo_multi_currency_nonce'] ) && ! wp_verify_nonce( sanitize_text_field( $_REQUEST['_woo_multi_currency_nonce'] ), 'woo_multi_currency_reports' ) ) {
			return $woocommerce_currency;
		}
		$view_default = isset( $_GET['wmc-view-default-currency'] ) ? sanitize_text_field( wp_unslash( $_GET['wmc-view-default-currency'] ) ) : '';
		$currency     = isset( $_GET['wmc-currency'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_GET['wmc-currency'] ) ) ) : '';
		if ( is_admin() && ! empty( $_GET['wmc-currency'] ) && $view_default !== 'yes' ) {
			if ( $currency !== $this->default_currency ) {
				$woocommerce_currency = $currency;
			}
		}

		return $woocommerce_currency;
	}

	/**Filter orders by selected currency
	 *
	 * @param $args
	 *
	 * @return mixed
	 */
	public function report_by_currency( $args ) {
		if ( isset( $_REQUEST['_woo_multi_currency_nonce'] ) && ! wp_verify_nonce( sanitize_text_field( $_REQUEST['_woo_multi_currency_nonce'] ), 'woo_multi_currency_reports' ) ) {
			return $args;
		}
		global $pagenow;
		if ( $pagenow === 'index.php' ) {
			/**
			 * For WooCommerce Status in WP dashboard
			 */
			if ( ( ! empty( $args['data']['_order_total'] ) || ( ! empty( $args['data']['_product_id'] ) && ! empty( $args['data']['_line_total'] ) ) ) && empty( $args['data']['ID'] ) ) {
				$args['data']['ID'] = array(
					'type'     => 'post_data',
					'function' => '',
					'name'     => 'order_id',
				);
				$args['group_by']   = 'order_id';
				$args['nocache']    = true;
				$this->is_dashboard = true;
			}
		} else {
			$report   = isset( $_GET['report'] ) ? sanitize_text_field( wp_unslash( $_GET['report'] ) ) : '';
			$tab      = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'orders';
			$currency = isset( $_GET['wmc-currency'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_GET['wmc-currency'] ) ) ) : '';
			if ( $currency ) {
				if ( $currency !== $this->default_currency ) {
					$args['nocache'] = true;
				}
				if ( ( $tab === 'orders' && $report !== 'coupon_usage' ) || ( $tab === 'customers' && $report === 'customers' ) ) {
					$args['where_meta'][]           = array(
						'meta_key'   => '_order_currency',// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
						'meta_value' => $currency,// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
						'operator'   => '=',
					);
					$args['where_meta']['relation'] = 'AND';
				}
			}
		}

		return $args;
	}
}PK     Td\CeVR;  ;    analytics.phpnu [        <?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class WOOMULTI_CURRENCY_F_Admin_Analytics
 */
class WOOMULTI_CURRENCY_F_Admin_Analytics {
	protected $settings;
	protected $args;
	protected $default_currency;

	public function __construct() {
		$this->settings = WOOMULTI_CURRENCY_F_Data::get_ins();
		$this->default_currency = $this->settings->get_default_currency();
		/*Orders*/
//		add_filter( 'woocommerce_analytics_orders_select_query', array(
//			$this,
//			'woocommerce_analytics_orders_select_query'
//		) );
//		/*Orders stats*/
//		add_filter( 'woocommerce_analytics_orders_stats_query_args', array(
//			$this,
//			'woocommerce_analytics_query_args'
//		) );
//		add_filter( 'woocommerce_analytics_orders_stats_select_query', array(
//			$this,
//			'convert_orders_stats'
//		) );
//		/*Revenue*/
//		add_filter( 'woocommerce_analytics_revenue_query_args', array(
//			$this,
//			'woocommerce_analytics_query_args'
//		) );
//		add_filter( 'woocommerce_analytics_revenue_select_query', array(
//			$this,
//			'convert_orders_stats'
//		) );
//		/*Products*/
//		add_filter( 'woocommerce_analytics_products_query_args', array(
//			$this,
//			'woocommerce_analytics_query_args'
//		) );
//		add_filter( 'woocommerce_analytics_products_select_query', array(
//			$this,
//			'convert_orders_stats'
//		) );
//		/*Products stats*/
//		add_filter( 'woocommerce_analytics_products_stats_query_args', array(
//			$this,
//			'woocommerce_analytics_query_args'
//		) );
//		add_filter( 'woocommerce_analytics_products_stats_select_query', array(
//			$this,
//			'convert_orders_stats'
//		) );
//		/*Categories*/
//		add_filter( 'woocommerce_analytics_categories_query_args', array(
//			$this,
//			'woocommerce_analytics_query_args'
//		) );
//		add_filter( 'woocommerce_analytics_categories_select_query', array(
//			$this,
//			'convert_orders_stats'
//		) );

		add_filter( 'woocommerce_analytics_update_order_stats_data', [ $this, 'import_order_to_order_stats_table' ], 10, 2 );
		add_action( 'woocommerce_analytics_update_product', [ $this, 'import_order_product_to_order_product_lookup_table' ], 10, 2 );
		add_action( 'woocommerce_analytics_update_coupon', [ $this, 'import_order_coupon_to_order_coupon_lookup_table' ], 10, 2 );
		add_action( 'woocommerce_analytics_update_tax', [ $this, 'import_order_tax_to_order_tax_lookup_table' ], 10, 2 );
	}

	/**
	 * @param $order WC_Order
	 *
	 * @return float|int
	 */
	public function get_rate( $order ) {
		$order = $order->get_parent_id() ? wc_get_order( $order->get_parent_id() ) : $order;

		$rate             = 1;
		$order_id         = $order->get_id();
		$order_currency   = $order->get_currency();
		$default_currency = $this->default_currency;
		$order_info       = $order->get_meta('wmc_order_info', true );

		if ( isset( $order_info[ $order_currency ], $order_info[ $default_currency ], $order_info[ $default_currency ]['is_main'] )
		     && $order_info[ $default_currency ]['is_main'] == 1
		     && $order_info[ $order_currency ]['rate'] > 0 ) {

			$rate = floatval( $order_info[ $order_currency ]['rate'] );
		}

		return $rate;
	}

	public function import_order_to_order_stats_table( $order_data, $order ) {
		$rate = $this->get_rate( $order );

		if ( $rate && $rate != 1 ) {
			$order_data['total_sales']    = $order_data['total_sales'] / $rate;
			$order_data['tax_total']      = $order_data['tax_total'] / $rate;
			$order_data['shipping_total'] = $order_data['shipping_total'] / $rate;
			$order_data['net_total']      = $order_data['net_total'] / $rate;
		}

		return $order_data;
	}

	public function import_order_product_to_order_product_lookup_table( $order_item_id, $order_id ) {
		global $wpdb;
		$table_name = $wpdb->prefix . 'wc_order_product_lookup';
		$order      = wc_get_order( $order_id );
		$rate       = $this->get_rate( $order );

		if ( $rate && $rate != 1 ) {
			$items      = $order->get_items();
			$order_item = $items[ $order_item_id ];
			$decimals   = wc_get_price_decimals();
			$round_tax  = 'no' === get_option( 'woocommerce_tax_round_at_subtotal' );

			// Tax amount.
			$tax_amount  = 0;
			$order_taxes = $order->get_taxes();
			$tax_data    = $order_item->get_taxes();
			foreach ( $order_taxes as $tax_item ) {
				$tax_item_id = $tax_item->get_rate_id();
				$tax_amount  += isset( $tax_data['total'][ $tax_item_id ] ) ? (float) $tax_data['total'][ $tax_item_id ] : 0;
			}

			$net_revenue = round( $order_item->get_total( 'edit' ) / $rate, $decimals );

			if ( $round_tax ) {
				$tax_amount = round( $tax_amount, $decimals );
			}

			$tax_amount          = $tax_amount / $rate;
			$coupon_amount       = $order->get_item_coupon_amount( $order_item ) / $rate;
			$shipping_amount     = $order->get_item_shipping_amount( $order_item ) / $rate;
			$shipping_tax_amount = $order->get_item_shipping_tax_amount( $order_item ) / $rate;

			$wpdb->update( $table_name,// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				[
					'product_net_revenue'   => $net_revenue,
					'coupon_amount'         => $coupon_amount,
					'tax_amount'            => $tax_amount,
					'shipping_amount'       => $shipping_amount,
					'shipping_tax_amount'   => $shipping_tax_amount,
					'product_gross_revenue' => $net_revenue + $tax_amount + $shipping_amount + $shipping_tax_amount,
				],
				[ 'order_item_id' => $order_item_id ],
				[
					'%f', // product_net_revenue.
					'%f', // coupon_amount.
					'%f', // tax_amount.
					'%f', // shipping_amount.
					'%f', // shipping_tax_amount.
					'%f', // product_gross_revenue.
				]
			);
		}
	}

	public function import_order_coupon_to_order_coupon_lookup_table( $coupon_id, $order_id ) {
		global $wpdb;
		$table_name = $wpdb->prefix . 'wc_order_coupon_lookup';
		$order      = wc_get_order( $order_id );
		$rate       = $this->get_rate( $order );

		if ( $rate && $rate != 1 ) {
			$coupon_items    = $order->get_items( 'coupon' );
			$discount_amount = 0;

			foreach ( $coupon_items as $coupon_item ) {
				$c_data = $coupon_item->get_meta( 'coupon_data', true );
				$c_id   = $c_data['id'] ?? wc_get_coupon_id_by_code( $coupon_item->get_code() );
				if ( $c_id == $coupon_id ) {
					$discount_amount = $coupon_item->get_discount();
				}
			}

			$discount_amount = $discount_amount / $rate;

			$wpdb->update( $table_name, [ 'discount_amount' => $discount_amount, ], [ 'order_id' => $order_id ], [ '%f', ] );// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		}
	}

	public function import_order_tax_to_order_tax_lookup_table( $tax_rate_id, $order_id ) {
		global $wpdb;
		$table_name = $wpdb->prefix . 'wc_order_tax_lookup';
		$order      = wc_get_order( $order_id );
		$rate       = $this->get_rate( $order );

		if ( $rate && $rate != 1 ) {
			$tax_items = $order->get_items( 'tax' );

			$shipping_tax = 0;
			$order_tax    = 0;
			$total_tax    = 0;

			foreach ( $tax_items as $tax_item ) {
				if ( $tax_item->get_rate_id() == $tax_rate_id ) {
					$shipping_tax = $tax_item->get_shipping_tax_total() / $rate;
					$order_tax    = $tax_item->get_tax_total() / $rate;
					$total_tax    = ( (float) $tax_item->get_tax_total() + (float) $tax_item->get_shipping_tax_total() ) / $rate;
				}
			}

			$wpdb->update( $table_name,// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				[
					'shipping_tax' => $shipping_tax,
					'order_tax'    => $order_tax,
					'total_tax'    => $total_tax
				],
				[ 'order_id' => $order_id ], [ '%f', '%f', '%f', ] );
		}
	}

	/**
	 * Only to save args for later use
	 *
	 * @param $args
	 *
	 * @return mixed
	 */
	public function woocommerce_analytics_query_args( $args ) {
		$this->args = $args;

		return $args;
	}

	/**
	 * Convert order stats based on rate stored in order meta wmc_order_info
	 *
	 * @param $order_data
	 * @param $default_currency
	 *
	 * @return array
	 */
	private static function get_converted_order( $order_data, $default_currency ) {
		$order_id   = $order_data['order_id'];
		$parent_id  = $order_data['parent_id'] ?? '';
		$order = wc_get_order( $order_id );
		if ( $parent_id ) {
			$order_info = get_post_meta( $parent_id, 'wmc_order_info', true );
		} else {
			$order_info = $order->get_meta('wmc_order_info', true );
		}
		$currency   = $order->get_meta( $order_id, '_order_currency', true );
		$rate       = 1;
		if ( isset( $order_info[ $currency ], $order_info[ $default_currency ], $order_info[ $default_currency ]['is_main'] ) && $order_info[ $default_currency ]['is_main'] == 1 && $order_info[ $currency ]['rate'] > 0 ) {
			$rate = floatval( $order_info[ $currency ]['rate'] );
		}
		$converted_order = array(
			'date_created' => strtotime( $order_data['date_created'] ),
			'gross_sales'  => 0,
			'refunds'      => 0,
			'net_revenue'  => self::format_price( floatval( $order_data['net_total'] ) / $rate ),
			'coupons'      => 0,
			'taxes'        => 0,
			'shipping'     => 0,
			'total_sales'  => self::format_price( floatval( $order_data['total_sales'] ) / $rate ),
		);

		if ( $order ) {
			if ( $order_data['net_total'] < 0 ) {
				$converted_order['refunds'] = abs( $converted_order['net_revenue'] );
			}
			$converted_order['coupons']  = self::format_price( floatval( $order->get_total_discount() ) / $rate );
			$converted_order['taxes']    = self::format_price( floatval( $order->get_total_tax() ) / $rate );
			$converted_order['shipping'] = self::format_price( floatval( $order->get_shipping_total() ) / $rate );
		}
		$converted_order['gross_sales'] = $converted_order['total_sales'] + $converted_order['coupons'] - $converted_order['taxes'] - $converted_order['shipping'] + $converted_order['refunds'];

		return $converted_order;
	}

	/**
	 * Convert orders stats
	 *
	 * @param $results
	 *
	 * @return mixed
	 * @throws Exception
	 */
	public function convert_orders_stats( $results ) {
		if ( $this->args !== null ) {
			$args           = $this->args;
			$args['fields'] = '';
//			$args['extended_info'] = 1;
			$data_store     = \WC_Data_Store::load( 'report-orders' );
			$results_orders = $data_store->get_data( $args );
			$converted      = array(
				'gross_sales' => 0,
				'refunds'     => 0,
				'net_revenue' => 0,
				'coupons'     => 0,
				'taxes'       => 0,
				'shipping'    => 0,
				'total_sales' => 0,
			);
			if ( count( $results_orders->data ) ) {
				$orders_data = $results_orders->data;
				if ( $results_orders->pages > 1 ) {
					for ( $i = 2; $i <= $results_orders->pages; $i ++ ) {
						$args['page']   = $i;
						$results_orders = $data_store->get_data( $args );
						if ( count( $results_orders->data ) ) {
							$orders_data = array_merge( $orders_data, $results_orders->data );
						}
					}
				}

				$default_currency = $this->settings->get_default_currency();
				$converted_orders = array();
				foreach ( $orders_data as $order_data ) {
					if ( ! empty( $order_data['order_id'] ) ) {
						$converted_order = self::get_converted_order( $order_data, $default_currency );
						foreach ( $converted_order as $converted_order_k => $converted_order_v ) {
							if ( isset( $converted[ $converted_order_k ] ) ) {
								$converted[ $converted_order_k ] += $converted_order_v;
							}
						}
						$converted_orders[] = $converted_order;
					}
				}
				foreach ( $converted as $key => $value ) {
					if ( isset( $results->totals->{$key} ) ) {
						$results->totals->{$key} = $value;
					}
				}
				if ( isset( $results->totals->avg_order_value, $results->totals->orders_count ) && $results->totals->orders_count > 0 ) {
					$results->totals->avg_order_value = $results->totals->net_revenue / $results->totals->orders_count;
				}
				if ( isset( $results->intervals ) && count( $results->intervals ) && count( $converted_orders ) ) {
					foreach ( $results->intervals as $key => $interval ) {
						if ( isset( $interval['subtotals'] ) && isset( $interval['subtotals']->gross_sales, $interval['subtotals']->total_sales, $interval['subtotals']->net_revenue ) && ( $interval['subtotals']->gross_sales > 0 || $interval['subtotals']->net_revenue > 0 || $interval['subtotals']->gross_sales > 0 ) ) {
							$subtotals = array(
								'gross_sales'     => 0,
								'total_sales'     => 0,
								'coupons'         => 0,
								'refunds'         => 0,
								'taxes'           => 0,
								'shipping'        => 0,
								'net_revenue'     => 0,
								'avg_order_value' => 0,
							);
							$found     = false;
							foreach ( $converted_orders as $converted_order ) {
								if ( $converted_order['date_created'] >= strtotime( $interval['date_start'] ) && $converted_order['date_created'] <= strtotime( $interval['date_end'] ) ) {
									$found                    = true;
									$subtotals['net_revenue'] += $converted_order['net_revenue'];
									$subtotals['total_sales'] += $converted_order['total_sales'];
									$subtotals['refunds']     += $converted_order['refunds'];
									$subtotals['coupons']     += $converted_order['coupons'];
									$subtotals['taxes']       += $converted_order['taxes'];
									$subtotals['shipping']    += $converted_order['shipping'];
									$subtotals['gross_sales'] += $converted_order['gross_sales'];
								} elseif ( $found ) {
									break;
								}
							}
							if ( $found ) {
								if ( isset( $interval['subtotals']->avg_order_value, $interval['subtotals']->orders_count ) && $interval['subtotals']->orders_count > 0 ) {
									$subtotals['avg_order_value'] = $subtotals['net_revenue'] / $interval['subtotals']->orders_count;
								}
								foreach ( $subtotals as $subtotals_k => $subtotals_v ) {
									if ( isset( $interval['subtotals']->{$subtotals_k} ) ) {
										$results->intervals[ $key ]['subtotals']->{$subtotals_k} = $subtotals_v;
									}
								}
							}
						}
					}
				}
			}
			$this->args = null;
		}

		return $results;
	}

	/**
	 * Convert net_total and total_sales of every order
	 *
	 * @param $results
	 *
	 * @return mixed
	 */
	public function woocommerce_analytics_orders_select_query( $results ) {
		$default_currency = $this->settings->get_default_currency();
		foreach ( $results->data as $key => $order_data ) {
			if ( ! empty( $order_data['order_id'] ) ) {
				$converted_order                      = self::get_converted_order( $order_data, $default_currency );
				$results->data[ $key ]['net_total']   = $converted_order['net_revenue'];
				$results->data[ $key ]['total_sales'] = $converted_order['total_sales'];
			}
		}

		return $results;
	}

	/**
	 * Format price after converting
	 *
	 * @param $price
	 *
	 * @return float
	 */
	private static function format_price( $price ) {
		return $price > 0 ? floatval( str_replace( ',', '', number_format( $price, wc_get_price_decimals(), '.', ',' ) ) ) : $price;
	}
}PK     Td\L    
  widget.phpnu [        <?php

/*
Class Name: WOOMULTI_CURRENCY_F_Admin_Widget
Author: Andy Ha (support@villatheme.com)
Author URI: http://villatheme.com
Copyright 2015-2017 villatheme.com. All rights reserved.
*/
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class WOOMULTI_CURRENCY_F_Admin_Widget {
	protected $settings;

	public function __construct() {
		$this->settings = WOOMULTI_CURRENCY_F_Data::get_ins();

		add_action( 'widgets_init', array( $this, 'widgets_init' ) );


	}


	/**
	 * Init widget
	 */
	public function widgets_init() {
		register_widget( 'WMC_Widget' );
		register_widget( 'WMC_Widget_Rates' );
	}


}

?>PK     Td\U8      cryptocurrency.phpnu [        <?php

/**
 * Class WOOMULTI_CURRENCY_F_Admin_Cryptocurrency
 */
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class WOOMULTI_CURRENCY_F_Admin_Cryptocurrency {
	protected $settings;

	public function __construct() {
		$this->settings = WOOMULTI_CURRENCY_F_Data::get_ins();
		add_filter( 'woocommerce_currencies', array( $this, 'woocommerce_currencies' ) );
		add_filter( 'woocommerce_currency_symbols', array( $this, 'woocommerce_currency_symbols' ) );
	}

	/**
	 * @param $currency
	 *
	 * @return mixed
	 */
	public function woocommerce_currencies( $currency ) {
		if ( is_admin() || $this->settings->get_enable() ) {
			$currency['LTC'] = esc_html__( 'Litecoin', 'woo-multi-currency' );
			$currency['ETH'] = esc_html__( 'Ethereum', 'woo-multi-currency' );
			$currency['ZWL'] = esc_html__( 'Zimbabwe', 'woo-multi-currency' );
		}

		return $currency;
	}

	/**
	 * @param $symbols
	 *
	 * @return mixed
	 */
	public function woocommerce_currency_symbols( $symbols ) {
		if ( is_admin() || $this->settings->get_enable() ) {
			$symbols['LTC'] = "LTC";
			$symbols['ETH'] = "ETH";
			$symbols['ZWL'] = "ZWL";
		}

		return $symbols;
	}
}PK     \i      menu/base.phpnu [        <?php
namespace Elementor\Core\Admin\Menu;

use Elementor\Core\Base\Base_Object;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

abstract class Base extends Base_Object {

	private $args;

	private $submenus = [];

	abstract protected function get_init_args();

	public function __construct() {
		$this->init_args();

		add_action( 'admin_menu', function() {
			$this->register();
		} );
	}

	public function get_args( $arg = null ) {
		return self::get_items( $this->args, $arg );
	}

	public function add_submenu( $submenu_args ) {
		$default_submenu_args = [
			'page_title' => '',
			'capability' => $this->args['capability'],
			'function' => null,
			'index' => null,
		];

		$this->submenus[] = array_merge( $default_submenu_args, $submenu_args );
	}

	protected function register_default_submenus() {}

	protected function register() {
		$args = $this->args;

		add_menu_page( $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'], $args['icon_url'], $args['position'] );

		$this->register_default_submenus();

		do_action( 'elementor/admin/menu_registered/' . $args['menu_slug'], $this );

		usort( $this->submenus, function( $a, $b ) {
			return $a['index'] - $b['index'];
		} );

		foreach ( $this->submenus as $index => $submenu_item ) {
			$submenu_args = [
				$args['menu_slug'],
				$submenu_item['page_title'],
				$submenu_item['menu_title'],
				$submenu_item['capability'],
				$submenu_item['menu_slug'],
				$submenu_item['function'],
			];

			if ( 0 === $submenu_item['index'] ) {
				$submenu_args[] = 0;
			}

			add_submenu_page( ...$submenu_args );

			if ( ! empty( $submenu_item['class'] ) ) {
				global $submenu;

				$submenu[ $args['menu_slug'] ][ $index + 1 ][4] = $submenu_item['class']; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
			}
		}
	}

	private function init_args() {
		$default_args = [
			'function' => null,
			'icon_url' => null,
			'position' => null,
		];

		$this->args = array_merge( $default_args, $this->get_init_args() );
	}
}
PK     \      menu/main.phpnu [        <?php

namespace Elementor\Core\Admin\Menu;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Main extends Base {

	protected function get_init_args() {
		return [
			'page_title' => esc_html__( 'Elementor', 'elementor' ),
			'menu_title' => esc_html__( 'Elementor', 'elementor' ),
			'capability' => 'manage_options',
			'menu_slug' => 'elementor',
			'function' => null,
			'position' => 58.5,
		];
	}
}
PK     \зkE
  
    menu/admin-menu-manager.phpnu [        <?php

namespace Elementor\Core\Admin\Menu;

use Elementor\Core\Admin\Menu\Interfaces\Admin_Menu_Item;
use Elementor\Core\Admin\Menu\Interfaces\Admin_Menu_Item_Has_Position;
use Elementor\Core\Admin\Menu\Interfaces\Admin_Menu_Item_With_Page;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

class Admin_Menu_Manager {

	/**
	 * @var Admin_Menu_Item[]
	 */
	private $items = [];

	public function register( $item_slug, Admin_Menu_Item $item ) {
		$this->items[ $item_slug ] = $item;
	}

	public function unregister( $item_slug ) {
		unset( $this->items[ $item_slug ] );
	}

	public function get( $item_slug ) {
		if ( empty( $this->items[ $item_slug ] ) ) {
			return null;
		}

		return $this->items[ $item_slug ];
	}

	public function get_all() {
		return $this->items;
	}

	public function register_actions() {
		add_action( 'admin_menu', function () {
			$this->register_wp_menus();
		}, 20 );

		add_action( 'admin_head', function () {
			$this->hide_invisible_menus();
		} );
	}

	private function register_wp_menus() {
		do_action( 'elementor/admin/menu/register', $this );

		$hooks = [];

		foreach ( $this->get_all() as $item_slug => $item ) {
			$is_top_level = empty( $item->get_parent_slug() );

			if ( $is_top_level ) {
				$hooks[ $item_slug ] = $this->register_top_level_menu( $item_slug, $item );
			} else {
				$hooks[ $item_slug ] = $this->register_sub_menu( $item_slug, $item );
			}
		}

		do_action( 'elementor/admin/menu/after_register', $this, $hooks );
	}

	private function register_top_level_menu( $item_slug, Admin_Menu_Item $item ) {
		$has_page = ( $item instanceof Admin_Menu_Item_With_Page );
		$has_position = ( $item instanceof Admin_Menu_Item_Has_Position );

		$page_title = $has_page ? $item->get_page_title() : '';
		$callback = $has_page ? [ $item, 'render' ] : '';
		$position = $has_position ? $item->get_position() : null;

		return add_menu_page(
			$page_title,
			$item->get_label(),
			$item->get_capability(),
			$item_slug,
			$callback,
			'',
			$position
		);
	}

	private function register_sub_menu( $item_slug, Admin_Menu_Item $item ) {
		$has_page = ( $item instanceof Admin_Menu_Item_With_Page );

		$page_title = $has_page ? $item->get_page_title() : '';
		$callback = $has_page ? [ $item, 'render' ] : '';

		return add_submenu_page(
			$item->get_parent_slug(),
			$page_title,
			$item->get_label(),
			$item->get_capability(),
			$item_slug,
			$callback
		);
	}

	private function hide_invisible_menus() {
		foreach ( $this->get_all() as $item_slug => $item ) {
			if ( $item->is_visible() ) {
				continue;
			}

			$is_top_level = empty( $item->get_parent_slug() );

			if ( $is_top_level ) {
				remove_menu_page( $item_slug );
			} else {
				remove_submenu_page( $item->get_parent_slug(), $item_slug );
			}
		}
	}
}
PK     \~      0  menu/interfaces/admin-menu-item-has-position.phpnu [        <?php

namespace Elementor\Core\Admin\Menu\Interfaces;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

interface Admin_Menu_Item_Has_Position {
	public function get_position();
}
PK     \M%  %  #  menu/interfaces/admin-menu-item.phpnu [        <?php

namespace Elementor\Core\Admin\Menu\Interfaces;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

interface Admin_Menu_Item {
	public function get_capability();

	public function get_label();

	public function get_parent_slug();

	public function is_visible();
}
PK     \3      -  menu/interfaces/admin-menu-item-with-page.phpnu [        <?php

namespace Elementor\Core\Admin\Menu\Interfaces;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

interface Admin_Menu_Item_With_Page extends Admin_Menu_Item {
	public function get_page_title();

	public function render();
}
PK     \d7      notices/base-notice.phpnu [        <?php
namespace Elementor\Core\Admin\Notices;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

abstract class Base_Notice {
	/**
	 * Determine if the notice should be printed or not.
	 *
	 * @return boolean
	 */
	abstract public function should_print();

	/**
	 * Returns the config of the notice itself.
	 * based on that config the notice will be printed.
	 *
	 * @see \Elementor\Core\Admin\Admin_Notices::admin_notices
	 *
	 * @return array
	 */
	abstract public function get_config();
}
PK     \"&_    +  editor-one-menu/menu/abstract-menu-item.phpnu [        <?php

namespace Elementor\Core\Admin\EditorOneMenu\Menu;

use Elementor\Core\Admin\EditorOneMenu\Interfaces\Menu_Item_Third_Level_Interface;
use Elementor\Modules\EditorOne\Classes\Menu_Config;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

abstract class Abstract_Menu_Item implements Menu_Item_Third_Level_Interface {

	public function get_capability(): string {
		return Menu_Config::CAPABILITY_MANAGE_OPTIONS;
	}

	public function get_parent_slug(): string {
		return Menu_Config::ELEMENTOR_MENU_SLUG;
	}

	public function is_visible(): bool {
		return true;
	}

	public function get_group_id(): string {
		return Menu_Config::EDITOR_GROUP_ID;
	}

	public function has_children(): bool {
		return false;
	}

	abstract public function get_label(): string;

	abstract public function get_position(): int;

	abstract public function get_slug(): string;

	abstract public function get_icon(): string;
}
PK     \$    7  editor-one-menu/menu/legacy-submenu-item-not-mapped.phpnu [        <?php

namespace Elementor\Core\Admin\EditorOneMenu\Menu;

use Elementor\Core\Admin\EditorOneMenu\Interfaces\Menu_Item_Interface;
use Elementor\Modules\EditorOne\Classes\Menu_Config;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Legacy_Submenu_Item_Not_Mapped implements Menu_Item_Interface {

	private $submenu_data;

	private $parent_slug;

	private $position;

	public function __construct( array $submenu_data, ?string $parent_slug = null, ?int $position = 100 ) {
		$this->submenu_data = $submenu_data;
		$this->parent_slug = $parent_slug ?? Menu_Config::ELEMENTOR_MENU_SLUG;
		$this->position = $position;
	}

	public function get_label(): string {
		return $this->submenu_data[0] ?? '';
	}

	public function get_capability(): string {
		return $this->submenu_data[1] ?? Menu_Config::CAPABILITY_MANAGE_OPTIONS;
	}

	public function get_slug(): string {
		return $this->submenu_data[2] ?? '';
	}

	public function get_parent_slug(): string {
		return $this->parent_slug;
	}

	public function is_visible(): bool {
		return true;
	}

	public function get_page_title(): string {
		return $this->submenu_data[3] ?? $this->get_label();
	}

	public function get_position(): int {
		return $this->position;
	}

	public function get_group_id(): string {
		return Menu_Config::THIRD_PARTY_GROUP_ID;
	}
}
PK     \"    2  editor-one-menu/menu/abstract-level4-menu-item.phpnu [        <?php

namespace Elementor\Core\Admin\EditorOneMenu\Menu;

use Elementor\Core\Admin\EditorOneMenu\Interfaces\Menu_Item_Interface;
use Elementor\Modules\EditorOne\Classes\Menu_Config;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

abstract class Abstract_Level4_Menu_Item implements Menu_Item_Interface {

	public function get_capability(): string {
		return Menu_Config::CAPABILITY_MANAGE_OPTIONS;
	}

	public function get_parent_slug(): string {
		return Menu_Config::ELEMENTOR_MENU_SLUG;
	}

	public function is_visible(): bool {
		return true;
	}

	abstract public function get_label(): string;

	abstract public function get_position(): int;

	abstract public function get_slug(): string;

	abstract public function get_group_id(): string;
}
PK     \$+  +  ,  editor-one-menu/menu/legacy-submenu-item.phpnu [        <?php

namespace Elementor\Core\Admin\EditorOneMenu\Menu;

use Elementor\Core\Admin\EditorOneMenu\Interfaces\Menu_Item_Third_Level_Interface;
use Elementor\Modules\EditorOne\Classes\Menu_Config;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Legacy_Submenu_Item implements Menu_Item_Third_Level_Interface {

	private $submenu_data;

	private $parent_slug;

	private $position;

	public function __construct( array $submenu_data, ?string $parent_slug = null, ?int $position = 100 ) {
		$this->submenu_data = $submenu_data;
		$this->parent_slug = $parent_slug ?? Menu_Config::ELEMENTOR_MENU_SLUG;
		$this->position = $position;
	}

	public function get_label(): string {
		return $this->submenu_data[0] ?? '';
	}

	public function get_capability(): string {
		return $this->submenu_data[1] ?? Menu_Config::CAPABILITY_MANAGE_OPTIONS;
	}

	public function get_slug(): string {
		return $this->submenu_data[2] ?? '';
	}

	public function get_parent_slug(): string {
		return $this->parent_slug;
	}

	public function is_visible(): bool {
		return true;
	}

	public function get_page_title(): string {
		return $this->submenu_data[3] ?? $this->get_label();
	}

	public function get_position(): int {
		return $this->position;
	}

	public function get_group_id(): string {
		return $this->submenu_data[4] ?? Menu_Config::EDITOR_GROUP_ID;
	}

	public function get_icon(): string {
		$item_slug = $this->get_slug();
		$icon = Menu_Config::get_attribute_mapping()[ $item_slug ]['icon'] ?? 'admin-generic';

		return $icon;
	}

	public function has_children(): bool {
		return false;
	}
}
PK     \i    /  editor-one-menu/menu/third-party-pages-menu.phpnu [        <?php

namespace Elementor\Core\Admin\EditorOneMenu\Menu;

use Elementor\Core\Admin\EditorOneMenu\Interfaces\Menu_Item_Third_Level_Interface;
use Elementor\Modules\EditorOne\Classes\Menu_Config;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Third_Party_Pages_Menu implements Menu_Item_Third_Level_Interface {

	public function get_capability(): string {
		return Menu_Config::CAPABILITY_EDIT_POSTS;
	}

	public function get_parent_slug(): string {
		return Menu_Config::ELEMENTOR_HOME_MENU_SLUG;
	}

	public function is_visible(): bool {
		return true;
	}

	public function get_label(): string {
		return esc_html__( 'Addons', 'elementor' );
	}

	public function get_position(): int {
		return 200;
	}

	public function get_slug(): string {
		return 'elementor-third-party-pages';
	}

	public function get_icon(): string {
		return 'extension';
	}

	public function get_group_id(): string {
		return Menu_Config::THIRD_PARTY_GROUP_ID;
	}

	public function has_children(): bool {
		return true;
	}
}
PK     \}L    8  editor-one-menu/menu/editor-one-custom-elements-menu.phpnu [        <?php

namespace Elementor\Core\Admin\EditorOneMenu\Menu;

use Elementor\Core\Admin\EditorOneMenu\Interfaces\Menu_Item_Third_Level_Interface;
use Elementor\Modules\EditorOne\Classes\Menu_Config;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Editor_One_Custom_Elements_Menu implements Menu_Item_Third_Level_Interface {

	public function get_capability(): string {
		return Menu_Config::CAPABILITY_MANAGE_OPTIONS;
	}

	public function get_parent_slug(): string {
		return Menu_Config::ELEMENTOR_MENU_SLUG;
	}

	public function is_visible(): bool {
		return true;
	}

	public function get_label(): string {
		return esc_html__( 'Custom Elements', 'elementor' );
	}

	public function get_position(): int {
		return 70;
	}

	public function get_slug(): string {
		return 'elementor-custom-elements';
	}

	public function get_icon(): string {
		return 'adjustments';
	}

	public function get_group_id(): string {
		return Menu_Config::CUSTOM_ELEMENTS_GROUP_ID;
	}

	public function has_children(): bool {
		return true;
	}
}
PK     \hȯܩ'  '  .  editor-one-menu/elementor-one-menu-manager.phpnu [        <?php

namespace Elementor\Core\Admin\EditorOneMenu;

use Elementor\Core\Admin\EditorOneMenu\Menu\Editor_One_Custom_Elements_Menu;
use Elementor\Core\Admin\EditorOneMenu\Interfaces\Menu_Item_Interface;
use Elementor\Modules\EditorOne\Classes\Legacy_Submenu_Interceptor;
use Elementor\Modules\EditorOne\Classes\Menu_Config;
use Elementor\Modules\EditorOne\Classes\Menu_Data_Provider;
use Elementor\Modules\EditorOne\Classes\Slug_Normalizer;
use Elementor\Plugin;
use Elementor\Utils;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Elementor_One_Menu_Manager {

	private Menu_Data_Provider $menu_data_provider;

	private bool $is_pro_module_enabled = false;

	private Legacy_Submenu_Interceptor $legacy_submenu_interceptor;

	public function __construct() {
		$this->menu_data_provider = Menu_Data_Provider::instance();
		$this->legacy_submenu_interceptor = new Legacy_Submenu_Interceptor(
			$this->menu_data_provider,
			new Slug_Normalizer()
		);
		$this->register_actions();
	}

	private function register_actions(): void {
		add_action( 'init', [ $this, 'check_if_pro_module_is_enabled' ] );
		add_action( 'admin_menu', [ $this, 'register_elementor_home_submenus' ], 9 );

		add_action( 'admin_menu', function () {
			do_action( 'elementor/editor-one/menu/register', $this->menu_data_provider );
		} );

		add_action( 'admin_menu', [ $this, 'register_pro_submenus' ], 100 );

		add_action( 'admin_menu', [ $this, 'intercept_legacy_submenus' ], 10003 );
		add_action( 'admin_menu', [ $this, 'register_flyout_items_as_hidden_submenus' ], 10004 );
		add_action( 'admin_menu', [ $this, 'remove_all_submenus_for_edit_posts_users' ], 10005 );
		add_action( 'admin_menu', [ $this, 'override_elementor_page_for_edit_posts_users' ], 1006 );
		add_filter( 'add_menu_classes', [ $this, 'fix_theme_builder_submenu_url' ] );
		add_action( 'admin_head', [ $this, 'hide_flyout_items_from_wp_menu' ] );
		add_action( 'admin_head', [ $this, 'hide_legacy_templates_menu' ] );
		add_action( 'admin_head', [ $this, 'hide_old_elementor_menu' ] );
		add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_menu_assets' ] );
		add_action( 'admin_print_scripts-toplevel_page_elementor', [ $this, 'enqueue_home_screen_on_editor_page' ] );
	}

	public function check_if_pro_module_is_enabled(): void {
		$this->is_pro_module_enabled = apply_filters( 'elementor/modules/editor-one/is_pro_module_enabled', false );

		if ( ! $this->is_pro_module_enabled && Utils::has_pro() ) {
			$this->menu_data_provider->register_menu( new Editor_One_Custom_Elements_Menu() );
		}
	}

	public function register_elementor_home_submenus(): void {
		add_submenu_page(
			Menu_Config::ELEMENTOR_HOME_MENU_SLUG,
			esc_html__( 'Editor', 'elementor' ),
			esc_html__( 'Editor', 'elementor' ),
			Menu_Config::CAPABILITY_EDIT_POSTS,
			Menu_Config::ELEMENTOR_MENU_SLUG,
			[ $this, 'render_editor_page' ],
			20
		);

		do_action( 'elementor/editor-one/menu/register_submenus' );
	}

	/**
	 * TODO: This can be removed in v4.1.0 [ED-22806]
	 */
	public function register_pro_submenus(): void {
		if ( ! $this->is_pro_module_enabled &&
			Utils::has_pro() &&
			class_exists( '\ElementorPro\License\API' ) &&
			\ElementorPro\License\API::is_license_active()
		) {
			add_submenu_page(
				Menu_Config::ELEMENTOR_HOME_MENU_SLUG,
				esc_html__( 'Theme Builder', 'elementor' ),
				esc_html__( 'Theme Builder', 'elementor' ),
				Menu_Config::CAPABILITY_EDIT_POSTS,
				'elementor-theme-builder',
				'',
				70
			);

			add_submenu_page(
				Menu_Config::ELEMENTOR_HOME_MENU_SLUG,
				esc_html__( 'Submissions', 'elementor' ),
				esc_html__( 'Submissions', 'elementor' ),
				'edit_posts',
				'e-form-submissions',
				'',
				80
			);
		}
	}

	public function remove_all_submenus_for_edit_posts_users(): void {
		$user_capabilities = Menu_Data_Provider::get_current_user_capabilities();

		if ( ! $user_capabilities['is_edit_posts_user'] ) {
			return;
		}

		global $submenu;

		if ( empty( $submenu[ Menu_Config::ELEMENTOR_MENU_SLUG ] ) ) {
			return;
		}

		$submenu_items = $submenu[ Menu_Config::ELEMENTOR_MENU_SLUG ];

		foreach ( $submenu_items as $index => $submenu_item ) {
			if ( 0 === $index ) {
				continue;
			}

			$submenu_slug = $submenu_item[2] ?? '';
			if ( ! empty( $submenu_slug ) ) {
				remove_submenu_page( Menu_Config::ELEMENTOR_MENU_SLUG, $submenu_slug );
			}
		}
	}

	public function render_editor_page(): void {
		Plugin::instance()->settings->display_home_screen();
	}

	public function override_elementor_page_for_edit_posts_users(): void {
		$user_capabilities = Menu_Data_Provider::get_current_user_capabilities();

		if ( ! $user_capabilities['is_edit_posts_user'] ) {
			return;
		}

		$page = filter_input( INPUT_GET, 'page', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ?? '';
		if ( Menu_Config::ELEMENTOR_MENU_SLUG !== $page ) {
			return;
		}

		$templates_url = admin_url( 'edit.php?post_type=elementor_library&tabs_group=library' );
		wp_safe_redirect( $templates_url );
		exit;
	}

	public function enqueue_home_screen_on_editor_page(): void {
		$home_module = Plugin::instance()->modules_manager->get_modules( 'home' );

		if ( $home_module && method_exists( $home_module, 'enqueue_home_screen_scripts' ) ) {
			$home_module->enqueue_home_screen_scripts();
		}
	}

	public function fix_theme_builder_submenu_url( $menu ) {
		global $submenu;

		$menu_slugs = [ Menu_Config::ELEMENTOR_HOME_MENU_SLUG ];

		foreach ( $menu_slugs as $menu_slug ) {
			if ( empty( $submenu[ $menu_slug ] ) ) {
				continue;
			}

			foreach ( $submenu[ $menu_slug ] as &$item ) {
				if ( 'elementor-theme-builder' === $item[2] ) {
					$item[2] = $this->get_theme_builder_url(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
					break;
				}
			}
		}

		return $menu;
	}

	private function get_theme_builder_url(): string {
		return $this->menu_data_provider->get_theme_builder_url();
	}

	public function hide_legacy_templates_menu(): void {
		?>
		<style type="text/css">
			#menu-posts-elementor_library {
				display: none !important;
			}
		</style>
		<?php
	}

	public function hide_old_elementor_menu(): void {
		$this->remove_elementor_separator();
		?>
		<style type="text/css">
			#toplevel_page_elementor {
				display: none !important;
			}
		</style>
		<?php
	}

	private function remove_elementor_separator(): void {
		global $menu;

		foreach ( $menu as $key => $item ) {
			if ( isset( $item[2] ) && 'separator-elementor' === $item[2] ) {
				unset( $menu[ $key ] );
				break;
			}
		}
	}

	public function register_flyout_items_as_hidden_submenus(): void {
		$hooks = [];

		$this->iterate_all_flyout_items( function( string $item_slug, Menu_Item_Interface $item ) use ( &$hooks ) {
			$hook = $this->register_hidden_submenu( $item_slug, $item );

			if ( $hook ) {
				$hooks[ $item_slug ] = $hook;
			}
		} );

		do_action( 'elementor/editor-one/menu/after_register_hidden_submenus', $hooks );
	}

	private function register_hidden_submenu( string $item_slug, Menu_Item_Interface $item ) {
		$original_parent = $this->get_original_parent_slug( $item );
		$parent_slug = $this->resolve_hidden_submenu_parent( $original_parent );
		$has_page = method_exists( $item, 'render' );
		$page_title = $has_page ? $item->get_page_title() : '';
		$callback = $has_page ? [ $item, 'render' ] : '';
		$capability = $item->get_capability();
		$position = $item->get_position();

		return add_submenu_page(
			$parent_slug,
			$page_title,
			$item->get_label(),
			$capability,
			$item_slug,
			$callback,
			$position
		);
	}

	private function resolve_hidden_submenu_parent( ?string $parent_slug ): string {
		$default_parent_slug = Menu_Config::ELEMENTOR_HOME_MENU_SLUG;
		if ( empty( $parent_slug ) ) {
			return $default_parent_slug;
		}

		$elementor_parent_slugs = [
			Menu_Config::EDITOR_GROUP_ID => true,
			Menu_Config::EDITOR_MENU_SLUG => true,
			Menu_Config::TEMPLATES_GROUP_ID => true,
			Menu_Config::LEGACY_TEMPLATES_SLUG => true,
			Menu_Config::SETTINGS_GROUP_ID => true,
			Menu_Config::CUSTOM_ELEMENTS_GROUP_ID => true,
			Menu_Config::SYSTEM_GROUP_ID => true,
		];

		if ( isset( $elementor_parent_slugs[ $parent_slug ] ) ) {
			return $default_parent_slug;
		}

		return $parent_slug;
	}

	private function iterate_all_flyout_items( callable $callback ): void {
		$level3_items = $this->menu_data_provider->get_level3_items();
		$level4_items = $this->menu_data_provider->get_level4_items();

		$all_items = array_merge_recursive( $level3_items, $level4_items );

		foreach ( $all_items as $group_items ) {
			foreach ( $group_items as $item_slug => $item ) {
				$callback( $item_slug, $item );
			}
		}
	}

	private function get_original_parent_slug( $item ): ?string {
		return $item->get_parent_slug();
	}

	public function hide_flyout_items_from_wp_menu(): void {
		$protected_wp_menu_slugs = [
			Menu_Config::EDITOR_MENU_SLUG,
			'elementor-theme-builder',
			'e-form-submissions',
		];

		$this->iterate_all_flyout_items( function( string $item_slug, Menu_Item_Interface $item ) use ( $protected_wp_menu_slugs ) {
			if ( in_array( $item_slug, $protected_wp_menu_slugs, true ) ) {
				return;
			}

			$original_parent = $this->get_original_parent_slug( $item );
			$parent_slug = $this->resolve_hidden_submenu_parent( $original_parent );
			remove_submenu_page( $parent_slug, $item_slug );
		} );
	}

	public function intercept_legacy_submenus(): void {
		$this->legacy_submenu_interceptor->intercept_all( $this->is_pro_module_enabled );
	}

	public function enqueue_admin_menu_assets(): void {

		$min_suffix = Utils::is_script_debug() ? '' : '.min';

		wp_enqueue_style(
			'elementor-admin-menu',
			ELEMENTOR_ASSETS_URL . 'css/modules/editor-one/admin-menu' . $min_suffix . '.css',
			[],
			ELEMENTOR_VERSION
		);

		$config = [
			'editorFlyout' => $this->menu_data_provider->get_third_level_data(
				Menu_Data_Provider::THIRD_LEVEL_FLYOUT_MENU
			),
		];

		wp_enqueue_script(
			'editor-one-menu',
			ELEMENTOR_ASSETS_URL . 'js/editor-one-menu' . $min_suffix . '.js',
			[],
			ELEMENTOR_VERSION,
			true
		);

		wp_localize_script(
			'editor-one-menu',
			'editorOneMenuConfig',
			$config
		);
	}
}

PK     \';    2  editor-one-menu/interfaces/menu-item-interface.phpnu [        <?php

namespace Elementor\Core\Admin\EditorOneMenu\Interfaces;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

interface Menu_Item_Interface {

	public function get_capability(): string;

	public function get_label(): string;

	public function get_parent_slug(): string;

	public function is_visible(): bool;

	public function get_position(): int;

	public function get_slug(): string;

	public function get_group_id(): string;
}
PK     \&      B  editor-one-menu/interfaces/menu-item-with-custom-url-interface.phpnu [        <?php

namespace Elementor\Core\Admin\EditorOneMenu\Interfaces;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

interface Menu_Item_With_Custom_Url_Interface {

	public function get_menu_url(): string;
}
PK     \    >  editor-one-menu/interfaces/menu-item-third-level-interface.phpnu [        <?php

namespace Elementor\Core\Admin\EditorOneMenu\Interfaces;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

interface Menu_Item_Third_Level_Interface extends Menu_Item_Interface {

	public function get_icon(): string;

	public function has_children(): bool;
}
PK     \u 3      feedback.phpnu [        <?php
namespace Elementor\Core\Admin;

use Elementor\Api;
use Elementor\Core\Base\Module;
use Elementor\Plugin;
use Elementor\Tracker;
use Elementor\Utils;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

class Feedback extends Module {

	/**
	 * @since 2.2.0
	 * @access public
	 */
	public function __construct() {
		add_action( 'current_screen', function () {
			if ( ! $this->is_plugins_screen() ) {
				return;
			}

			add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_feedback_dialog_scripts' ] );
		} );

		// Ajax.
		add_action( 'wp_ajax_elementor_deactivate_feedback', [ $this, 'ajax_elementor_deactivate_feedback' ] );
	}

	/**
	 * Get module name.
	 *
	 * Retrieve the module name.
	 *
	 * @since  1.7.0
	 * @access public
	 *
	 * @return string Module name.
	 */
	public function get_name() {
		return 'feedback';
	}

	/**
	 * Enqueue feedback dialog scripts.
	 *
	 * Registers the feedback dialog scripts and enqueues them.
	 *
	 * @since 1.0.0
	 * @access public
	 */
	public function enqueue_feedback_dialog_scripts() {
		add_action( 'admin_footer', [ $this, 'print_deactivate_feedback_dialog' ] );

		$suffix = Utils::is_script_debug() ? '' : '.min';

		wp_register_script(
			'elementor-admin-feedback',
			ELEMENTOR_ASSETS_URL . 'js/admin-feedback' . $suffix . '.js',
			[
				'elementor-common',
				'wp-i18n',
			],
			ELEMENTOR_VERSION,
			true
		);

		wp_enqueue_script( 'elementor-admin-feedback' );

		wp_set_script_translations( 'elementor-admin-feedback', 'elementor' );
	}

	/**
	 * Print deactivate feedback dialog.
	 *
	 * Display a dialog box to ask the user why he deactivated Elementor.
	 *
	 * Fired by `admin_footer` filter.
	 *
	 * @since 1.0.0
	 * @access public
	 */
	public function print_deactivate_feedback_dialog() {
		$deactivate_reasons = [
			'no_longer_needed' => [
				'title' => esc_html__( 'I no longer need the plugin', 'elementor' ),
				'input_placeholder' => '',
			],
			'found_a_better_plugin' => [
				'title' => esc_html__( 'I found a better plugin', 'elementor' ),
				'input_placeholder' => esc_html__( 'Please share which plugin', 'elementor' ),
			],
			'couldnt_get_the_plugin_to_work' => [
				'title' => esc_html__( 'I couldn\'t get the plugin to work', 'elementor' ),
				'input_placeholder' => '',
			],
			'temporary_deactivation' => [
				'title' => esc_html__( 'It\'s a temporary deactivation', 'elementor' ),
				'input_placeholder' => '',
			],
			'elementor_pro' => [
				'title' => esc_html__( 'I have Elementor Pro', 'elementor' ),
				'input_placeholder' => '',
				'alert' => esc_html__( 'Wait! Don\'t deactivate Elementor. You have to activate both Elementor and Elementor Pro in order for the plugin to work.', 'elementor' ),
			],
			'other' => [
				'title' => esc_html__( 'Other', 'elementor' ),
				'input_placeholder' => esc_html__( 'Please share the reason', 'elementor' ),
			],
		];

		?>
		<div id="elementor-deactivate-feedback-dialog-wrapper">
			<div id="elementor-deactivate-feedback-dialog-header">
				<i class="eicon-elementor-square" aria-hidden="true"></i>
				<span id="elementor-deactivate-feedback-dialog-header-title"><?php echo esc_html__( 'Quick Feedback', 'elementor' ); ?></span>
			</div>
			<form id="elementor-deactivate-feedback-dialog-form" method="post">
				<?php
				wp_nonce_field( '_elementor_deactivate_feedback_nonce' );
				?>
				<input type="hidden" name="action" value="elementor_deactivate_feedback" />

				<div id="elementor-deactivate-feedback-dialog-form-caption"><?php echo esc_html__( 'If you have a moment, please share why you are deactivating Elementor:', 'elementor' ); ?></div>
				<div id="elementor-deactivate-feedback-dialog-form-body">
					<?php foreach ( $deactivate_reasons as $reason_key => $reason ) : ?>
						<div class="elementor-deactivate-feedback-dialog-input-wrapper">
							<input id="elementor-deactivate-feedback-<?php echo esc_attr( $reason_key ); ?>" class="elementor-deactivate-feedback-dialog-input" type="radio" name="reason_key" value="<?php echo esc_attr( $reason_key ); ?>" />
							<label for="elementor-deactivate-feedback-<?php echo esc_attr( $reason_key ); ?>" class="elementor-deactivate-feedback-dialog-label"><?php echo esc_html( $reason['title'] ); ?></label>
							<?php if ( ! empty( $reason['input_placeholder'] ) ) : ?>
								<input class="elementor-feedback-text" type="text" name="reason_<?php echo esc_attr( $reason_key ); ?>" placeholder="<?php echo esc_attr( $reason['input_placeholder'] ); ?>" />
							<?php endif; ?>
							<?php if ( ! empty( $reason['alert'] ) ) : ?>
								<div class="elementor-feedback-text"><?php echo esc_html( $reason['alert'] ); ?></div>
							<?php endif; ?>
						</div>
					<?php endforeach; ?>
				</div>
			</form>
		</div>
		<?php
	}

	/**
	 * Ajax elementor deactivate feedback.
	 *
	 * Send the user feedback when Elementor is deactivated.
	 *
	 * Fired by `wp_ajax_elementor_deactivate_feedback` action.
	 *
	 * @since 1.0.0
	 * @access public
	 */
	public function ajax_elementor_deactivate_feedback() {
		$wpnonce = Utils::get_super_global_value( $_POST, '_wpnonce' ); // phpcs:ignore -- Nonce verification is made in `wp_verify_nonce()`.
		if ( ! wp_verify_nonce( $wpnonce, '_elementor_deactivate_feedback_nonce' ) ) {
			wp_send_json_error();
		}

		if ( ! current_user_can( 'activate_plugins' ) ) {
			wp_send_json_error( 'Permission denied' );
		}

		$reason_key = Utils::get_super_global_value( $_POST, 'reason_key' ) ?? '';
		$reason_text = Utils::get_super_global_value( $_POST, "reason_{$reason_key}" ) ?? '';

		Api::send_feedback( $reason_key, $reason_text );

		wp_send_json_success();
	}

	/**
	 * @since 2.3.0
	 * @access private
	 */
	private function is_plugins_screen() {
		return in_array( get_current_screen()->id, [ 'plugins', 'plugins-network' ] );
	}
}
PK     \?      canary-deployment.phpnu [        <?php
namespace Elementor\Core\Admin;

use Elementor\Api;
use Elementor\Core\Base\Module;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * TODO: Move this class to pro version for better architecture.
 */
class Canary_Deployment extends Module {

	const CURRENT_VERSION = ELEMENTOR_VERSION;
	const PLUGIN_BASE = ELEMENTOR_PLUGIN_BASE;

	private $canary_deployment_info = null;

	/**
	 * Get module name.
	 *
	 * Retrieve the module name.
	 *
	 * @since  2.6.0
	 * @access public
	 *
	 * @return string Module name.
	 */
	public function get_name() {
		return 'canary-deployment';
	}

	/**
	 * Check version.
	 *
	 * @since 2.6.0
	 * @access public
	 *
	 * @param object $transient Plugin updates data.
	 *
	 * @return object Plugin updates data.
	 */
	public function check_version( $transient ) {
		// First transient before the real check.
		if ( ! isset( $transient->response ) ) {
			return $transient;
		}

		// Placeholder
		$stable_version = '0.0.0';

		if ( ! empty( $transient->response[ static::PLUGIN_BASE ]->new_version ) ) {
			$stable_version = $transient->response[ static::PLUGIN_BASE ]->new_version;
		}

		if ( null === $this->canary_deployment_info ) {
			$this->canary_deployment_info = $this->get_canary_deployment_info();
		}

		// Can be false - if canary version is not available.
		if ( empty( $this->canary_deployment_info ) ) {
			return $transient;
		}

		if ( ! version_compare( $this->canary_deployment_info['new_version'], $stable_version, '>' ) ) {
			return $transient;
		}

		$canary_deployment_info = $this->canary_deployment_info;

		// Most of plugin info comes from the $transient but on first check - the response is empty.
		if ( ! empty( $transient->response[ static::PLUGIN_BASE ] ) ) {
			$canary_deployment_info = array_merge( (array) $transient->response[ static::PLUGIN_BASE ], $canary_deployment_info );
		}

		$transient->response[ static::PLUGIN_BASE ] = (object) $canary_deployment_info;

		return $transient;
	}

	protected function get_canary_deployment_remote_info( $force ) {
		return Api::get_canary_deployment_info( $force );
	}

	private function get_canary_deployment_info() {
		global $pagenow;

		$force = 'update-core.php' === $pagenow && isset( $_GET['force-check'] );

		$canary_deployment = $this->get_canary_deployment_remote_info( $force );

		if ( empty( $canary_deployment['plugin_info']['new_version'] ) ) {
			return false;
		}

		$canary_version = $canary_deployment['plugin_info']['new_version'];

		if ( version_compare( $canary_version, static::CURRENT_VERSION, '<=' ) ) {
			return false;
		}

		if ( ! empty( $canary_deployment['conditions'] ) && ! $this->check_conditions( $canary_deployment['conditions'] ) ) {
			return false;
		}

		return $canary_deployment['plugin_info'];
	}

	private function check_conditions( $groups ) {
		foreach ( $groups as $group ) {
			if ( $this->check_group( $group ) ) {
				return true;
			}
		}

		return false;
	}

	private function check_group( $group ) {
		$is_or_relation = ! empty( $group['relation'] ) && 'OR' === $group['relation'];
		unset( $group['relation'] );
		$result = false;

		foreach ( $group as $condition ) {
			// Reset results for each condition.
			$result = false;
			switch ( $condition['type'] ) {
				case 'wordpress': // phpcs:ignore WordPress.WP.CapitalPDangit.MisspelledInText
					// include an unmodified $wp_version
					include ABSPATH . WPINC . '/version.php';
					$result = version_compare( $wp_version, $condition['version'], $condition['operator'] );
					break;
				case 'multisite':
					$result = is_multisite() === $condition['multisite'];
					break;
				case 'language':
					$in_array = in_array( get_locale(), $condition['languages'], true );
					$result = 'in' === $condition['operator'] ? $in_array : ! $in_array;
					break;
				case 'plugin':
					if ( ! empty( $condition['plugin_file'] ) ) {
						$plugin_file = $condition['plugin_file']; // For PHP Unit tests.
					} else {
						$plugin_file = WP_PLUGIN_DIR . '/' . $condition['plugin']; // Default.
					}

					$version = '';

					if ( is_plugin_active( $condition['plugin'] ) && file_exists( $plugin_file ) ) {
						$plugin_data = get_plugin_data( $plugin_file );
						if ( isset( $plugin_data['Version'] ) ) {
							$version = $plugin_data['Version'];
						}
					}

					$result = version_compare( $version, $condition['version'], $condition['operator'] );
					break;
				case 'theme':
					$theme = wp_get_theme();
					if ( wp_get_theme()->parent() ) {
						$theme = wp_get_theme()->parent();
					}

					if ( $theme->get_template() === $condition['theme'] ) {
						$version = $theme->version;
					} else {
						$version = '';
					}

					$result = version_compare( $version, $condition['version'], $condition['operator'] );
					break;

			}

			if ( ( $is_or_relation && $result ) || ( ! $is_or_relation && ! $result ) ) {
				return $result;
			}
		}

		return $result;
	}

	/**
	 * @since 2.6.0
	 * @access public
	 */
	public function __construct() {
		add_filter( 'pre_set_site_transient_update_plugins', [ $this, 'check_version' ] );
	}
}
PK     \k}	  }	    ui/components/button.phpnu [        <?php
namespace Elementor\Core\Admin\UI\Components;

use Elementor\Core\Base\Base_Object;
use Elementor\Utils;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

class Button extends Base_Object {

	private $options;

	/**
	 * @inheritDoc
	 */
	public function get_name() {
		return 'admin-button';
	}

	public function print_button() {
		$options = $this->get_options();

		if ( empty( $options['text'] ) ) {
			return;
		}

		$html_tag = ! empty( $options['url'] ) ? 'a' : 'button';
		$before = '';
		$icon = '';
		$attributes = [];

		if ( ! empty( $options['icon'] ) ) {
			$icon = '<i class="' . esc_attr( $options['icon'] ) . '"></i>';
		}

		$classes = $options['classes'];

		$default_classes = $this->get_default_options( 'classes' );

		$classes = array_merge( $classes, $default_classes );

		if ( ! empty( $options['type'] ) ) {
			$classes[] = 'e-button--' . $options['type'];
		}

		if ( ! empty( $options['variant'] ) ) {
			$classes[] = 'e-button--' . $options['variant'];
		}

		if ( ! empty( $options['before'] ) ) {
			$before = '<span>' . wp_kses_post( $options['before'] ) . '</span>';
		}

		if ( ! empty( $options['url'] ) ) {
			$attributes['href'] = $options['url'];
			if ( $options['new_tab'] ) {
				$attributes['target'] = '_blank';
			}
		}

		$attributes['class'] = $classes;

		$html = $before . '<' . $html_tag . ' ' . Utils::render_html_attributes( $attributes ) . '>';
		$html .= $icon;
		$html .= '<span>' . sanitize_text_field( $options['text'] ) . '</span>';
		$html .= '</' . $html_tag . '>';

		echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	}

	/**
	 * @param string $option Optional default is null.
	 * @return array|mixed
	 */
	private function get_options( $option = null ) {
		return $this->get_items( $this->options, $option );
	}

	/**
	 * @param null $option
	 * @return array
	 */
	private function get_default_options( $option = null ) {
		$default_options = [
			'classes' => [ 'e-button' ],
			'icon' => '',
			'new_tab' => false,
			'text' => '',
			'type' => '',
			'url' => '',
			'variant' => '',
			'before' => '',
		];

		if ( null !== $option && -1 !== in_array( $option, $default_options, true ) ) {
			return $default_options[ $option ];
		}

		return $default_options;
	}

	public function __construct( array $options ) {
		$this->options = $this->merge_properties( $this->get_default_options(), $options );
	}
}
PK     \F oÐ  Ð    admin-notices.phpnu [        <?php
namespace Elementor\Core\Admin;

use Elementor\Api;
use Elementor\Core\Admin\UI\Components\Button;
use Elementor\Core\Base\Module;
use Elementor\Core\Upgrade\Manager;
use Elementor\Core\Utils\Hints;
use Elementor\Core\Utils\Promotions\Filtered_Promotions_Manager;
use Elementor\Plugin;
use Elementor\Settings;
use Elementor\Tracker;
use Elementor\User;
use Elementor\Utils;
use Elementor\Core\Admin\Notices\Base_Notice;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

class Admin_Notices extends Module {

	const DEFAULT_EXCLUDED_PAGES = [ 'plugins.php', 'plugin-install.php', 'plugin-editor.php' ];
	const LOCAL_GOOGLE_FONTS_DISABLED_NOTICE_ID = 'local_google_fonts_disabled';
	const LOCAL_GOOGLE_FONTS_NOTICE_MIN_VERSION = '3.33.3';

	const EXIT_EARLY_FOR_BACKWARD_COMPATIBILITY = false;

	private $plain_notices = [
		'api_notice',
		'api_upgrade_plugin',
		'tracker',
		'tracker_last_update',
		'rate_us_feedback',
		'role_manager_promote',
		'experiment_promotion',
		'site_mailer_promotion',
		'plugin_image_optimization',
		'ally_pages_promotion',
		self::LOCAL_GOOGLE_FONTS_DISABLED_NOTICE_ID,
	];

	private $elementor_pages_count = null;

	private $install_time = null;

	private $current_screen_id = null;

	private function get_notices() {
		/**
		 * Admin notices.
		 *
		 * Filters Elementor admin notices.
		 *
		 * This hook can be used by external developers to manage existing
		 * admin notice or to add new notices for Elementor add-ons.
		 *
		 * @param array $notices A list of notice classes.
		 */
		$notices = apply_filters( 'elementor/core/admin/notices', [] );

		return $notices;
	}

	private function get_install_time() {
		if ( null === $this->install_time ) {
			$this->install_time = Plugin::$instance->get_install_time();
		}

		return $this->install_time;
	}

	private function get_elementor_pages_count() {
		if ( null === $this->elementor_pages_count ) {
			$elementor_pages = new \WP_Query( [
				'no_found_rows' => true,
				'post_type' => 'any',
				'post_status' => 'publish',
				'fields' => 'ids',
				'update_post_meta_cache' => false,
				'update_post_term_cache' => false,
				'meta_key' => '_elementor_edit_mode',
				'meta_value' => 'builder',
			] );

			$this->elementor_pages_count = $elementor_pages->post_count;
		}

		return $this->elementor_pages_count;
	}

	private function notice_api_upgrade_plugin() {
		$upgrade_notice = Api::get_upgrade_notice();
		if ( empty( $upgrade_notice ) ) {
			return false;
		}

		if ( ! current_user_can( 'update_plugins' ) ) {
			return false;
		}

		if ( ! $this->is_elementor_admin_screen_with_system_info() ) {
			return false;
		}

		// Check for upgrades.
		$update_plugins = get_site_transient( 'update_plugins' );

		$has_remote_update_package = ! ( empty( $update_plugins ) || empty( $update_plugins->response[ ELEMENTOR_PLUGIN_BASE ] ) || empty( $update_plugins->response[ ELEMENTOR_PLUGIN_BASE ]->package ) );

		if ( ! $has_remote_update_package && empty( $upgrade_notice['update_link'] ) ) {
			return false;
		}

		if ( $has_remote_update_package ) {
			$product = $update_plugins->response[ ELEMENTOR_PLUGIN_BASE ];

			$details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $product->slug . '&section=changelog&TB_iframe=true&width=600&height=800' );
			$upgrade_url = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' . ELEMENTOR_PLUGIN_BASE ), 'upgrade-plugin_' . ELEMENTOR_PLUGIN_BASE );
			$new_version = $product->new_version;
		} else {
			$upgrade_url = $upgrade_notice['update_link'];
			$details_url = $upgrade_url;

			$new_version = $upgrade_notice['version'];
		}

		// Check if upgrade messages should be shown.
		if ( version_compare( ELEMENTOR_VERSION, $upgrade_notice['version'], '>=' ) ) {
			return false;
		}

		$notice_id = 'upgrade_notice_' . $upgrade_notice['version'];
		if ( User::is_user_notice_viewed( $notice_id ) ) {
			return false;
		}

		$message = sprintf(
			/* translators: 1: Details URL, 2: Accessibility text, 3: Version number, 4: Update URL, 5: Accessibility text. */
			__( 'There is a new version of Elementor Page Builder available. <a href="%1$s" class="thickbox open-plugin-details-modal" aria-label="%2$s">View version %3$s details</a> or <a href="%4$s" class="update-link" aria-label="%5$s">update now</a>.', 'elementor' ),
			esc_url( $details_url ),
			sprintf(
				/* translators: %s: Elementor version. */
				esc_attr__( 'View Elementor version %s details', 'elementor' ),
				$new_version
			),
			$new_version,
			esc_url( $upgrade_url ),
			esc_attr__( 'Update Now', 'elementor' )
		);

		$options = [
			'title' => esc_html__( 'Update Notification', 'elementor' ),
			'description' => $message,
			'button' => [
				'icon_classes' => 'dashicons dashicons-update',
				'text' => esc_html__( 'Update Now', 'elementor' ),
				'url' => $upgrade_url,
			],
			'id' => $notice_id,
		];

		$this->print_admin_notice( $options );

		return true;
	}

	private function notice_api_notice() {
		$admin_notice = Api::get_admin_notice();
		if ( empty( $admin_notice ) ) {
			return false;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		if ( ! $this->is_elementor_admin_screen_with_system_info() ) {
			return false;
		}

		$notice_id = 'admin_notice_api_' . $admin_notice['notice_id'];
		if ( User::is_user_notice_viewed( $notice_id ) ) {
			return false;
		}

		$options = [
			'title' => esc_html__( 'Update Notification', 'elementor' ),
			'description' => $admin_notice['notice_text'],
			'id' => $notice_id,
		];

		$this->print_admin_notice( $options );

		return true;
	}

	private function notice_tracker() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		// Show tracker notice after 24 hours from installed time.
		if ( strtotime( '+24 hours', $this->get_install_time() ) > time() ) {
			return false;
		}

		if ( '1' === get_option( 'elementor_tracker_notice' ) ) {
			return false;
		}

		if ( Tracker::is_allow_track() ) {
			return false;
		}

		if ( 2 > $this->get_elementor_pages_count() ) {
			return false;
		}

		// TODO: Skip for development env.
		$optin_url = wp_nonce_url( add_query_arg( 'elementor_tracker', 'opt_into' ), 'opt_into' );
		$optout_url = wp_nonce_url( add_query_arg( 'elementor_tracker', 'opt_out' ), 'opt_out' );

		$tracker_description_text = esc_html__( 'Become a super contributor by helping us understand how you use our service to enhance your experience and improve our product.', 'elementor' );

		/**
		 * Tracker admin description text.
		 *
		 * Filters the admin notice text for non-sensitive data collection.
		 *
		 * @since 1.0.0
		 *
		 * @param string $tracker_description_text Description text displayed in admin notice.
		 */
		$tracker_description_text = apply_filters( 'elementor/tracker/admin_description_text', $tracker_description_text );

		$message = esc_html( $tracker_description_text ) . ' <a href="https://go.elementor.com/usage-data-tracking/" target="_blank">' . esc_html__( 'Learn more.', 'elementor' ) . '</a>';

		$options = [
			'title' => esc_html__( 'Want to shape the future of web creation?', 'elementor' ),
			'description' => $message,
			'dismissible' => false,
			'button' => [
				'text' => esc_html__( 'Sure! I\'d love to help', 'elementor' ),
				'url' => $optin_url,
				'type' => 'cta',
			],
			'button_secondary' => [
				'text' => esc_html__( 'No thanks', 'elementor' ),
				'url' => $optout_url,
				'variant' => 'outline',
				'type' => 'cta',
			],
		];

		$this->print_admin_notice( $options );

		return true;
	}

	private function notice_tracker_last_update() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		if ( ! Tracker::has_terms_changed() ) {
			return false;
		}

		$notice_id = 'tracker_last_update_' . Tracker::LAST_TERMS_UPDATED;

		if ( User::is_user_notice_viewed( $notice_id ) ) {
			return false;
		}

		$optin_url = wp_nonce_url( add_query_arg( 'elementor_tracker', 'opt_into' ), 'opt_into' );

		$message = esc_html__( 'We\'re updating our Terms and Conditions to include the collection of usage and behavioral data. This information helps us understand how you use Elementor so we can make informed improvements to the product.', 'elementor' );

		$options = [
			'id' => $notice_id,
			'title' => esc_html__( 'Update regarding usage data collection', 'elementor' ),
			'description' => $message,
			'button' => [
				'text' => esc_html__( 'Opt in', 'elementor' ),
				'url' => $optin_url,
				'type' => 'cta',
			],
			'button_secondary' => [
				'text' => esc_html__( 'Learn more', 'elementor' ),
				'url' => 'https://go.elementor.com/wp-dash-update-usage-notice/',
				'new_tab' => true,
				'type' => 'cta',
			],
		];

		$this->print_admin_notice( $options );

		return true;
	}

	private function notice_rate_us_feedback() {
		$notice_id = 'rate_us_feedback';

		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		if ( 'dashboard' !== $this->current_screen_id || User::is_user_notice_viewed( $notice_id ) ) {
			return false;
		}

		if ( 10 >= $this->get_elementor_pages_count() ) {
			return false;
		}

		$dismiss_url = add_query_arg( [
			'action' => 'elementor_set_admin_notice_viewed',
			'notice_id' => esc_attr( $notice_id ),
			'_wpnonce' => wp_create_nonce( 'elementor_set_admin_notice_viewed' ),
		], admin_url( 'admin-post.php' ) );

		$options = [
			'title' => esc_html__( 'Congrats!', 'elementor' ),
			'description' => esc_html__( 'You created over 10 pages with Elementor. Great job! If you can spare a minute, please help us by leaving a five star review on WordPress.org.', 'elementor' ),
			'id' => $notice_id,
			'button' => [
				'text' => esc_html__( 'Happy To Help', 'elementor' ),
				'url' => 'https://go.elementor.com/admin-review/',
				'new_tab' => true,
				'type' => 'cta',
			],
			'button_secondary' => [
				'text' => esc_html__( 'Hide Notification', 'elementor' ),
				'classes' => [ 'e-notice-dismiss' ],
				'url' => esc_url_raw( $dismiss_url ),
				'new_tab' => true,
				'type' => 'cta',
			],
		];

		$this->print_admin_notice( $options );

		return true;
	}

	private function notice_role_manager_promote() {
		$notice_id = 'role_manager_promote';

		if ( Utils::has_pro() ) {
			return false;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		if ( 'elementor_page_elementor-role-manager' !== $this->current_screen_id || User::is_user_notice_viewed( $notice_id ) ) {
			return false;
		}

		$users = new \WP_User_Query( [
			'fields' => 'ID',
			'number' => 10,
		] );

		if ( 5 > $users->get_total() ) {
			return false;
		}

		$options = [
			'title' => esc_html__( 'Managing a multi-user site?', 'elementor' ),
			'description' => esc_html__( 'With Elementor Pro, you can control user access and make sure no one messes up your design.', 'elementor' ),
			'id' => $notice_id,

			'button' => [
				'text' => esc_html__( 'Learn More', 'elementor' ),
				'url' => 'https://go.elementor.com/plugin-promotion-role-manager/',
				'new_tab' => true,
				'type' => 'cta',
			],
		];

		$options = Filtered_Promotions_Manager::get_filtered_promotion_data( $options, 'core/admin/notice_role_manager_promote', 'button', 'url' );

		$this->print_admin_notice( $options );

		return true;
	}

	private function notice_experiment_promotion() {
		$notice_id = 'experiment_promotion';

		if ( ! current_user_can( 'manage_options' ) || User::is_user_notice_viewed( $notice_id ) ) {
			return false;
		}

		$experiments = Plugin::$instance->experiments;
		$is_all_performance_features_active = (
			$experiments->is_feature_active( 'e_font_icon_svg' ) &&
			$experiments->is_feature_active( 'e_optimized_markup' )
		);

		if ( $is_all_performance_features_active ) {
			return false;
		}

		$options = [
			'title' => esc_html__( 'Improve your site’s performance score.', 'elementor' ),
			'description' => esc_html__( 'With our experimental speed boosting features you can go faster than ever before. Look for the Performance label on our Experiments page and activate those experiments to improve your site loading speed.', 'elementor' ),
			'id' => $notice_id,
			'button' => [
				'text' => esc_html__( 'Try it out', 'elementor' ),
				'url' => Settings::get_settings_tab_url( 'experiments' ),
				'type' => 'cta',
			],
			'button_secondary' => [
				'text' => esc_html__( 'Learn more', 'elementor' ),
				'url' => 'https://go.elementor.com/wp-dash-experiment-promotion/',
				'new_tab' => true,
				'type' => 'cta',
			],
		];

		$this->print_admin_notice( $options );

		return true;
	}

	private function site_has_forms_plugins() {
		return defined( 'WPFORMS_VERSION' ) || defined( 'WPCF7_VERSION' ) || defined( 'FLUENTFORM_VERSION' ) || class_exists( '\GFCommon' ) || class_exists( '\Ninja_Forms' ) || function_exists( 'load_formidable_forms' ) || did_action( 'metform/after_load' ) || defined( 'FORMINATOR_PLUGIN_BASENAME' );
	}

	private function site_has_woocommerce() {
		return class_exists( 'WooCommerce' );
	}

	private function get_installed_form_plugin_name() {
		static $detected_form_plugin = null;

		if ( null !== $detected_form_plugin ) {
			return $detected_form_plugin;
		}

		$form_plugins_constants_to_name_mapper = [
			'WPFORMS_VERSION' => 'WPForms',
			'WPCF7_VERSION' => 'Contact Form 7',
		];

		foreach ( $form_plugins_constants_to_name_mapper as $constant => $name ) {
			if ( defined( $constant ) ) {
				$detected_form_plugin = $name;
				return $detected_form_plugin;
			}
		}

		$form_plugins_classes_to_name_mapper = [
			'\GFCommon' => 'Gravity Forms',
			'\Ninja_Forms' => 'Ninja Forms',
		];

		foreach ( $form_plugins_classes_to_name_mapper as $class => $name ) {
			if ( class_exists( $class ) ) {
				$detected_form_plugin = $name;
				return $detected_form_plugin;
			}
		}

		$detected_form_plugin = false;
		return $detected_form_plugin;
	}

	private function notice_local_google_fonts_disabled() {

		if ( ! $this->is_elementor_page() && ! $this->is_elementor_admin_screen() ) {
			return false;
		}

		if ( ! Manager::had_install_prior_to( self::LOCAL_GOOGLE_FONTS_NOTICE_MIN_VERSION ) ) {
			return false;
		}

		if ( User::is_user_notice_viewed( self::LOCAL_GOOGLE_FONTS_DISABLED_NOTICE_ID ) ) {
			return false;
		}

		$is_local_gf_enabled = (bool) get_option( 'elementor_local_google_fonts', '0' );

		if ( $is_local_gf_enabled ) {
			return false;
		}

		$options = [
			'title' => esc_html__( 'Important: Local Google Fonts Settings in Elementor', 'elementor' ),
			'description' => esc_html__( 'Please note: The "Load Google Fonts Locally" feature has been disabled by default on all websites. To turn it back on, go to Elementor → Settings → Performance → Enable Load Google Fonts Locally.', 'elementor' ),
			'id' => self::LOCAL_GOOGLE_FONTS_DISABLED_NOTICE_ID,
			'type' => '',
			'button' => [
				'text' => esc_html__( 'Take me there', 'elementor' ),
				'url' => '../wp-admin/admin.php?page=elementor-settings#tab-performance',
				'new_tab' => false,
				'type' => 'cta',
			],
			'button_secondary' => [
				'text' => esc_html__( 'Learn more', 'elementor' ),
				'url' => 'https://go.elementor.com/wp-dash-google-fonts-locally-notice/',
				'new_tab' => true,
				'type' => 'cta',
			],
		];

		$this->print_admin_notice( $options );

		return true;
	}

	private function notice_ally_pages_promotion() {
		global $pagenow;
		$notice_id = 'ally_pages_promotion';

		if ( 'edit.php' !== $pagenow || empty( $_GET['post_type'] ) || 'page' !== $_GET['post_type'] ) {
			return false;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		if ( User::is_user_notice_viewed( $notice_id ) ) {
			return false;
		}

		$plugin_slug = 'pojo-accessibility';
		$plugin_file_path = 'pojo-accessibility/pojo-accessibility.php';

		$one_subscription = Hints::is_plugin_connected_to_one_subscription();
		$is_installed = Hints::is_plugin_installed( $plugin_slug );
		$is_active = Hints::is_plugin_active( $plugin_slug );

		if ( $is_active ) {
			return false;
		}

		if ( $one_subscription ) {
			$learn_more_url = 'https://go.elementor.com/acc-plg-learn-more-one';

			if ( ! $is_installed ) {
				$description = esc_html__( 'Make sure your site has an accessibility statement page. Install Ally, included in ONE, to create it in a few clicks.', 'elementor' );
				$button_text = esc_html__( 'Install now', 'elementor' );
				$button_url = $this->get_plugin_button_install_url( $plugin_slug );
				$campaign_data = [
					'name' => 'elementor_ea11y_campaign',
					'campaign' => 'acc-statement-plg-pages-one-install',
					'source' => 'wp-pages-one-install',
					'medium' => 'wp-dash-one',
				];
			} elseif ( ! $is_active ) {
				$description = esc_html__( 'Your ONE subscription includes Ally. Activate it to create your accessibility statement page quickly.', 'elementor' );
				$button_text = esc_html__( 'Activate now', 'elementor' );
				$button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
				$campaign_data = [
					'name' => 'elementor_ea11y_campaign',
					'campaign' => 'acc-statement-plg-pages-one-activate',
					'source' => 'wp-pages-one-activate',
					'medium' => 'wp-dash-one',
				];
			}
		} else {
			$description = esc_html__( "Create a more inclusive site experience for all your visitors. With Ally, it's easy to add your statement page in just a few clicks.", 'elementor' );
			$learn_more_url = 'https://go.elementor.com/acc-plg-learn-more';

			if ( ! $is_installed ) {
				$button_text = esc_html__( 'Install now', 'elementor' );
				$button_url = $this->get_plugin_button_install_url( $plugin_slug );
				$campaign_data = [
					'name' => 'elementor_ea11y_campaign',
					'campaign' => 'acc-statement-plg-pages-install',
					'source' => 'wp-pages-install',
					'medium' => 'wp-dash',
				];
			} elseif ( ! $is_active ) {
				$button_text = esc_html__( 'Activate now', 'elementor' );
				$button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
				$campaign_data = [
					'name' => 'elementor_ea11y_campaign',
					'campaign' => 'acc-statement-plg-pages-activate',
					'source' => 'wp-pages-activate',
					'medium' => 'wp-dash',
				];
			}
		}

		$options = [
			'title' => esc_html__( 'Make sure your site has an accessibility statement page', 'elementor' ),
			'description' => $description,
			'id' => $notice_id,
			'type' => 'cta',
			'button' => [
				'text' => $button_text,
				'url' => self::add_plg_campaign_data( $button_url, $campaign_data ),
				'type' => 'cta',
			],
			'button_secondary' => [
				'text' => esc_html__( 'Learn more', 'elementor' ),
				'url' => $learn_more_url,
				'new_tab' => true,
				'type' => 'cta',
			],
		];

		$this->print_admin_notice( $options );

		return true;
	}

	private function notice_site_mailer_promotion() {
		$notice_id = 'site_mailer_promotion';
		$has_forms = $this->site_has_forms_plugins();
		$has_woocommerce = $this->site_has_woocommerce();

		if ( ! $has_forms && ! $has_woocommerce ) {
			return false;
		}

		if ( ! $this->is_elementor_page() && ! $this->is_elementor_admin_screen() ) {
			return false;
		}

		if ( ( Utils::has_pro() && ! $has_woocommerce ) || ! current_user_can( 'install_plugins' ) || User::is_user_notice_viewed( $notice_id ) ) {
			return false;
		}

		$plugin_slug = 'site-mailer';
		$plugin_file_path = 'site-mailer/site-mailer.php';

		$one_subscription = Hints::is_plugin_connected_to_one_subscription();
		$is_woocommerce = $this->should_render_woocommerce_hint( $has_forms, $has_woocommerce );
		$is_installed = Hints::is_plugin_installed( $plugin_slug );
		$is_active = Hints::is_plugin_active( $plugin_slug );

		if ( $is_active ) {
			return false;
		}

		if ( $one_subscription ) {
			if ( $is_woocommerce ) {
				$title = esc_html__( 'Improve transactional email deliverability', 'elementor' );

				if ( ! $is_installed ) {
					$description = esc_html__( 'Use Site Mailer to ensure store emails like purchase confirmations and shipping updates reach the inbox every time. Included in your ONE subscription.', 'elementor' );
					$button_text = esc_html__( 'Install now', 'elementor' );
					$button_url = $this->get_plugin_button_install_url( $plugin_slug );
					$campaign_data = [
						'name' => 'elementor_site_mailer_campaign',
						'campaign' => 'sm-plg-one',
						'source' => 'sm-core-woo-one-install',
						'medium' => 'wp-dash',
					];
				} elseif ( ! $is_active ) {
					$description = esc_html__( 'Site Mailer is installed and included in your ONE subscription. Activate it to ensure store emails like purchase confirmations and shipping updates reach the inbox every time.', 'elementor' );
					$button_text = esc_html__( 'Activate now', 'elementor' );
					$button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
					$campaign_data = [
						'name' => 'elementor_site_mailer_campaign',
						'campaign' => 'sm-plg-one',
						'source' => 'sm-core-woo-one-activate',
						'medium' => 'wp-dash',
					];
				}
			} else {
				$title = esc_html__( 'Keep your form emails out of the spam folder', 'elementor' );

				if ( ! $is_installed ) {
					$description = esc_html__( 'Use Site Mailer to ensure emails reach the inbox and track delivery with built-in logs. Included in your ONE subscription.', 'elementor' );
					$button_text = esc_html__( 'Install now', 'elementor' );
					$button_url = $this->get_plugin_button_install_url( $plugin_slug );
					$campaign_data = [
						'name' => 'elementor_site_mailer_campaign',
						'campaign' => 'sm-plg-one',
						'source' => 'sm-core-form-one-install',
						'medium' => 'wp-dash',
					];
				} elseif ( ! $is_active ) {
					$description = esc_html__( 'Use Site Mailer to ensure emails reach the inbox and track delivery with built-in logs. Site Mailer is included in your ONE subscription. Activate it to continue.', 'elementor' );
					$button_text = esc_html__( 'Activate now', 'elementor' );
					$button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
					$campaign_data = [
						'name' => 'elementor_site_mailer_campaign',
						'campaign' => 'sm-plg-one',
						'source' => 'sm-core-form-one-activate',
						'medium' => 'wp-dash',
					];
				}
			}
		// phpcs:ignore Universal.ControlStructures.DisallowLonelyIf.Found
		} else {
			if ( $is_woocommerce ) {
				$title = esc_html__( 'Improve Transactional Email Deliverability', 'elementor' );
				$description = esc_html__( "Use Elementor's Site Mailer to ensure your store emails like purchase confirmations, shipping updates and more are reliably delivered.", 'elementor' );

				if ( ! $is_installed ) {
					$button_text = esc_html__( 'Install now', 'elementor' );
					$button_url = $this->get_plugin_button_install_url( $plugin_slug );
					$campaign_data = [
						'name' => 'elementor_site_mailer_campaign',
						'campaign' => 'sm-plg',
						'source' => 'sm-core-woo-install',
						'medium' => 'wp-dash',
					];
				} elseif ( ! $is_active ) {
					$button_text = esc_html__( 'Activate now', 'elementor' );
					$button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
					$campaign_data = [
						'name' => 'elementor_site_mailer_campaign',
						'campaign' => 'sm-plg',
						'source' => 'sm-core-woo-activate',
						'medium' => 'wp-dash',
					];
				}
			} else {
				$title = esc_html__( 'Ensure your form emails avoid the spam folder!', 'elementor' );
				$description = esc_html__( 'Use Site Mailer for improved email deliverability, detailed email logs, and an easy setup.', 'elementor' );

				if ( ! $is_installed ) {
					$button_text = esc_html__( 'Install now', 'elementor' );
					$button_url = $this->get_plugin_button_install_url( $plugin_slug );
					$campaign_data = [
						'name' => 'elementor_site_mailer_campaign',
						'campaign' => 'sm-plg',
						'source' => 'sm-core-form-install',
						'medium' => 'wp-dash',
					];
				} elseif ( ! $is_active ) {
					$button_text = esc_html__( 'Activate now', 'elementor' );
					$button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
					$campaign_data = [
						'name' => 'elementor_site_mailer_campaign',
						'campaign' => 'sm-plg',
						'source' => 'sm-core-form-activate',
						'medium' => 'wp-dash',
					];
				}
			}
		}

		$learn_more_url = $one_subscription && $is_woocommerce
			? 'https://go.elementor.com/sm-woo-learn-more-one'
			: 'https://go.elementor.com/sm-core-form/';

		$options = [
			'title' => $title,
			'description' => $description,
			'id' => $notice_id,
			'type' => 'cta',
			'button' => [
				'text' => $button_text,
				'url' => self::add_plg_campaign_data( $button_url, $campaign_data ),
				'type' => 'cta',
				'data' => [
					'campaign' => $campaign_data['campaign'],
					'source' => $campaign_data['source'],
					'medium' => $campaign_data['medium'],
				],
			],
			'button_secondary' => [
				'text' => esc_html__( 'Learn more', 'elementor' ),
				'url' => $learn_more_url,
				'new_tab' => true,
				'type' => 'cta',
			],
		];

		if ( $is_woocommerce ) {
			// We include WP's default notice class so it will be properly handled by WP's js handler
			// And add a new one to distinguish between the two types of notices
			$options['classes'] = [ 'notice', 'e-notice', 'sm-notice-wc' ];
		}

		$this->print_admin_notice( $options );

		return true;
	}

	private function should_render_woocommerce_hint( $has_forms, $has_woocommerce ): bool {
		if ( ! $has_forms && ! $has_woocommerce ) {
			return false;
		}

		if ( ! $has_forms && $has_woocommerce ) {
			return true;
		}

		if ( $has_forms && $has_woocommerce && Utils::has_pro() ) {
			return true;
		}

		if ( ! $has_woocommerce ) {
			return false;
		}

		return (bool) wp_rand( 0, 1 );
	}

	private function is_elementor_page(): bool {
		return 0 === strpos( $this->current_screen_id, 'elementor_page' );
	}

	private function is_elementor_admin_screen(): bool {
		return in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library' ], true );
	}

	private function is_elementor_admin_screen_with_system_info(): bool {
		return in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library', 'elementor_page_elementor-system-info', 'dashboard' ], true );
	}
	private function get_plugin_button_install_url( $plugin_slug ) {
		return wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=' . $plugin_slug ), 'install-plugin_' . $plugin_slug );
	}

	private function get_plugin_button_activate_url( $plugin_file_path ) {
		return wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . $plugin_file_path . '&amp;plugin_status=all&amp;paged=1&amp;s', 'activate-plugin_' . $plugin_file_path );
	}

	private function get_plugin_button_connect_url( $plugin_settings_page ) {
		return self_admin_url( $plugin_settings_page );
	}

	private function get_plugin_cta_data( $plugin_slug, $plugin_file_path ) {
		if ( Hints::is_plugin_active( $plugin_slug ) ) {
			return false;
		}

		if ( Hints::is_plugin_installed( $plugin_slug ) ) {
			$url = $this->get_plugin_button_activate_url( $plugin_file_path );
			$cta_text = esc_html__( 'Activate now', 'elementor' );
		} else {
			$url = $this->get_plugin_button_install_url( $plugin_slug );
			$cta_text = esc_html__( 'Install now', 'elementor' );
		}

		return [
			'url' => $url,
			'text' => $cta_text,
		];
	}

	/**
	 * For testing purposes
	 */
	public function get_elementor_version() {
		return ELEMENTOR_VERSION;
	}

	private function notice_plugin_image_optimization() {
		$notice_id = 'plugin_image_optimization';

		if ( 'upload' !== $this->current_screen_id ) {
			return false;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		if ( User::is_user_notice_viewed( $notice_id ) ) {
			return false;
		}

		$attachments = new \WP_Query( [
			'post_type' => 'attachment',
			'post_status' => 'any',
			'fields' => 'ids',
		] );

		if ( 1 > $attachments->found_posts ) {
			return false;
		}

		$plugin_slug = 'image-optimization';
		$plugin_file_path = 'image-optimization/image-optimization.php';

		$one_subscription = Hints::is_plugin_connected_to_one_subscription();
		$is_installed = Hints::is_plugin_installed( $plugin_slug );
		$is_active = Hints::is_plugin_active( $plugin_slug );

		if ( $is_active ) {
			return false;
		}

		if ( $one_subscription ) {
			if ( ! $is_installed ) {
				$description = esc_html__( 'Automatically optimize images to improve site speed and performance. Included with your ONE subscription.', 'elementor' );
				$button_text = esc_html__( 'Install now', 'elementor' );
				$button_url = $this->get_plugin_button_install_url( $plugin_slug );
				$campaign_data = [
					'name' => 'elementor_image_optimization_campaign',
					'campaign' => 'io-plg-one',
					'source' => 'io-wp-media-library-one-install',
					'medium' => 'wp-dash-one',
				];
			} elseif ( ! $is_active ) {
				$description = esc_html__( 'Your ONE subscription includes Image Optimizer. Activate it to optimize images and improve site performance.', 'elementor' );
				$button_text = esc_html__( 'Activate now', 'elementor' );
				$button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
				$campaign_data = [
					'name' => 'elementor_image_optimization_campaign',
					'campaign' => 'io-plg-one',
					'source' => 'io-wp-media-library-one-activate',
					'medium' => 'wp-dash-one',
				];
			}
		} else {
			$description = esc_html__( 'Automatically compress and optimize images, resize larger files, or convert to WebP. Optimize images individually, in bulk, or on upload.', 'elementor' );

			if ( ! $is_installed ) {
				$button_text = esc_html__( 'Install now', 'elementor' );
				$button_url = $this->get_plugin_button_install_url( $plugin_slug );
				$campaign_data = [
					'name' => 'elementor_image_optimization_campaign',
					'campaign' => 'io-plg',
					'source' => 'io-wp-media-library-install',
					'medium' => 'wp-dash',
				];
			} elseif ( ! $is_active ) {
				$button_text = esc_html__( 'Activate now', 'elementor' );
				$button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
				$campaign_data = [
					'name' => 'elementor_image_optimization_campaign',
					'campaign' => 'io-plg',
					'source' => 'io-wp-media-library-activate',
					'medium' => 'wp-dash',
				];
			}
		}

		$options = [
			'title' => esc_html__( 'Speed up your website with Image Optimizer', 'elementor' ),
			'description' => $description,
			'id' => $notice_id,
			'type' => 'cta',
			'button' => [
				'text' => $button_text,
				'url' => self::add_plg_campaign_data( $button_url, $campaign_data ),
				'type' => 'cta',
				'data' => [
					'campaign' => $campaign_data['campaign'],
					'source' => $campaign_data['source'],
					'medium' => $campaign_data['medium'],
				],
			],
		];

		$this->print_admin_notice( $options );

		return true;
	}

	public function print_admin_notice( array $options, $exclude_pages = self::DEFAULT_EXCLUDED_PAGES ) {
		global $pagenow;

		if ( in_array( $pagenow, $exclude_pages, true ) ) {
			return;
		}

		$default_options = [
			'id' => null,
			'title' => '',
			'description' => '',
			'classes' => [ 'notice', 'e-notice' ], // We include WP's default notice class so it will be properly handled by WP's js handler
			'type' => '',
			'dismissible' => true,
			'icon' => 'eicon-elementor-circle',
			'button' => [],
			'button_secondary' => [],
		];

		$options = array_replace_recursive( $default_options, $options );

		$notice_classes = $options['classes'];
		$dismiss_button = '';
		$icon = '';

		if ( $options['type'] ) {
			$notice_classes[] = 'e-notice--' . $options['type'];
		}

		$wrapper_attributes = [
			'role' => 'region',
			'aria-label' => esc_html__( 'Elementor notice', 'elementor' ),
		];

		if ( $options['dismissible'] ) {
			$label = esc_html__( 'Dismiss this notice.', 'elementor' );
			$notice_classes[] = 'e-notice--dismissible';
			$dismiss_button = '<i class="e-notice__dismiss" role="button" aria-label="' . $label . '" tabindex="0"></i>';

			$wrapper_attributes['data-nonce'] = wp_create_nonce( 'elementor_set_admin_notice_viewed' );
		}

		if ( $options['icon'] ) {
			$notice_classes[] = 'e-notice--extended';
			$icon = '<div class="e-notice__icon-wrapper"><i class="' . esc_attr( $options['icon'] ) . '" aria-hidden="true"></i></div>';
		}

		$wrapper_attributes['class'] = $notice_classes;

		if ( $options['id'] ) {
			$wrapper_attributes['data-notice_id'] = $options['id'];
		}

		if ( ! empty( $options['source'] ) ) {
			$wrapper_attributes['data-source'] = $options['source'];
		}
		?>
		<div <?php Utils::print_html_attributes( $wrapper_attributes ); ?>>
			<?php echo $dismiss_button; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
			<div class="e-notice__aside">
				<?php echo $icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
			</div>
			<div class="e-notice__content">
				<?php if ( $options['title'] ) { ?>
					<h3><?php echo wp_kses_post( $options['title'] ); ?></h3>
				<?php } ?>

				<?php if ( $options['description'] ) { ?>
					<p><?php echo wp_kses_post( $options['description'] ); ?></p>
				<?php } ?>

				<?php if ( ! empty( $options['button']['text'] ) || ! empty( $options['button_secondary']['text'] ) ) { ?>
					<div class="e-notice__actions">
						<?php
						$one_subscription = Hints::is_plugin_connected_to_one_subscription();
						foreach ( [ $options['button'], $options['button_secondary'] ] as $index => $button_settings ) {
							if ( empty( $button_settings['variant'] ) && $index ) {
								$button_settings['variant'] = 'outline';
							}

							if ( empty( $button_settings['text'] ) ) {
								continue;
							}

							if ( $one_subscription ) {
								if ( ! isset( $button_settings['classes'] ) ) {
									$button_settings['classes'] = [];
								}
								if ( ! is_array( $button_settings['classes'] ) ) {
									$button_settings['classes'] = [ $button_settings['classes'] ];
								}
								// index 0 = button, index 1 = button_secondary
								$button_class = ( 0 === $index ) ? 'button-primary' : 'button-secondary';
								$button_settings['classes'][] = $button_class;
							}

							$button = new Button( $button_settings );
							$button->print_button();
						} ?>
					</div>
				<?php } ?>
			</div>
		</div>
	<?php }

	public function admin_notices() {
		$this->install_time = Plugin::$instance->get_install_time();
		$this->current_screen_id = get_current_screen()->id;

		foreach ( $this->plain_notices as $notice ) {
			$method_callback = "notice_{$notice}";
			if ( $this->$method_callback() ) {
				return;
			}
		}

		/** @var Base_Notice $notice_instance */
		foreach ( $this->get_notices() as $notice_instance ) {
			if ( ! $notice_instance->should_print() ) {
				continue;
			}

			$this->print_admin_notice( $notice_instance->get_config() );

			// It exits the method to make sure it prints only one notice.
			return;
		}
	}

	public function maybe_log_campaign() {
		if ( empty( $_GET['plg_campaign'] ) || empty( $_GET['plg_campaign_name'] ) ) {
			return;
		}

		$allowed_plgs = [
			'elementor_image_optimization_campaign',
			'elementor_ea11y_campaign',
			'elementor_site_mailer_campaign',
		];

		if ( ! in_array( $_GET['plg_campaign_name'], $allowed_plgs, true ) ) {
			return;
		}

		if ( ! isset( $_GET['plg_campaign_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['plg_campaign_nonce'] ), sanitize_key( $_GET['plg_campaign_name'] ) ) ) {
			return;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		if ( empty( $_GET['plg_source'] ) || empty( $_GET['plg_medium'] ) ) {
			return;
		}

		$campaign_data = [
			'source' => sanitize_key( $_GET['plg_source'] ),
			'campaign' => sanitize_key( $_GET['plg_campaign'] ),
			'medium' => sanitize_key( $_GET['plg_medium'] ),
		];

		set_transient( sanitize_key( $_GET['plg_campaign_name'] ), $campaign_data, 30 * DAY_IN_SECONDS );
	}

	public static function add_plg_campaign_data( $url, $campaign_data ) {

		foreach ( [ 'name', 'campaign' ] as $key ) {
			if ( empty( $campaign_data[ $key ] ) ) {
				return $url;
			}
		}

		return add_query_arg( [
			'plg_campaign_name' => $campaign_data['name'],
			'plg_campaign' => $campaign_data['campaign'],
			'plg_source' => empty( $campaign_data['source'] ) ? '' : $campaign_data['source'],
			'plg_medium' => empty( $campaign_data['medium'] ) ? '' : $campaign_data['medium'],
			'plg_campaign_nonce' => wp_create_nonce( $campaign_data['name'] ),
		], $url );
	}

	/**
	 * @since 2.9.0
	 * @access public
	 */
	public function __construct() {
		add_action( 'admin_notices', [ $this, 'admin_notices' ], 20 );
		add_action( 'admin_action_install-plugin', [ $this, 'maybe_log_campaign' ] );
		add_action( 'admin_action_activate', [ $this, 'maybe_log_campaign' ] );
	}

	/**
	 * Get module name.
	 *
	 * Retrieve the module name.
	 *
	 * @since  2.9.0
	 * @access public
	 *
	 * @return string Module name.
	 */
	public function get_name() {
		return 'admin-notices';
	}
}
PK     Ȝ\jhç      consent.phpnu [        <?php

namespace CookieAdmin\Admin;

if(!defined('COOKIEADMIN_VERSION') || !defined('ABSPATH')){
	die('Hacking Attempt');
}

class Consent{
	
	static function consent_form(){
		global $cookieadmin_lang, $cookieadmin_error, $cookieadmin_msg;
		
		$view = get_option('cookieadmin_law', 'cookieadmin_gdpr');		
		$policy = cookieadmin_load_policy();
		
		$raw_template = cookieadmin_load_consent_template($policy[$view], $view);
		
		if(!is_array($raw_template) || empty($raw_template)){
			return false;
		}

		$templates = implode("", $raw_template);
		
		if(empty($templates)){
			echo '<div class="notice notice-error">
					<p>
						<strong>CookieAdmin Error:</strong> Cannot load required template file. 
						Please reinstall the plugin or contact support.
					</p>
				</div>';
			return false;
		}
		
		$cookieadmin_requires_pro = \CookieAdmin\Admin::is_feature_available(1);
		
		$icons_grid = apply_filters('cookieadmin_reconsent_icons', '', $policy[$view]);

		//Start UI
		\CookieAdmin\Admin::header_theme(__('Consent Form', 'cookieadmin'));

		echo '
		<div class="cookieadmin_consent-wrap">
			<form action="" method="post" id="consent_submenu">
			
			<div class="cookieadmin_consent-contents">
				<div class="cookieadmin_consent_settings">
					<div class="cookieadmin-contents cookieadmin_consent">
					
						<div class="cookieadmin-setting">
							<label class="cookieadmin-title" for="cookieadmin_consent_type">'.esc_html__('Consent Type', 'cookieadmin').'</label>
							<div class="cookieadmin-setting-contents">
								<select name="cookieadmin_consent_type" id="cookieadmin_consent_type">
									<option name="cookieadmin_gdpr" id="cookieadmin_gdpr" '.((!empty($view) && $view === 'cookieadmin_gdpr') ? 'selected' : '').' value="cookieadmin_gdpr">'.esc_html__('GDPR', 'cookieadmin').'</option>
									<option name="cookieadmin_us" id="cookieadmin_us" '.((!empty($view) && $view === 'cookieadmin_us') ? 'selected' : '').' value="cookieadmin_us">'.esc_html__('US State Laws', 'cookieadmin').'</option>
								</select>
							</div>
						</div>
						
						<div class="cookieadmin-setting cookieadmin_consent-expiry">
							<label class="cookieadmin-title" for="cookieadmin_consent_expiry">'.esc_html__('Consent Expiry', 'cookieadmin').'</label>
							<div class="cookieadmin-setting-contents">
								<input type="number" name="cookieadmin_days" id="cookieadmin_consent_expiry" style="max-width:70px;" value="'.esc_attr($policy[$view]['cookieadmin_days']).'">
							</div>
						</div>
						
						<div class="cookieadmin-setting consent-layout">
							<label class="cookieadmin-title">'.esc_html__('Notice Type', 'cookieadmin').'</label>
							<div class="cookieadmin-setting-contents">
								<span>
									<input name="cookieadmin_layout" type="radio" id="cookieadmin_layout_box" value="box">
									<label class="cookieadmin-input" for="cookieadmin_layout_box">'.esc_html__('Box', 'cookieadmin').'</label>
								</span>
								<span>
									<input name="cookieadmin_layout" type="radio" id="cookieadmin_layout_footer" value="footer">
									<label class="cookieadmin-input" for="cookieadmin_layout_footer">'.esc_html__('Footer', 'cookieadmin').'</label>
								</span>
								<span>
									<input name="cookieadmin_layout" type="radio" id="cookieadmin_layout_popup"  value="popup">
									<label for="cookieadmin_layout_popup">'.esc_html__('Popup', 'cookieadmin').'</label>
								</span>
							</div>
						</div>
						
						<div class="cookieadmin-setting consent-position">
							<label class="cookieadmin-title">'.esc_html__('Notice Position', 'cookieadmin').'</label>
							<div class="cookieadmin-setting-contents">
								<span>
									<input class="cookieadmin_box_layout" id="cookieadmin_position_bottom_left" name="cookieadmin_position" type="radio" value="bottom_left" checked>
									<label class="cookieadmin_box_layout cookieadmin-input" for="cookieadmin_position_bottom_left">'.esc_html__('Bottom Left', 'cookieadmin').'</label>
								</span>
								<span>
									<input class="cookieadmin_box_layout" id="cookieadmin_position_bottom_right" name="cookieadmin_position" type="radio" value="bottom_right">
									<label class="cookieadmin_box_layout cookieadmin-input" for="cookieadmin_position_bottom_right">'.esc_html__('Bottom Right', 'cookieadmin').'</label>
								</span>
								<span>
									<input class="cookieadmin_box_layout" id="cookieadmin_position_top_left" name="cookieadmin_position" type="radio" value="top_left">
									<label class="cookieadmin_box_layout cookieadmin-input" for="cookieadmin_position_top_left">'.esc_html__('Top Left', 'cookieadmin').'</label>
								</span>
								<span>
									<input class="cookieadmin_box_layout" id="cookieadmin_position_top_right" name="cookieadmin_position" type="radio" value="top_right">
									<label class="cookieadmin_box_layout cookieadmin-input" for="cookieadmin_position_top_right">'.esc_html__('Top Right', 'cookieadmin').'</label>
								</span>
								<span>
									<input class="cookieadmin_foter_layout" id="cookieadmin_position_top" name="cookieadmin_position" type="radio" value="top" style="display:none;">
									<label class="cookieadmin_foter_layout cookieadmin-input" for="cookieadmin_position_top" style="display:none;">'.esc_html__('Top', 'cookieadmin').'</label>
								</span>
								<span>
									<input class="cookieadmin_foter_layout" id="cookieadmin_position_bottom" name="cookieadmin_position" type="radio" value="bottom" style="display:none;">
									<label class="cookieadmin_foter_layout" for="cookieadmin_position_bottom" style="display:none;">'.esc_html__('Bottom', 'cookieadmin').'</label>
								</span>
							</div>
						</div>
						
						<div class="cookieadmin-setting consent-modal-layout">
							<label class="cookieadmin-title">'.esc_html__('Preference Position', 'cookieadmin').'</label>
							<div class="cookieadmin-setting-contents">
								<span>
									<input id="cookieadmin_modal_center" name="cookieadmin_modal" type="radio" value="center" checked>
									<label class="cookieadmin-input" for="cookieadmin_modal_center">'.esc_html__('Center', 'cookieadmin').'</label>
								</span>
								<span>
									<input id="cookieadmin_modal_side" name="cookieadmin_modal" type="radio" value="side">
									<label class="cookieadmin-input" for="cookieadmin_modal_side">'.esc_html__('Side', 'cookieadmin').'</label>
								</span>
								<span>
									<input id="cookieadmin_modal_down" name="cookieadmin_modal" type="radio" value="down">
									<label for="cookieadmin_modal_down">'.esc_html__('Draw down', 'cookieadmin').'</label>
								</span>
							</div>
						</div>
						
						<div class="cookieadmin-setting consent-notice">
							<label class="cookieadmin-title">'.esc_html__('Notice Section', 'cookieadmin').'</label>
							<div class="cookieadmin-setting-contents cookieadmin-vertical">
								<label for="cookieadmin_notice_title_layout">'.esc_html__('Title', 'cookieadmin').'</label>
								<input type="text" id="cookieadmin_notice_title_layout" name="cookieadmin_notice_title" style="width: 52vw;" value="'.esc_attr($policy[$view]['cookieadmin_notice_title']).'">
								<label for="cookieadmin_notice_layout" style="margin-top:20px;">'.esc_html__('Notice', 'cookieadmin').'</label>
								<textarea rows="5vh" cols="100vw" id="cookieadmin_notice_layout" name="cookieadmin_notice">'.esc_html($policy[$view]['cookieadmin_notice']).'</textarea>
								<div class="cookieadmin-setting-colors cookieadmin-setting-contents cookieadmin-horizontal">
									<div class="cookieadmin-setting-colors cookieadmin-vertical" >
										<label for="cookieadmin_notice_title_color">'.esc_html__('Title', 'cookieadmin').'</label>
										<div class="cookieadmin-color-holder cookieadmin-horizontal">
											<input type="color" id="cookieadmin_notice_title_color_box" name="cookieadmin_notice_title_color_box" value="'.esc_attr($policy[$view]['cookieadmin_notice_title_color']).'">
											<input type="text" id="cookieadmin_notice_title_color" name="cookieadmin_notice_title_color" value="'.esc_attr($policy[$view]['cookieadmin_notice_title_color']).'" class="cookieadmin-color-input">
										</div>
									</div>
									<div class="cookieadmin-setting-colors cookieadmin-vertical">
										<label for="cookieadmin_notice_color">'.esc_html__('Content', 'cookieadmin').'</label>
										<div class="cookieadmin-color-holder cookieadmin-horizontal">
											<input type="color" id="cookieadmin_notice_color_box" name="cookieadmin_notice_color_box" value="'.esc_attr($policy[$view]['cookieadmin_notice_color']).'">
											<input type="text" id="cookieadmin_notice_color" name="cookieadmin_notice_color" value="'.esc_attr($policy[$view]['cookieadmin_notice_color']).'" class="cookieadmin-color-input">
										</div>
									</div>
									<div class="cookieadmin-setting-colors cookieadmin-vertical">
										<label for="cookieadmin_consent_inside_bg_color">'.esc_html__('Background', 'cookieadmin').'</label>
										<div class="cookieadmin-color-holder cookieadmin-horizontal">
											<input type="color" id="cookieadmin_consent_inside_bg_color_box" name="cookieadmin_consent_inside_bg_color_box" value="'.esc_attr($policy[$view]['cookieadmin_consent_inside_bg_color']).'">
											<input type="text" id="cookieadmin_consent_inside_bg_color" name="cookieadmin_consent_inside_bg_color" value="'.esc_attr($policy[$view]['cookieadmin_consent_inside_bg_color']).'" class="cookieadmin-color-input">
										</div>
									</div>
									<div class="cookieadmin-setting-colors cookieadmin-vertical">
										<label for="cookieadmin_consent_inside_border_color">'.esc_html__('Border', 'cookieadmin').'</label>
										<div class="cookieadmin-color-holder cookieadmin-horizontal">
											<input type="color" id="cookieadmin_consent_inside_border_color_box" name="cookieadmin_consent_inside_border_color_box" value="'.esc_attr($policy[$view]['cookieadmin_consent_inside_border_color']).'">
											<input type="text" id="cookieadmin_consent_inside_border_color" name="cookieadmin_consent_inside_border_color" value="'.esc_attr($policy[$view]['cookieadmin_consent_inside_border_color']).'" class="cookieadmin-color-input">
										</div>
									</div>
								</div>
							</div>
						</div>
					</div>
					<div class="cookieadmin-setting">
						<label class="cookieadmin-title">'.esc_html__('Buttons', 'cookieadmin').'</label>
						<div class="cookieadmin-buttons cookieadmin-setting-contents cookieadmin-horizontal">
							<div class="cookieadmin-button cookieadmin-vertical">
								<input id="cookieadmin_customize_btn" name="cookieadmin_customize_btn" style="max-width:130px;text-align:center;" value="'.esc_attr($policy[$view]['cookieadmin_customize_btn']).'">
								<div class="cookieadmin-color-holder cookieadmin-horizontal">
									<input type="color" id="cookieadmin_customize_btn_color_box" name="cookieadmin_customize_btn_color_box" value="'.esc_attr($policy[$view]['cookieadmin_customize_btn_color']).'">
									<input type="text" id="cookieadmin_customize_btn_color" name="cookieadmin_customize_btn_color" value="'.esc_attr($policy[$view]['cookieadmin_customize_btn_color']).'" class="cookieadmin-color-input">
								</div>
								<div class="cookieadmin-color-holder cookieadmin-horizontal">
									<input type="color" id="cookieadmin_customize_btn_bg_color_box" name="cookieadmin_customize_btn_bg_color_box" value="'.esc_attr($policy[$view]['cookieadmin_customize_btn_bg_color']).'">
									<input type="text" id="cookieadmin_customize_btn_bg_color" name="cookieadmin_customize_btn_bg_color" value="'.esc_attr($policy[$view]['cookieadmin_customize_btn_bg_color']).'" class="cookieadmin-color-input">
								</div>
							</div>
							<div class="cookieadmin-button cookieadmin-vertical">
								<input id="cookieadmin_reject_btn" name="cookieadmin_reject_btn" style="max-width:130px;text-align:center;" value="'.esc_attr($policy[$view]['cookieadmin_reject_btn']).'">
								<div class="cookieadmin-color-holder cookieadmin-horizontal">
									<input type="color" id="cookieadmin_reject_btn_color_box" name="cookieadmin_reject_btn_color_box" value="'.esc_attr($policy[$view]['cookieadmin_reject_btn_color']).'">
									<input type="text" id="cookieadmin_reject_btn_color" name="cookieadmin_reject_btn_color" value="'.esc_attr($policy[$view]['cookieadmin_reject_btn_color']).'" class="cookieadmin-color-input">
								</div>
								<div class="cookieadmin-color-holder cookieadmin-horizontal">
									<input type="color" id="cookieadmin_reject_btn_bg_color_box" name="cookieadmin_reject_btn_bg_color_box" value="'.esc_attr($policy[$view]['cookieadmin_reject_btn_bg_color']).'">
									<input type="text" id="cookieadmin_reject_btn_bg_color" name="cookieadmin_reject_btn_bg_color" value="'.esc_attr($policy[$view]['cookieadmin_reject_btn_bg_color']).'" class="cookieadmin-color-input">
								</div>
							</div>
							<div class="cookieadmin-button cookieadmin-vertical">
								<input id="cookieadmin_accept_btn" name="cookieadmin_accept_btn" style="max-width:130px;text-align:center;" value="'.esc_attr($policy[$view]['cookieadmin_accept_btn']).'">
								<div class="cookieadmin-color-holder cookieadmin-horizontal">
									<input type="color" id="cookieadmin_accept_btn_color_box" name="cookieadmin_accept_btn_color_box" value="'.esc_attr($policy[$view]['cookieadmin_accept_btn_color']).'">
									<input type="text" id="cookieadmin_accept_btn_color" name="cookieadmin_accept_btn_color" value="'.esc_attr($policy[$view]['cookieadmin_accept_btn_color']).'" class="cookieadmin-color-input">
								</div>
								<div class="cookieadmin-color-holder cookieadmin-horizontal">
									<input type="color" id="cookieadmin_accept_btn_bg_color_box" name="cookieadmin_accept_btn_bg_color_box" value="'.esc_attr($policy[$view]['cookieadmin_accept_btn_bg_color']).'">
									<input type="text" id="cookieadmin_accept_btn_bg_color" name="cookieadmin_accept_btn_bg_color" value="'.esc_attr($policy[$view]['cookieadmin_accept_btn_bg_color']).'" class="cookieadmin-color-input">
								</div>
							</div>
							<div class="cookieadmin-button cookieadmin-vertical">
								<input id="cookieadmin_save_btn" name="cookieadmin_save_btn" style="max-width:130px;text-align:center;" value="'.esc_attr($policy[$view]['cookieadmin_save_btn']).'">
								<div class="cookieadmin-color-holder cookieadmin-horizontal">
									<input type="color" id="cookieadmin_save_btn_color_box" name="cookieadmin_save_btn_color_box" value="'.esc_attr($policy[$view]['cookieadmin_save_btn_color']).'">
									<input type="text" id="cookieadmin_save_btn_color" name="cookieadmin_save_btn_color" value="'.esc_attr($policy[$view]['cookieadmin_save_btn_color']).'" class="cookieadmin-color-input">
								</div>
								<div class="cookieadmin-color-holder cookieadmin-horizontal">
									<input type="color" id="cookieadmin_save_btn_bg_color_box" name="cookieadmin_save_btn_bg_color_box" value="'.esc_attr($policy[$view]['cookieadmin_save_btn_bg_color']).'">
									<input type="text" id="cookieadmin_save_btn_bg_color" name="cookieadmin_save_btn_bg_color" value="'.esc_attr($policy[$view]['cookieadmin_save_btn_bg_color']).'" class="cookieadmin-color-input">
								</div>
							</div>
						</div>
					</div>
					<div class="cookieadmin-setting consent-preference">
						<label class="cookieadmin-title">'.esc_html__('Preference Section', 'cookieadmin').'</label>
						<div class="cookieadmin-setting-contents cookieadmin-vertical">
							<label for="cookieadmin_preference_title_layout">'.esc_html__('Title', 'cookieadmin').'</label>
							<input type="text" id="cookieadmin_preference_title_layout" name="cookieadmin_preference_title" style="width: 52vw;" value="'.esc_html($policy[$view]['cookieadmin_preference_title']).'">
							<label for="cookieadmin_preference_layout" style="margin-top:20px;">'.esc_html__('Privacy Notice', 'cookieadmin').'</label>
							<textarea rows="8vh" cols="100vw" id="cookieadmin_preference_layout" name="cookieadmin_preference">'.esc_html($policy[$view]['cookieadmin_preference']).'</textarea>
							<div class="cookieadmin-setting-colors cookieadmin-setting-contents cookieadmin-horizontal">
								<div class="cookieadmin-setting-colors cookieadmin-vertical">
									<label for="cookieadmin_preference_title_color">'.esc_html__('Title', 'cookieadmin').'</label>
									<div class="cookieadmin-color-holder cookieadmin-horizontal">
										<input type="color" id="cookieadmin_preference_title_color_box" name="cookieadmin_preference_title_color_box" value="'.esc_attr($policy[$view]['cookieadmin_preference_title_color']).'">
										<input type="text" id="cookieadmin_preference_title_color" name="cookieadmin_preference_title_color" value="'.esc_attr($policy[$view]['cookieadmin_preference_title_color']).'" class="cookieadmin-color-input">
									</div>
								</div>
								<div class="cookieadmin-setting-colors cookieadmin-vertical">
									<label for="cookieadmin_details_wrapper_color">'.esc_html__('Content', 'cookieadmin').'</label>
									<div class="cookieadmin-color-holder cookieadmin-horizontal">
										<input type="color" id="cookieadmin_details_wrapper_color_box" name="cookieadmin_details_wrapper_color_box" value="'.esc_attr($policy[$view]['cookieadmin_details_wrapper_color']).'">
										<input type="text" id="cookieadmin_details_wrapper_color" name="cookieadmin_details_wrapper_color" value="'.esc_attr($policy[$view]['cookieadmin_details_wrapper_color']).'" class="cookieadmin-color-input">
									</div>
								</div>
								<div class="cookieadmin-setting-colors cookieadmin-vertical">
									<label for="cookieadmin_cookie_modal_bg_color">'.esc_html__('Background', 'cookieadmin').'</label>
									<div class="cookieadmin-color-holder cookieadmin-horizontal">
										<input type="color" id="cookieadmin_cookie_modal_bg_color_box" name="cookieadmin_cookie_modal_bg_color_box" value="'.esc_attr($policy[$view]['cookieadmin_cookie_modal_bg_color']).'">
										<input type="text" id="cookieadmin_cookie_modal_bg_color" name="cookieadmin_cookie_modal_bg_color" value="'.esc_attr($policy[$view]['cookieadmin_cookie_modal_bg_color']).'" class="cookieadmin-color-input">
									</div>
								</div>
								<div class="cookieadmin-setting-colors cookieadmin-vertical">
									<label for="cookieadmin_cookie_modal_border_color">'.esc_html__('Border', 'cookieadmin').'</label>
									<div class="cookieadmin-color-holder cookieadmin-horizontal">
										<input type="color" id="cookieadmin_cookie_modal_border_color_box" name="cookieadmin_cookie_modal_border_color_box" value="'.esc_attr($policy[$view]['cookieadmin_cookie_modal_border_color']).'">
										<input type="text" id="cookieadmin_cookie_modal_border_color" name="cookieadmin_cookie_modal_border_color" value="'.esc_attr($policy[$view]['cookieadmin_cookie_modal_border_color']).'" class="cookieadmin-color-input">
									</div>
								</div>
							</div>
							
							<div class="cookieadmin-setting-colors cookieadmin-setting-contents cookieadmin-horizontal" cookieadmin-pro-only="1">
								<div class="cookieadmin-setting-color cookieadmin-vertical">
									<label for="cookieadmin_links_color">'.esc_html__('Links', 'cookieadmin').wp_kses_post($cookieadmin_requires_pro).'</label>
									<div class="cookieadmin-color-holder cookieadmin-horizontal">
										<input type="color" id="cookieadmin_links_color_box" name="cookieadmin_links_color_box" value="'.esc_attr($policy[$view]['cookieadmin_links_color']).'">
										<input type="text" id="cookieadmin_links_color" name="cookieadmin_links_color" value="'.esc_attr($policy[$view]['cookieadmin_links_color']).'" class="cookieadmin-color-input">
									</div>
								</div>
								<div class="cookieadmin-setting-colors cookieadmin-vertical">
									<label for="cookieadmin_slider_on_bg_color">'.esc_html__('Button Switch On', 'cookieadmin').wp_kses_post($cookieadmin_requires_pro).'</label>
									<div class="cookieadmin-color-holder cookieadmin-horizontal">
										<input type="color" id="cookieadmin_slider_on_bg_color_box" name="cookieadmin_slider_on_bg_color_box" value="'.esc_attr($policy[$view]['cookieadmin_slider_on_bg_color']).'">
										<input type="text" id="cookieadmin_slider_on_bg_color" name="cookieadmin_slider_on_bg_color" value="'.esc_attr($policy[$view]['cookieadmin_slider_on_bg_color']).'" class="cookieadmin-color-input">
									</div>
								</div>
								<div class="cookieadmin-setting-colors cookieadmin-vertical">
									<label for="cookieadmin_slider_off_bg_color">'.esc_html__('Button Switch Off', 'cookieadmin').wp_kses_post($cookieadmin_requires_pro).'</label>
									<div class="cookieadmin-color-holder cookieadmin-horizontal">
										<input type="color" id="cookieadmin_slider_off_bg_color_box" name="cookieadmin_slider_off_bg_color_box" value="'.esc_attr($policy[$view]['cookieadmin_slider_off_bg_color']).'">
										<input type="text" id="cookieadmin_slider_off_bg_color" name="cookieadmin_slider_off_bg_color" value="'.esc_attr($policy[$view]['cookieadmin_slider_off_bg_color']).'" class="cookieadmin-color-input">
									</div>
								</div>
							</div>
							
						</div>
					</div>
					
					<div class="cookieadmin-setting reconsent">
						<label class="cookieadmin-title">'.esc_html__('Re-consent Icon', 'cookieadmin').wp_kses_post($cookieadmin_requires_pro).'</label>
						<div class="cookieadmin-setting-contents cookieadmin-vertical" cookieadmin-pro-only="1">
						
							<div class="cookieadmin-setting-contents cookieadmin-reconsent-icons-grid">
								' . wp_kses($icons_grid, cookieadmin_kses_allowed_html()) . '
								<div class="cookieadmin-custom-reconsent-url">
									<input type="text" id="cookieadmin_reconsent_img_url" name="cookieadmin_reconsent_img_url" style="width: 50vw;" placeholder="'.esc_attr__('Insert custom icon url here', 'cookieadmin').'" value="'.(!empty($policy[$view]['cookieadmin_reconsent_img_url']) ? esc_attr($policy[$view]['cookieadmin_reconsent_img_url']) : '').'">
								</div>
								<div class="cookieadmin-reconsent-file-upload">
									<input type="button" class="button button-secondary" id="cookieadmin_upload_icon_btn" value="'.esc_attr__( 'Upload Icon', 'cookieadmin' ).'">
								</div>
							</div>
							
							<div class="cookieadmin-setting-contents cookieadmin-setting-colors cookieadmin-horizontal">
								<div class="cookieadmin-setting-colors cookieadmin-vertical">
									<label for="cookieadmin_re_consent_bg_color">'.esc_html__('Background', 'cookieadmin').'</label>
									<div class="cookieadmin-color-holder cookieadmin-horizontal">
										<input type="color" id="cookieadmin_re_consent_bg_color_box" name="cookieadmin_re_consent_bg_color_box" value="'.(!empty($policy[$view]['cookieadmin_re_consent_bg_color']) ? esc_attr($policy[$view]['cookieadmin_re_consent_bg_color']) : '#374FD4').'">
										<input type="text" id="cookieadmin_re_consent_bg_color" name="cookieadmin_re_consent_bg_color" value="'.(!empty($policy[$view]['cookieadmin_re_consent_bg_color']) ? esc_attr($policy[$view]['cookieadmin_re_consent_bg_color']) : '#374FD4').'" class="cookieadmin-color-input">
									</div>
								</div>
							</div>					
						</div>
					</div>
					<div class="cookieadmin-setting">
						<label class="cookieadmin-title">'.esc_html__('Policy Links', 'cookieadmin').wp_kses_post($cookieadmin_requires_pro).'</label>
						<div class="cookieadmin-setting-contents cookieadmin-vertical cookieadmin-policy-links" cookieadmin-pro-only="1">
							<div class="cookieadmin-policy-link cookieadmin-vertical">
									<label for="cookieadmin_privacy_policy">'.esc_html__('Privacy Policy', 'cookieadmin').'</label>
									<input type="text" id="cookieadmin_privacy_policy" name="cookieadmin_privacy_policy" style="width: 61vw;" placeholder="'.__('Insert Privacy Policy link here...', 'cookieadmin').'" value="'.(!empty($policy[$view]['cookieadmin_privacy_policy']) ? esc_attr($policy[$view]['cookieadmin_privacy_policy']) : '').'">
							</div>
							<div class="cookieadmin-policy-link cookieadmin-vertical">
									<label for="cookieadmin_cookie_policy">'.esc_html__('Cookie Policy', 'cookieadmin').'</label>
									<input type="text" id="cookieadmin_cookie_policy" name="cookieadmin_cookie_policy" style="width: 61vw;" placeholder="'.__('Insert Cookie Policy link here...', 'cookieadmin').'" value="'.(!empty($policy[$view]['cookieadmin_cookie_policy']) ? esc_attr($policy[$view]['cookieadmin_cookie_policy']) : '').'">
							</div>
							
							<div class="cookieadmin-vertical">
								<label for="cookieadmin_privacy_policy_visibility">'.esc_html__('Visiblity', 'cookieadmin').'</label>
								<div class="cookieadmin-horizontal cookieadmin-privacy-policy-visibility">
									<span>
										<input type="checkbox" id="cookieadmin_privacy_policy_banner" name="cookieadmin_privacy_policy_banner" '.(!empty($policy[$view]['cookieadmin_privacy_policy_banner']) ? 'checked' : '').'>
										<label for="cookieadmin_privacy_policy_banner">'.esc_html__('Banner', 'cookieadmin').'</label>
									</span>
									<span>
										<input type="checkbox" id="cookieadmin_privacy_policy_pref" name="cookieadmin_privacy_policy_pref" '.(!empty($policy[$view]['cookieadmin_privacy_policy_pref']) ? 'checked' : '').'>
										<label for="cookieadmin_privacy_policy_pref">'.esc_html__('Preference', 'cookieadmin').'</label>
									</span>
								</div>
							</div>
							
							<div class="cookieadmin-horizontal">
								<div class="cookieadmin-setting-colors cookieadmin-vertical">
									<label for="cookieadmin_policy_link_color">'.esc_html__('Link', 'cookieadmin').'</label>
									<div class="cookieadmin-color-holder cookieadmin-horizontal">
										<input type="color" id="cookieadmin_policy_link_color_box" name="cookieadmin_policy_link_color_box" value="'.(!empty($policy[$view]['cookieadmin_policy_link_color']) ? esc_attr($policy[$view]['cookieadmin_policy_link_color']) : '').'">
										<input type="text" id="cookieadmin_policy_link_color" name="cookieadmin_policy_link_color" value="'.(!empty($policy[$view]['cookieadmin_policy_link_color']) ? esc_attr($policy[$view]['cookieadmin_policy_link_color']) : '').'" class="cookieadmin-color-input">
									</div>
								</div>
							</div>					
						</div>
					</div>
					
					<div class="cookieadmin-setting cookieadmin-save-settings">
						<div class="cookieadmin-setting-contents">
							<input type="submit" name="cookieadmin_save_settings" class="cookieadmin-btn cookieadmin-btn-primary action" value="'.esc_html__('Save Settings', 'cookieadmin').'">
							<input type="button" id="cookieadmin_show_preview" name="cookieadmin_show_preview" class="cookieadmin-btn cookieadmin-btn-secondary" value="'.esc_html__('Show Preview', 'cookieadmin').'">
						<div>
					<div>
				</div>
			</div>
			';	
			wp_nonce_field('cookieadmin_admin_nonce', 'cookieadmin_security');
			echo '<br/>
			<br/>
			</form>
		</div>';
		\CookieAdmin\Admin::footer_theme();
		
		$allowed_tags = cookieadmin_kses_allowed_html();
		echo wp_kses($templates, $allowed_tags);
	}
	
	static function save_consent_form(){
		global $cookieadmin_lang, $cookieadmin_error, $cookieadmin_msg, $cookieadmin_settings, $cookieadmin_policies;
		// debug_print_backtrace();die;
		
		check_admin_referer('cookieadmin_admin_nonce', 'cookieadmin_security');
		
		if(!current_user_can('administrator')){
			wp_send_json_error(array('message' => __('Sorry, but you do not have permissions to perform this action', 'cookieadmin')));
		}
		
		$policy = cookieadmin_load_policy();
		
		$cookieadmin_consent_type = isset( $_REQUEST['cookieadmin_consent_type'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['cookieadmin_consent_type'] ) ) : '';
		
		if(!empty($cookieadmin_consent_type)){
			
			$laws = array('cookieadmin_gdpr' => '', 'cookieadmin_us' => '');
			
			$law = array_key_exists($cookieadmin_consent_type, $laws) ? $cookieadmin_consent_type : 'cookieadmin_gdpr';
			
			if(empty($cookieadmin_error)){
				update_option('cookieadmin_law', $law);
			}
		}
		
		$setting['cookieadmin_geo_tgt'] = (!empty($_REQUEST['cookieadmin_geo_tgt'])) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_geo_tgt'])) : 'www';
		
		$setting['cookieadmin_layout'] = (!empty($_REQUEST['cookieadmin_layout']) && in_array($_REQUEST['cookieadmin_layout'], array('box', 'footer', 'popup'))) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_layout'])) : (!empty($policy[$law]['cookieadmin_layout']) ? $policy[$law]['cookieadmin_layout'] : 'box');
		
		$setting['cookieadmin_position'] = (!empty($_REQUEST['cookieadmin_position']) && in_array($_REQUEST['cookieadmin_position'],  array('bottom_left', 'bottom_right', 'top_left', 'top_right', 'top', 'bottom'))) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_position'])) : (!empty($policy[$law]['cookieadmin_position']) ? $policy[$law]['cookieadmin_position'] : 'bottom_left');

		$setting['cookieadmin_modal'] = (isset($_REQUEST['cookieadmin_modal']) && in_array($_REQUEST['cookieadmin_modal'], array('center', 'side', 'down'))) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_modal'])) : (!empty($policy[$law]['cookieadmin_modal']) ? $policy[$law]['cookieadmin_modal'] : 'center');
		
		if($setting['cookieadmin_layout'] == 'popup'){
			$setting['cookieadmin_modal'] = 'center';
			unset($setting['cookieadmin_position']);
		}		

		$setting['cookieadmin_notice_title'] = !empty($_REQUEST['cookieadmin_notice_title']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_notice_title'])) : $policy[$law]['cookieadmin_notice_title'];
		$setting['cookieadmin_notice_title_color'] = !empty($_REQUEST['cookieadmin_notice_title_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_notice_title_color'])) : (!empty($policy[$law]['cookieadmin_notice_title_color']) ? $policy[$law]['cookieadmin_notice_title_color'] : '#000000');
		
		$setting['cookieadmin_notice'] = !empty($_REQUEST['cookieadmin_notice']) ? wp_kses(wp_unslash($_REQUEST['cookieadmin_notice']), cookieadmin_kses_allowed_html()) : $policy[$law]['cookieadmin_notice'];
		$setting['cookieadmin_notice_color'] = !empty($_REQUEST['cookieadmin_notice_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_notice_color'])) : (!empty($policy[$law]['cookieadmin_notice_color']) ? $policy[$law]['cookieadmin_notice_color'] : '#000000');
		
		$setting['cookieadmin_consent_inside_bg_color'] = !empty($_REQUEST['cookieadmin_consent_inside_bg_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_consent_inside_bg_color'])) : (!empty($policy[$law]['cookieadmin_consent_inside_bg_color']) ? $policy[$law]['cookieadmin_consent_inside_bg_color'] : '#ffffff');
		$setting['cookieadmin_consent_inside_border_color'] = !empty($_REQUEST['cookieadmin_consent_inside_border_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_consent_inside_border_color'])) : (!empty($policy[$law]['cookieadmin_consent_inside_border_color']) ? $policy[$law]['cookieadmin_consent_inside_border_color'] : '#000000');
		
		$setting['cookieadmin_customize_btn'] = !empty($_REQUEST['cookieadmin_customize_btn']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_customize_btn'])) : (!empty($policy[$law]['cookieadmin_customize_btn']) ? $policy[$law]['cookieadmin_customize_btn'] : 'Customize');
		$setting['cookieadmin_customize_btn_color'] = !empty($_REQUEST['cookieadmin_customize_btn_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_customize_btn_color'])) : (!empty($policy[$law]['cookieadmin_customize_btn_color']) ? $policy[$law]['cookieadmin_customize_btn_color'] : '#ffffff');
		$setting['cookieadmin_customize_btn_bg_color'] = !empty($_REQUEST['cookieadmin_customize_btn_bg_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_customize_btn_bg_color'])) : (!empty($policy[$law]['cookieadmin_customize_btn_bg_color']) ? $policy[$law]['cookieadmin_customize_btn_bg_color'] : '#0000ff');
		
		$setting['cookieadmin_reject_btn'] = !empty($_REQUEST['cookieadmin_reject_btn']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_reject_btn'])) : (!empty($policy[$law]['cookieadmin_reject_btn']) ? $policy[$law]['cookieadmin_reject_btn'] : 'Reject All');
		$setting['cookieadmin_reject_btn_color'] = !empty($_REQUEST['cookieadmin_reject_btn_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_reject_btn_color'])) : (!empty($policy[$law]['cookieadmin_reject_btn_color']) ? $policy[$law]['cookieadmin_reject_btn_color'] : '#ffffff');
		$setting['cookieadmin_reject_btn_bg_color'] = !empty($_REQUEST['cookieadmin_reject_btn_bg_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_reject_btn_bg_color'])) : (!empty($policy[$law]['cookieadmin_reject_btn_bg_color']) ? $policy[$law]['cookieadmin_reject_btn_bg_color'] : '#ff0000');

		$setting['cookieadmin_accept_btn'] = !empty($_REQUEST['cookieadmin_accept_btn']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_accept_btn'])) : (!empty($policy[$law]['cookieadmin_accept_btn']) ? $policy[$law]['cookieadmin_accept_btn'] : 'Accept All');
		$setting['cookieadmin_accept_btn_color'] = !empty($_REQUEST['cookieadmin_accept_btn_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_accept_btn_color'])) : (!empty($policy[$law]['cookieadmin_accept_btn']) ? $policy[$law]['cookieadmin_accept_btn_color'] : '#ffffff');
		$setting['cookieadmin_accept_btn_bg_color'] = !empty($_REQUEST['cookieadmin_accept_btn_bg_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_accept_btn_bg_color'])) : (!empty($policy[$law]['cookieadmin_accept_btn_bg_color']) ? $policy[$law]['cookieadmin_accept_btn_bg_color'] : '#00ff00');

		$setting['cookieadmin_save_btn'] = !empty($_REQUEST['cookieadmin_save_btn']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_save_btn'])) : (!empty($policy[$law]['cookieadmin_save_btn']) ? $policy[$law]['cookieadmin_save_btn'] : 'Save Preferences');
		$setting['cookieadmin_save_btn_color'] = !empty($_REQUEST['cookieadmin_save_btn_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_save_btn_color'])) : (!empty($policy[$law]['cookieadmin_save_btn_color']) ? $policy[$law]['cookieadmin_save_btn_color'] : '#ffffff');
		$setting['cookieadmin_save_btn_bg_color'] = !empty($_REQUEST['cookieadmin_save_btn_bg_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_save_btn_bg_color'])) : (!empty($policy[$law]['cookieadmin_save_btn_bg_color']) ? $policy[$law]['cookieadmin_save_btn_bg_color'] : '#183833');

		$setting['cookieadmin_preference_title'] = !empty($_REQUEST['cookieadmin_preference_title']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_preference_title'])) : $policy[$law]['cookieadmin_preference_title'];
		$setting['cookieadmin_preference_title_color'] = !empty($_REQUEST['cookieadmin_preference_title_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_preference_title_color'])) : (!empty($policy[$law]['cookieadmin_preference_title_color']) ? $policy[$law]['cookieadmin_preference_title_color'] : '#000000');
		
		$setting['cookieadmin_preference'] = !empty($_REQUEST['cookieadmin_preference']) ? wp_kses(wp_unslash($_REQUEST['cookieadmin_preference']), cookieadmin_kses_allowed_html()) : $policy[$law]['cookieadmin_preference'];
		$setting['cookieadmin_details_wrapper_color'] = !empty($_REQUEST['cookieadmin_details_wrapper_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_details_wrapper_color'])) : (!empty($policy[$law]['cookieadmin_details_wrapper_color']) ? $policy[$law]['cookieadmin_details_wrapper_color'] : '#000000');
		
		$setting['cookieadmin_cookie_modal_bg_color'] = !empty($_REQUEST['cookieadmin_cookie_modal_bg_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_cookie_modal_bg_color'])) : (!empty($policy[$law]['cookieadmin_cookie_modal_bg_color']) ? $policy[$law]['cookieadmin_cookie_modal_bg_color'] : '#ffffff');
		$setting['cookieadmin_cookie_modal_border_color'] = !empty($_REQUEST['cookieadmin_cookie_modal_border_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_cookie_modal_border_color'])) : (!empty($policy[$law]['cookieadmin_cookie_modal_border_color']) ? $policy[$law]['cookieadmin_cookie_modal_border_color'] : '#000000');

		$setting['cookieadmin_slider_off_bg_color'] = !empty($_REQUEST['cookieadmin_slider_off_bg_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_slider_off_bg_color'])) : (!empty($policy[$law]['cookieadmin_slider_off_bg_color']) ? $policy[$law]['cookieadmin_slider_off_bg_color'] : '#808080');
		$setting['cookieadmin_slider_on_bg_color'] = !empty($_REQUEST['cookieadmin_slider_on_bg_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_slider_on_bg_color'])) : (!empty($policy[$law]['cookieadmin_slider_on_bg_color']) ? $policy[$law]['cookieadmin_slider_on_bg_color'] : '#3582c4');
		$setting['cookieadmin_links_color'] = !empty($_REQUEST['cookieadmin_links_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_links_color'])) : (!empty($policy[$law]['cookieadmin_links_color']) ? $policy[$law]['cookieadmin_links_color'] : '#1863dc');
		
		// Set Reconsent Icons 
		$setting['cookieadmin_reconsent_icon'] = !empty($_REQUEST['cookieadmin_reconsent_icon']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_reconsent_icon'])) : '';
		$setting['cookieadmin_reconsent_img_url'] = !empty($_REQUEST['cookieadmin_reconsent_img_url']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_reconsent_img_url'])) : '';
		$setting['cookieadmin_re_consent_bg_color'] = !empty($_REQUEST['cookieadmin_re_consent_bg_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_re_consent_bg_color'])) : (!empty($policy[$law]['cookieadmin_re_consent_bg_color']) ? $policy[$law]['cookieadmin_re_consent_bg_color'] : '#374FD4');

		// Set Policy Links
		$setting['cookieadmin_privacy_policy'] = !empty($_REQUEST['cookieadmin_privacy_policy']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_privacy_policy'])) : '';
		$setting['cookieadmin_cookie_policy'] = !empty($_REQUEST['cookieadmin_cookie_policy']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_cookie_policy'])) : '';
		$setting['cookieadmin_privacy_policy_banner'] = !empty($_REQUEST['cookieadmin_privacy_policy_banner']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_privacy_policy_banner'])) : 0;
		$setting['cookieadmin_privacy_policy_pref'] = !empty($_REQUEST['cookieadmin_privacy_policy_pref']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_privacy_policy_pref'])) : 0;
		$setting['cookieadmin_policy_link_color'] = !empty($_REQUEST['cookieadmin_policy_link_color']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_policy_link_color'])) : '#cbba8d';
		
		$setting['cookieadmin_days'] = !empty($_REQUEST['cookieadmin_days']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_days'])) : (!empty($policy[$law]['cookieadmin_days']) ? $policy[$law]['cookieadmin_days'] : '365');
		
		$policy[$law] = $setting;
		
		// Check for certain fields to be saved only if their values is not the same as default
		$cookieadmin_check_changes = array('cookieadmin_notice_title', 'cookieadmin_notice', 'cookieadmin_preference_title', 'cookieadmin_preference', 'reConsent_title', 'cookieadmin_customize_btn', 'cookieadmin_reject_btn', 'cookieadmin_accept_btn', 'cookieadmin_save_btn');
		
		foreach($cookieadmin_check_changes as $c_field){
			foreach($policy as $c_law => $c_val){
				if(!empty($c_val[$c_field]) && $c_val[$c_field] == $cookieadmin_policies[$c_law][$c_field]){
					unset($policy[$c_law][$c_field]);
				}
			}
		}
		
		update_option('cookieadmin_consent_settings', $policy);
		
		if(empty($cookieadmin_error)){
			$cookieadmin_msg = __('Settings saved successfully', 'cookieadmin');
		}
	}
}PK     Ȝ\1ut
  t
    dashboard.phpnu [        <?php

namespace CookieAdmin\Admin;

if(!defined('COOKIEADMIN_VERSION') || !defined('ABSPATH')){
	die('Hacking Attempt');
}

class Dashboard{
	
	static function dashboard(){
		
		global $cookieadmin_lang, $cookieadmin_error, $cookieadmin_msg, $cookieadmin_settings;
		
		\CookieAdmin\Admin::header_theme(__('Dashboard', 'cookieadmin'));
		
		$view = get_option('cookieadmin_law', 'cookieadmin_gdpr');
		
		echo '
		<div class="cookieadmin_consent-wrap">
			<div class="cookieadmin-admin-row">
				<div class="cookieadmin-stats-block cookieadmin-is-block-25">
					<div class="cookieadmin-stats-name">'.esc_html__('Consent Banner', 'cookieadmin').'</div>
					<div class="cookieadmin-stats-number cookieadmin-green">'.esc_html__('Enabled', 'cookieadmin').'</div>
				</div>
				
				<div class="cookieadmin-stats-block cookieadmin-is-block-25">
					<div class="cookieadmin-stats-name">'.esc_html__('Consent Type', 'cookieadmin').'&nbsp;
						<div class="cookieadmin-block-link"><a href="'.esc_url(admin_url('admin.php?page=cookieadmin-consent')).'">['.esc_html__('Edit', 'cookieadmin').']</a></div>
					</div>
					<div class="cookieadmin-stats-number cookieadmin-uppercase">'.(!empty($view) && $view == 'cookieadmin_us' ? esc_html__('US State Laws', 'cookieadmin') : esc_html__('GDPR', 'cookieadmin')).'</div>
				</div>
				
				<div class="cookieadmin-stats-block cookieadmin-is-block-25">
					<div class="cookieadmin-stats-name">'.esc_html__('Google Consent Mode v2', 'cookieadmin').'&nbsp;
						<div class="cookieadmin-block-link"><a href="'.esc_url(admin_url('admin.php?page=cookieadmin-settings')).'">['.esc_html__('Edit', 'cookieadmin').']</a></div>
					</div>
					'.(!empty($cookieadmin_settings['google_consent_mode_v2']) ? '<div class="cookieadmin-stats-number cookieadmin-green">'.esc_html__('Enabled', 'cookieadmin').'</div>' : '<div class="cookieadmin-stats-number">'.esc_html__('Disabled', 'cookieadmin').'</div>').'
				</div>
				
				<div class="cookieadmin-stats-block cookieadmin-is-block-25">
					<div class="cookieadmin-stats-name">'.esc_html__('Auto Scan', 'cookieadmin').'&nbsp;
						<div class="cookieadmin-block-link"><a href="'.esc_url(admin_url('admin.php?page=cookieadmin-settings')).'">['.esc_html__('Edit', 'cookieadmin').']</a></div>
					</div>
					'.(!empty($cookieadmin_settings['cookieadmin_auto_scan']) ? '<div class="cookieadmin-stats-number cookieadmin-green">'.esc_html__('Enabled', 'cookieadmin').'</div>' : '<div class="cookieadmin-stats-number">'.esc_html__('Disabled', 'cookieadmin').'</div>').'
				</div>
				
				<div style="width:25%">
					
				</div>
			</div>
		</div>';
		
		\CookieAdmin\Admin::footer_theme();
	}
}PK     Ȝ\NL|OYL  YL    scan.phpnu [        <?php

namespace CookieAdmin\Admin;

if(!defined('COOKIEADMIN_VERSION') || !defined('ABSPATH')){
	die('Hacking Attempt');
}

class Scan{
	
	static function show_cookies(){
		global $cookieadmin_lang, $cookieadmin_error, $cookieadmin_msg, $wpdb;
		
		\CookieAdmin\Admin::header_theme(__('Manage Cookies', 'cookieadmin'));
		
		$cookieadmin_requires_pro = \CookieAdmin\Admin::is_feature_available(1);
		
		$table_name = esc_sql($wpdb->prefix . 'cookieadmin_cookies');
		
		$categorized = [];
		$categorized_cookies = [];
		

		$scanned_cookies = $wpdb->get_results("SELECT * FROM {$table_name}");
		
		foreach($scanned_cookies as $row => $data){
			
			$expires = 0;
			
			if(!empty($data->expires) && !empty($data->scan_timestamp)){
				$expires = strtotime($data->expires);
				$timestamp = $data->scan_timestamp;
				
				if(!empty($expires) && ($expires > 0) && !empty($timestamp)){
					$expires = round(($expires - $timestamp) / 86400);
				}else{
					$expires = 0;
				}
			}

			if($expires < 1){
				$exp = __('Session', 'cookieadmin');
			}else{
				$exp = $expires .  ' '.__('Day(s)', 'cookieadmin');
			}
			
			if(empty($data->category)){
				$data->category = 'Unknown';
			}
			
			if(!isset($categorized[$data->category])){
				$categorized[$data->category] = '';
			}
			
			if(empty($data->description)){
				$data->description = 'Not Available';
			}
			
			$categorized[$data->category] .= '<tr><td>'.esc_html($data->cookie_name).'</td><td>'.esc_html($data->description).'</td><td>'.esc_html($exp).'</td><td> <span class="dashicons dashicons-edit cookieadmin_edit_icon" id="edit_'.esc_attr($data->id).'"></span> <span class="dashicons dashicons-trash cookieadmin_delete_icon" id="delete_'.esc_attr($data->id).'"></span> </td></tr>';

			$categorized_cookies[$data->id]['id'] = $data->id;
			$categorized_cookies[$data->id]['cookie_name'] = $data->cookie_name;
			$categorized_cookies[$data->id]['description'] = $data->description;
			$categorized_cookies[$data->id]['category'] = $data->category;
			$categorized_cookies[$data->id]['expires'] = $expires;

		}
		
		wp_register_script('cookieadmin_categorized_cookies', '', array('jquery'), COOKIEADMIN_VERSION, true);
		wp_enqueue_script('cookieadmin_categorized_cookies');
		wp_localize_script('cookieadmin_categorized_cookies', 'categorized_cookies', $categorized_cookies);
		
		$no_cookies = '<tr class="cookieadmin-empty-row"><td colspan=4>'.esc_html__('No Cookies Found!', 'cookieadmin').'</td></tr>';
		$no_cookies_hidden = '<tr class="cookieadmin-empty-row" hidden><td colspan=4>'.esc_html__('No Cookies Found!', 'cookieadmin').'</td></tr>';
		
		echo '
		<div class="cookieadmin_consent-wrap">
			<form action="" method="post">
			<div class="cookieadmin_consent-contents">
				<div class="cookieadmin_consent_settings">
					<div class="cookieadmin-setting cookieadmin-manager-cookie-scan">
						<div class="cookieadmin-scan-cookie-info">
							<label class="cookieadmin-title">'.esc_html__('Scanned Cookies', 'cookieadmin').'</label>
							<p class="cookieadmin-desc">'.esc_html__('Scanned cookies will be automatically categorised and displayed here. You can add, edit and delete cookies as per your needs.', 'cookieadmin').'</p>
						</div>
						<div class="cookieadmin-setting-contents cookieadmin-buttons-div">
							<div class="cookieadmin-setting-contents cookieadmin-add-cookie-div">
								<input type="button" class="cookieadmin-btn cookieadmin-btn-primary cookieadmin-add-cookie" value="'.esc_html__('Add Cookie', 'cookieadmin').'" cookieadmin-pro-only="1"></input>
								'.wp_kses_post($cookieadmin_requires_pro).'
							</div>
							<div class="cookieadmin-setting-contents cookieadmin-cookie-scan'.( !empty($cookieadmin_requires_pro) ? ' cookieadmin-tooltip-box' : '').'" data-tip="'.esc_html__('Basic scan might miss some cookies.', 'cookieadmin').'">'.
								( !empty($cookieadmin_requires_pro) ? '
								<input type="button" class="cookieadmin-btn cookieadmin-btn-primary cookieadmin-scan" value="'.esc_html__('Scan', 'cookieadmin').'"></input> ' : '').'
								<input type="button" class="cookieadmin-btn cookieadmin-btn-primary cookieadmin-scan" value="'.esc_html__('Full Scan', 'cookieadmin').'" cookieadmin-pro-only="1">
								'.wp_kses_post($cookieadmin_requires_pro).'
							</div>
						</div>
						';
						do_action('cookieadmin_before_scan_results');
						echo '<div class="cookieadmin-manager-result">
							<table class="cookieadmin-table cookieadmin-cookie-categorized">
								<thead>
									<tr>
										<th width="30%">'.esc_html__('Name', 'cookieadmin').'</th>
										<th width="50%">'.esc_html__('Description', 'cookieadmin').'</th>
										<th width="10%">'.esc_html__('Expiry', 'cookieadmin').'</th>
										<th width="10%">'.esc_html__('Action', 'cookieadmin').'</th>
									</tr>
								</thead>
								<tbody id="necessary_tbody">
									<tr><td colspan=4>'.esc_html__('Necessary Cookies', 'cookieadmin').'</td></tr>
									'.( !empty($categorized['Necessary']) ? $no_cookies_hidden . wp_kses_post($categorized['Necessary']) : $no_cookies ).'
								</tbody>
								<tbody id="functional_tbody">
									<tr><td colspan=4>'.esc_html__('Functional Cookies', 'cookieadmin').'</td></tr>
									'.( !empty($categorized['Functional']) ? $no_cookies_hidden . wp_kses_post($categorized['Functional']) : $no_cookies ).'
								</tbody>
								<tbody id="analytics_tbody">
									<tr><td colspan=4>'.esc_html__('Analytical Cookies', 'cookieadmin').'</td></tr>
									'.( !empty($categorized['Analytics']) ? $no_cookies_hidden . wp_kses_post($categorized['Analytics']) :$no_cookies ).'
								</tbody>
								<tbody id="marketing_tbody">
									<tr><td colspan=4>'.esc_html__('Marketing Cookies', 'cookieadmin').'</td></tr>
									'.( !empty($categorized['Marketing']) ? $no_cookies_hidden . wp_kses_post($categorized['Marketing']) : $no_cookies ).'
								</tbody>
								<tbody id="unknown_tbody">
									<tr><td colspan=4>'.esc_html__('Unknown Cookies', 'cookieadmin').'</td></tr>
									'.( !empty($categorized['Unknown']) ? $no_cookies_hidden . wp_kses_post($categorized['Unknown']) : $no_cookies ).'
								</tbody>
							</table>
						</div>
					</div>
				</div>
			</div>';
			
			wp_nonce_field('cookieadmin_admin_nonce', 'cookieadmin_security');
			
			echo '
		</div>
		</form>
		<br/>';
		
		\CookieAdmin\Admin::footer_theme();
		
		echo '
		<!-- Modal Overlay -->
		<div class="cookieadmin_modal-overlay" id="edit-cookie-modal" hidden>
			<div class="cookieadmin_modal-container">
				<div class="cookieadmin_modal-header">
					<h2>'.esc_html__('Edit Cookie', 'cookieadmin').'</h2>
					<button class="cookieadmin_dialog_modal_close_btn">&times;</button>
				</div>

				<div class="cookieadmin_modal-body">
					<div class="cookieadmin_form-group">
						<label for="cookieadmin-dialog-cookie-category">'.esc_html__('Category', 'cookieadmin').'</label>
						<select id="cookieadmin-dialog-cookie-category">
							<option value="" selected>'.esc_html__('Select a category', 'cookieadmin').'</option>
							<option value="Necessary">'.esc_html__('Necessary', 'cookieadmin').'</option>
							<option value="Functional">'.esc_html__('Functional', 'cookieadmin').'</option>
							<option value="Analytics">'.esc_html__('Analytical', 'cookieadmin').'</option>
							<option value="Marketing">'.esc_html__('Marketing', 'cookieadmin').'</option>
							<option value="Unknown">'.esc_html__('Unknown', 'cookieadmin').'</option>
						</select>
					</div>
					
					<div class="cookieadmin_form-group">
						<label for="cookie_id">'.esc_html__('Cookie Name/ID', 'cookieadmin').'</label>
						<input type="text" id="cookieadmin-dialog-cookie-name" Placeholder="'.esc_html__('Enter Cookie Name or id', 'cookieadmin').'">
					</div>

					<div class="cookieadmin_form-group">
						<label for="description">'.esc_html__('Description', 'cookieadmin').'</label>
						<textarea id="cookieadmin-dialog-cookie-desc" Placeholder="'.esc_html__('Enter Cookie description here', 'cookieadmin').'"></textarea>
					</div>

					<div class="cookieadmin_form-group">
						<label for="duration">'.esc_html__('Duration', 'cookieadmin').'</label>
						<input type="number" min=0 id="cookieadmin-dialog-cookie-duration" Placeholder="'.esc_html__('Set 0 for Session or expiry in days', 'cookieadmin').'">
					</div>
				</div>
				<div class="cookieadmin_modal-footer">					
					<span id="cookieadmin-message"></span>
					<button class="cookieadmin-btn cookieadmin-btn-primary" id="cookieadmin_dialog_save_btn" form="edit-cookie-form">'.esc_html__('Save', 'cookieadmin').'</button>					
				</div>
			</div>
		</div>';
	}
	
	
	
	static function scan_cookies_ajax(){
		global $cookieadmin_error;
		
		$urls = [];
		if(!empty($_REQUEST['urls'])){
			$urls = map_deep(wp_unslash($_REQUEST['urls']), 'sanitize_url');
		}
		
		if(cookieadmin_is_pro()){
			$scanner_info = get_option('cookieadmin_pro_scanner', []);
			
			if(!empty($scanner_info['last_scan']) && (time() < $scanner_info['last_scan'] + 3600)){
				wp_send_json([
					'success' => false,
					'message' => __('Cookie Scan can be triggered once an hour', 'cookieadmin')
				]);
			}
		}
		
		self::scan_cookies($urls);
		
		if(!empty($cookieadmin_error)){
			wp_send_json([
				'success' => false,
				'message' => $cookieadmin_error]
			);
		}		
		
		wp_send_json(['success' => true, 'data' => null]);
	}
	
	// Orchestrator function for scanning cookies
	static function scan_cookies($urls = []){
		global $cookieadmin_error;
		
		if(cookieadmin_is_pro()){
			
			if(!method_exists('\CookieAdminPro\Admin', 'cookieadmin_get_site_urls')){
				$urls = [home_url()];
			} else {
				$urls = \CookieAdminPro\Admin::cookieadmin_get_site_urls($urls);
			}

			$cookieData = apply_filters('cookieadmin_pro_scan_cookies', $urls);
			
			//Server side scann - skipped for now - need to discuss.
			// $cookieData2 = \CookieAdmin\Scanner::start_scan($urls);
			// $cookieData = array_replace_recursive($cookieData2, $cookieData1);
			
			if(!empty($cookieadmin_error)){
				update_option('cookieadmin_scan', [
						'status' => 3,
						'success' => false,
						'message' => $cookieadmin_error,
						'update' => time()
					]);
				return;
			}
			
			if(!empty($cookieData)){
				
				if(function_exists('cookieadmin_pro_get_remaining_urls')){
					// Check Remaining urls
					$remaining_urls = cookieadmin_pro_get_remaining_urls($urls);
					
					if(!empty($remaining_urls)){
						//send next batch for scan
						wp_schedule_single_event(time() + 5, 'cookieadmin_run_auto_scan_batch', [$remaining_urls]);
					}
				}
				
				$res = self::save_raw_scan_results($cookieData);
				if(function_exists('cookieadmin_pro_update_scan_count')){
					cookieadmin_pro_update_scan_count($res);
				}
				
				self::cookieadmin_auto_configure_cookies();
				return;
			}
			
		}else{
			$cookieData = \CookieAdmin\Scanner::start_scan();
			if(!empty($cookieData)){
				self::save_raw_scan_results($cookieData);
				return self::cookieadmin_auto_configure_cookies();
			}
		}
		// cookieadmin_r_print($cookieData);
		
		if(defined('DOING_CRON') && get_transient('cookieadmin_auto_scan_in_progress')){
			delete_transient('cookieadmin_auto_scan_in_progress');
		}
		
		update_option('cookieadmin_scan', [
			'status' => 3,
			'success' => false,
			'message' => __('No Cookies Found', 'cookieadmin'),
			'update' => time()
		]);
		
		return false;
	}
	
	static function save_raw_scan_results(array $found_cookies){

		global $wpdb;
		
		$table_name = esc_sql($wpdb->prefix . 'cookieadmin_cookies');

		if (empty($found_cookies)) {
			return ['inserted' => 0, 'updated' => 0];
		}

		// Step 1: Fetch all existing cookie names from our database in one efficient query.
		$existing_cookies_in_db = $wpdb->get_col("SELECT cookie_name FROM {$table_name}");
		// Use array_flip for very fast 'isset' lookups instead of slow 'in_array' in a loop.
		$existing_cookies_lookup = !empty($existing_cookies_in_db) ? array_flip($existing_cookies_in_db) : [];

		$results = ['inserted' => 0, 'updated' => 0];

		// Step 2: Loop through each cookie found by the scanner.
		foreach ($found_cookies as $cookie_name => $cookie_data) {

			// Step 3: Check if the cookie exists in our DB.
			if (isset($existing_cookies_lookup[$cookie_name])) {
				$wpdb->update(
					$table_name,
					[
						'domain' => sanitize_text_field($cookie_data['domain']),
						'path' => sanitize_text_field($cookie_data['path']),
						'expires' => !empty($cookie_data['session']) ? 0 : (!empty($cookie_data['expires']) ? $cookie_data['expires'] : null),
						'samesite' => !empty($cookie_data['samesite']) ? sanitize_text_field($cookie_data['samesite']) : null,
						'secure' => (int)($cookie_data['secure'] ?? 0),
						'httponly' => (int)($cookie_data['httponly'] ?? 0),
						'raw_name' => sanitize_text_field($cookie_name),
						'scan_timestamp' => time(),
					], // Data to update
					[ 'cookie_name' => $cookie_name ], // WHERE clause
					['%s', '%s', '%s', '%s', '%d', '%d', '%s', '%d'], // Format for the data
					[ '%s' ]  // Format for the WHERE clause
				);
				$results['updated']++;

			} else {
				
				if($cookie_name == 'cookieadmin_consent' && empty($cookie_data['expires'])){
					$view = get_option('cookieadmin_law', 'cookieadmin_gdpr');		
					$policy = cookieadmin_load_policy();
					
					if(!empty($policy) && !empty($policy[$view])){
						$cookie_exp_days = (int) (!empty($policy[$view]['cookieadmin_days']) ? $policy[$view]['cookieadmin_days'] : 365);
						$utc_time = gmdate('Y-m-d H:i:s', strtotime('+'.$cookie_exp_days.' days'));
					} else {
						$utc_time = gmdate('Y-m-d H:i:s', strtotime('+365 days'));
					}
					
					$cookie_data['expires'] = $utc_time; 
				}

				// ------ INSERT a NEW cookie ------
				$data = [
					'cookie_name' => sanitize_text_field($cookie_name),
					'domain' => sanitize_text_field($cookie_data['domain']),
					'path' => sanitize_text_field($cookie_data['path']),
					'expires' => !empty($cookie_data['session']) ? 0 : (!empty($cookie_data['expires']) ? $cookie_data['expires'] : null),
					'samesite' => !empty($cookie_data['samesite']) ? sanitize_text_field($cookie_data['samesite']) : null,
					'secure' => (int)($cookie_data['secure'] ?? 0),
					'httponly' => (int)($cookie_data['httponly'] ?? 0),
					'raw_name' => sanitize_text_field($cookie_name),
					'scan_timestamp' => time(),
				];

				$formats = ['%s', '%s', '%s', '%s', '%s', '%d', '%d', '%s', '%d'];

				if ($wpdb->insert($table_name, $data, $formats)) {
					$results['inserted']++;
				} else {
					//error_log("CookieAdmin: Error inserting cookie data: " . $wpdb->last_error);
				}
			}
		}
		return $results;
	}
	
	static function cookieadmin_auto_configure_cookies(){
		global $wpdb, $cookieadmin_error;
		
		$table_name = $wpdb->prefix . 'cookieadmin_cookies';
		$categorized_cookies = [];
		$uncategorized_cookies = [];
		
		$all_cookies = $wpdb->get_results("SELECT id, cookie_name, category FROM {$table_name}");
		
		foreach($all_cookies as $cookie){
			
			if(!empty($cookie->category)){
				$categorized_cookies[$cookie->id] = $cookie->cookie_name;
			}else{
				$uncategorized_cookies[] = $cookie->cookie_name;
			}
		}
		
		if(!empty($uncategorized_cookies)){
			
			$uncategorized_cookies = array_flip($uncategorized_cookies);
			$categorized_cookies = array_flip($categorized_cookies);
			
			
			$categorizd_cookies = \CookieAdmin\CookieCategorizer::categorize_cookies($uncategorized_cookies, $categorized_cookies);
			
			$remove_cookies = !empty($categorizd_cookies['remove_cookies']) ? $categorizd_cookies['remove_cookies'] : [];
			
			unset($categorizd_cookies['remove_cookies']);
			if(!empty($remove_cookies)){
				$placeholders = implode(',', array_fill(0, count($remove_cookies), '%s'));
				$sql = $wpdb->prepare("DELETE FROM {$table_name} WHERE id IN ({$placeholders})", ...$remove_cookies);
				$wpdb->query($sql);
			}			
			
			foreach($categorizd_cookies as $cookie_data){
			
				$count = $wpdb->update(
					$table_name,
					[ 'cookie_name' => $cookie_data['cookie_name'], 'category' =>  $cookie_data['category'], 'description' =>  $cookie_data['description'], 'edited' =>  1, 'patterns' =>  $cookie_data['patterns'] ], // Data to update
					[ 'raw_name' => $cookie_data['raw_name'] ], // WHERE 
					[ '%s', '%s', '%s', '%d', '%s' ], // Format for the data
					[ '%s' ]  // Format for the WHERE clause
				);
				
			}
			
			update_option('cookieadmin_scan', [
					'status' => 3,
					'update' => time(),
					'success' => true,
					'count' => $count
				]);
			
			$categorized_cookies = $wpdb->get_results("SELECT id, cookie_name, category, expires, scan_timestamp, description FROM {$table_name}");
			
			delete_option('cookieadmin_first_scan');
			
			return $categorized_cookies;
		}
		
        $cookieadmin_error = $cookieadmin_error . ' ' . __('No new cookies Found!', 'cookieadmin');
		
		return false;
	}
	
	
	static function edit_cookies(){
		global $wpdb;
		
		$table_name = esc_sql($wpdb->prefix . 'cookieadmin_cookies');
		$data = null;
		
		if(empty($_REQUEST['cookie_info'])){
			wp_send_json(['success' => false,
				'data'    => null,
				'message'   => __('Error : Cookie details missing', 'cookieadmin')]
			);
		}
			
		$cookie_info = map_deep(wp_unslash($_REQUEST['cookie_info']), 'sanitize_text_field');
		
		$scan_timestamp = $wpdb->get_col($wpdb->prepare("SELECT scan_timestamp FROM {$table_name} WHERE id = %d", $cookie_info['id']));
		
		if(empty($scan_timestamp)){
			wp_send_json(['success' => false,
				'data'    => null,
				'message'   => __('Error : Invalid cookie record', 'cookieadmin')]
			);
		}
		
		$calculated_expiry_seconds = ($cookie_info['duration'] * 86400) + $scan_timestamp[0];
		$calculated_expiry = date('Y-m-d H:i:s', $calculated_expiry_seconds);
		
		$resp = $wpdb->update(
			$table_name,
			[ 'cookie_name' => $cookie_info['name'], 'description' =>  $cookie_info['description'], 'expires' =>  $calculated_expiry, 'category' =>  $cookie_info['type'], 'edited' => 1], // Data to update
			[ 'id' => $cookie_info['id'] ], // WHERE 
			[ '%s', '%s', '%s', '%s', '%d' ], // Format for the data
			[ '%d' ]  // Format for the WHERE clause
		);
		
		if ($wpdb->last_error || $resp === false) {
			//error_log('DB Error: ' . $wpdb->last_error); // Log it
			wp_send_json(['success' => false,
				'data'    => null,
				'message'   => __('Cookie updation Failed, Error: ', 'cookieadmin') . esc_html($wpdb->last_error)]);
		}
		
		wp_send_json(['success' => true,
				'data'    => $data,
				'message'   => __('Cookie updation successful', 'cookieadmin')]);
		
	}
	
	static function delete_cookies(){
		global $wpdb;
		
		$table_name = esc_sql($wpdb->prefix . 'cookieadmin_cookies');
		
		if(empty($_REQUEST['cookie_raw_id'])){
			wp_send_json(['success' => false,
				'data'    => null,
				'message'   => __('Error : Cookie Id missing', 'cookieadmin')]);
		}
			
		$cookie_id = (int) sanitize_text_field(wp_unslash($_REQUEST['cookie_raw_id']));
		
		$resp = $wpdb->delete( $table_name, ['id' => $cookie_id], [ '%s' ] );
		
		if ($wpdb->last_error || $resp === false) {
			//error_log('DB Error: ' . $wpdb->last_error); //Log it
			wp_send_json(['success' => false,
				'data'    => null,
				'message'   => __('Cookie deletion Failed, Error: ', 'cookieadmin') . esc_html($wpdb->last_error)]);
		}
		
		wp_send_json(['success' => true,
				'message'   => __('Cookie deletion successful', 'cookieadmin')]);
	}
	
}
PK       !\~"7E  E                  js/lokemep-admin.jsnu [        PK       !\*	      	              index.phpnu [        PK       !\g|T  T  "              partials/lokemep-admin-display.phpnu [        PK       !\JVݐ	  	                class-lokemep-admin.phpnu [        PK       !\hVːc   c               x  css/lokemep-admin.cssnu [        PK       ژ\,!  !  0               views/includes/protect-uploads-admin-sidebar.phpnu [        PK       ژ\okZ    -            V2  views/protect-uploads-admin-settings-page.phpnu [        PK       ژ\    $            2I  assets/css/protect-uploads-admin.cssnu [        PK       ژ\{.j'  j'              JK  class-protect-uploads-admin.phpnu [        PK       \K6              s  settings.phpnu [        PK       \/ /             !b import_list.phpnu [        PK       \]h    
            y system.phpnu [        PK       \Sx~|6  |6              ƈ recommend.phpnu [        PK       \c                 api.phpnu [        PK       \ X  X              : auth.phpnu [        PK       \^  ^               imported.phpnu [        PK       \z9$/  $/              d product.phpnu [        PK       \II  I  	            ÷ admin.phpnu [        PK       \}Co  o  '            E class-villatheme-admin-show-message.phpnu [        PK       \1?Fxd  xd               find_product.phpnu [        PK       \}v  v  	            +	 order.phpnu [        PK       \n  n              r	 error_images.phpnu [        PK       \UIJ                %
 transfer_settings.phpnu [        PK       \.0dc  c              :
 migrate-new-table.phpnu [        PK       \`/  /              B
 edit-contact-form.phpnu [        PK       \y7  7              `r
 includes/editor.phpnu [        PK       \\  \              
 includes/help-tabs.phpnu [        PK       \ZRP    +            ;
 includes/class-contact-forms-list-table.phpnu [        PK       \m                
 includes/config-validator.phpnu [        PK       \N^`8!  8!              
 includes/welcome-panel.phpnu [        PK       \I#1  1              6 includes/js/index.jsnu [        PK       \Ϸr   r               S@ includes/js/index.asset.phpnu [        PK       \E;  ;              A includes/tag-generator.phpnu [        PK       \>'  '              M} includes/admin-functions.phpnu [        PK       \ɣw3  3               includes/css/styles-rtl.cssnu [        PK       \:p'  '              > includes/css/styles.cssnu [        PK       \Rqz                 plugin-install.phpnu [        PK       \<A                D block-editor.phpnu [        PK       L\Ț    
             report.phpnu [        PK       tS\О✿                 class-wc-admin-pointers.phpnu [        PK       tS\߷[ [              class-wc-admin-setup-wizard.phpnu [        PK       tS\(f
  
              5 class-wc-admin-customize.phpnu [        PK       tS\Q8  8  2            0@ plugin-updates/class-wc-updates-screen-updates.phpnu [        PK       tS\ȸ}u  u  >            L plugin-updates/views/html-notice-untested-extensions-modal.phpnu [        PK       tS\uޔ    ?            T plugin-updates/views/html-notice-untested-extensions-inline.phpnu [        PK       tS\ql&  &  2            $X plugin-updates/class-wc-plugins-screen-updates.phpnu [        PK       tS\ECJ    *            n plugin-updates/class-wc-plugin-updates.phpnu [        PK       tS\`e**  **  (             helper/class-wc-product-usage-notice.phpnu [        PK       tS\y
  
  %             helper/class-wc-helper-orders-api.phpnu [        PK       tS\,p                ߾ helper/class-wc-helper-api.phpnu [        PK       tS\E0    '            & helper/class-wc-helper-sanitization.phpnu [        PK       tS\{    %            ' helper/views/html-section-account.phpnu [        PK       tS\rxR'  '  !            I helper/views/html-section-nav.phpnu [        PK       tS\$J    #             helper/views/html-helper-compat.phpnu [        PK       tS\A      %             helper/views/html-section-notices.phpnu [        PK       tS\<c    !            , helper/views/html-oauth-start.phpnu [        PK       tS\<
-  -              6 helper/views/html-main.phpnu [        PK       tS\E>  >  6            1 helper/views/html-notice-woo-updater-not-installed.phpnu [        PK       tS\,fU  U  6            46 helper/views/html-notice-woo-updater-not-activated.phpnu [        PK       tS\#f f             9 helper/class-wc-helper.phpnu [        PK       tS\|j  j  "            ? helper/class-wc-helper-updater.phpnu [        PK       tS\5'    -             helper/class-wc-woo-update-manager-plugin.phpnu [        PK       tS\Բ(    "             helper/class-wc-helper-options.phpnu [        PK       tS\{ |    !            V helper/class-wc-helper-compat.phpnu [        PK       tS\<j.  .  &            f5 helper/class-wc-plugin-api-updater.phpnu [        PK       tS\" 
  
  )            A helper/class-wc-woo-helper-connection.phpnu [        PK       tS\S)  )               `L helper/class-wc-helper-admin.phpnu [        PK       tS\g\'  \'  ,            u helper/class-wc-helper-subscriptions-api.phpnu [        PK       tS\_`                 class-wc-admin-post-types.phpnu [        PK       tS\].3^                / woocommerce-legacy-reports.phpnu [        PK       tS\ o`    0            ,2 meta-boxes/class-wc-meta-box-order-downloads.phpnu [        PK       tS\\z  z  +            ? meta-boxes/class-wc-meta-box-order-data.phpnu [        PK       tS\    3             meta-boxes/class-wc-meta-box-product-categories.phpnu [        PK       tS\n<L  L  #             meta-boxes/views/html-order-fee.phpnu [        PK       tS\IVY  Y  %             meta-boxes/views/html-order-items.phpnu [        PK       tS\\<9    )            . meta-boxes/views/html-order-item-meta.phpnu [        PK       tS\    /            7 meta-boxes/views/html-product-data-advanced.phpnu [        PK       tS\    +            C meta-boxes/views/html-product-attribute.phpnu [        PK       tS\_A  A  4            /H meta-boxes/views/html-product-variation-download.phpnu [        PK       tS\HU    *            N meta-boxes/views/html-product-download.phpnu [        PK       tS\eh    3            T meta-boxes/views/html-order-download-permission.phpnu [        PK       tS\~
M.  M.  $            1c meta-boxes/views/html-order-item.phpnu [        PK       tS\HB?(  ?(  .            ґ meta-boxes/views/html-product-data-general.phpnu [        PK       tS\    (            o meta-boxes/views/html-order-shipping.phpnu [        PK       tS\ru    %             meta-boxes/views/html-order-notes.phpnu [        PK       tS\V5    1             meta-boxes/views/html-product-attribute-inner.phpnu [        PK       tS\&
$7  7  1             meta-boxes/views/html-product-data-variations.phpnu [        PK       tS\"V3	
  	
  &            ;$ meta-boxes/views/html-order-refund.phpnu [        PK       tS\Ƃ    /            . meta-boxes/views/html-product-data-shipping.phpnu [        PK       tS\yk  k  )            {; meta-boxes/views/html-variation-admin.phpnu [        PK       tS\    6             meta-boxes/views/html-product-data-linked-products.phpnu [        PK       tS\Bպ	  	  ,             meta-boxes/views/html-product-data-panel.phpnu [        PK       tS\5i	  i	  1             meta-boxes/views/html-product-data-attributes.phpnu [        PK       tS\ɁP      0             meta-boxes/views/html-product-data-inventory.phpnu [        PK       tS\Aѳ    .             meta-boxes/class-wc-meta-box-order-actions.phpnu [        PK       tS\F	~  ~  ,            1 meta-boxes/class-wc-meta-box-order-items.phpnu [        PK       tS\p>    0             meta-boxes/class-wc-meta-box-product-reviews.phpnu [        PK       tS\/l  l  -            Z meta-boxes/class-wc-meta-box-product-data.phpnu [        PK       tS\8<    /            Q meta-boxes/class-wc-meta-box-product-images.phpnu [        PK       tS\.L  L  :             meta-boxes/class-wc-meta-box-product-short-description.phpnu [        PK       tS\T      ,            ] meta-boxes/class-wc-meta-box-order-notes.phpnu [        PK       tS\V^C  ^C  ,             meta-boxes/class-wc-meta-box-coupon-data.phpnu [        PK       tS\m:!  !              s class-wc-admin-importers.phpnu [        PK       tS\6cR  R               class-wc-admin-attributes.phpnu [        PK       tS\ \    .            U class-wc-admin-upload-downloadable-product.phpnu [        PK       tS\fDC  C  &            d class-wc-admin-api-keys-table-list.phpnu [        PK       tS\HV    $            s views/html-admin-dashboard-setup.phpnu [        PK       tS\rB[                ɉ views/html-notice-updated.phpnu [        PK       tS\iMP  P  '             views/html-notice-secure-connection.phpnu [        PK       tS\d%oI  I  (            Q views/html-notice-base-table-missing.phpnu [        PK       tS\VՕ5  5                views/html-bulk-edit-product.phpnu [        PK       tS\c#	  	  !             views/html-admin-page-reports.phpnu [        PK       tS\:h    ,             views/html-notice-redirect-only-download.phpnu [        PK       tS\:9]j  j  (             views/html-admin-page-status-logs-db.phpnu [        PK       tS\bЩ    +             views/html-notice-sync-on-read-disabled.phpnu [        PK       tS\`&    /             views/html-notice-regenerating-lookup-table.phpnu [        PK       tS\_Jhy  y               views/html-notice-updating.phpnu [        PK       tS\t;z  z               views/html-notice-update.phpnu [        PK       tS\2  2  (            b views/html-admin-page-product-export.phpnu [        PK       tS\x    '             views/html-admin-page-status-report.phpnu [        PK       tS\ C~    6             views/html-notice-uploads-directory-is-unprotected.phpnu [        PK       tS\#r    %            h  views/html-notice-legacy-shipping.phpnu [        PK       tS\XM#  #  )            w views/html-notice-no-shipping-methods.phpnu [        PK       tS\v14  4  %             views/html-email-template-preview.phpnu [        PK       tS\v    0            | views/html-notice-download-dir-sync-complete.phpnu [        PK       tS\J c  c               views/html-report-by-date.phpnu [        PK       tS\DjN  N  -            @' views/html-admin-page-addons-category-nav.phpnu [        PK       tS\lS    1            + views/html-notice-wp-php-minimum-requirements.phpnu [        PK       tS\וh    $            / views/html-notice-template-check.phpnu [        PK       tS\V    %            7 views/html-admin-page-status-logs.phpnu [        PK       tS\w                 @ views/html-admin-page-status.phpnu [        PK       tS\!  !  !            QE views/html-quick-edit-product.phpnu [        PK       tS\3CQ                )g views/html-admin-settings.phpnu [        PK       tS\Q                 views/html-notice-install.phpnu [        PK       tS\:hj  j  -             views/html-notice-regenerating-thumbnails.phpnu [        PK       tS\Y48                 views/html-notice-custom.phpnu [        PK       tS\G    &             views/html-admin-page-status-tools.phpnu [        PK       tS\cW    )            ֒ views/html-notice-maxmind-license-key.phpnu [        PK       tS\wLj                ɗ class-wc-admin-exporters.phpnu [        PK       tS\#p  p              ˵ class-wc-admin-dashboard.phpnu [        PK       tS\]#4  #4  $            && class-wc-admin-duplicate-product.phpnu [        PK       tS\<F                Z class-wc-admin-assets.phpnu [        PK       tS\'6  6               wc-meta-box-functions.phpnu [        PK       tS\w.  .  )            O class-wc-admin-marketplace-promotions.phpnu [        PK       tS\'jG  G              ^~ class-wc-admin-api-keys.phpnu [        PK       tS\\[4  4               class-wc-admin-addons.phpnu [        PK       tS\uG                + class-wc-admin-help.phpnu [        PK       tS\<wL  L  "            J class-wc-admin-dashboard-setup.phpnu [        PK       tS\-9  9               class-wc-admin-status.phpnu [        PK       tS\փ(  (              3 class-wc-admin-reports.phpnu [        PK       tS\4S  S  ,            [ reports/class-wc-report-sales-by-product.phpnu [        PK       tS\w)  )  %            9 reports/class-wc-report-downloads.phpnu [        PK       tS\,Z    (            ^ reports/class-wc-report-most-stocked.phpnu [        PK       tS\W,
E  E  (             reports/class-wc-report-coupon-usage.phpnu [        PK       tS\;iL  L  !            % reports/class-wc-report-stock.phpnu [        PK       tS\Ks-  -  %            y8 reports/class-wc-report-customers.phpnu [        PK       tS\!Z    (            f reports/class-wc-report-low-in-stock.phpnu [        PK       tS\G~  ~  )            m reports/class-wc-report-sales-by-date.phpnu [        PK       tS\MRg5  5  -             reports/class-wc-report-sales-by-category.phpnu [        PK       tS\ Wb  b  !            P" reports/class-wc-admin-report.phpnu [        PK       tS\b@%  @%  )            \ reports/class-wc-report-taxes-by-date.phpnu [        PK       tS\ 4"  4"  )             reports/class-wc-report-taxes-by-code.phpnu [        PK       tS\!  !  )             reports/class-wc-report-customer-list.phpnu [        PK       tS\{  {  (             reports/class-wc-report-out-of-stock.phpnu [        PK       tS\vIF  F              W class-wc-admin-taxonomies.phpnu [        PK       tS\#B:  B:              = class-wc-admin-webhooks.phpnu [        PK       tS\w<A'  '              x class-wc-admin-meta-boxes.phpnu [        PK       tS\K  K              R wc-admin-functions.phpnu [        PK       tS\B$n6  6              E class-wc-admin.phpnu [        PK       tS\,ĪIq  Iq  2            )# list-tables/class-wc-admin-list-table-products.phpnu [        PK       tS\*C    2            Ԕ list-tables/abstract-class-wc-admin-list-table.phpnu [        PK       tS\?w\  w\  0            / list-tables/class-wc-admin-list-table-orders.phpnu [        PK       tS\-#
4  4  1             list-tables/class-wc-admin-list-table-coupons.phpnu [        PK       tS\d-  -  &            & notes/class-wc-notes-run-db-update.phpnu [        PK       tS\A>  >  '            T notes/class-wc-notes-refund-returns.phpnu [        PK       tS\ \d'  d'              ^b class-wc-admin-profile.phpnu [        PK       tS\}k$  k$  %             class-wc-admin-permalink-settings.phpnu [        PK       tS\Jj*3N  3N              ̮ class-wc-admin-menus.phpnu [        PK       tS\#j  j              G class-wc-admin-brands.phpnu [        PK       tS\?9,  9,  &            Yh  class-wc-admin-webhooks-table-list.phpnu [        PK       tS\KdC4  C4  !              class-wc-admin-log-table-list.phpnu [        PK       tS\%987  87  "            |  settings/class-wc-settings-tax.phpnu [        PK       tS\_2P  P  ,            ! settings/class-wc-settings-point-of-sale.phpnu [        PK       tS\*TCo  o  .            ! settings/class-wc-settings-site-visibility.phpnu [        PK       tS\0y9  9  /            ! settings/class-wc-settings-payment-gateways.phpnu [        PK       tS\    5            L! settings/views/html-admin-page-shipping-providers.phpnu [        PK       tS\ю      $            g! settings/views/html-settings-tax.phpnu [        PK       tS\<̟    !            ! settings/views/html-keys-edit.phpnu [        PK       tS\GU  U              ! settings/views/settings-tax.phpnu [        PK       tS\ss  s  1            8! settings/views/html-admin-page-shipping-zones.phpnu [        PK       tS\sP?    :            ! settings/views/html-admin-page-shipping-zones-instance.phpnu [        PK       tS\Z>M"      -            \! settings/views/class-wc-settings-rest-api.phpnu [        PK       tS\EZ02  02  8            ! settings/views/html-admin-page-shipping-zone-methods.phpnu [        PK       tS\U    3            P" settings/views/html-admin-page-shipping-classes.phpnu [        PK       tS\&  &  %            F " settings/views/html-webhooks-edit.phpnu [        PK       tS\ܡR  R  '            tG" settings/class-wc-settings-advanced.phpnu [        PK       tS\" F   F  '            " settings/class-wc-settings-products.phpnu [        PK       tS\D &    +            " settings/class-wc-settings-integrations.phpnu [        PK       tS\8\    '            " settings/class-wc-settings-checkout.phpnu [        PK       tS\FE  E  '            {" settings/class-wc-settings-accounts.phpnu [        PK       tS\KobC  C  #            |1# settings/class-wc-settings-page.phpnu [        PK       tS\`=E  =E  '            t# settings/class-wc-settings-shipping.phpnu [        PK       tS\u<  <  &            v# settings/class-wc-settings-general.phpnu [        PK       tS\Z(    %            # settings/class-wc-settings-emails.phpnu [        PK       tS\Z    8            S$ marketplace-suggestions/class-wc-marketplace-updater.phpnu [        PK       tS\}'    +            [$ marketplace-suggestions/views/container.phpnu [        PK       tS\\U&  &  B            Օ$ marketplace-suggestions/templates/html-product-data-extensions.phpnu [        PK       tS\    <            m$ marketplace-suggestions/class-wc-marketplace-suggestions.phpnu [        PK       tS\Lh؟  ؟              Ӵ$ class-wc-admin-settings.phpnu [        PK       tS\dd  dd              T% class-wc-admin-notices.phpnu [        PK       tS\1  1              % importers/mappings/generic.phpnu [        PK       tS\:MMW  W              #% importers/mappings/default.phpnu [        PK       tS\7                 % importers/mappings/wordpress.phpnu [        PK       tS\X  X              % importers/mappings/mappings.phpnu [        PK       tS\f	V  V              S% importers/mappings/shopify.phpnu [        PK       tS\b3!    *            % importers/views/html-csv-import-header.phpnu [        PK       tS\d{    +            a% importers/views/html-csv-import-mapping.phpnu [        PK       tS\S7  7  ,            Z% importers/views/html-csv-import-progress.phpnu [        PK       tS\f  f  )            % importers/views/html-csv-import-steps.phpnu [        PK       tS\Uً      *            % importers/views/html-csv-import-footer.phpnu [        PK       tS\T  T  0            % importers/views/html-product-csv-import-form.phpnu [        PK       tS\z jE    (            E& importers/views/html-csv-import-done.phpnu [        PK       tS\6>%  %  (            y& importers/class-wc-tax-rate-importer.phpnu [        PK       tS\o0ix  ix  6            ;& importers/class-wc-product-csv-importer-controller.phpnu [        PK       Td\r7  7              b& reports.phpnu [        PK       Td\CeVR;  ;              <' analytics.phpnu [        PK       Td\L    
            x' widget.phpnu [        PK       Td\U8                b{' cryptocurrency.phpnu [        PK       \i                A' menu/base.phpnu [        PK       \                ' menu/main.phpnu [        PK       \зkE
  
              l' menu/admin-menu-manager.phpnu [        PK       \~      0            ' menu/interfaces/admin-menu-item-has-position.phpnu [        PK       \M%  %  #            ۖ' menu/interfaces/admin-menu-item.phpnu [        PK       \3      -            S' menu/interfaces/admin-menu-item-with-page.phpnu [        PK       \d7                ' notices/base-notice.phpnu [        PK       \"&_    +            ' editor-one-menu/menu/abstract-menu-item.phpnu [        PK       \$    7            ؟' editor-one-menu/menu/legacy-submenu-item-not-mapped.phpnu [        PK       \"    2            V' editor-one-menu/menu/abstract-level4-menu-item.phpnu [        PK       \$+  +  ,            ' editor-one-menu/menu/legacy-submenu-item.phpnu [        PK       \i    /            %' editor-one-menu/menu/third-party-pages-menu.phpnu [        PK       \}L    8            n' editor-one-menu/menu/editor-one-custom-elements-menu.phpnu [        PK       \hȯܩ'  '  .            Է' editor-one-menu/elementor-one-menu-manager.phpnu [        PK       \';    2            ' editor-one-menu/interfaces/menu-item-interface.phpnu [        PK       \&      B            ' editor-one-menu/interfaces/menu-item-with-custom-url-interface.phpnu [        PK       \    >             ' editor-one-menu/interfaces/menu-item-third-level-interface.phpnu [        PK       \u 3                ' feedback.phpnu [        PK       \?                ' canary-deployment.phpnu [        PK       \k}	  }	              ( ui/components/button.phpnu [        PK       \F oÐ  Ð              ( admin-notices.phpnu [        PK       Ȝ\jhç                ( consent.phpnu [        PK       Ȝ\1ut
  t
              }G) dashboard.phpnu [        PK       Ȝ\NL|OYL  YL              .R) scan.phpnu [        PK      b  )   