Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.0.x bp-better-diretories #7

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open

1.0.x bp-better-diretories #7

wants to merge 18 commits into from

Conversation

pierre-dickinson
Copy link

Hi Boone,
I'm wondering if i still can use your plugin, but i have been trying to simply update the Members Loop using Ajax on a "click" event on a link in the Members directory but i can't figure out what is wrong? the loop is not refreshed in ajax on click. please help ! here is my code :

function special_bp_dtheme_ajax_querystring( $query_string, $object ) {

    /* for testing purpose : Now pass the querystring to override default values. */
    $list_of_members = '1,2,3';
    $query_string .= '&type=active&action=active&include='. $list_of_members .'&page=1';
    return $query_string;
}
// this doesnt work
//add_filter( 'bp_dtheme_ajax_querystring', 'special_bp_dtheme_ajax_querystring', 11, 2 );

 // this work (on page load not in ajax)
//add_filter( 'bp_ajax_querystring', 'special_bp_dtheme_ajax_querystring', 11, 2 );

/*
* source: https://buddypress.org/support/topic/simply-trying-to-filter-the-bp_ajax_querystring-via-ajax/
*  this action is located in _inc/ajax.php : 
add_action( 'wp_ajax_members_filter', 'bp_dtheme_object_filter' );
*/
function my_ajax() {
    //add_action( 'wp_ajax_members_filter', 'special_bp_dtheme_ajax_querystring' );
    //add_filter( 'bp_ajax_querystring', 'special_bp_dtheme_ajax_querystring', 11, 2 );
    add_filter( 'bp_dtheme_ajax_querystring', 'special_bp_dtheme_ajax_querystring', 11, 2 );
}

and here is my js :

$('#custom-members-search-trigger').on('click', function (e) {
                    e.preventDefault;
                    console.log('button clicked!');

                    $.post(
                        ajaxurl, 
                        {
                            'action': 'my_ajax',
                            'data':   'test'
                        }, 
                        function(response){
                            alert('The server responded: ' + response);
                        }
                    );

                });

What's wrong? Please help me with this, it must be "simple" ;-)

@boonebgorges
Copy link
Owner

@mecanographik

function(response){
    alert('The server responded: ' + response);
}

I'm assuming that the alert is showing nothing. If you are sending an AJAX request with action: 'my_ajax', then you need a PHP callback hooked to 'wp_ajax_my_ajax'. https://www.smashingmagazine.com/2011/10/how-to-use-ajax-in-wordpress/ is a good tutorial.

In order to refresh the member directory using AJAX, your PHP callback needs to load the templates. BP does it with a generic template loader: https://buddypress.trac.wordpress.org/browser/tags/2.6.1/src/bp-templates/bp-legacy/buddypress-functions.php#L748

Your filter on bp_dtheme_ajax_querystring will only do anything if you're actually loading the members directory in your AJAX callback. Once you get that part working, you'll be in a better position to debug whether your filter is working properly. A hint: you're probably going to need to have some sort of if statement to make sure you're not always filtering the querysting, but are only doing it on my_ajax requests.

@pierre-dickinson
Copy link
Author

Hi @boonebgorges thanks for your answer.
I did have already put the 'wp_ajax_my_ajax' part, but i'm sorry i've forgotten to paste it with the previous comment ;-)
I understand the ajax template loader concept, but do i need to create some extra templates and load them in ajax depending on the filter i need to apply in ajax?
How do i call the following action ? like this ?

add_action( 'wp_ajax_members_filter', 'bp_legacy_theme_object_template_loader');

Where do i pass the $query_string parameters to rebuild the query with some meta keys / meta values for example?

Do i need to use the bp_dtheme_ajax_querystring function define in ajax.php ?

Thanks for your answer

@SebastienGicquel
Copy link

Hi @boonebgorges

I’m working with @mecanographik on this project.

I follow your advices and here is what i can do :

I load the template BuddyPress in my php callback and i can update the member directory using AJAX.

Is it the best way to load the template and update the loop ?

// check for routing via AJAX
if (defined('DOING_AJAX') AND DOING_AJAX) {
    add_filter('bp_dtheme_ajax_querystring', 'my_ajax_test', 11, 2);
}
function my_bp_loop_querystring( $query_string, $object ) {
    if ( ! empty( $query_string ) ) {
        $query_string .= '&';
    }

    $list_of_members = '1, 2, 5, 33, 43';

    $query_string .= '&type=active&action=active&include=' . $list_of_members . '&page=1';

    return $query_string;
}
function my_ajax_test($query_string, $object) {

    add_action('bp_legacy_theme_ajax_querystring', 'my_bp_loop_querystring', 20, 2);

    bp_get_template_part('members/members-loop');

    wp_die();
}

my_ajax_test() returns an HTML string. I update the DOM with this string.

$('#buddypress #members-directory-form').html(data);

Thanks for your help !

@boonebgorges
Copy link
Owner

Hi @vinylroads - Yes, something like this seems correct. The DOING_AJAX check for filtering bp_dtheme_ajax_querystring is probably going to be too general, though - it'll add the include parameter for any directory that is powered by AJAX. It looks to me like you can just remove this chunk and rely on the add_action() call inside of my_ajax_test().

@SebastienGicquel
Copy link

SebastienGicquel commented Oct 17, 2016

Hi @boonebgorges

Glad to see it seems ok for you.

I thought of an improvement :

Previously, i have tested and call JS function members_filter() in the JS AJAX function :

            type: "POST",
            url: ajaxurl,
            data: {
                action: 'members_filter',
                object: 'members',
                cookie: encodeURIComponent(document.cookie),
                search_terms: 'pierre'

            }

This function is really simple to use : It refreshes the member loop without the need to update the DOM in the success: function

Unfortunately, we can only send in $_POST : page, exclude_just_posted, search_terms.

I need to filter users with meta_value.

So, in bp_dtheme_ajax_querystring() (in buddypress/bp-themes/bp-default/_inc/ajax.php), i see after all the datas are received with POST :

// Now pass the querystring to override default values.

So, i was wondering if it would be possible to modify the querystring here in order to pass meta_value (or anything else possible with querystring).

@boonebgorges
Copy link
Owner

Unfortunately, we can only send in $_POST : page, exclude_just_posted, search_terms.

I don't understand why you have this restriction. exclude_just_posted is related to activity, not to members. And if you're writing your own JS to make the AJAX call, just add things like meta_value and meta_key to your data array.

So, i was wondering if it would be possible to modify the querystring here in order to pass meta_value (or anything else possible with querystring).

I would think that something like the following would work:

function my_bp_loop_querystring( $query_string, $object ) {
    if ( ! empty( $query_string ) ) {
        $query_string .= '&';
    }

    $query_string .= '&type=active&action=active&page=1';

    if ( isset( $_POST['meta_key'] ) && isset( $_POST['meta_value'] ) ) {
        $meta_key = wp_unslash( $_POST['meta_key'] );
        $meta_value = wp_unslash( $_POST['meta_value'] );
        $query_string .= '&meta_key=' . urlencode( $meta_key ) . '&meta_value=' . urlencode( $meta_value );
    }

    return $query_string;
}

@SebastienGicquel
Copy link

Thanks for the code. I think i know how to filter with meta_value because i already do it without ajax (with simple page refresh).

I was just wondering if it was possible to use a built in function like members_filter() but nevermind. I will use my own JS in order to add custom filter to the Members and Groups. I’ll show you the result when the site will be online.

Regards,

Sébastien

@boonebgorges
Copy link
Owner

Thanks! Looking forward to seeing how it works out.

On 10/17/2016 03:07 PM, vinylroads wrote:

Thanks for the code. I think i know how to filter with meta_value
because i already do it without ajax (with simple page refresh).

I was just wondering if it was possible to use a built in function like
|members_filter()| but nevermind. I will use my own JS in order to add
custom filter to the Members and Groups. I’ll show you the result when
the site will be online.

Regards,

Sébastien


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#7 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAPDY9BSo1pGsCN_JvrFOBZCx46KcjiAks5q09WSgaJpZM4KX1NR.

@pierre-dickinson
Copy link
Author

pierre-dickinson commented Oct 18, 2016

Thanks so much @boonebgorges @imath @vinylroads ,
This snippet looks promising. The members_filter action (in ajax.php) seemed to be the best way but it looks like we can't manage Meta Key filtering with this core action. So this custom function will help us to break through the Buddypress Ajax template loading and filtering system. We won't forget to share the final Plugin or Public Gist with the whole working snippet and the demo URL ;-)

@SebastienGicquel
Copy link

Hi @boonebgorges,

Could you give me an advice on this ?

I would like to filter the members loop with multiple meta_key and meta_value (because i have multiple selects in my form).

for example :

meta_key=city
meta_value=chicago

meta_key=job
meta_value=developer

Here is how i build my query. I’ve tested it with a simple native WordPress $user_query = new WP_User_Query($args); and it was working. So i think my array is correct.

So, how can i pass this array to the buddypress querystring.

Here is the code :

    $query_string .= '&type=active&action=active&page=1';

    $query_array = array('relation' => 'AND');

    // querystring as an array
    $defaults = array(
        'type' => 'active',
        'action' => 'active',
        'scope' => 'all',
        'page' => 1,
        'user_id' => 0,
        'search_terms' => '',
        'exclude' => false,
    );

    $args = array(
        'meta_query' => $query_array,
    );

When i retrieve the datas sent by POST, i use array_push in order to build the array :

    if (!empty($_POST['ville'])) {
        $meta_value_ville = $_POST['ville'];
        array_push($query_array, array('meta_key' => 'ville', 'meta_value' => $meta_value_ville));
    }

Then, i use bp_parse_args

$query_string = bp_parse_args($args, $defaults);

Here is a print of the final array with multiple meta_key and meta_value :

Array

(
    [type] => active
    [action] => active
    [scope] => all
    [page] => 1
    [user_id] => 0
    [search_terms] => 
    [exclude] => 
    [meta_query] => Array
        (
            [relation] => AND
            [0] => Array
                (
                    [meta_key] => ville
                    [meta_value] => Nantes
                )

            [1] => Array
                (
                    [meta_key] => user_metiers
                    [meta_value] => 297
                )

        )

)

This array seems correct. But the query string is not filtered.

If i add a 'search_terms' in thedefault array` :

'search_terms' => 'pierre',

I can get all the members containing 'pierre' so i think that this is correct :

$query_string = bp_parse_args($args, $defaults);

The query string is filtered.

Do you think it’s possible to have multiple meta_key / meta_value with the buddyPress querystring ? (i know it’s possible with WordPress, already done that).

Thank you for your help, regards !

@SebastienGicquel
Copy link

SebastienGicquel commented Oct 18, 2016

Hi,

Let me know when you have time if it’s possible to use nested arrays (complex queries / Multiple custom user fields handling) like as we can use with WordPress. Something like https://codex.wordpress.org/Class_Reference/WP_Meta_Query

But otherwise, i found an easy solution which is ok. I would prefer to use nested array because i guess it’s cleaner.

So, my solution : I get all the user ids :

$user_query = new WP_User_Query($args);

I build a coma separated list :

foreach ($user_query->results as $user) {
        $users_list .= $prefix  . $user->ID;
        $prefix = ', ';
    }

(here, i could improve my code without a foreach and use something like $users_list = implode(', ', $user_query); but i need to rebuild user_query It's on my toDoList ;-)

Then, the querystring :

$query_string .= '&include='.$users_list;

It works, i can filter members loop with different meta_key / meta_value ... yeah !

@boonebgorges
Copy link
Owner

Hi @vinylroads - Thanks for the updates!

It might be possible to build a complex meta_query parameter as part of the querystring. It'd have to look like this:

&meta_query[first_clause][key]=foo&meta_query[first_clause][value]=bar...

This would probably work, but it'd be quite clumsy. Your solution is probably just as good.

In the future, it'd be nice if there were an easier way to intervene in bp_ajax_querystring() without having to build an actual querystring. This can currently be done at the level of the individual queries, using filters like bp_pre_has_members_parse_args, but there's no global way to do it.

@pierre-dickinson
Copy link
Author

pierre-dickinson commented Apr 5, 2017

Hi @boonebgorges @imath - How are you?
I want to thank you again for your precious help on this project, you can check it out the buddypress acf ajax search demo we have built here :
https://v2.laplateforme.net/individus/

click on the yellow button "filtres" ... ;-)

Regards,

@boonebgorges
Copy link
Owner

boonebgorges commented Apr 5, 2017 via email

@SebastienGicquel
Copy link

Hello, could you try again ? We can can see the page, not sur why you can't...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants