Jump to content
sirhc

Like page (photo) for logged in user

Recommended Posts

Hi all,

Im working on a photography website where users can comment and like on photos (which are pages). I solved the comment part with the comment module, but I also want a 'like' system. Which includes;

- Like a photo. Like count on the photo adds up.
- If user has a few favourite photos, i would like a 'Favourites' section on the user profile page, with all of the liked photos.
- Apart from the likes, i would like to have a page 'Most liked photos of this week', so each week the community can see the photos with the most likes that week.

I came across the Like plug-in, but i would like to have a little more tailored solution and keep it to logged-in users only and be able to see all of the liked photos of a user.

Any idea how to keep track of the likes and build a 'Most liked this week' page?
Help would be appreciated!

Thnx.

Share this post


Link to post
Share on other sites

hi sirhc,

you could create a page reference field on your photo-template and when a user clicks on like you can add this user to the pagefield. if you have lots of users (likes) that could cause some problems on the page edit screen i guess, but if you set the field to hidden it should work.

like count is as easy as counting referenced pages (users).

show all liked photos would be an easy selector like "template=photo,likes=youruserid"

 

most likes this week... hmmm... that's not possible with the setup above. then maybe it's better to create 2 new templates:

1) likes (just the parent for all likes)
2) like (pagefield referencing the photo, user that liked)

then you can create a new "like" page whenever a user likes a photo and then you can also count all likes of that week: $pages->count("template=like,photo=yourphotoid,created>xxx,created<yyy");

and counting all likes for one photo would be even easier: $pages->count("template=like,photo=yourphotoid");

  • Like 1

Share this post


Link to post
Share on other sites

I would have taken another way. 

As each photo are Page, he could create a module which work with a custom MySQL table where he update the like of a page with some informations aside, like the userID (the user who like the page), the pageID (the page being liked) , a likeStatus (like or unliked) and a timestamp.

 

I made a small module to show the idea :

 

Spoiler

<?php namespace ProcessWire;

class LikeSystem extends WireData implements Module {

    const minVersion = '3.0.0';
    protected $tableName = 'likes_system';

    public static function getModuleInfo()
    {
        return [
            'title' => 'LikeSystem',
            'version' => "0.0.1",
            'summary' => 'Like System for ProcessWire.',
            'author' => 'flydev',
            'href' => 'https://processwire.com',
            'singular' => false,
            'autoload' => false,
            'icon' => 'thumbs-up',
            'requires' => [
                'ProcessWire>=3.0.0'
            ]
        ];
    }

    protected function createTable() {

        $sql =  "CREATE TABLE IF NOT EXISTS " . $this->tableName . " ( " .
                "id int unsigned NOT NULL AUTO_INCREMENT, " .
                "userId int unsigned NOT NULL, " .
                "pageId int unsigned NOT NULL, " .
                "likes boolean NOT NULL," .
                "ts timestamp NULL DEFAULT CURRENT_TIMESTAMP, " .
                "PRIMARY KEY (id) " .
                ")";
        $this->database->exec($sql);
        $sql = "CREATE UNIQUE INDEX userId_pageId ON " . $this->tableName . " ('userId', 'pageId');";
        $this->database->exec($sql);

    }

    public function ___install() {

        if (version_compare($this->config->version, self::minVersion, '<'))
            throw new WireException("This module requires ProcessWire " . self::minVersion . " or newer.");

        $this->createTable();
    }

    public function ___uninstall() {
        $sql = "DROP TABLE IF EXISTS " . $this->tableName;
        $this->database->exec($sql);
    }

    public function init() {
        // check if the button 'like' as been clicked
        if(wire('input')->post->likethispage) {
            $status = (wire('input')->post->likethispage === 'like') ? 1 : 0;
            $this->likePage($status);
        }
    }

    // Like or unlike a page
    protected function likePage($status) {
        $userId = wire('user')->id;
        $sql = "INSERT INTO " . $this->tableName . "(userId, pageId, likes) VALUES ('".$userId."', '".wire('page')->id. "', '" . $status . "')
                ON DUPLICATE KEY UPDATE 
                likes = $status,
                ts = CURRENT_TIMESTAMP;";
        $this->database->exec($sql);
    }

    // get the total of like of $pageId or current page
    public function getTotal($pageId = '') {
        $pageId = empty($pageId) ? wire('page')->id : $pageId;
        $sql = "SELECT pageId FROM " . $this->tableName . " WHERE pageId = '" . $pageId . "' and likes = '1';";
        $res = $this->database->query($sql);
        $row = $res->fetchAll();
        return count($row);
    }

    // get the most liked page, if $limit is defined, it return the N most liked page
    public function getMostLikedPage($limit = 5) {
        $sql = "SELECT pageId, count(pageId) as likesCount FROM " . $this->tableName .
               " WHERE likes='1' GROUP BY pageId ORDER BY likesCount DESC LIMIT $limit;";
        $res = $this->database->query($sql);
        $row = $res->fetchAll();

        return $row;
    }

    public function render() {

        $modules = wire('modules');

        $sql = "SELECT pageId, likes FROM " . $this->tableName . " WHERE pageId = '" . wire('page')->id . "' and userId = '". wire('user')->id ."';";
        $res = $this->database->query($sql);
        $row = $res->fetch();
        $label = 'like';
        if(count($row)) {
            if($row['likes'] == 1) $label = 'unlike';
        }

        $form = $modules->get("InputfieldForm");
        $form->action = './';
        $form->method = 'post';
        $form->attr('id+name', 'likeSystemForm');

        $field = $modules->get("InputfieldSubmit");
        $field->value = $label;
        $field->icon = "thumbs-up";
        $field->attr('id+name', 'likethispage');

        $form->append($field);

        return $form->render();
    }
}

 

 

then in the frontend, you can render a 'like' button on choosen templates, and finaly get the total number of likes of a page and the most liked page, see:

 

<?php namespace ProcessWire;

$likesmod = $modules->get('LikeSystem');
// render a 'like' button
$content = $likesmod->render();
// total like of the page
$content .= "Number of likes for this page: " . $likesmod->getTotal($page->id);
// most liked page
$limit = 1
$mostliked = $likesmod->getMostLikedPage($limit);
$content .= "<br>Most liked page: " . $pages->get($mostliked[0]['pageId'])->title . "(" . $mostliked[0]['pageId'] . ") " . " (N likes: ". $mostliked[0]['likesCount'] . ")";

 

Edited by flydev
code typo
  • Like 5

Share this post


Link to post
Share on other sites
7 hours ago, bernhard said:

most likes this week... hmmm... that's not possible with the setup above.

There is the Page Reference with Date Field module that might be useful for this sort of thing. I've never used it and the module page doesn't indicate that it is compatible with PW3.

But the real problem with using Page Reference fields for likes or any purpose that could potentially use thousands of pages is that there is no pagination or limiting possible when getting the field value. So it's not just a matter of dealing with the inputfield in Page Edit but also the impact on memory when getting the value via the API.

There's an open request about this but no sign of activity.

  • Like 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By angelo, italy
      Hi guys,
      I've always used WP but I want to swtich to PW. I'm not sure ....
      I'd like to know if it's possible to create a website for an online photo contest.
      The participants of the competition could create their own account, in which they upload their photos. The photos uploaded remain visible only to themselves and the judges.
      From their account they can make the "entrance fee" payment.
      The judges of the competition can create their own account... entering they see the photos of the participants and vote photos
      At the main page I imagine the title of the competition, a button to read the regulation, and a button to register.
      The website should be in Italian and English.
      Thank you!!
       
       
    • By Marcel
      Hey,
      I am about to use the tool Create Users Batcher. We have 450 users. When I tryed it with like 20 test users it worked but it took a while. Now my concerns are that 450 might be to stressful? Does anyone have experience with several hundreds of users? My thoughts are to split it in smaller goups and upload them one group after another.
      best wishes
      marcel
    • By Peter Knight
      I have a demo site which I moved to a new VPS for client testing
      We noticed that leaving a page open and then revisiting the site can result in a 25 second(ish) to load time and will then throw a 500 Error.
      The hosting guys had a look and confirmed that the server is fine but the issue could be related to authentication or sessions.
      We are running Page Protector and ProCache so I wondered if there were any known bugs here and any recommended actions.
      My actual PW log doesn't show anything but the server log has plenty of these
       
      2018-12-06 08:14:00 Error xxx.141.1x.101 500 POST /who-we-are/ HTTP/1.0     1.58 K Apache access 2018-12-06 08:14:45 Warning xxx.141.1x.131   mod_fcgid: read data timeout in 45 seconds, referer: http://demo.abc.not/who-we-are/       Apache error 2018-12-06 08:14:45 Error xxx.141.1x.131   End of script output before headers: index.php, referer: http://demo.abc.not/who-we-are/       Apache error 2018-12-06 09:03:18 Error xxx.141.1x.131   2614#0: *667 recv() failed (104: Connection reset by peer) while reading response header from upstream       nginx error Thanks
      P
    • By Marcel
      Hey all,
      I want to customize the mywebsite/processwire/profile page. It's almost all good but I want to get rid of the sections 'Admin Theme' and 'Language' so that the user can just set a new password. (see image)
      Do I have to modify the admin template or how can I do that? Because when I go tree>Admin>Profile there are no fields to add or remove.
      Or where can I find the php file?
      I would appreciate your help.

    • By ridgedale
      Reference: PW 3.0.111 and uikit3 based site using the Regular-Master profile.
      I'm trying to automatically redirect a logged-in user to a custom profile page using $session->redirect() and need to add $user->name to the redirect path.
      All my attempts appear to have failed:
      $session->redirect('/user-profile/')->name; $session->redirect('/user-profile/')->$user->name; $session->redirect('/user-profile/' . get($user->name . '/')); $session->redirect('/user-profile/' & get($user->name)); Can anyone point out where I am going wrong?
×
×
  • Create New...