Özel yazı türünü sayfa hiyerarşisine entegre etme


14

Ekip üyeleri için özel bir yazı türüne sahip bir tema oluşturuyorum, ayrıca aşağıdaki sayfa yapısına sahibim:

about  <-- this is a page
about/team-members  <-- this is a page, lists all the team members
about/team-members/joe-bloggs  <-- this is a custom post type (team member) entry

Buradaki üçüncü yapı about ve ekip üyesi sayfalarını kullanıyor, ancak ebeveynlerinin ekip üyesi ve hakkında olduğu gibi görünmesini sağlamak için özel posta türü slug'u kullanmaya devam ediyor. Bunu özel gönderi türünde aşağıdaki seçenekleri ayarlayarak başardım:

...
'rewrite' => array( 'slug' => 'about/team-members', 'with_front' => false)
...

Bu harika çalışıyor, ancak ekip üyesi gönderi düzeyine düştüğümde artık üst sayfalarda geçerli sayfa, geçerli ata sınıflarını alamıyorum. Bunun neden olduğunu biliyorum, çünkü teknik olarak bu sayfaların sayfalarını takip eden bir ebeveyn üzerinde değiliz, ancak sayfaların ebeveyn olarak görünmesi için kandırıp düzeltebileceğim bir yol var mı?

Bunu ekip üyeleri için sayfalar kullanarak güzel bir şekilde başardım, ancak bunun yerine yönetici için kolay kullanım için özel bir gönderi türü seçildi.

Teşekkürler çocuklar + kızlar!


ekip üyeleri sayfa kimliğini post_parent özel yayın türünüz olarak ayarlamanız gerekir.
Bainternet

register_post_typeBelgelerde bu seçeneği göremiyorum, yardımcı olabilir misiniz?
Ben Everard

Yanıtlar:


6

Sayfalarla çalışırken bir üst sayfa seçebilirsiniz ve bu değer, post_parentveritabanındaki alt sayfanın alanına üst sayfa kimlik numarası olarak kaydedilir .

Sizin durumunuzda, üst sayfa için kendi meta kutunuzu oluşturmanız gerekecek şekilde özel bir yazı türü kullanıyorsunuz; gibi bir şey:

/* Define the custom box */
add_action('add_meta_boxes', 'child_cpt_add_custom_box');

/* Adds a box to the main column on the custom post type edit screens */
function child_cpt_add_custom_box() {
    add_meta_box('child_cpt', __( 'My child_cpt parent'),'team_member_inner_custom_box','team_member');
}

/* Prints the box content */
function team_member_inner_custom_box() {
    global $post;
    // Use nonce for verification
    wp_nonce_field( plugin_basename(__FILE__), 'team_member_inner_custom_box' );
    echo 'Select the parent page';
    $mypages = get_pages();
    echo '<select name="cpt_parent">';
    foreach($mypages as $page){     
        echo '<option value="'.$page->ID.'"';
        if ($page->ID == $post->post_parent) {echo ' selected';}
        echo '>"'.$page->post_title.'</option>';
    }
    echo '</select>';
}
/* Do something with the data entered */
add_action('wp_insert_post_data', 'myplugin_save_postdata');

/* When the post is saved, saves our custom data */
function myplugin_save_postdata( $data, $postarr ) {
    global $post;
      // verify this came from the our screen and with proper authorization,
      // because save_post can be triggered at other times

      if ( !wp_verify_nonce( $_POST['team_member_inner_custom_box'], plugin_basename(__FILE__) ) )
          return $data;

      // verify if this is an auto save routine. 
      // If it is our form has not been submitted, so we dont want to do anything
      if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
          return $data;
      // OK, we're authenticated: we need to find and save the data

      if ($post->post_type == "team_member")
          $data['post_parent'] = $_POST['cpt_parent'];

     return $data;
}

Bunun bir ilgisi yok register_post_type. WordPress'i, başka bir yazı türünün (sayfa) alt sayfası olduğunu düşünerek kandırıyorsunuz.


1
Righto, bu yüzden bu "WordPress" belirli bir sayfanın üst olduğunu düşünmek nasıl "aptal" görebilirsiniz, ancak ben ne zaman üst sayfaya sayfa üst sınıf eklemiyor wp_list_pages.
Ben Everard

1
Ben de bu slug / permalink yapısı ile karışıklık fark ettim ...: S
Ben Everard

2
Ben ile aynı şeyi elde etmeye çalışıyorum ama kullanıyorum wp_nav_menu- post_parent hakkında / ekip üyeleri ama navigasyon benim "normal" blog yazılarının ana öğeyi vurgular ... nasıl başka bir fikrin bu düzeltmek olabilir?
pkyeck

@BenEverard: Kalıcı bağlantı yapısı karışıklığı için bir çözüm buldunuz mu?
abaumg

0

Benzer bir şey elde etmek için özel bir yürüteç ile gittim ... özel alanların ihtiyaçlarını önler, ancak bir türdeki tüm yayınların sayfa ağacında aynı noktanın altında oturması gerekir.

class Walker_Page_CustomPostTypeHack extends Walker_Page {
    function walk($elements, $max_depth) {
        $called_with = func_get_args();
        // current page is arg 3... see walk_page_tree for why
        $current_page = $called_with[3];

        // if there's no parent - see if we can find one.
        // some ACF options would be an easy way to make this configurable instad of constants
        if ($current_page === 0) {
            global $wp_query;
            $current_post = $wp_query->get_queried_object();
            switch ($current_post->post_type) {
                case 'course':
                    $current_page = POST_COURSES;
                    break;
                case 'project':
                    $current_page = POST_PROJECTS;
                    break;
                case 'story':
                    $current_page = POST_STORIES;
                    break;
            }
        }

        // now pass on into parent
        $called_with[3] = $current_page;
        return call_user_func_array(array('parent', 'walk'), $called_with);
    }

}

0

Feragatname: Denedikten sonra bu benim için artık mevcut olmayan bir sorun gibi görünüyor, çünkü - en azından benim için - sadece WP 3.9.2 kurulumumda çalışıyor. Uygun bir hata izci bulamadı.


Bunu test etmek için birisine yardımcı olabilecek küçük bir eklentim var. Ama yukarıdaki feragatnamede söylediğim gibi, mevcut bir wordpress kurulumunda sorunu tekrarlayamadım. Eklentiyi dört dosyaya ayırdım, birlikte eklenti dizini içindeki bir dizine gidiyorlar.

plugin-cpt_menu_hierarchy.php :

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: CPT Menu Hierarchy Fix?
 * Description: CPT Menu Hierarchy Fix?
 * Author:      ialocin
 * Author URL:  http://wordpress.stackexchange.com/users/22534/ialocin
 * Plugin URL:  http://wordpress.stackexchange.com/q/13308/22534
 */

// registering nonsense post type
include 'include-register_post_type.php';

// adding meta box to nosense custom post type
include 'include-cpt_parent_meta_box.php';

// menu highlighting fix
include 'include-menu_highlighting.php';

include-register_post_type.php :

<?php
defined( 'ABSPATH' ) OR exit;

// See: http://codex.wordpress.org/Function_Reference/register_post_type
add_action( 'init', 'wpse13308_basic_reigister_post_type');
function wpse13308_basic_reigister_post_type() {
    $args = array(
        'public' => true,
        'label'  => 'Nonsense'
    );
    register_post_type( 'nonsense', $args );
}

include-cpt_parent_meta_box.php :

<?php
defined( 'ABSPATH' ) OR exit;

// pretty much like @bainternet's answer

// Add Meta Box
add_action( 'add_meta_boxes', 'nonsense_add_meta_box' );
function nonsense_add_meta_box() {
    add_meta_box(
        'nonsense',
        __( 'Nonsense parent' ),
        'nonsense_inner_meta_box',
        'nonsense'
    );
}

// Meta Box Content
function nonsense_inner_meta_box() {
    global $post;

    wp_nonce_field(
        plugin_basename( __FILE__ ),
        'nonsense_inner_meta_box'
    );
    echo 'Parent Page:&nbsp;&nbsp;';
    $mypages = get_pages();
    echo '<select name="cpt_parent">';
    foreach($mypages as $page){     
        echo '<option value="'.$page->ID.'"';
        if ($page->ID == $post->post_parent) {echo ' selected';}
        echo '>'.$page->post_title.'</option>';
    }
    echo '</select>';
}

// Save Data From Meta Box
add_action( 'wp_insert_post_data', 'nonsense_save_meta_box_data' );
function nonsense_save_meta_box_data( $data, $postarr ) {
    global $post;

    if (
        ! wp_verify_nonce(
            $_POST['nonsense_inner_meta_box'],
            plugin_basename( __FILE__ )
        )
    ) {
        return $data;
    }

    if (
        defined('DOING_AUTOSAVE')
        && DOING_AUTOSAVE
    ) {
        return $data;
    }

    if ( $post->post_type == 'nonsense' ) {
        $data['post_parent'] = $_POST['cpt_parent'];
    }
    return $data;
}

include-menu_highlighting.php :

<?php
defined( 'ABSPATH' ) OR exit;

// altering WordPress' nav menu classes via »nav_menu_css_class« filter
add_filter( 'nav_menu_css_class', 'wpse13308_fix_nav_menu_highlighting', 10, 2 );
function wpse13308_fix_nav_menu_highlighting( $classes, $item ) {
    // data of the current post
    global $post;

    // setting up some data from the current post
    $current_post_post_type = $post->post_type;
    $current_post_parent_id = $post->post_parent;
    // id of the post the current menu item represents
    $current_menu_item_id   = $item->object_id;

    // do this for a certain post type
    if( $current_post_post_type == 'nonsense' ) {
        // remove unwanted highlighting class via array_filter and callback
        // http://php.net/manual/de/function.array-filter.php
        $classes = array_filter(
            $classes,
            'wpse13308_remove_highlighting_classes'
        );
        // when the parents id equals the menu items id, we want to
        // highlight the parent menu item, so we check for:
        if( $current_post_parent_id == $current_menu_item_id ) {
            // use the css class used for highlighting
            $classes[] = 'replace-with-css-class';
        }
    }
    return $classes;
}

// callback to remove highlighting classes
function wpse13308_remove_highlighting_classes( $class ) {
    return
        (
            // use the class(es) you need, overview over nav menu item css classes:
            // http://codex.wordpress.org/Function_Reference/wp_nav_menu#Menu_Item_CSS_Classes
            $class == 'highlight-class'
            // uncomment next line if you want to check for more then one class
            // repeat the line if you want to check for a third, fourth and so on
            // || $class == 'replace-with-css-class'
        ) 
        ? false
        : true
    ;
}



  • Bu biraz genelleştirilmiş bir kod örneğidir.
  • Gerçek kullanım kutusuna takılmalıdır.

0

Olası bir çözüm, özel gönderi türü her kaydedildiğinde, üst öğesini about/team-membersprematik olarak ayarlayabilirsiniz.

İşte adımlar:

  1. Birisi bir yayını kaydetmeye çalıştığında 'yakalamak' için save_post kancasını kullanabilirsiniz .
  2. Bu gönderi peşinde olduğunuz özel gönderi türüyse, devam edin.
  3. Özel yayının üst öğesini istediğiniz sayfaya ayarladığınızdan emin olun (silmediğiniz sürece sayfa kimliğini kodlayabilirsiniz). Ebeveyni kaydetmek için wp_update_post kullanabilirsiniz (Bunu kendim denemedim, ama neden çalışmaması gerektiğini anlamıyorum).

Ben bunun için bazı kod görmek istiyorum! Bu mükemmel olurdu, ama mysef'in çalışmasını sağlayamıyorum.
Johan Dahl

0

Bunu kendime kazmak için biraz daha zamanım vardı (kimsenin zamanını boşa harcıyorsam özür dilerim) ve benim için vurgulama sorununu çözmenin en iyi yolunun _wp_menu_item_classes_by_context(), yaptıklarını yeniden yapmak olduğunu anladım , bu her şeyi tekrarlıyor Özel yazı türümün üst öğesi olarak işlev gören menü öğesinin ebeveynleri ve ataları ve sınıfları uygun şekilde ekleyin.

Ayrıca, özel yazı türüm için üst sayfanın sabit olmasını ve ebeveyn değiştiğinde tüm yayınları güncellemek zorunda kalmadan kolayca değiştirilmesini istediğim için, post_parentözel yazı türü yayınlarımın alanını doldurmak yerine bir seçenek kullanmaya karar verdim . Bunun için ACF kullandım çünkü temamda zaten kullanıyorum, ancak varsayılan WordPress seçenek işlevini kullanmak elbette de yapardı.

İhtiyaçlarım için wp_nav_menu_objectsfiltreden yararlanabilirim. Ayrıca ,page_for_posts yanlış / boş bir değer döndürecek şekilde seçeneği filtrelemek zorunda kaldım , bu da varsayılan yayınlar sayfasının da vurgulanmasını önler.

Ben tüm yol gitmedi unutmayın, filtre sadece current-menu-ancestorve current-menu-parentsınıfları ekler , çünkü bu benim ihtiyaçları için yeterli oldu!

/**
 * Filters the `page_for_posts` option on specific custom post types in
 * order to avoid the wrong menu item being marked as
 * `current-page-parent`.
 *
 * @see _wp_menu_item_classes_by_context()
 */
function wpse13308_pre_option_page_for_posts_filter()
{
    $types = array
    (
        'my_custom_post_type_x',
        'my_custom_post_type_y',
        'my_custom_post_type_z'
    );
    if(in_array(get_post_type(), $types))
    {
        return 0;
    }
    return false;
}
add_filter('pre_option_page_for_posts', 'wpse13308_pre_option_page_for_posts_filter');


/**
 * Returns the current posts parent page ID
 *
 * @return int
 */
function wpse13308_get_parent_page_id()
{
    $postType = get_post_type();
    $parentPageId = null;
    switch($postType)
    {
        case 'my_custom_post_type_x':
        case 'my_custom_post_type_y':
        case 'my_custom_post_type_z':
            $parentPageId = (int)get_field('page_for_' . $postType, 'options')->ID;
            break;

        case 'post':
            $parentPageId = (int)get_option('page_for_posts');
            break;
    }
    return $parentPageId;
}

/**
 * Adds proper context based classes so that the parent menu items are
 * being highlighted properly for custom post types and regular posts.
 *
 * @param array $menuItems
 * @return array
 *
 * @see _wp_menu_item_classes_by_context()
 */
function wpse13308_wp_nav_menu_objects_filter(array $menuItems)
{
    $parentPageId = wpse13308_get_parent_page_id();

    if($parentPageId !== null)
    {
        $activeAncestorItemIds = array();
        $activeParentItemIds = array();
        foreach($menuItems as $menuItem)
        {
            if((int)$parentPageId === (int)$menuItem->object_id)
            {
                $ancestorId = (int)$menuItem->db_id;

                while
                (
                    ($ancestorId = (int)get_post_meta($ancestorId, '_menu_item_menu_item_parent', true)) &&
                    !in_array($ancestorId, $activeAncestorItemIds)
                )
                {
                    $activeAncestorItemIds[] = $ancestorId;
                }
                $activeParentItemIds[] = (int)$menuItem->db_id;
            }
        }
        $activeAncestorItemIds = array_filter(array_unique($activeAncestorItemIds));
        $activeParentItemIds = array_filter(array_unique($activeParentItemIds));

        foreach($menuItems as $key => $menuItem)
        {
            $classes = $menuItems[$key]->classes;
            if(in_array(intval($menuItem->db_id), $activeAncestorItemIds))
            {
                $classes[] = 'current-menu-ancestor';
                $menuItems[$key]->current_item_ancestor = true;
            }

            if(in_array($menuItem->db_id, $activeParentItemIds))
            {
                $classes[] = 'current-menu-parent';
                $menuItems[$key]->current_item_parent = true;
            }

            $menuItems[$key]->classes = array_unique($classes);
        }
    }

    return $menuItems;
}
add_filter('wp_nav_menu_objects', 'wpse13308_wp_nav_menu_objects_filter');

Tamlık uğruna, seçenekleri kullanmak yerine doldururkenpost_parent ( @ Bainternet'in cevabına bakın ), daha sonra üst kimliği almak aşağıdaki gibi görünebilir:

/**
 * Returns the current posts parent page ID
 *
 * @return int
 */
function wpse13308_get_parent_page_id()
{
    $parentPageId = null;
    $post = get_post();
    switch($post->post_type)
    {
        case 'my_custom_post_type_x':
        case 'my_custom_post_type_y':
        case 'my_custom_post_type_z':
            $parentPageId = (int)$post->post_parent;
            break;

        case 'post':
            $parentPageId = (int)get_option('page_for_posts');
            break;
    }
    return $parentPageId;
}

Zamanımı boşa harcamadınız :) Başka bir şey, bunun hala bir sorun olduğundan emin misiniz? Çünkü WP 3.9.2 kurulumumda yeniden üretemedim. Doğru menü öğesini vurgulamak kutudan çıkar çıkmaz işe yaradı.
Nicolai

Evet, bu kesinlikle bir problem @ialocin. Bunu 0 seviye menüsü ve varsayılan yazı tipiyle test ediyor olabilir misiniz?
ndm

Hayır, cevabımda yayınlanan kodla denedim. Böylece özel yazı tipi ile ve 1. ve 2. seviye menü öğesi olarak ilgili yazı tipinden bir sayfaya. Test etmek için wordpress çekirdek paketli temaları kullandım.
Nicolai

@ialocin Sizi doğru anladığımdan emin değilim, çünkü " gönderilen kodla denenmiş " ve " kutunun dışında " gibi şeyler birbirini dışlar. ;) Vurgulama düzeltmesine değil, yalnızca özel gönderi türüne mi başvuruyorsunuz?
ndm

Doğru :) Tamam, kesin olarak, senaryo için bir CPT gerekli, bu yüzden elbette kaydettirdim. Vurgulama, meta kutusu ve vurgulama düzeltmesi kullanılmadan çalışır. Örneğin bir menü yapısı ile: büyükbaba veya büyükanne (sayfa)> ebeveyn (sayfa)> bir şey (posta)> başka bir şey (cpt)> bir şey daha (cpt) - her öğe doğru css sınıflarını alır; Tema burada yirmi on üç kullanıldı.
Nicolai

-1
<?php
the_post();

// $postType holds all the information of the post type of the current post you are viewing
$postType = get_post_type_object(get_post_type());

// $postSlug is the slug you defined in the rewrite column: about/team-members
$postSlug = $postType->rewrite['slug'];

// $datas = { [0] => 'about', [1] => 'team-members' }
$datas = explode('/', $postSlug);

// $pageSlug = 'about'
$pageSlug = $datas[0];

// all the page information you require.
$page = get_page_by_path($pageSlug, OBJECT, 'page');
?>

http://codex.wordpress.org/Function_Reference/get_post_type_object http://codex.wordpress.org/Function_Reference/get_page_by_path

DÜZENLEME 1:

İşaretçiler çalışmadığından:

add_filter('wp_nav_menu_objects', 'my_menu_class_edit');
function my_menu_class_edit($items)
{
    if (is_single()) {
        $postType = get_post_type_object(get_post_type());
        $postSlug = $postType->rewrite['slug'];
        if($postSlug  != 'about/team-members')
            return $items;
        $datas = explode('/', $postSlug);
        $pageAbout = get_page_by_path($datas[0], OBJECT, 'page');
        $pageTeamMembers = get_page_by_path($datas[1], OBJECT, 'page');

        foreach ($items as $item) {
            if ($item->title == $pageAbout->post_title) {
                $item->classes[] = 'current-ancestor';
            } else if ($item->title == $pageTeamMembers->post_title) {
                $item->classes[] = 'current-page';
            }
        }
   }
    return $items;
}

İşte böyle. Wp_nav_menu_objects filtre kancası içine eklendi.
aifrim
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.