Pinned Posts Download 7.3dev2

5.0
German Michael Zülsdorff 12 months ago

Pinned Posts

An example of step-by-step development

The goal of this component is enabling the admin to pin one or more posts on top of the newsfeed, as requested here:: https://www.opensource-socialnetwork.org/discussion/view/6844


Changelog:
ready to use,
v7.3dev2: fixed wrong merging of extra 'wheres' to get*Posts queries
v7.3dev1: + option to un-/collapse pinned posts contributed by Dominik L.

v7.2dev4: + compatibility fix for Friends-Online component as reported by Dominik L.
v7.2dev3: + 'Pin' menu entries on any wall post
v7.2dev2: + 'Unpin' menu entries on Pinned Post's frontend panel
v7.2dev1: + option to hide/display comments

ready to use, but not recommended
v7.1dev4: + eight selectable background colors + language files

early releases NOT to be used in production environments
v7.1dev3: pinned posts being removed from original location + crash debug
v7.1dev2: pinned posts appear on top of the newsfeed
v7.1dev1: admin backend to save post ids + basic placement on top of newfeed


How to pin one or more posts:
Choose the post you want to pin, open its menu on the right and click 'Pin':


enter image description here


The page reloads and the result will look like this.
(With Greetings and Site Announcement installed, Pinned Posts will care about a meaningful ordering by the way.)


enter image description here


How to unpin one or more pinned posts:
Choose the post you want to unpin, open its menu on the right and click 'Unpin':


enter image description here


Collapsing pinned posts:
Since members may not be too delighted to find the same pinned posts again and again whenever they visit the newsfeed, they may collapse any post they don't want to see anymore...


enter image description here


to just one line ...


enter image description here

Comments
German Michael Zülsdorff Replied 11 months ago

Oops, I thought it would be obvious when I wrote that I intentionally changed Arsalan's line of valid code

$return['order_by'] = 'o.guid ASC';

to this invalid line

$return['order_by'] = 'CRASH_ME!';

in order to force some debug output....

Okay, it was not. Then, what can we do?

1) Revert back to Arsalan's original code. But that would change the sort order in general. And that's not what you wanted.
2) Leave Arsalan's line in place but reverse the ordering in a valid way like

$return['order_by'] = 'o.guid DESC';

which wouldn't hurt but doesn't make too much sense because the default ordering is already DESCENDING
3) simply remove the invalid line :)

Bulgarian Georgi Shindarov Replied 11 months ago

Ok, what needs to be done next to get the component working?

German Michael Zülsdorff Replied 11 months ago

Yeah, what should happen next ... A closer look under the hood and a little explaining can't be bad, I think. ;)

So, let's recall what Arsalan suggested 2 weeks ago. His idea was using 3 hooks calling a function to simply reverse the default DESCENDING sort order to get the oldest post on top like:

function wall_posts_order($hook, $type, $return, $params){
                $return['order_by'] = 'o.guid ASC';
                return $return;
}

But since this didn't solve exactly what you wanted, we found a different way with release dev1 and dev2 to pin the post on top - using some code from the Site announcement component and the page handler of OssnWall.
Next, you requested to hide the original post - and that's where Arsalan's idea comes into conclusion again. Just a little changed - not to reverse the sort order but exclude the pinned posts instead.
Time to open ossn_com.php of this component now, and see what has changed:

if (isset($settings->PinnedPosts) && !empty($settings->PinnedPosts)) {
    // yes we have!
    // so let's extend the original SQL query to exclude these post ids
    $return['wheres'] = "o.guid NOT IN ({$settings->PinnedPosts})";
    // and stop here and see how the resulting query looks like ....
    $return['order_by'] = 'CRASH_ME!';
    return $return;
}

Aside from some checking if there are pinned posts at all, it's actually just one line to get that accomplished:

$return['wheres'] = "o.guid NOT IN ({$settings->PinnedPosts})";

Okay, but how do these wheres have an impact on fetching wall posts? In order to get a better understanding I decided to leave Arsalan's former line in place and change 'ASC' to 'CRASH_ME'. That's in fact no valid SQL the database could handle and hence throwing the error message:

OssnDatabaseException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CRASH LIMIT 0, 10' at line 1 

SELECT DISTINCT  o.guid, o.time_created FROM ossn_object as o JOIN ossn_entities as e0 ON e0.owner_guid=o.guid JOIN ossn_entities_metadata as emd0 ON e0.guid=emd0.guid JOIN ossn_entities as e1 ON e1.owner_guid=o.guid JOIN ossn_entities_metadata as emd1 ON e1.guid=emd1.guid WHERE(o.subtype='wall' AND o.type='user' AND (e0.type='object' AND e0.subtype='access' AND (1=1) AND e1.type='object' AND e1.subtype='poster_guid' AND (emd0.value=2 OR emd0.value=3)) AND o.guid NOT IN (156))  ORDER by o.guid CRASH LIMIT 0, 10; 

Let's have a closer look at the query above:
Initially, the query would fetch ALL ids from the ossn_object table:

SELECT DISTINCT  o.guid, o.time_created FROM ossn_object ...

but then there are a lot of extra conditions to sort out those records which are actually posts:

WHERE(o.subtype='wall' AND o.type='user' AND (e0.type='object' AND e0.subtype='access' AND (1=1) AND e1.type='object' AND e1.subtype='poster_guid' AND (emd0.value=2 OR emd0.value=3)) AND o.guid NOT IN (156))

And now it becomes clear, which way the code

$return['wheres'] = "o.guid NOT IN ({$settings->PinnedPosts})";

was 'translated' to SQL and added to all other wheres at the end as

AND o.guid NOT IN (156)

with your post 156 which was already pinned and needs to be excluded from the original location on the wall as requested by you.

Bulgarian Georgi Shindarov Replied 11 months ago

Yes.. apparently this is some kind of test.. and what should happen next?

German Michael Zülsdorff Replied 11 months ago

Yep, this release leads to a crash - that's why I named it "the_crasher" :)
Thanks for sending the error report. So, the id of your pinned post is 156?

Bulgarian Georgi Shindarov Replied 11 months ago

Unfortunately there is some problem and the component is not working properly.. I am attaching an image

enter image description here

German Michael Zülsdorff Replied 11 months ago

I have implemented the hooks as suggested by Arsalan in release 7.1dev3_the_crasher now.
See ossn_com.php for details

Bulgarian Georgi Shindarov Replied 11 months ago

Can you show me in my thread or here how to do it.. How do I hide the original posts? I will be very thankful!

German Michael Zülsdorff Replied 11 months ago

I'd rather call this a problem - at least not a problem of my component - if you got only a handful of posts on your site and both the fixed and original appear twice on the same page. :)) It's just another feature request.

Anyway: Arsalan posted some the code to accomplish things like that 2 weeks ago in your thread already. That is: Use these hooks, and change the accompanying function to exclude the saved post ids.

Bulgarian Georgi Shindarov Replied 11 months ago

Thank you very much for starting to develop this component.. And is it possible to make it so that the original post that appears in the top position disappears from its previous position in the list of posts.. because at the moment we get very close repetition of posts and it seems a bit overloaded and unnecessary.. Will you be able to fix this problem in the next version of this component. Thank you again!

Component

Developer: Michael
License GPL v2
Type: Site admin
Requires Ossn Version : 7.1
Latest Version: 7.3dev2
Last Updated 4 weeks ago
Repository Url View Repository

Versions