__('Used item', 'usedkit'), 'target' => 'usedkit_item_data', 'class' => array(), 'priority' => 15); return $tabs; }); add_action('woocommerce_product_data_panels', function () { if (!has_action('usedkit_item_panel')) { return; } global $product_object; echo ''; }); /* The product form's own nonce for what Usedkit saves from it (the tab, and the purchase fields under the price), whether or not the tab is shown. */ add_action('woocommerce_product_data_panels', function () { wp_nonce_field('usedkit_product', 'usedkit_product_nonce', false); }); /** Whether this product form's Usedkit fields may be saved: our nonce, and the right to * edit this product (or products, when none is given). Checked once per request. */ function usedkit_product_form_ok($product = null) { $nonce = sanitize_text_field(wp_unslash($_POST['usedkit_product_nonce'] ?? '')); if (!wp_verify_nonce($nonce, 'usedkit_product')) { return false; } return $product ? current_user_can('edit_post', $product->get_id()) : current_user_can('edit_products'); } /** A heading between sections of the tab. */ function usedkit_panel_heading($text) { echo '

' . esc_html($text) . '

'; } /** A posted field from the product form, unslashed and sanitised; null when absent. */ function usedkit_posted($name, $multiline = false) { if (!usedkit_product_form_ok()) { // the nonce and the right to edit first return null; } // phpcs:disable WordPress.Security.NonceVerification -- verified just above, in usedkit_product_form_ok() if (!isset($_POST[$name])) { return null; } return $multiline ? sanitize_textarea_field(wp_unslash($_POST[$name])) : sanitize_text_field(wp_unslash($_POST[$name])); // phpcs:enable } /** Set or delete a meta value: empty deletes, so an emptied field leaves nothing behind. */ function usedkit_set_meta($product, $key, $value) { if ($value === null) { return; } if ($value === '') { $product->delete_meta_data($key); } else { $product->update_meta_data($key, $value); } }