Adding settings page to a custom post type

I had some struggles with this and now I describe how to do it and what helped me figure out my problem.

1. Register custom post type

First we need to register the desired custom post type.
http://codex.wordpress.org/Function_Reference/register_post_type#Example

add_action( 'init', 'cpt_payment' );
function cpt_payment() {
    $args = array( ... );
    register_post_type( 'payment', $args );
}

2. Add submenu

http://codex.wordpress.org/Function_Reference/add_submenu_page#Example

    function payment_settings() {

        /*
         * Add a settings page for this plugin to the custom post type menu.
         *
         * NOTE:  Alternative menu locations are available via WordPress administration menu functions.
         *
         *        Administration Menus: http://codex.wordpress.org/Administration_Menus
         *
         *   For reference: http://codex.wordpress.org/Roles_and_Capabilities
         */
        add_submenu_page(
            "edit.php?post_type=payment",
            'Payment settings',
            'Settings',
            'manage_options',
            "payment-settings",
            'show_settings_admin_page'
        );

    }
    add_action( 'admin_menu', 'payment_settings' ) );

The take away

I had a different post_type parameter value in add_submenu_page first argument, that’s why the submenu didn’t appear.
To figure this out I echoed the generated submenu in wp-admin/includes/plugin.php of add_submenu_page function.

// wp-admin/includes/plugin.php
1133     $submenu[$parent_slug][] = array ( $menu_title, $capability, $menu_slug, $page_title );
1134     echo "<pre>"; print_r($submenu); echo "</pre>";exit;

And the output snippet of that debug line:

Array
(
    [index.php] => Array
        (
            [0] => Array
                (
                    [0] => Home
                    [1] => read
                    [2] => index.php
                )

            [10] => Array
                (
                    [0] => Updates 0
                    [1] => update_core
                    [2] => update-core.php
                )

        )

    [edit.php] => Array
        (
            [5] => Array
                (
                    [0] => All Posts
                    [1] => edit_posts
                    [2] => edit.php
                )

            [10] => Array
                (
                    [0] => Add New
                    [1] => edit_posts
                    [2] => post-new.php
                )

            [15] => Array
                (
                    [0] => Categories
                    [1] => manage_categories
                    [2] => edit-tags.php?taxonomy=category
                )

            [16] => Array
                (
                    [0] => Tags
                    [1] => manage_categories
                    [2] => edit-tags.php?taxonomy=post_tag
                )

        )
    [edit.php?post_type=payment] => Array
        (
            [5] => Array
                (
                    [0] => All Payments
                    [1] => edit_posts
                    [2] => edit.php?post_type=payment
                )

            [11] => Array
                (
                    [0] => Settings
                    [1] => manage_options
                    [2] => payment-settings
                    [3] => Payments settings
                )

        )

After seeing that output I saw the solution.
Hope it helps others. For me it was a learning bomb better understaing a code block from WP.

Custom post type Settings subpage

Special thanks to:

http://www.billrobbinsdesign.com/custom-post-type-admin-page/

http://justintadlock.com/archives/2010/04/29/custom-post-types-in-wordpress

Advertisements

Disable, turn off CSS

My internet connection is out 😦

740 packets transmitted, 220 received, +501 errors, 70% packet loss,
time 740082ms
rtt min/avg/max/mdev = 4.201/5.043/7.303/0.593 ms

So I switched to mobile, but I used my prepaid 700MB data limit so downstream is only 64kbps 😦
Needed to find a way to turn off CSS and found http://sumtips.com/2012/07/turn-off-css-on-a-specific-website-in-browser-for-testing.html

Converting gettext .po files to binary .mo files via command line

Updated a WP plugin and translation needed fixation. I edited the .po file, but no change was on the site. I needed to convert it to .mo file.
Thanks to Joss Crowcroft and his post http://www.josscrowcroft.com/2011/code/php-mo-convert-gettext-po-file-to-binary-mo-file-php/ I was able to convert.

$ msgfmt -cv -o wp-content/plugins/woocommerce/i18n/languages/woocommerce-sk_SK.mo wp-content/plugins/woocommerce/i18n/languages/woocommerce-sk_SK.po
1939 translated messages, 2 untranslated messages.

WooCommerce advanced (product attribute) search

I couldn’t find answers why Googling, how to make search work with product attributes of WooCommerce products.
Wrote the code, but it was always 404 page. URLs with /taxonomy/term_slug (example.com/radius/16/) were working, but example.com/?s=&post_type=product&pa_radius=TERM_ID&pa_width=TERM_ID&pa_manufacturer=TERM_ID wasn’t outputing any products.

header.php

 <form action="<?php echo site_url( '/' ); ?>" class="search2">
 <input type="hidden" name="s" value=""/>
 <input type="hidden" name="post_type" value="product"/>
 <img src="<?php echo get_template_directory_uri(); ?>/img/box_holder.png">

 <div class="search_box">
 <h3 class="search_title">Search by attribute</h3>
 <select class="selectBox" name="pa_season">
 <?php echo pf_get_filter_options( 'Season', 'pa_season' ); ?>
 </select>
 <select class="selectBox" name="pa_radius">
 <?php echo pf_get_filter_options( 'Radius', 'pa_radius' ); ?>
 </select>
 <select class="selectBox" name="pa_height">
 <?php echo pf_get_filter_options( 'Height', 'pa_height' ); ?>
 </select>
 <select class="selectBox" name="pa_width">
 <?php echo pf_get_filter_options( 'Width', 'pa_width' ); ?>
 </select>
 <select class="selectBox" name="pa_speedindex">
 <?php echo pf_get_filter_options( 'Speed index', 'pa_speedindex' ); ?>
 </select>
 <select class="selectBox" name="pa_manufacturer">
 <?php echo pf_get_filter_options( 'Manufacturer', 'pa_manufacturer' ); ?>
 </select>
 <button class="search-button" type="submit">Search ➤</button>
 </div>
 </form>

functions.php

/**
 * Output for specified taxonomy ( product attributee)
 *
 * @return string  list
 */
function pf_get_filter_options( $title, $taxonomy ) {

    global $wp_query;

    $options = '' . $title . '';

    $data = get_terms( $taxonomy );

    foreach ( $data as $term ) {

        // Skip some weird terms
        switch ( $taxonomy ) {
            case 'pa_radius':
                if ( in_array($term->slug, array('13c','14c','15c','1616c','16c')) )
                    continue( 2 );

                break;

            case 'pa_width':
                if ( in_array($term->slug, array('195205','255265')) )
                    continue( 2 );

                break;
        }

        $selected = isset( $wp_query->query_vars[$taxonomy] ) && $wp_query->query_vars[$taxonomy] == $term->term_id ? ' selected="selected"' : '';
        $options .= '<option value="' . $term->term_id . '"' . $selected . '>' . $term->name . '</option>';

    }

    return $options;

}

So I decided to watch https://www.youtube.com/watch?v=v7Uj3pLQseM to free my mind a bit.
In the talk Debug Bar was mentioned that I tried before, but I’m used
to watch errors in OSX Console.app so I wasn’t using Debug Bar.

What catched my attention was the SQL queries log so I added
define('SAVEQUERIES', true); to my wp-config.php and installed Debug Bar
to give it another try.

So I clicked Debug, went over the queries and found the solution.

Debug Bar Queries
Debug Bar Queries

Solution

The problem was that as value I was using $term->term_id instead $term->slug by which the queries search in code.

Different wp_title and WooCommerce page title by terms

In a project I needed wp_title with the separator, but WC page title without separator for specific terms of a taxonomy.

Here’s the code I used:

/**
 * Add more descriptive page title to some taxonomy term
 *
 * @param string $title    Page title.
 * @param string $sep      Title separator.
 * @return string
 **/
function pf_fix_title( $title, $sep = null ) {

    $term = get_queried_object();

    if ( is_front_page() && $sep !== null )
        return "Lacné letné a zimné pneumatiky $sep";
    if (is_404() && $sep !== null )
        return "Stránka neexistuje $sep";

    switch ( $term->taxonomy ) {

        case 'pa_radius':
            $title = "$term->name-palcové pneumatiky $sep";
            break;

        case 'pa_season':
            $tax = get_taxonomy( $term->taxonomy );
            $title = "$term->name pneumatiky $sep";
            if ( $sep !== null )
                $title .= " $tax->label $sep";
            break;

    }

    return $title;
}
add_filter( 'wp_title', 'pf_fix_title', 10, 2 );
add_filter( 'woocommerce_page_title', 'pf_fix_title' );

My first WordPress plugin

Finally finished my first WordPress plugin. With the help of  Woocommerce CSV importer I successfully imported 4175 products into WooCommerce and needed to import attributes. WP All Import is a very good paid alternative (tried there awesome demo), but as a newcomer coder I wanted to learn WP so wrote the plugin that imports those attributes.

virtuemart-import
The plugin to import
product-attributes
Set product attributes
woocommerce-product-attributes
All attributes
database-stats
DB stats for 4175 products with their attributes