WooCommerce custom bacs payment gateway not saving bank account details - wordpress

I build a plugin-based upon gateway BACS, I followed this guide
https://docs.woocommerce.com/document/payment-gateway-api/
I also found some other examples which are used some code from, maybe not a good idea.
The plugin works, it shows op as a payment method, click manage and I go the admin page, can change, update the fields and this is saved but the problem is the bank accounts table at the bottom, these are not saved and I cannot find out why.
Here is my code, please keep in mind, writing plugins is not my profession so if the mistakes are stupid, it is due to my lack of knowledge. Any help would be appreciated.
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
add_action('plugins_loaded', 'init_gateway_revolut_class');
function init_gateway_revolut_class()
{
/**
* Custom Payment Gateway.
*
* Provides a Custom Payment Gateway, to modify revolut formatting.
*/
class WC_Gateway_Revolut extends WC_Payment_Gateway
{
// public $domain;
public $locale;
/**
* Referral Url.
*
* #var string
*/
public $revolut_url;
/**
* Constructor for the gateway.
*/
public function __construct()
{
$this->id = 'revolut';
$this->icon = apply_filters('woocommerce_revolut_icon', '');
$this->has_fields = false;
$this->method_title = __('Revolut Multi Currency', 'woocommerce');
$this->method_description = __('Allows payments in different currencies to your Revolut bank account, more commonly known as direct bank/wire transfer.', 'woocommerce');
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Define user set variables
$this->title = $this->get_option('title');
$this->description = $this->get_option('description');
$this->instructions = $this->get_option('instructions');
$this->referral_text = $this->get_option('referral_text');
$this->referral_link = $this->get_option('referral_link');
$this->revolut_url = $this->revolut_url;
$this->order_status = $this->get_option('order_status');
$this->status_text = $this->get_option('status_text');
if (!empty($this->referral_link)) {
$this->description .= ' ' . $this->get_referral_link();
// $this->description = trim( $this->description );
}
// revolut account fields shown on the thanks page and in emails
$this->account_details = get_option('woocommerce_revolut_accounts', array(
array(
'currency' => $this->get_option('currency'),
'account_name' => $this->get_option('account_name'),
'account_number' => $this->get_option('account_number'),
'bank_name' => $this->get_option('bank_name'),
'sort_code' => $this->get_option('sort_code'),
'iban' => $this->get_option('iban'),
'bic' => $this->get_option('bic')
)
));
// Actions
add_action('woocommerce_update_options_payment_gateways_' . $this->id, array(
$this,
'process_admin_options'
));
add_action('woocommerce_update_options_payment_gateways_' . $this->id, array(
$this,
'save_account_details'
));
add_action('woocommerce_thankyou_direct_deposit', array(
$this,
'thankyou_page'
));
// Customer Emails
add_action('woocommerce_email_before_order_table', array(
$this,
'email_instructions'
), 10, 3);
}
/**
* Initialise Gateway Settings Form Fields.
*/
public function init_form_fields()
{
$this->form_fields = array(
'enabled' => array(
'title' => __('Enable/Disable', 'woocommerce'),
'type' => 'checkbox',
'label' => __('Enable Bank Transfer', 'woocommerce'),
'default' => 'no'
),
'title' => array(
'title' => __('Title', 'woocommerce'),
'type' => 'text',
'description' => __('This controls the title which the user sees during checkout.', 'woocommerce'),
'default' => __('Revolut Direct Bank Transfer', 'woocommerce'),
'desc_tip' => true
),
'description' => array(
'title' => __('Description', 'woocommerce'),
'type' => 'textarea',
'description' => __('Payment method description that the customer will see on your checkout. Link to open new account will be added.', 'woocommerce'),
'default' => __('Do your payment directly into TeCuro\'s Ltd. bank account. If you are a Revolut account holder, payment will be instant. If you open a new account you will receive an extra discount.', 'woocommerce'),
'desc_tip' => true
),
'instructions' => array(
'title' => __('Instructions', 'woocommerce'),
'type' => 'textarea',
'description' => __('Instructions that will be added to the thank you page and emails.', 'woocommerce'),
'default' => __('Please use your Order ID as the payment reference. When the funds have cleared in our account your order will be shipped.', 'woocommerce'),
'desc_tip' => true
),
'referral_text' => array(
'title' => __('Referal Link', 'woocommerce'),
'type' => 'text',
'description' => __('This is the text link to Revolut.', 'woocommerce'),
'default' => __('Click here to open a free account with Revolut', 'woocommerce'),
'desc_tip' => true
),
'referral_link' => array(
'title' => __('Referal Link', 'woocommerce'),
'type' => 'text',
'description' => __('Please paste your referal code you received from Revolut. When not empty referral link will be added.', 'woocommerce'),
'default' => '',
'desc_tip' => true
),
'order_status' => array(
'title' => __('Order Status', 'woocommerce'),
'type' => 'select',
'description' => __('Choose whether order status you wish after checkout.', 'woocommerce'),
'default' => 'wc-on-hold',
'desc_tip' => true,
'class' => 'wc-enhanced-select',
'options' => wc_get_order_statuses()
),
'status_text' => array(
'title' => __('Order Status Text', 'woocommerce'),
'type' => 'text',
'description' => __('Set the text for the selected order status.', 'woocommerce'),
'default' => __('Awaiting Revolut payment', 'woocommerce'),
'desc_tip' => true
),
'account_details' => array(
'type' => 'account_details'
)
);
}
/**
* Generate account details html.
*
* #return string
*/
public function generate_account_details_html()
{
ob_start();
$country = WC()->countries->get_base_country();
$locale = $this->get_country_locale();
// Get sortcode label in the $locale array and use appropriate one
$sortcode = isset($locale[$country]['sortcode']['label']) ? $locale[$country]['sortcode']['label'] : __('Sort Code', 'woocommerce');
?>
<tr valign="top">
<th scope="row" class="titledesc"><?php _e('Account Details', 'woocommerce');?>:</th>
<td class="forminp" id="revolut_accounts">
<div class="wc_input_table_wrapper">
<table class="widefat wc_input_table sortable" cellspacing="0">
<thead>
<tr>
<th class="sort"> </th>
<th><?php _e('Currency', 'woocommerce');?></th>
<th><?php _e('Account Name', 'woocommerce');?></th>
<th><?php _e('Account Number', 'woocommerce');?></th>
<th><?php _e('Bank', 'woocommerce');?></th>
<th><?php echo $sortcode;?></th>
<th><?php _e('IBAN', 'woocommerce');?></th>
<th><?php _e('BIC / Swift', 'woocommerce');?></th>
</tr>
</thead>
<tbody class="accounts">
<?php
$i = -1;
if ($this->account_details) {
foreach ($this->account_details as $account) {
$i++;
echo '<tr class="account">
<td class="sort"></td>
<td><select class="wc-enhanced-select" name="revolut_currency[' . $i . ']" id="revolut_currency">
<option value="">Select</option>
<option ' . ($account['currency'] == 'AUD') ? 'selected' : '' . ' value="AUD">AUD</option>
<option ' . ($account['currency'] == 'BGN') ? 'selected' : '' . ' value="BGN">BGN</option>
<option ' . ($account['currency'] == 'CAD') ? 'selected' : '' . ' value="CAD">CAD</option>
<option ' . ($account['currency'] == 'CHF') ? 'selected' : '' . ' value="CHF">CHF</option>
<option ' . ($account['currency'] == 'CZK') ? 'selected' : '' . ' value="CZK">CZK</option>
<option ' . ($account['currency'] == 'CHF') ? 'selected' : '' . ' value="CHF">CHF</option>
<option ' . ($account['currency'] == 'DKK') ? 'selected' : '' . ' value="DKK">DKK</option>
<option ' . ($account['currency'] == 'EUR') ? 'selected' : '' . ' value="EUR">EUR</option>
<option ' . ($account['currency'] == 'GBP') ? 'selected' : '' . ' value="GBP">GBP</option>
<option ' . ($account['currency'] == 'HKD') ? 'selected' : '' . ' value="HKD">HKD</option>
<option ' . ($account['currency'] == 'HRK') ? 'selected' : '' . ' value="HRK">HRK</option>
<option ' . ($account['currency'] == 'HUF') ? 'selected' : '' . ' value="HUF">HUF</option>
<option ' . ($account['currency'] == 'JPY') ? 'selected' : '' . ' value="JPY">JPY</option>
<option ' . ($account['currency'] == 'NOK') ? 'selected' : '' . ' value="NOK">NOK</option>
<option ' . ($account['currency'] == 'PLN') ? 'selected' : '' . ' value="PLN">PLN</option>
<option ' . ($account['currency'] == 'RON') ? 'selected' : '' . ' value="RON">RON</option>
<option ' . ($account['currency'] == 'SEK') ? 'selected' : '' . ' value="SEK">SEK</option>
<option ' . ($account['currency'] == 'USD') ? 'selected' : '' . ' value="USD">USD</option>
<option ' . ($account['currency'] == 'ZAR') ? 'selected' : '' . ' value="ZAR">ZAR</option>
</select></td>
<td><input type="text" value="' . esc_attr(wp_unslash($account['account_name'])) . '" name="revolut_account_name[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr($account['account_number']) . '" name="revolut_account_number[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr(wp_unslash($account['bank_name'])) . '" name="revolut_bank_name[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr($account['sort_code']) . '" name="revolut_sort_code[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr($account['iban']) . '" name="revolut_iban[' . $i . ']" /></td>
<td><input type="text" value="' . esc_attr($account['bic']) . '" name="revolut_bic[' . $i . ']" /></td>
</tr>';
}
}
?>
</tbody>
<tfoot>
<tr>
<th colspan="8"><?php _e('+ Add Account', 'woocommerce');?>
<?php _e('Remove selected account(s)', 'woocommerce');?></th>
</tr>
</tfoot>
</table>
</div>
<script type="text/javascript">
jQuery(function() {
jQuery('#revolut_accounts').on( 'click', 'a.add', function(){
var size = jQuery('#revolut_accounts').find('tbody .account').length;
var accountname = jQuery("#revolut_accounts tr:nth-child(1) td:nth-child(3) input[type='text']").val();
if(accountname == null){
accountname = '';
} else{
accountname = accountname;
}
jQuery('<tr class="account">\
<td class="sort"></td>\
<td><select class="wc-enhanced-select" name="revolut_currency[' + size + ']">\
<option value="">↓</option>\
<option value="AUD">AUD</option>\
<option value="BGN">BGN</option>\
<option value="CAD">CAD</option>\
<option value="CHF">CHF</option>\
<option value="CZK">CZK</option>\
<option value="CHF">CHF</option>\
<option value="DKK">DKK</option>\
<option value="EUR">EUR</option>\
<option value="GBP">GBP</option>\
<option value="HKD">HKD</option>\
<option value="HRK">HRK</option>\
<option value="HUF">HUF</option>\
<option value="JPY">JPY</option>\
<option value="NOK">NOK</option>\
<option value="PLN">PLN</option>\
<option value="RON">RON</option>\
<option value="SEK">SEK</option>\
<option value="USD">USD</option>\
<option value="ZAR">ZAR</option>\
</select>\
</td>\
<td><input type="text" value="' + accountname + '" name="revolut_account_name[' + size + ']" /></td>\
<td><input type="text" name="revolut_account_number[' + size + ']" /></td>\
<td><input type="text" value="REVOLUT" name="revolut_bank_name[' + size + ']"/></td>\
<td><input type="text" name="revolut_sort_code[' + size + ']" /></td>\
<td><input type="text" name="revolut_iban[' + size + ']" /></td>\
<td><input type="text" value="REVOGB21" name="revolut_bic[' + size + ']" /></td>\
</tr>').appendTo('#revolut_accounts table tbody');
return false;
});
});
</script>
</td>
</tr>
<?php
return ob_get_clean();
}
/**
* Save account details table.
*/
public function save_account_details()
{
$accounts = array();
if (isset($_POST['revolut_currency']) && isset($_POST['revolut_account_name']) && isset($_POST['revolut_account_number']) && isset($_POST['revolut_bank_name']) && isset($_POST['revolut_sort_code']) && isset($_POST['revolut_iban']) && isset($_POST['revolut_bic'])) {
$currencies = array_map('wc_clean', $_POST['revolut_currency']);
$account_names = array_map('wc_clean', $_POST['revolut_account_name']);
$account_numbers = array_map('wc_clean', $_POST['revolut_account_number']);
$bank_names = array_map('wc_clean', $_POST['revolut_bank_name']);
$sort_codes = array_map('wc_clean', $_POST['revolut_sort_code']);
$ibans = array_map('wc_clean', $_POST['revolut_iban']);
$bics = array_map('wc_clean', $_POST['revolut_bic']);
foreach ($account_names as $i => $name) {
if (!isset($account_names[$i])) {
continue;
}
$accounts[] = array(
'currency' => $currencies[$i],
'account_name' => $account_names[$i],
'account_number' => $account_numbers[$i],
'bank_name' => $bank_names[$i],
'sort_code' => $sort_codes[$i],
'iban' => $ibans[$i],
'bic' => $bics[$i]
);
}
}
update_option('woocommerce_revolut_accounts', $accounts);
}
/**
* Return the referral_link for admin screens.
*
* #return url
*/
public function get_referral_link()
{
$link = $this->referral_link; //get_option( 'referral_link', true );
$text = $this->referral_text; //get_option( 'referral_text', true );
if (!empty($this->referral_link)) {
$revolut_url = sprintf('%s', $link, $text);
} else {
$revolut_url = sprintf('%s', $text);
}
return $revolut_url;
}
// apply_filters( 'woocommerce_get_referral_link', $referral_link );
/**
* Output the input fields in checkout.
* todo: add input box for return code Revolut
*/
/*
/**
* Output for the order received page.
*
* #param int $order_id
*/
public function thankyou_page($order_id)
{
if ($this->instructions) {
echo wpautop(wptexturize(wp_kses_post($this->instructions)));
}
$this->bank_details($order_id);
}
/**
* Add content to the WC emails.
*
* #param WC_Order $order
* #param bool $sent_to_admin
* #param bool $plain_text
*/
public function email_instructions($order, $sent_to_admin, $plain_text = false)
{
/*
if ( ! $sent_to_admin && 'revolut' === $order->payment_method && $order->has_status( 'on-hold' ) ) {
if ( $this->instructions ) {
echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL;
}
$this->bank_details( $order->id );
}
*/
if ($this->instructions && !$sent_to_admin && $this->id === $order->get_payment_method() && $order->has_status($this->order_status)) {
echo wpautop(wptexturize($this->instructions)) . PHP_EOL;
}
$this->bank_details($order->id);
}
/**
* Get bank details and place into a list format.
*
* #param int $order_id
*/
private function bank_details($order_id = '')
{
if (empty($this->account_details)) {
return;
}
// Get order and store in $order
$order = wc_get_order($order_id);
// Get the order country and country $locale
$country = $order->billing_country;
$locale = $this->get_country_locale();
// Get sortcode label in the $locale array and use appropriate one
$sortcode = isset($locale[$country]['sortcode']['label']) ? $locale[$country]['sortcode']['label'] : __('Sort Code', 'woocommerce');
$revolut_accounts = apply_filters('woocommerce_revolut_accounts', $this->account_details);
if (!empty($revolut_accounts)) {
echo '<h2 class="wc-revolut-bank-details-heading">' . __('Our Bank Details', 'woocommerce') . '</h2>' . PHP_EOL;
foreach ($revolut_accounts as $revolut_account) {
$revolut_account = (object) $revolut_account;
if ($revolut_account->account_name || $revolut_account->bank_name) {
echo '<h3>' . wp_unslash(implode(' - ', array_filter(array(
$revolut_account->account_name,
$revolut_account->bank_name
)))) . '</h3>' . PHP_EOL;
}
echo '<ul class="wc-revolut-bank-details order_details revolut_details">' . PHP_EOL;
//echo 'PAYMENT DETAILS RIGHT HERE!!!';
// revolut account fields shown on the thanks page and in emails
$account_fields = apply_filters('woocommerce_revolut_account_fields', array(
'currency' => array(
'label' => __('Currency', 'woocommerce'),
'value' => $revolut_account->currency
),
'bank_name' => array(
'label' => __('Bank Name', 'woocommerce'),
'value' => $revolut_account->bank_name
),
'sort_code' => array(
'label' => $sortcode,
'value' => $revolut_account->sort_code
),
'account_name' => array(
'label' => __('Account Name', 'woocommerce'),
'value' => $revolut_account->account_name
),
'account_number' => array(
'label' => __('Account Number', 'woocommerce'),
'value' => $revolut_account->account_number
),
'iban' => array(
'label' => __('IBAN', 'woocommerce'),
'value' => $revolut_account->iban
),
'bic' => array(
'label' => __('BIC', 'woocommerce'),
'value' => $revolut_account->bic
)
), $order_id);
foreach ($account_fields as $field_key => $field) {
if (!empty($field['value'])) {
echo '<li class="' . esc_attr($field_key) . '">' . esc_attr($field['label']) . ': <strong>' . wptexturize($field['value']) . '</strong></li>' . PHP_EOL;
}
}
echo '</ul>';
}
}
}
/**
* Process the payment and return the result.
*
* #param int $order_id
* #return array
*/
public function process_payment($order_id)
{
$order = wc_get_order($order_id);
// Mark as on-hold (we're awaiting the payment)
//$order->update_status( 'on-hold', __( 'Awaiting Revolut payment', 'woocommerce' ) );
if ($order->get_total() > 0) {
// Mark as on-hold (we're awaiting the payment).
// $order->update_status( apply_filters( 'woocommerce_bacs_process_payment_order_status', 'on-hold', $order ), __( 'Awaiting BACS payment', 'woocommerce' ) );
$order->update_status($this->order_status, $this->status_text);
} else {
$order->payment_complete();
}
// Reduce stock levels
//$order->reduce_order_stock();
wc_reduce_stock_levels($order->get_id());
// Remove cart
WC()->cart->empty_cart();
// Return thankyou redirect
return array(
'result' => 'success',
'redirect' => $this->get_return_url($order)
);
}
/**
* Get country locale if localized.
*
* #return array
*/
public function get_country_locale()
{
if (empty($this->locale)) {
// Locale information to be used - only those that are not 'Sort Code'
$this->locale = apply_filters('woocommerce_get_revolut_locale', array(
'AU' => array(
'sortcode' => array(
'label' => __('BSB', 'woocommerce')
)
),
'CA' => array(
'sortcode' => array(
'label' => __('Bank Transit Number', 'woocommerce')
)
),
'IN' => array(
'sortcode' => array(
'label' => __('IFSC', 'woocommerce')
)
),
'IT' => array(
'sortcode' => array(
'label' => __('Branch Sort', 'woocommerce')
)
),
'NZ' => array(
'sortcode' => array(
'label' => __('Bank Code', 'woocommerce')
)
),
'SE' => array(
'sortcode' => array(
'label' => __('Bank Code', 'woocommerce')
)
),
'US' => array(
'sortcode' => array(
'label' => __('Routing Number', 'woocommerce')
)
),
'ZA' => array(
'sortcode' => array(
'label' => __('Branch Code', 'woocommerce')
)
)
));
}
return $this->locale;
}
}
}
add_filter('woocommerce_payment_gateways', 'add_gateway_revolut_class');
function add_gateway_revolut_class($methods)
{
$methods[] = 'WC_Gateway_Revolut';
return $methods;
}
}

Okay found the mistake, the select is not working, changed it to input with a datalist. Works now and accounts are saved.

Related

Wordpress CPT add new overwrites existing ones

I'm working on a Wordpress projekt and added some custom post types and metaboxes. Inside my VM it all works fine, but on the server, the second CPT I add overwrites the previous one. This only happens for the CPT shops, the other ones I've added work like they should.
I've placed the code for CPT and the metaboxes in different files and included them inside my functions.php for each CPT.
Here's the file custom-post-type-shop.php for the shop
<?php
/**
* Plugin Name: BUYeinander Shops
* Version: 0.1
* Text Domain: buy_shops
**/
// Register Shop Custom Post Type
function buy_shops()
{
$labels = array(
'name' => _x('Shops', 'Post Type General Name', 'buy_shops'),
'singular_name' => _x('Shop', 'Post Type Singular Name', 'buy_shops'),
'menu_name' => __('Shops', 'buy_shops'),
'name_admin_bar' => __('Shops', 'buy_shops'),
'archives' => __('Shop Archives', 'buy_shops'),
'attributes' => __('Shop Attributes', 'buy_shops'),
'parent_item_colon' => __('Parent Shop:', 'buy_shops'),
'all_items' => __('All Shops', 'buy_shops'),
'add_new_item' => __('Add New Shop', 'buy_shops'),
'add_new' => __('Add New', 'buy_shops'),
'new_item' => __('New Shop', 'buy_shops'),
'edit_item' => __('Edit Shop', 'buy_shops'),
'update_item' => __('Update Shop', 'buy_shops'),
'view_item' => __('View Shop', 'buy_shops'),
'view_items' => __('View Shops', 'buy_shops'),
'search_items' => __('Search Shop', 'buy_shops'),
'not_found' => __('Not found', 'buy_shops'),
'not_found_in_trash' => __('Not found in Trash', 'buy_shops'),
'featured_image' => __('Shop Image', 'buy_shops'),
'set_featured_image' => __('Set Shop image', 'buy_shops'),
'remove_featured_image' => __('Remove Shop image', 'buy_shops'),
'use_featured_image' => __('Use as Shop image', 'buy_shops'),
'insert_into_item' => __('Insert into Shop', 'buy_shops'),
'uploaded_to_this_item' => __('Uploaded to this Shop', 'buy_shops'),
'items_list' => __('Shops list', 'buy_shops'),
'items_list_navigation' => __('Shops list navigation', 'buy_shops'),
'filter_items_list' => __('Filter Shops list', 'buy_shops'),
);
$args = array(
'label' => __('Shops', 'buy_shops'),
'description' => __('Shop-Eintrag', 'buy_shops'),
'labels' => $labels,
'supports' => array(
'title',
// 'editor',
// 'thumbnail',
// 'comments',
'revisions',
// 'custom-fields'
),
// 'taxonomies' => array( 'category' ),
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 20,
'menu_icon' => 'dashicons-store',
'show_in_admin_bar' => true,
'show_in_nav_menus' => true,
'can_export' => true,
'has_archive' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'capability_type' => 'page',
'show_in_rest' => true,
);
register_post_type('Shops', $args);
}
add_action('init', 'buy_shops', 0);
This is the file meta-box-shop.php for the metabox
<?php
// Metabox for shops
$prefix_shop = 'buy_shop_';
$regionargs = array(
'post_type' => "regionen",
'post_status' => 'publish'
);
$regionquery = new WP_Query($regionargs);
$regions = [];
if ($regionquery->have_posts()) {
while ($regionquery->have_posts()) {
$regionquery->the_post();
$regionTitle = $regionquery->post->post_title;
if (!in_array($regionTitle, $regions)) {
$regions[] = $regionTitle;
}
}
}
$shop_meta_box = array(
'id' => 'shop-meta-box',
'title' => 'Shop Informationen',
'page' => 'Shops',
'context' => 'normal',
'priority' => 'high',
'fields' => array(
array(
'name' => 'Untertitel',
'desc' => '',
'id' => $prefix_shop . 'description',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Straße',
'desc' => '',
'id' => $prefix_shop . 'street',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Hausnummer',
'desc' => '',
'id' => $prefix_shop . 'housenumber',
'type' => 'number',
'std' => ''
),
array(
'name' => 'Postleitzahl',
'desc' => '',
'id' => $prefix_shop . 'zipcode',
'type' => 'number',
'std' => ''
),
array(
'name' => 'Stadt',
'desc' => '',
'id' => $prefix_shop . 'city',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Internetadresse',
'desc' => '',
'id' => $prefix_shop . 'url',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Region',
'desc' => '',
'id' => $prefix_shop . 'region',
'type' => 'select',
'std' => '',
'options' => $regions
),
array(
'name' => 'Zweigstelle',
'desc' => '',
'id' => $prefix_shop . 'branch',
'type' => 'checkbox',
'std' => ''
),
)
);
add_action('admin_menu', 'shop_add_box');
// Add meta box
function shop_add_box()
{
global $shop_meta_box;
add_meta_box($shop_meta_box['id'], $shop_meta_box['title'], 'shop_show_box', $shop_meta_box['page'], $shop_meta_box['context'], $shop_meta_box['priority']);
}
// Callback function to show fields in meta box
function shop_show_box()
{
global $shop_meta_box, $post;
// Use nonce for verification
echo '<input type="hidden" name="shop_meta_box_nonce" value="', wp_create_nonce(basename(__FILE__)), '" />';
echo '<table class="form-table">';
foreach ($shop_meta_box['fields'] as $field) {
// get current post meta data
$meta = get_post_meta($post->ID, $field['id'], true);
echo '<tr>',
'<th style="width:20%"><label for="', $field['id'], '">', $field['name'], '</label></th>',
'<td>';
switch ($field['type']) {
case 'text':
echo '<input type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $meta ? $meta : $field['std'], '" size="30" style="width:97%" />', '<br />', $field['desc'];
break;
case 'number':
echo '<input type="number" name="', $field['id'], '" id="', $field['id'], '" value="', $meta ? $meta : $field['std'], '" size="30" style="width:50%" />', '<br />', $field['desc'];
break;
// case 'textarea':
// echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="4" style="width:97%">', $meta ? $meta : $field['std'], '</textarea>', '<br />', $field['desc'];
// break;
case 'select':
echo '<select name="', $field['id'], '" id="', $field['id'], '">';
foreach ($field['options'] as $option) {
echo '<option ', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>';
}
echo '</select>';
break;
// case 'radio':
// foreach ($field['options'] as $option) {
// echo '<input type="radio" name="', $field['id'], '" value="', $option['value'], '"', $meta == $option['value'] ? ' checked="checked"' : '', ' />', $option['name'];
// }
break;
case 'checkbox':
echo '<input type="checkbox" name="', $field['id'], '" id="', $field['id'], '"', $meta ? ' checked="checked"' : '', ' />';
break;
}
echo '</td><td>',
'</td></tr>';
}
echo '</table>';
}
add_action('save_post', 'shop_save_data');
// Save data from meta box
function shop_save_data($post_id)
{
global $shop_meta_box;
// verify nonce
if (!wp_verify_nonce($_POST['shop_meta_box_nonce'], basename(__FILE__))) {
return $post_id;
}
// check autosave
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return $post_id;
}
// check permissions
if ('page' == $_POST['post_type']) {
if (!current_user_can('edit_page', $post_id)) {
return $post_id;
}
} elseif (!current_user_can('edit_post', $post_id)) {
return $post_id;
}
foreach ($shop_meta_box['fields'] as $field) {
$old = get_post_meta($post_id, $field['id'], true);
$new = $_POST[$field['id']];
if ($new && $new != $old) {
update_post_meta($post_id, $field['id'], $new);
} elseif ('' == $new && $old) {
delete_post_meta($post_id, $field['id'], $old);
}
}
}
/*
* Add a meta box for image upload
*/
function lacuna2_case_study_bg( $post ) {
wp_nonce_field( 'case_study_bg_submit', 'case_study_bg_nonce' );
$lacuna2_stored_meta = get_post_meta( $post->ID ); ?>
<p>
<img style="max-width:200px;height:auto;" id="meta-image-preview" src="<?php if ( isset ( $lacuna2_stored_meta['meta-image'] ) ){ echo $lacuna2_stored_meta['meta-image'][0]; } ?>" /> <br>
<input type="text" name="meta-image" id="meta-image" class="meta_image" value="<?php if ( isset ( $lacuna2_stored_meta['meta-image'] ) ){ echo $lacuna2_stored_meta['meta-image'][0]; } ?>" />
<input type="button" id="meta-image-button" class="button" value="Choose or Upload an Image" />
</p>
<script>
jQuery('#meta-image-button').click(function() {
var send_attachment_bkp = wp.media.editor.send.attachment;
wp.media.editor.send.attachment = function(props, attachment) {
jQuery('#meta-image').val(attachment.url);
jQuery('#meta-image-preview').attr('src',attachment.url);
wp.media.editor.send.attachment = send_attachment_bkp;
}
wp.media.editor.open();
return false;
});
</script>
<?php
}
/**
* Add Case Study background image metabox to the back end of Case Study posts
*/
function lacuna2_add_meta_boxes() {
add_meta_box( 'case-study-bg', 'Shop Bilddatei', 'lacuna2_case_study_bg', 'shops', 'normal', 'high' );
}
add_action( 'add_meta_boxes', 'lacuna2_add_meta_boxes' );
/**
* Save background image metabox for Case Study posts
*/
function save_case_study_bg_meta_box( $post_id ) {
$is_autosave = wp_is_post_autosave( $post_id );
$is_revision = wp_is_post_revision( $post_id );
$is_valid_nonce = ( isset( $_POST[ 'case_study_bg_nonce' ] ) && wp_verify_nonce( $_POST[ 'case_study_bg_nonce' ], 'case_study_bg_submit' ) ) ? 'true' : 'false';
// Exits script depending on save status
if ( $is_autosave || $is_revision || !$is_valid_nonce ) {
return;
}
// Checks for input and sanitizes/saves if needed
if( isset( $_POST[ 'meta-image' ] ) ) {
update_post_meta( $post_id, 'meta-image', $_POST[ 'meta-image' ] );
}
}
add_action( 'save_post', 'save_case_study_bg_meta_box' );
1) Make sure both post_types use an unique post_type key. That is the first parameter for the register_post_type function. See docs: https://developer.wordpress.org/
2) Also: make sure to use a post_type key with only lowercase characters. As I may quote the documentation:
$post_type (string) (Required) Post type key. Must not exceed 20
characters and may only contain lowercase alphanumeric characters,
dashes, and underscores.
So change:
register_post_type('Shops', $args);
into:
register_post_type('shops', $args);
In register_post_type() function, you have to put a unique post_type_key for each Custom Post Type. You're providing the same post_type_key for both Custom Post Type that's why the second one is overriding the first one. As you're using
register_post_type('shops', $args);
for the first one, you should use something else as post_type_key at the first parameter for the second Custom Post Type. You have to use anything unique for this. For example,
register_post_type('my-shop', $args);
Visit the official doc for details.

WooCommerce add heading at start of custom fields

I have created custom fields in my WooCommerce checkout page billing form. It all works fine but I am trying to add an h3 element with text in between. So basically I ask for some additional information in the billing form, but I want to give that a heading.
I tried to create a h3 dynamically with Javascript/jQuery and insert before the specific id I want it to be. But this didn't work as I liked and I rather have a server-side solution.
Thanks in advance!
Here's the function where I define my custom fields. I've tried an echo at the beginning but it ends up displaying at the top of the entire form.
// Modify billing fields
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
function custom_override_checkout_fields( $fields ) {
unset($fields['billing']['billing_phone']);
unset($fields['billing']['billing_email']);
//echo '<h3>Wie is de verzender?</h3>';
$fields['billing']['name_sender'] = array(
'label' => __('Uw naam', 'woocommerce'),
'required' => true,
'class' => array('form-row-wide'),
'clear' => true
);
$fields['billing']['email_sender'] = array(
'label' => __('Uw email', 'woocommerce'),
'required' => true,
'class' => array('form-row-wide'),
'clear' => true
);
$fields['billing']['phone_sender'] = array(
'label' => __('Uw telefoonnummer', 'woocommerce'),
'required' => true,
'class' => array('form-row-wide'),
'clear' => true
);
$fields['billing']['anoniem'] = array(
'label' => __('Anoniem verzenden?', 'woocommerce'),
'type' => 'checkbox',
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
A visual explanation:
Visual explanation
You can hook into the woocommerce_form_field_<field_type> filter. This allows us to add HTML output for an additional field type (and in this case we can output HTML for a heading instead) and we can use this new heading "field type" when modifying checkout fields with the woocommerce_checkout_fields filter.
// Add field type to WooCommerce form field
add_filter( 'woocommerce_form_field_heading','sc_woocommerce_form_field_heading', 10, 4 );
function sc_woocommerce_form_field_heading($field, $key, $args, $value) {
$output = '<h3 class="form-row form-row-wide">'.__( $args['label'], 'woocommerce' ).'</h3>';
echo $output;
}
// Modify checkout fields
add_filter( 'woocommerce_checkout_fields','custom_override_checkout_fields' );
function custom_override_checkout_fields( $fields ) {
$fields['billing']['billing_heading_name'] = array(
'type' => 'heading',
'label' => 'Heading here',
);
When modifying fields using the woocommerce_checkout_fields filter you can now place your new heading field in any position you need.
function filter_woocommerce_form_field_radio( $field, $key, $args, $value ) {
// Based on key
if ( $key == 'radio_choice' ) {
if ( ! empty( $args['options'] ) ) {
$field = '<div><h1>Heading</h1><ul>';
foreach ( $args['options'] as $option_key => $option_text ) {
$field .= '<li>';
$field .= '<input type="radio" value="' . esc_attr( $option_key ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '_' . esc_attr( $option_key ) . '" />';
$field .= '<label>' . esc_html( $option_text ) . '</label>';
$field .= '</li>';
}
$field .= '</ul></div>';
}
}
return $field;
}
add_filter( 'woocommerce_form_field_radio', 'filter_woocommerce_form_field_radio', 10, 4 );

Custom post meta showing on localhost, but not live server?

I'm having an issue and, honestly, I have absolutely no idea what's going on...
I have some custom meta fields for my custom post type (called review). On my local installation, they appear and work perfectly:
However, on live, they don't show up! Completely vanished!
The panel is selected in Screen Options too, so that's not the issue:
Here is the code for my entire custom post type... perhaps I've done something stupid?
<?php
// Register Custom Post Type
function review() {
$labels = array(
'name' => 'Reviews',
'singular_name' => 'Review',
'menu_name' => 'Reviews',
'name_admin_bar' => 'Review',
'archives' => 'Review Archives',
'parent_item_colon' => 'Parent Item:',
'all_items' => 'All Items',
'add_new_item' => 'Add New Item',
'add_new' => 'Add New',
'new_item' => 'New Item',
'edit_item' => 'Edit Item',
'update_item' => 'Update Item',
'view_item' => 'View Item',
'search_items' => 'Search Item',
'not_found' => 'Not found',
'not_found_in_trash' => 'Not found in Trash',
'featured_image' => 'Featured Image',
'set_featured_image' => 'Set featured image',
'remove_featured_image' => 'Remove featured image',
'use_featured_image' => 'Use as featured image',
'insert_into_item' => 'Insert into item',
'uploaded_to_this_item' => 'Uploaded to this item',
'items_list' => 'Items list',
'items_list_navigation' => 'Items list navigation',
'filter_items_list' => 'Filter items list',
);
$args = array(
'label' => 'Review',
'description' => 'A product review',
'labels' => $labels,
'supports' => array( 'title', 'editor', 'excerpt', 'author', 'thumbnail', 'comments', 'revisions'),
'taxonomies' => array( 'category', 'post_tag' ),
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-edit',
'show_in_admin_bar' => true,
'show_in_nav_menus' => true,
'can_export' => true,
'has_archive' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'capability_type' => 'page',
);
register_post_type( 'review', $args );
}
add_action( 'init', 'review', 0 );
//Review options meta
/**
* Generated by the WordPress Meta Box generator
* at http://jeremyhixon.com/tool/wordpress-meta-box-generator/
*/
function review_options_get_meta( $value ) {
global $post;
$field = get_post_meta( $post->ID, $value, true );
if ( ! empty( $field ) ) {
return is_array( $field ) ? stripslashes_deep( $field ) : stripslashes( wp_kses_decode_entities( $field ) );
} else {
return false;
}
}
function review_options_add_meta_box() {
add_meta_box(
'review_options-review-options',
__( 'Review options', 'review_options' ),
'review_options_html',
'review',
'core',
'high'
);
}
add_action( 'add_meta_boxes', 'review_options_add_meta_box' );
function review_options_html( $post) {
wp_nonce_field( '_review_options_nonce', 'review_options_nonce' ); ?>
<p>Options for your reviews</p>
<p>
<label for="review_options_review_score"><?php _e( 'Review Score', 'review_options' ); ?></label><br>
<select name="review_options_review_score" id="review_options_review_score" style="width: 50%;">
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '1' ) ? 'selected' : '' ?>>1</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '2' ) ? 'selected' : '' ?>>2</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '3' ) ? 'selected' : '' ?>>3</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '4' ) ? 'selected' : '' ?>>4</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '5' ) ? 'selected' : '' ?>>5</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '6' ) ? 'selected' : '' ?>>6</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '7' ) ? 'selected' : '' ?>>7</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '8' ) ? 'selected' : '' ?>>8</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '9' ) ? 'selected' : '' ?>>9</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '10' ) ? 'selected' : '' ?>>10</option>
</select>
</p> <p>
<label for="review_options_review_title_colour"><?php _e( 'Review title colour', 'review_options' ); ?></label><br>
<select name="review_options_review_title_colour" id="review_options_review_title_colour">
<option <?php echo (review_options_get_meta( 'review_options_review_title_colour' ) === '' ) ? 'selected' : '' ?>>Default</option>
<option <?php echo (review_options_get_meta( 'review_options_review_title_colour' ) === 'black' ) ? 'selected' : '' ?>>Black</option>
<option <?php echo (review_options_get_meta( 'review_options_review_title_colour' ) === 'white' ) ? 'selected' : '' ?>>White</option>
</select>
</p><?php
}
function review_options_save( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( ! isset( $_POST['review_options_nonce'] ) || ! wp_verify_nonce( $_POST['review_options_nonce'], '_review_options_nonce' ) ) return;
if ( ! current_user_can( 'edit_post', $post_id ) ) return;
if ( isset( $_POST['review_options_review_score'] ) )
update_post_meta( $post_id, 'review_options_review_score', esc_attr( $_POST['review_options_review_score'] ) );
if ( isset( $_POST['review_options_review_title_colour'] ) )
update_post_meta( $post_id, 'review_options_review_title_colour', esc_attr( $_POST['review_options_review_title_colour'] ) );
}
add_action( 'save_post', 'review_options_save' );
/*
Usage: review_options_get_meta( 'review_options_review_score' )
Usage: review_options_get_meta( 'review_options_review_title_colour' )
*/
?>
Or perhaps it's something to do with my only other post type?
<?php // Register Custom Post Type
function product() {
$labels = array(
'name' => _x( 'Products', 'Post Type General Name', 'text_domain' ),
'singular_name' => _x( 'Product', 'Post Type Singular Name', 'text_domain' ),
'menu_name' => __( 'Product', 'text_domain' ),
'name_admin_bar' => __( 'Product', 'text_domain' ),
'archives' => __( 'Products', 'text_domain' ),
'parent_item_colon' => __( 'Product', 'text_domain' ),
'all_items' => __( 'All Products', 'text_domain' ),
'add_new_item' => __( 'Add New Product', 'text_domain' ),
'add_new' => __( 'Add New', 'text_domain' ),
'new_item' => __( 'New Product', 'text_domain' ),
'edit_item' => __( 'Edit Product', 'text_domain' ),
'update_item' => __( 'Update Product', 'text_domain' ),
'view_item' => __( 'View Product', 'text_domain' ),
'search_items' => __( 'Search Products', 'text_domain' ),
'not_found' => __( 'Not found', 'text_domain' ),
'not_found_in_trash' => __( 'Not found in Trash', 'text_domain' ),
'featured_image' => __( 'Featured Image', 'text_domain' ),
'set_featured_image' => __( 'Set featured image', 'text_domain' ),
'remove_featured_image' => __( 'Remove featured image', 'text_domain' ),
'use_featured_image' => __( 'Use as featured image', 'text_domain' ),
'insert_into_item' => __( 'Insert into Product', 'text_domain' ),
'uploaded_to_this_item' => __( 'Uploaded to this Product', 'text_domain' ),
'items_list' => __( 'Product list', 'text_domain' ),
'items_list_navigation' => __( 'Product list navigation', 'text_domain' ),
'filter_items_list' => __( 'Filter Product list', 'text_domain' ),
);
$args = array(
'label' => __( 'Product', 'text_domain' ),
'description' => __( 'A product', 'text_domain' ),
'labels' => $labels,
'supports' => array( 'title', 'editor', 'thumbnail', ),
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 8,
'menu_icon' => 'dashicons-archive',
'show_in_admin_bar' => true,
'show_in_nav_menus' => true,
'can_export' => true,
'has_archive' => true,
'exclude_from_search' => true,
'publicly_queryable' => true,
'capability_type' => 'page',
);
register_post_type( 'product', $args );
}
add_action( 'init', 'product', 0 );
//Creation of Meta Box for post type "destination_category" (Start)
add_action( 'admin_init', 'my_destination_category' );
//destination_sub_category_admin - is the required HTML id attribute
//Select Destination Sub Category - is the text visible in the heading of the meta box section
//display_destination_subcategory_meta_box - is the callback which renders the contents of the meta box
//destination_category - is the name of the custom post type where the meta box will be displayed
// normal - defines the part of the page where the edit screen section should be shown
// high - defines the priority within the context where the boxes should show
function my_destination_category() {
foreach( array( 'post', 'review' ) as $pt )
add_meta_box(
'destination_sub_category_admin',
'Select Destination Sub Category',
'display_destination_subcategory_meta_box',
$pt,
'normal',
'high');
function display_destination_subcategory_meta_box( $select_category ) {
// Retrieve Current Selected Category ID based on the Category Created
global $wpdb;
$selectcat="SELECT * FROM ".$wpdb->prefix."posts WHERE `post_type`='product' AND `post_status`='publish' ORDER BY `ID` DESC";
$resultant = $wpdb->get_results($selectcat);
$rescount=count($resultant);
$category_selected_id = intval( get_post_meta( $select_category->ID, 'destination_category_id', true ) );
?>
<table>
<tr>
<td style="width: 150px">Select Category</td>
<td>
<select style="width: 100px" name="category_selection" id="meta_box_category" style="float:left; width:50%; !important">
<?php
if($rescount==0)
{?>
<option value="null">No Posts have been created</option>
<?php
}
else
{
// Generate all items of drop-down list
?>
<option value="">None</option>
<?php
foreach($resultant as $singleresultant)
{
?>
<option value="<?php echo $singleresultant->ID; ?>" <?php echo selected( $singleresultant->ID, $category_selected_id ); ?>>
<?php echo $singleresultant->post_title; ?>
</option>
<?php
}
}
?>
</select>
</td>
</tr>
</table>
<?php
}
// Registering a Save Post Function
add_action( 'save_post', 'destination_admin_sub_category', 10, 2 );
function destination_admin_sub_category( $select_category_id, $select_category ) {
if ( $select_category->post_type == 'post' || 'review' ) {
if ( isset( $_POST['category_selection'] ) && $_POST['category_selection'] != '' ) {
echo update_post_meta( $select_category_id, 'destination_category_id', $_POST['category_selection'] );
} }
}
}
/**
* Generated by the WordPress Meta Box Generator at
*/
class Rational_Meta_Box {
private $screens = array(
'product',
);
private $fields = array(
array(
'id' => 'box-art',
'label' => 'Box Art',
'type' => 'media',
),
array(
'id' => 'developer',
'label' => 'Developer',
'type' => 'text',
),
array(
'id' => 'publisher',
'label' => 'Publisher',
'type' => 'text',
),
array(
'id' => 'release-date',
'label' => 'Release Date',
'type' => 'date',
),
);
/**
* Class construct method. Adds actions to their respective WordPress hooks.
*/
public function __construct() {
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
add_action( 'admin_footer', array( $this, 'admin_footer' ) );
add_action( 'save_post', array( $this, 'save_post' ) );
}
/**
* Hooks into WordPress' add_meta_boxes function.
* Goes through screens (post types) and adds the meta box.
*/
public function add_meta_boxes() {
foreach ( $this->screens as $screen ) {
add_meta_box(
'product-options',
__( 'Product Options', 'product-options' ),
array( $this, 'add_meta_box_callback' ),
$screen,
'advanced',
'core'
);
}
}
/**
* Generates the HTML for the meta box
*
* #param object $post WordPress post object
*/
public function add_meta_box_callback( $post ) {
wp_nonce_field( 'product_options_data', 'product_options_nonce' );
echo 'Options for products';
$this->generate_fields( $post );
}
/**
* Hooks into WordPress' admin_footer function.
* Adds scripts for media uploader.
*/
public function admin_footer() {
?><script>
// https://codestag.com/how-to-use-wordpress-3-5-media-uploader-in-theme-options/
jQuery(document).ready(function($){
if ( typeof wp.media !== 'undefined' ) {
var _custom_media = true,
_orig_send_attachment = wp.media.editor.send.attachment;
$('.rational-metabox-media').click(function(e) {
var send_attachment_bkp = wp.media.editor.send.attachment;
var button = $(this);
var id = button.attr('id').replace('_button', '');
_custom_media = true;
wp.media.editor.send.attachment = function(props, attachment){
if ( _custom_media ) {
$("#"+id).val(attachment.url);
} else {
return _orig_send_attachment.apply( this, [props, attachment] );
};
}
wp.media.editor.open(button);
return false;
});
$('.add_media').on('click', function(){
_custom_media = false;
});
}
});
</script><?php
}
/**
* Generates the field's HTML for the meta box.
*/
public function generate_fields( $post ) {
$output = '';
foreach ( $this->fields as $field ) {
$label = '<label for="' . $field['id'] . '">' . $field['label'] . '</label>';
$db_value = get_post_meta( $post->ID, 'product_options_' . $field['id'], true );
switch ( $field['type'] ) {
case 'media':
$input = sprintf(
'<input class="regular-text" id="%s" name="%s" type="text" value="%s"> <input class="button rational-metabox-media" id="%s_button" name="%s_button" type="button" value="Upload" />',
$field['id'],
$field['id'],
$db_value,
$field['id'],
$field['id']
);
break;
default:
$input = sprintf(
'<input %s id="%s" name="%s" type="%s" value="%s">',
$field['type'] !== 'color' ? 'class="regular-text"' : '',
$field['id'],
$field['id'],
$field['type'],
$db_value
);
}
$output .= $this->row_format( $label, $input );
}
echo '<table class="form-table"><tbody>' . $output . '</tbody></table>';
}
/**
* Generates the HTML for table rows.
*/
public function row_format( $label, $input ) {
return sprintf(
'<tr><th scope="row">%s</th><td>%s</td></tr>',
$label,
$input
);
}
/**
* Hooks into WordPress' save_post function
*/
public function save_post( $post_id ) {
if ( ! isset( $_POST['product_options_nonce'] ) )
return $post_id;
$nonce = $_POST['product_options_nonce'];
if ( !wp_verify_nonce( $nonce, 'product_options_data' ) )
return $post_id;
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return $post_id;
foreach ( $this->fields as $field ) {
if ( isset( $_POST[ $field['id'] ] ) ) {
switch ( $field['type'] ) {
case 'email':
$_POST[ $field['id'] ] = sanitize_email( $_POST[ $field['id'] ] );
break;
case 'text':
$_POST[ $field['id'] ] = sanitize_text_field( $_POST[ $field['id'] ] );
break;
}
update_post_meta( $post_id, 'product_options_' . $field['id'], $_POST[ $field['id'] ] );
} else if ( $field['type'] === 'checkbox' ) {
update_post_meta( $post_id, 'product_options_' . $field['id'], '0' );
}
}
}
}
new Rational_Meta_Box;
?>
Either way, I have absolutely no idea why it's working perfectly locally and messing up on my live server... it's baffling!
Thanks in advance for your help!

How do you add custom columns for these custom post types?

I've recently been developing a plugin that involves custom post types and taxonomies. What I'm struggling with at the moment is getting the custom post fields to display in the 'All Reservations' screen. I can get the columns to display, but cannot for the life of me get the fields within the columns to populate with the data from the database.
My custom post code is below:
function reservations_init() {
$labels = array(
'name' => _x( 'Reservations', 'post type general name' ),
'singular_name' => _x( 'Reservation', 'post type singular name' ),
'add_new' => _x( 'Add New', 'reservation' ),
'add_new_item' => __( 'Add New Reservation' ),
'edit_item' => __( 'Edit Reservation' ),
'new_item' => __( 'New Reservation' ),
'all_items' => __( 'Reservations' ),
'view_item' => __( 'View Reservation' ),
'search_items' => __( 'Search Reservations' ),
'not_found' => __( 'No reservations found' ),
'not_found_in_trash' => __( 'No reservations found in the Trash' ),
'parent_item_colon' => '',
'menu_name' => 'Reservations'
);
$args = array(
'labels' => $labels,
'description' => 'Holds our reservations',
'public' => true,
'menu_position' => 5,
'supports' => array( 'none' ),
'has_archive' => true,
'show_in_nav_menu' => true,
'show_in_menu' => 'edit.php?post_type=meals',
);
register_post_type( 'reservations', $args );
}
add_action( 'init', 'reservations_init' );
function restauranter_add_meta_box() {
$screens = array( 'reservations' );
foreach ( $screens as $screen ) {
add_meta_box(
'restauranter_firstname',
__( 'Reservation Details', 'restauranter' ),
'restauranter_reservation_details',
$screen,
'normal',
'high'
);
}
}
add_action( 'add_meta_boxes', 'restauranter_add_meta_box' );
function restauranter_reservation_details() {
global $post;
echo '<input type="hidden" name="reservationmeta_noncename" id="reservationmeta_noncename" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
$firstname = get_post_meta($post->ID, '_firstname', true);
$lastname = get_post_meta($post->ID, '_lastname', true);
$phone = get_post_meta($post->ID, '_phone', true);
$email = get_post_meta($post->ID, '_email', true);
$guests = get_post_meta($post->ID, '_guests', true);
$date = get_post_meta($post->ID, '_date', true);
$time = get_post_meta($post->ID, '_time', true);
echo '<p>First Name:</p>';
echo '<input type="text" name="_firstname" value="' . $firstname . '" class="widefat" />';
echo '<p>Last Name:</p>';
echo '<input type="text" name="_lastname" value="' . $lastname . '" class="widefat" />';
echo '<p>Phone Number:</p>';
echo '<input type="text" name="_phone" value="' . $phone . '" class="widefat" />';
echo '<p>Email:</p>';
echo '<input type="text" name="_email" value="' . $email . '" class="widefat" />';
echo '<p>Number of Guests:</p>';
echo '<input type="text" name="_guests" value="' . $guests . '" class="widefat" />';
echo '<p>Reservation Date:</p>';
echo '<input type="text" name="_date" value="' . $date . '" class="widefat date" />';
echo '<p>Reservation Time:</p>';
echo '<input type="text" name="_time" value="' . $time . '" class="widefat time" />';
echo '<input type="submit" name="_time" value="" class="widefat submit" />';
}
function restauranter_save_reservations_meta($post_id, $post) {
if ( !wp_verify_nonce( $_POST['reservationmeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
// Is the user allowed to edit the post or page?
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
$reservations_meta['_firstname'] = $_POST['_firstname'];
$reservations_meta['_lastname'] = $_POST['_lastname'];
$reservations_meta['_phone'] = $_POST['_phone'];
$reservations_meta['_email'] = $_POST['_email'];
$reservations_meta['_guests'] = $_POST['_guests'];
$reservations_meta['_date'] = $_POST['_date'];
$reservations_meta['_time'] = $_POST['_time'];
foreach ($reservations_meta as $key => $value) {
if( $post->post_type == 'revision' ) return;
$value = implode(',', (array)$value);
if(get_post_meta($post->ID, $key, FALSE)) {
update_post_meta($post->ID, $key, $value);
} else {
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key);
}
}
add_action('save_post', 'restauranter_save_reservations_meta', 1, 2); // save the custom fields
function add_new_reservations_columns($reservations_columns) {
$new_columns['cb'] = '<input type="checkbox" />';
$new_columns['_firstname'] = __('First Name', '_firstname');
return $new_columns;
}
add_filter('manage_edit-reservations_columns' , 'add_new_reservations_columns');
I have tried googling, I have tried numerous samples of code, I have tried playing about with the code my self also but still no joy.
You need one more function to add data into those columns....
function custom_edit-reservations_columns( $column, $post_id ) {
switch ( $column ) {
case "_firstname":
$firstname = get_post_meta($post_id, '_firstname', true);
echo $firstname;
break;
}
}
add_action( "manage_posts_custom_column", "custom_edit-reservations_columns", 10, 2 );
Hope that helps

Make table for this meta box? (wordpress)

I have been trying to display this meta box info in my template as a table, but it isn't working out.
What I want to do is make a simple table out of it. All I need is someone to help me start. The code for the meta box is done, but I have no idea how to output it.
$prefix = 'anime_';
$anime_box = array(
'id' => 'anime-meta-box',
'title' => 'Anime Details',
'page' => 'post',
'context' => 'normal',
'priority' => 'high',
'fields' => array(
array(
'name' => 'Name',
'desc' => 'Add the name of the Anime in either English or Japanese(Romanji).',
'id' => $prefix . 'anname',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Genre',
'desc' => 'Is it a thriller, action/adventure, etc...',
'id' => $prefix . 'angenre',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Directed by',
'desc' => 'Name of director(s).',
'id' => $prefix . 'an_director',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Music by',
'desc' => 'Name of composer(s)',
'id' => $prefix . 'anmusic',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Studio',
'desc' => 'Studio which owns the anime.',
'id' => $prefix . 'anstudio',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Licensed by',
'desc' => 'Name of both American and Japanese license holders.',
'id' => $prefix . 'anlicense',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Network(s)',
'desc' => 'Networks which air the show in both Japan and the United States.',
'id' => $prefix . 'annetwork',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Original run',
'desc' => 'Date of when the anime first aired and when it stopped.',
'id' => $prefix . 'anrun',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Episodes',
'desc' => 'Number of episodes.',
'id' => $prefix . 'anepisodes',
'type' => 'text',
'std' => ''
),
)
);
add_action('admin_menu', 'anime_add_box');
// Add meta box
function anime_add_box() {
global $anime_box;
add_meta_box($anime_box['id'], $anime_box['title'], 'anime_show_box', $anime_box['page'], $anime_box['context'], $anime_box['priority']);
}
// Callback function to show fields in meta box
function anime_show_box() {
global $anime_box, $post;
// Use nonce for verification
echo '<input type="hidden" name="anime_meta_box_nonce" value="', wp_create_nonce(basename(__FILE__)), '" />';
echo '<table class="form-table">';
foreach ($anime_box['fields'] as $field) {
// get current post meta data
$meta = get_post_meta($post->ID, $field['id'], true);
echo '<tr>',
'<th style="width:20%"><label for="', $field['id'], '"><strong>', $field['name'], ':</strong></label></th>',
'<td>';
switch ($field['type']) {
case 'text':
echo '<input type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $meta ? $meta : $field['std'], '" size="30" style="width:97%" />',
'<br /><small>', $field['desc'],'</small>';
break;
}
echo '<td>',
'</tr>';
}
echo '</table>';
}
add_action('save_post', 'anime_save_data');
// Save data from meta box
function anime_save_data($post_id) {
global $anime_box;
// verify nonce
if (!wp_verify_nonce($_POST['anime_meta_box_nonce'], basename(__FILE__))) {
return $post_id;
}
// check autosave
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return $post_id;
}
// check permissions
if ('page' == $_POST['post_type']) {
if (!current_user_can('edit_page', $post_id)) {
return $post_id;
}
} elseif (!current_user_can('edit_post', $post_id)) {
return $post_id;
}
foreach ($anime_box['fields'] as $field) {
$old = get_post_meta($post_id, $field['id'], true);
$new = $_POST[$field['id']];
if ($new && $new != $old) {
update_post_meta($post_id, $field['id'], $new);
} elseif ('' == $new && $old) {
delete_post_meta($post_id, $field['id'], $old);
}
}
}
I tried using
<table>
<tr>
<td><?php echo get_post_meta($post->ID, "anname", true); ?></td>
</tr>
</table>
As a way to test it out one field, but it hasn't worked. Any ideas?
I believe the code you are using should be correct, however, the meta data ID you retrieving seems to be missing your prefix variable out: "anime_". Try:
<?php echo get_post_meta($post->ID, "anime_anname", true); ?>

Resources