2

I am not asking you to write the all code or asking a plugin, I am asking a way to build this feature because I don't have any plan in my mind to build this feature.

This is the requirement : There are many posts on the website. Logged Users (Front-end users) should have a feature to save list of posts.

Ex :

  • List 01 : My favorite Posts
  • List 02 : Blogging related posts
  • List 03 : Watch later Posts

I want user to allow to create these types of list. Then they can add any number of posts. And these list are private. I mean only created user can access the list.

This is something like we label emails on gmail.

What can I use to save list? I have no idea what can I use for it... At least is this possible with WordPress?

  • You say you’re not asking for code. Are you asking for a plugin? If someone provided an answer that would involve you coding would that help? I’m not clear what you want as an answer. Almost anything is possible with WordPress but you haven’t given a good indication of what you’re able/willing to do to achieve it. – Jacob Peattie Dec 6 '17 at 7:12
  • @JacobPeattie I am sorry if it is not clear.... I am asking something like this. "You can use a custom post type to save...... ". And then you can use this techniques to set allow access........ Still not clear the question just read this example., Just take the gmail. We can label email. I need same feature in WordPress frontend. I mean users can create label and users can assign posts to label. But the difference is in gmail, email are only for that user. But here all posts are public. But labels are private. I mean others could not able to find which lable this user has, etc.... – I am the Most Stupid Person Dec 6 '17 at 7:39
  • Does your users would be logged in or anonymous? – kierzniak Dec 6 '17 at 8:21
  • @motivast Logged users – I am the Most Stupid Person Dec 6 '17 at 8:49
  • 1
    you can use a custom hierarchical taxonomy, and internally create a parent term for each user, and allow each user to create sub terms, one for each list. or, if the lists allowed are fixed, you can save an array of user ids of users who marked a post as belonging to a list as post meta. – inarilo Dec 6 '17 at 9:08
4

When I am thinking about UI something like this is comming to my mind.

enter image description here

Something similar has YouTube under the video.

When user fills input and clicks enter or submit button to create list, you will send ajax request with list name and save it as a record in wp_usermeta table with meta_key _list_user_1 and meta_value as list title.

To add post to this list you have to save record in wp_postmeta table with _list_post_1 value in meta_key field and value of umeta_id from _list_user_1 row in field meta_value.

wp_usermeta

+----------+---------+--------------+------------+
| umeta_id | user_id | meta_key     | meta_value |
+----------+---------+--------------+------------+
| 100      | 1       | _list_user_1 | List 1     |
+----------+---------+--------------+------------+

wp_postmeta

+---------+---------+--------------+------------+
| meta_id | post_id | meta_key     | meta_value |
+---------+---------+--------------+------------+
| 1       | 1       | _list_post_1 | 100        |
+---------+---------+--------------+------------+

To get all lists for user:

SELECT *
FROM `wp_usermeta`
WHERE `user_id` = 1
  AND `meta_key` LIKE "_list_user_%";

To get all posts for List 1:

SELECT *
FROM `wp_posts`
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
WHERE wp_postmeta.`meta_key` LIKE "_list_post_%"
  AND wp_postmeta.`meta_value` = 100;
| improve this answer | |
3

You can use a button on the front and save the ID of the currently displayed post in user's meta. Here's a simple way to do this:

Output a Button on Front

You need to create a button in your single.php ( or whatever page you want ) to allow the user to actually set the post as a favorite. The below template does this. The like-overlay class is used to create a loading effect while the request is being processed.

<div id="like-button" class="like btn btn-default" type="button">
    <span class="fa fa-heart"></span>
    <span class="like-overlay"><i class="fa fa-spin fa-circle-o-notch"></i></span>
</div>
<input type="hidden" value="<?php the_ID(); ?>" id="current-post-id"/>
<input type="hidden" value="<?php echo get_current_user_id(); ?>" id="current-user-id"/>

Add a Click event to the Button

When the user clicks the button, send an AJAX request to the server, and update the button based on the results. You might need to localize the script to pass the rest URL and other data.

$('#like-button').on('click',function (e) {
    e.preventDefault();
    $.ajax({
        type: 'GET',
        url: 'http://example.com/wp-json/my_route/v1/ajax_favorite',
        data: { post_id: $('#current-post-id').val(), user_id : $('#current-user-id').val() },
        beforeSend: function() {
            $('#like-button').addClass('active').prop('disabled', true);
        },
        success: function(data){

            $('#like-button').removeClass('active').prop('disabled', false);

            if( data != null ){

                if( data == '400' ) {
                    $('#like-button').removeClass('selected');
                } else if( data == '200') {
                    $('#like-button').addClass('selected');
                }
            }
        },
        error:function(){

        }
    });
});

Process the Ajax Request Using REST-API

Now create a rest route and process the data. If the received post ID doesn't exists in the user meta, add it and return a successful code. If it does, remove it and let your script know about it.

add_action( 'rest_api_init', 'my_rest_routes');
function my_rest_routes() {
    // Path to ajax like function
    register_rest_route(
        'my_route/v1',
        '/ajax_favorite/',
        array(
            'methods' => 'GET',
            'callback' => 'ajax_favorite'
        )
    );
}

function ajax_favorite(){

    // If the ID is not set, return
    if(!isset($_GET['post_id']) || !isset($_GET['user_id'])){
        return $data['status'] = '500';
    }

    // Store user and product's ID
    $post_id   = sanitize_text_field($_GET['post_id']);
    $user_id   = sanitize_text_field($_GET['user_id']);
    $user_meta = get_user_meta($user_id,'_favorite_posts',false);

    // Check if the post is favorited or not
    if( in_array( $post_id, $user_meta ) ){
        delete_user_meta($user_id,'_favorite_posts',$post_id);
        return $data['status'] = '400';
    } else {
        add_user_meta($user_id,'_favorite_posts',$post_id);
        return $data['status'] = '200';
    }

}

You can use this as a template to output any button that saves data from front-end to database. Don't forget to sanitize the data, and use nonce too.

Now of course all you need is to get the _favorite_posts user meta whenever you want to display it.

| improve this answer | |
2

I'd suggest using using custom tables to keep things lean.

Have two tables: A table of lists and a table of posts and which lists they belong to.

The lists table (let's call it wp_lists) would look like:

+----+---------+----------------+
| id | user_id |      name      |
+----+---------+----------------+
|  1 |       2 | My list        |
|  2 |       2 | My second list |
+----+---------+----------------+

You could have more columns here if lists had more data to them, like a description or associated colour. If the table starts growing you might want to split it into a two tables, with a separate table for user-list relationships.

And the lists-posts table (let's call it wp_post_list) would look like:

+---------+---------+
| post_id | list_id |
+---------+---------+
|       2 |       2 |
|       3 |       2 |
|       2 |       1 |
+---------+---------+

Maybe you'd want an ID column, but I'm not sure what you'd need it for, since the post_id/list_id combinations should all be unique, since posts can't be in a list more than once.

So when someone creates a list you'd insert it into wp_lists. They could create as many as they like, or you could limit it in PHP by checking how many they've already got.

To get the lists that belong to the current user you'd just query wp_lists based on the user_id column.

When someone adds a post to a list you'd insert the post ID into wp_post_list alongside the list it belongs to. When you want to see all posts within a list you'd query based on the list_id column, then put the resulting IDs into a WP_Query or get_posts().

When browsing posts you'd want to show which of the user's lists it already belongs too. In that case you'd query wp_post_list based on the post_id, but JOIN it to wp_lists and limit results to ones with lists that have the current user's ID.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.