प्रति पोस्ट आधार पर सहेजे गए खुले / बंद और छिपे / दिखाए गए मेटाबोक्स की स्थिति कैसे बनाएं?


9

मेरी वास्तविक समस्या थोड़ी जटिल है, इसलिए मैं इसे अमूर्त करने और इसे सरल बनाए रखने के लिए यहाँ कोशिश करूँगा।

मैं वर्डप्रेस पर आधारित एक कस्टम ऐप पर काम कर रहा हूं। मैंने एक कस्टम पोस्ट प्रकार पंजीकृत किया, चलो इसे "लोग" कहते हैं जहां मैं ... लोगों के बारे में जानकारी संग्रहीत करता हूं।

CPT केवल पोस्ट शीर्षक और पोस्ट सामग्री डिफ़ॉल्ट फ़ील्ड का समर्थन करता है, लेकिन व्यक्ति informations को संग्रहीत करने के लिए कुछ मेटाबॉक्सेस हैं (मेरे ऐप को पता पुस्तिका के रूप में सोचें)।

इसलिए व्यक्तिगत जानकारी संग्रहीत करने के लिए एक मेटाबेस है, एक सामाजिक नेटवर्क जानकारी संग्रहीत करने के लिए, दूसरा कार्य-संबंधित जानकारी संग्रहीत करने के लिए, अर्थात यदि वह व्यक्ति मेरे लिए ग्राहक, आपूर्तिकर्ता है, अगर हमारे पास क्रेडिट या डेबिट है ...

मैंने यहां सरलीकरण किया है, लेकिन मेटाबॉक्स की एक सुसंगत मात्रा है, चलो 12 कहते हैं।

मेरी समस्या यह है कि, कुछ लोग जिनके लिए मैं जानकारी संग्रहीत करना चाहता हूं वे केवल यादृच्छिक संपर्क हैं, और मैं केवल व्यक्तिगत जानकारी संग्रहीत करना चाहता हूं, अन्य मित्र हैं और मैं व्यक्तिगत जानकारी और सामाजिक नेटवर्क जानकारी संग्रहीत करना चाहता हूं, अन्य ग्राहक या आपूर्तिकर्ता हैं और मैं काम से संबंधित जानकारी संग्रहीत करना चाहते हैं।

यदि किसी पोस्ट को संपादित करते समय मैं छुपाता हूं ( स्क्रीन विकल्प मेनू के माध्यम से ) या किसी भी मेटाबॉक्स को बंद करने की आवश्यकता नहीं है, जब मैं एक और पोस्ट खोलता हूं जहां मुझे उनकी आवश्यकता होती है मुझे उन्हें फिर से दिखाना या खोलना होगा। ऐसा इसलिए है क्योंकि मेटाबेस स्थिति / स्थिति / आदेश उपयोगकर्ता मेटाडेटा के रूप में प्रति उपयोगकर्ता के आधार पर सहेजे जाते हैं

यदि आप कुछ पोस्टों में कल्पना करते हैं कि मुझे 2 मेटाबॉक्स की आवश्यकता है, कुछ 10 में और कुछ 5 में, तो आप समझते हैं कि यह कष्टप्रद है क्योंकि उन सभी को दिखाया गया है / खुले संपादन स्क्रीन को कम सुलभ बनाते हैं (स्क्रॉलबार अंतहीन लगता है), और कभी-कभी मैं जिस जानकारी की तलाश करता हूं। पृष्ठ के अंत में मेटाबोक्स का एक गुच्छा बिना किसी जानकारी के ...

सवाल:

क्या विशिष्ट पोस्ट प्रकार के लिए प्रति-पोस्ट आधार पर मेटाबोक्स की स्थिति / स्थिति / आदेश को सहेजना संभव है?


पुनश्च: मुझे पता है कि कुछ js / jQuery समस्या को हल कर सकते हैं, लेकिन यदि संभव हो तो मैं जावास्क्रिप्ट समाधान से बचूंगा।

जवाबों:


8

मुख्य समस्या:

यहाँ मुख्य समस्या यह है कि समापन में , छिपाना- और आदेश देना- अजाक्स कॉल करना, पेलोड के साथ कोई पोस्ट आईडी नहीं भेजना है। यहां दो फॉर्म डेटा उदाहरण हैं:

1) action:closed-postboxes
closed:formatdiv,tagsdiv-post_tag,trackbacksdiv,authordiv
hidden:slugdiv
closedpostboxesnonce:8723ee108f
page:post

2) action:meta-box-order
_ajax_nonce:b6b48d2d16
page_columns:2
page:post
order[side]:submitdiv,formatdiv,categorydiv,tagsdiv-post_tag,postimagediv
order[normal]:postexcerpt,postcustom,trackbacksdiv,commentsdiv,authordiv
order[advanced]:

हम एक और कस्टम अजाक्स कॉल का उपयोग करके इसे प्राप्त कर सकते हैं।

हम निश्चित रूप से हुक में save_postहुक लगा सकते हैं और हर बार पोस्ट को सहेजने के बाद डेटा को संशोधित कर सकते हैं। लेकिन यह सामान्य यूआई अनुभव नहीं है, इसलिए यहां पर विचार नहीं किया गया है

PHP के साथ एक और गैर-सुरुचिपूर्ण समाधान उपलब्ध है, जिसका वर्णन नीचे दिया गया है:

एक गैर जावास्क्रिप्ट समाधान:

सवाल यह है कि डेटा कहां स्टोर करें? के रूप में उपयोगकर्ता मेटा डेटा, पोस्ट मेटा डेटा या शायद एक कस्टम तालिका में?

यहां हम इसे उपयोगकर्ता मेटा डेटा के रूप में संग्रहीत करते हैं और एक उदाहरण के रूप में पोस्ट मेटा बॉक्स के समापन को लेते हैं ।

जब closedpostboxes_postमेटा वैल्यू को अपडेट किया जाता है, तो हम इसे closedpostboxes_post_{post_id}मेटा वैल्यू में भी सेव करते हैं ।

फिर हम closedpostboxes_postउपयोगकर्ता आईडी और पोस्ट आईडी के आधार पर संबंधित मेटा मान के साथ इसे ओवरराइड करने के लिए अपहृत करते हैं ।

a) closed-postboxesअजाक्स कार्रवाई के दौरान अद्यतन करना :

हम पोस्ट आईडी प्राप्त कर सकते हैं, इसके माध्यम से wp_get_referer()और फिर आसान url_to_postid()फ़ंक्शन का उपयोग कर सकते हैं। मैं पहले कुछ महीनों पहले @s_ha_dum से जवाब पढ़ने के बाद इस "मज़ेदार" फ़ंक्शन के बारे में जानता था ;-) दुर्भाग्य से फ़ंक्शन ?post=123जीईटी चर को नहीं पहचानता है, लेकिन हम इसे बदलने के लिए इसे बदलकर थोड़ा सा चाल कर सकते हैं p=123

हम हुक कर सकते हैं updated_user_meta, जिसे closedpostboxes_postअपडेट किए जाने के बाद उपयोगकर्ता मेटा डेटा के ठीक बाद निकाल दिया जाता है :

add_action( 'updated_user_meta',                           
    function ( $meta_id, $object_id, $meta_key, $_meta_value )
    {
        $post_id = url_to_postid( str_replace( 'post=', 'p=', wp_get_referer() ) );
        if( 'closedpostboxes_post' === $meta_key && $post_id > 0 )
            update_user_meta( 
                $object_id, 
                'closedpostboxes_post_' . $post_id, 
                $_meta_value 
            );
    }
, 10, 4 );

बी) डेटा लाना:

हम उपयोगकर्ता मेटा get_user_option_closedpostboxes_postसे closedpostboxes_postप्राप्त डेटा को संशोधित करने के लिए हुक में हुक कर सकते हैं :

add_filter( 'get_user_option_closedpostboxes_post',
    function ( $result, $option, $user )
    {
        $post_id = filter_input( INPUT_GET, 'post', FILTER_SANITIZE_NUMBER_INT );
        $newresult = get_user_option( 'closedpostboxes_post_'. $post_id , $user->ID );
        return ( $newresult ) ? $newresult : $result;
    }
, 10, 3 );

हम उस मामले के बारे में भी सोचना चाहते हैं जहां कोई पोस्ट closedpostboxes_post_{post_id}उपलब्ध नहीं है। तो यह अंतिम सहेजी गई सेटिंग्स का उपयोग करेगा closedpostboxes_post। हो सकता है कि आप उस डिफ़ॉल्ट मामले में यह सब खोलना या बंद करना चाहते हों। इस व्यवहार को संशोधित करना आसान होगा।

अन्य कस्टम पोस्ट प्रकारों के लिए हम संबंधित closedpostboxes_{post_type}हुक का उपयोग कर सकते हैं ।

उपयोगकर्ता और मेटा के साथ मेटाबोक्स के आदेश और छिपने के लिए समान संभव होना चाहिए ।metaboxhidden_{post_type}meta-box-order_{post_data}

पीएस: यह बहुत लंबे समय तक जवाब के लिए खेद है, क्योंकि वे हमेशा कम और हंसमुख होना चाहिए ;-)


महान +1। लंबे उत्तर के लिए एन / पी, मुझे कम लोगों की उम्मीद नहीं होगी। ईमानदार होने के लिए मुझे सप्ताहांत पर कोई उम्मीद नहीं थी :) दो चीजें मुझे बहुत पसंद आईं: 1 प्रति उपयोगकर्ता और प्रति-पोस्ट आधार पर डेटा स्टोर करने का विचार : मेरा विचार पोस्ट मेटा में स्टोर करना था, लेकिन इस तरह से सभी उपयोगकर्ताओं की समान स्थिति होगी। 'get_user_option_*_post'WP पहचान कस्टम डेटा बनाने के लिए उपयोग करने के लिए 2 विचार । केवल लगता है कि मैं बहुत ज्यादा पसंद नहीं के उपयोग है wp_get_refererवास्तव में पर कि $_SERVERकि वर वास्तव में विश्वसनीय नहीं ), लेकिन मुझे लगता है कि मेरे पास एक सुझाव "मुख्य समस्या" काबू पाने के लिए
gmazzap

धन्यवाद, मुझे लगता है कि यह उपयोगकर्ताओं और पदों की संख्या पर निर्भर करता है जहां डेटा को स्टोर करना सबसे अच्छा होगा। हो सकता है कि इस डेटा में कुछ टीटीएल होना चाहिए और इसे महीने में एक बार मिटाया जाना चाहिए? हां, मैं इस wp_get_referer()विधि के संबंध में आपसे सहमत हूं , इसीलिए मैंने इसे एक नॉन-एलिगेंट PHP सॉल्यूशन कहा है ;-) मैंने पहली बार प्रत्येक उपयोगकर्ता के लिए वर्तमान पोस्ट आईडी को स्टोर करने के बारे में सोचा था, लेकिन अगर कोई उपयोगकर्ता दो या दो से अधिक संपादन कर रहा है तो यह काम नहीं करता है। ब्राउज़र में पोस्ट। "मुख्य समस्या" पर अपने विचार के बारे में सुनने के लिए तत्पर
रहें

43 दिनों के बाद एक upvote ने मुझे इसका उत्तर देने के लिए याद किया। आपके उत्तर के लिए फिर से धन्यवाद।
gmazzap

6

जैसा कि उनके जवाब में बीरगायर ने कहा है , वर्डप्रेस मेटाबेस की स्थिति को अपडेट करने के लिए AJAX का उपयोग करता है और AJAX अनुरोध में पारित डेटा में पोस्ट आईडी शामिल नहीं है, और यह प्रति-पोस्ट आधार पर बक्से की स्थिति को अपडेट करना मुश्किल बनाता है।

एक बार जब मुझे पता चला कि AJAX की कार्रवाई वर्डप्रेस द्वारा उपयोग की जाती है 'closed-postboxes', तो मैंने इस स्ट्रिंग के लिए व्यवस्थापक js फ़ोल्डर में खोजा कि वर्डप्रेस कैसे AJAX का अनुरोध करता है।

मैंने पाया कि यह postbox.jsलाइन # 118 पर होता है ।

ऐसा दिखता है:

save_state : function(page) {
  var closed = $('.postbox').filter('.closed').map(function() {
      return this.id;
    }).get().join(',');
  var hidden = $('.postbox').filter(':hidden').map(function() {
      return this.id;
    }).get().join(',');
  $.post(ajaxurl, {
    action: 'closed-postboxes',
    closed: closed,
    hidden: hidden,
    closedpostboxesnonce: jQuery('#closedpostboxesnonce').val(),
    page: page
  });
}

अनिवार्य रूप से, वर्डप्रेस डोम आइटम को क्लास 'पोस्टबॉक्स' और क्लास 'क्लोज्ड' के साथ देखता है और उनकी आईडी की अल्पविराम से अलग सूची बनाता है। कक्षा के पोस्टबॉक्स के साथ छिपे हुए डोम आइटम के लिए भी यही किया जाता है।

तो, मेरा विचार यह था: मैं एक नकली मेटाबॉक्स बना सकता हूं जिसमें सही कक्षाएं हैं और जो छिपा हुआ है, इसकी आईडी को पोस्ट आईडी शामिल करने के लिए सेट किया गया है, और इस तरह मैं इसे एक AJAX अनुरोध में पुनः प्राप्त कर सकता हूं।

यही मैंने किया है:

add_action( 'dbx_post_sidebar', function() {
    global $post;
    if ( $post->post_type === 'mycpt' ) {
        $id = $post->ID;
        $f = '<span id="fakebox_pid_%d" class="postbox closed" style="display:none;"></span>';
        printf( $f, $id );
    }
});

इस तरह मैंने एक मेटाबॉक्स बनाया जो हमेशा बंद रहता है और हमेशा छिपा रहता है, इसलिए वर्डप्रेस $_POSTAJAX अनुरोध में var के रूप में अपनी आईडी भेजेगा , और एक बार फर्जी बॉक्स आईडी में पोस्ट आईडी होने की उम्मीद के मुताबिक, मैं इस पोस्ट को पहचान सकता हूं।

उसके बाद मैंने देखा कि कैसे वर्डप्रेस AJAX कार्य करता है।

में admin-ajax.phpलाइन 72 पर , वर्डप्रेस हुक 'wp_ajax_closed-postboxes'प्राथमिकता 1 के साथ।

इसलिए, वर्डप्रेस से पहले अभिनय करने के लिए, मैं उसी कार्रवाई को प्राथमिकता के साथ हुक कर सकता हूं।

add_action( 'wp_ajax_closed-postboxes', function() {

    // check if we are in right post type: WordPress passes it in 'page' post var
    $page = filter_input( INPUT_POST, 'page', FILTER_SANITIZE_STRING );
    if ( $page !== 'mycpt' ) return;

    // get post data
    $data = filter_input_array( INPUT_POST, array(
        'closed' => array( 'filter' => FILTER_SANITIZE_STRING ),
        'hidden' => array( 'filter' => FILTER_SANITIZE_STRING )
    ) );

    // search among closed boxes for the "fake" one, and return if not found
    $look_for_fake = array_filter( explode( ',', $data[ 'closed' ] ), function( $id ) {
         return strpos( $id, 'fakebox_pid_' ) === 0;
    } );
    if ( empty( $look_for_fake ) ) return;

    $post_id = str_replace( 'fakebox_pid_', '', $look_for_fake[0] );
    $user_id = get_current_user_id();

    // remove fake id from values
    $closed = implode(',', array_diff( explode(',', $data['closed'] ), $look_for_fake ) );
    $hidden = implode(',', array_diff( explode(',', $data['hidden'] ), $look_for_fake ) );

    // save metabox status on a per-post and per-user basis in a post meta
    update_post_meta( $post_id, "_mycpt_closed_boxes_{user_id}", $closed );
    update_post_meta( $post_id, "_mycpt_hidden_boxes_{user_id}", $hidden );

}, 0 );

पोस्ट मेटा में सहेजे गए डेटा के बाद पोस्ट मेटा से वर्डप्रेस लोड विकल्पों को मजबूर करने के लिए फ़िल्टर ( get_user_option_closedpostboxes_mycptऔर फ़िल्टर के get_user_option_metaboxhidden_mycptदोनों रूपों get_user_option_{$option}) को संभव बनाना संभव है :

add_filter( 'get_user_option_closedpostboxes_mycpt', function ( $result, $key, $user ) {
    global $post;
    $meta = get_post_meta( $post->ID, "_mycpt_closed_boxes_{$user->ID}", TRUE );
    if ( ! empty( $meta ) ) {
        $result = $meta;
    }
    return $result;
}, 10, 3 );

तथा

add_filter( 'get_user_option_metaboxhidden_mycpt', function ( $result, $key, $user ) {
    global $post;
    $meta = get_post_meta( $post->ID, "_mycpt_hidden_boxes_{$user->ID}", TRUE );
    if ( ! empty( $meta ) ) {
        $result = $meta;
    }
    return $result;
}, 10, 3 );

प्रासंगिक जानकारी +1 के साथ छिपे हुए
मेटाबॉक्स

धन्यवाद @birgire और धन्यवाद अपने एक के लिए फिर से, दोनों प्रति-उपयोगकर्ता और प्रति-पोस्ट आधार पर डेटा की बचत करने के विचार सब तुम्हारा :) है
gmazzap
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.