You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

296 lines
8.9 KiB

<?php
// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$
class SocialLib
{
private $relationlib;
private $networkType;
public function __construct()
{
global $prefs;
$this->relationlib = TikiLib::lib('relation');
$this->networkType = $prefs['social_network_type'] ?: 'follow';
}
public function listFriends($user)
{
return $this->getRelations('follow', $user);
}
public function listFollowers($user)
{
return $this->getRelations('follow.invert', $user);
}
public function listIncomingRequests($user)
{
return $this->getRelations('request.invert', $user);
}
public function listOutgoingRequests($user)
{
return $this->getRelations('request', $user);
}
public function addFriend($user, $newFriend)
{
if ($user == $newFriend) {
return false;
}
$userlib = TikiLib::lib('user');
if (! $userlib->user_exists($user) || ! $userlib->user_exists($newFriend)) {
return false;
}
$tx = TikiDb::get()->begin();
$hash = $this->createHash($user, $newFriend);
if ($this->networkType == 'follow') {
$this->addRelation('follow', $user, $newFriend);
TikiLib::events()->trigger(
'tiki.user.follow.add',
[
'type' => 'user',
'object' => $user,
'user' => $user,
'follow_id' => $newFriend,
'aggregate' => $hash,
]
);
TikiLib::events()->trigger(
'tiki.user.follow.incoming',
[
'type' => 'user',
'object' => $newFriend,
'user' => $newFriend,
'follow_id' => $user,
'aggregate' => $hash,
]
);
} elseif ($this->networkType == 'follow_approval' || $this->networkType == 'friend') {
$request = $this->getRelation('request.invert', $user, $newFriend);
$follow = $this->getRelation('follow.invert', $user, $newFriend);
if ($request || $follow) {
// If there was a pending request by the other side (or pre-approved), remove the request
// and approve both directions.
// Re-add or empty-delete are not an issue
$this->relationlib->remove_relation($request);
$this->addRelation('follow', $user, $newFriend);
$this->addRelation('follow.invert', $user, $newFriend);
$event = ($this->networkType == 'friend') ? 'tiki.user.friend.add' : 'tiki.user.follow.add';
TikiLib::events()->trigger(
$event,
[
'type' => 'user',
'object' => $user,
'user' => $user,
'follow_id' => $newFriend,
'aggregate' => $hash,
]
);
TikiLib::events()->trigger(
$event,
[
'type' => 'user',
'object' => $newFriend,
'user' => $newFriend,
'follow_id' => $user,
'aggregate' => $hash,
]
);
} else {
// New request
$this->addRelation('request', $user, $newFriend);
}
}
$tx->commit();
require_once('lib/search/refresh-functions.php');
refresh_index('user', $user);
refresh_index('user', $newFriend);
return true;
}
public function approveFriend($user, $newFriend)
{
if ($this->networkType != 'follow_approval') {
return false;
}
$request = $this->getRelation('request.invert', $user, $newFriend);
if ($request) {
$tx = TikiDb::get()->begin();
// If there was a pending request by the other side, remove the request
// and add them as follower
$this->relationlib->remove_relation($request);
$this->addRelation('follow.invert', $user, $newFriend);
TikiLib::events()->trigger(
'tiki.user.follow.add',
[
'type' => 'user',
'object' => $newFriend,
'user' => $newFriend,
'follow_id' => $user,
]
);
TikiLib::events()->trigger(
'tiki.user.follow.incoming',
[
'type' => 'user',
'object' => $user,
'user' => $user,
'follow_id' => $newFriend,
]
);
$tx->commit();
require_once('lib/search/refresh-functions.php');
refresh_index('user', $user);
refresh_index('user', $newFriend);
return true;
}
return false;
}
public function removeFriend($user, $oldFriend)
{
$follow = $this->getRelation('follow', $user, $oldFriend);
$followInvert = $this->getRelation('follow.invert', $user, $oldFriend);
$request = $this->getRelation('request', $user, $oldFriend);
$requestInvert = $this->getRelation('request.invert', $user, $oldFriend);
if ($follow) {
$this->relationlib->remove_relation($follow);
if ($this->networkType == 'friend') {
// Friendship breakups are bidirectional, not follow ones
$this->relationlib->remove_relation($followInvert);
}
require_once('lib/search/refresh-functions.php');
refresh_index('user', $user);
refresh_index('user', $oldFriend);
return true;
} elseif ($request || $requestInvert) {
$this->relationlib->remove_relation($request);
$this->relationlib->remove_relation($requestInvert);
require_once('lib/search/refresh-functions.php');
refresh_index('user', $user);
refresh_index('user', $oldFriend);
return true;
} else {
return false;
}
}
private function getRelations($type, $from)
{
$relations = $this->relationlib->get_relations_from('user', $from, 'tiki.friend.' . $type);
return array_map(
function ($relation) {
return [
'user' => $relation['itemId'],
];
},
$relations
);
}
private function addRelation($type, $from, $to)
{
return $this->relationlib->add_relation('tiki.friend.' . $type, 'user', $from, 'user', $to);
}
private function getRelation($type, $from, $to)
{
return $this->relationlib->get_relation_id('tiki.friend.' . $type, 'user', $from, 'user', $to);
}
private function createHash($a, $b)
{
// Hashing needs constant user ordering, so sort
if ($a > $b) {
$t = $b;
$b = $a;
$a = $t;
}
return sha1("friendrelation/$a/$b");
}
public function addLike($user, $type, $id)
{
$like = $this->getLike($user, $type, $id);
if (! $like) {
$this->relationlib->add_relation('tiki.social.like', 'user', $user, $type, $id);
TikiLib::events()->trigger(
'tiki.social.like.add',
[
'type' => $type,
'object' => $id,
'user' => $user,
]
);
return true;
}
return false;
}
public function removeLike($user, $type, $id)
{
$like = $this->getLike($user, $type, $id);
if ($like) {
$this->relationlib->remove_relation($like);
TikiLib::events()->trigger(
'tiki.social.like.remove',
[
'type' => $type,
'object' => $id,
'user' => $user,
]
);
return true;
}
return false;
}
public function getLikes($type, $id)
{
$relations = $this->relationlib->get_relations_to($type, $id, 'tiki.social.like');
return array_map(
function ($relation) {
return $relation['itemId'];
},
$relations
);
}
private function getLike($user, $type, $id)
{
return $this->relationlib->get_relation_id('tiki.social.like', 'user', $user, $type, $id);
}
}