2017-12-09 18:31:00 +00:00
< ? php
/**
* @ file src / Model / Group . php
*/
namespace Friendica\Model ;
use Friendica\BaseObject ;
2018-02-26 00:58:23 +00:00
use Friendica\Core\L10n ;
2018-07-20 12:19:26 +00:00
use Friendica\Database\DBA ;
2017-12-09 18:31:00 +00:00
require_once 'boot.php' ;
2017-12-17 20:24:57 +00:00
require_once 'include/dba.php' ;
2017-12-09 18:31:00 +00:00
require_once 'include/text.php' ;
/**
* @ brief functions for interacting with the group database table
*/
class Group extends BaseObject
{
/**
* @ brief Create a new contact group
*
* Note : If we found a deleted group with the same name , we restore it
*
* @ param int $uid
* @ param string $name
* @ return boolean
*/
public static function create ( $uid , $name )
{
$return = false ;
if ( x ( $uid ) && x ( $name )) {
$gid = self :: getIdByName ( $uid , $name ); // check for dupes
if ( $gid !== false ) {
// This could be a problem.
// Let's assume we've just created a group which we once deleted
// all the old members are gone, but the group remains so we don't break any security
// access lists. What we're doing here is reviving the dead group, but old content which
// was restricted to this group may now be seen by the new group members.
2018-07-20 12:19:26 +00:00
$group = DBA :: selectFirst ( 'group' , [ 'deleted' ], [ 'id' => $gid ]);
2018-07-21 12:40:21 +00:00
if ( DBA :: is_result ( $group ) && $group [ 'deleted' ]) {
2018-07-20 12:19:26 +00:00
DBA :: update ( 'group' , [ 'deleted' => 0 ], [ 'id' => $gid ]);
2018-01-21 18:33:59 +00:00
notice ( L10n :: t ( 'A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name.' ) . EOL );
2017-12-09 18:31:00 +00:00
}
return true ;
}
2018-07-20 12:19:26 +00:00
$return = DBA :: insert ( 'group' , [ 'uid' => $uid , 'name' => $name ]);
2017-12-13 01:52:50 +00:00
if ( $return ) {
2018-07-20 12:19:26 +00:00
$return = DBA :: lastInsertId ();
2017-12-13 01:52:50 +00:00
}
2017-12-09 18:31:00 +00:00
}
return $return ;
}
2018-04-07 13:54:26 +00:00
/**
* Update group information .
*
* @ param int $id Group ID
* @ param string $name Group name
*
* @ return bool Was the update successful ?
*/
public static function update ( $id , $name )
{
2018-07-20 12:19:26 +00:00
return DBA :: update ( 'group' , [ 'name' => $name ], [ 'id' => $id ]);
2018-04-07 13:54:26 +00:00
}
2017-12-09 18:31:00 +00:00
/**
* @ brief Get a list of group ids a contact belongs to
*
* @ param int $cid
* @ return array
*/
2017-12-17 00:21:56 +00:00
public static function getIdsByContactId ( $cid )
2017-12-09 18:31:00 +00:00
{
2017-12-16 16:50:58 +00:00
$condition = [ 'contact-id' => $cid ];
2018-07-20 12:19:26 +00:00
$stmt = DBA :: select ( 'group_member' , [ 'gid' ], $condition );
2017-12-09 18:31:00 +00:00
$return = [];
2017-12-10 20:12:23 +00:00
2018-07-20 12:19:26 +00:00
while ( $group = DBA :: fetch ( $stmt )) {
2017-12-10 20:12:23 +00:00
$return [] = $group [ 'gid' ];
2017-12-09 18:31:00 +00:00
}
return $return ;
}
/**
* @ brief count unread group items
*
* Count unread items of each groups of the local user
*
* @ return array
* 'id' => group id
* 'name' => group name
* 'count' => counted unseen group items
*/
public static function countUnseen ()
{
2018-07-20 12:19:26 +00:00
$stmt = DBA :: p ( " SELECT `group`.`id`, `group`.`name`,
2017-12-09 18:31:00 +00:00
( SELECT COUNT ( * ) FROM `item` FORCE INDEX ( `uid_unseen_contactid` )
WHERE `uid` = ?
AND `unseen`
AND `contact-id` IN
( SELECT `contact-id`
FROM `group_member`
2017-12-15 03:47:58 +00:00
WHERE `group_member` . `gid` = `group` . `id` )
2017-12-09 18:31:00 +00:00
) AS `count`
FROM `group`
WHERE `group` . `uid` = ? ; " ,
local_user (),
local_user ()
);
2018-07-21 02:03:40 +00:00
return DBA :: toArray ( $stmt );
2017-12-09 18:31:00 +00:00
}
/**
* @ brief Get the group id for a user / name couple
*
* Returns false if no group has been found .
*
* @ param int $uid
* @ param string $name
* @ return int | boolean
*/
public static function getIdByName ( $uid , $name )
{
2017-12-10 06:07:48 +00:00
if ( ! $uid || ! strlen ( $name )) {
2017-12-09 18:31:00 +00:00
return false ;
}
2018-07-20 12:19:26 +00:00
$group = DBA :: selectFirst ( 'group' , [ 'id' ], [ 'uid' => $uid , 'name' => $name ]);
2018-07-21 12:40:21 +00:00
if ( DBA :: is_result ( $group )) {
2017-12-09 18:31:00 +00:00
return $group [ 'id' ];
}
return false ;
}
/**
* @ brief Mark a group as deleted
*
2017-12-17 20:27:50 +00:00
* @ param int $gid
2017-12-09 18:31:00 +00:00
* @ return boolean
*/
public static function remove ( $gid ) {
if ( ! $gid ) {
return false ;
}
2018-07-20 12:19:26 +00:00
$group = DBA :: selectFirst ( 'group' , [ 'uid' ], [ 'id' => $gid ]);
2018-07-21 12:40:21 +00:00
if ( ! DBA :: is_result ( $group )) {
2017-12-17 20:31:37 +00:00
return false ;
}
2017-12-09 18:31:00 +00:00
// remove group from default posting lists
2018-07-20 12:19:26 +00:00
$user = DBA :: selectFirst ( 'user' , [ 'def_gid' , 'allow_gid' , 'deny_gid' ], [ 'uid' => $group [ 'uid' ]]);
2018-07-21 12:40:21 +00:00
if ( DBA :: is_result ( $user )) {
2017-12-09 18:31:00 +00:00
$change = false ;
if ( $user [ 'def_gid' ] == $gid ) {
$user [ 'def_gid' ] = 0 ;
$change = true ;
}
if ( strpos ( $user [ 'allow_gid' ], '<' . $gid . '>' ) !== false ) {
$user [ 'allow_gid' ] = str_replace ( '<' . $gid . '>' , '' , $user [ 'allow_gid' ]);
$change = true ;
}
if ( strpos ( $user [ 'deny_gid' ], '<' . $gid . '>' ) !== false ) {
$user [ 'deny_gid' ] = str_replace ( '<' . $gid . '>' , '' , $user [ 'deny_gid' ]);
$change = true ;
}
if ( $change ) {
2018-07-20 12:19:26 +00:00
DBA :: update ( 'user' , $user , [ 'uid' => $group [ 'uid' ]]);
2017-12-09 18:31:00 +00:00
}
}
// remove all members
2018-07-20 12:19:26 +00:00
DBA :: delete ( 'group_member' , [ 'gid' => $gid ]);
2017-12-09 18:31:00 +00:00
// remove group
2018-07-20 12:19:26 +00:00
$return = DBA :: update ( 'group' , [ 'deleted' => 1 ], [ 'id' => $gid ]);
2017-12-09 18:31:00 +00:00
return $return ;
}
/**
* @ brief Mark a group as deleted based on its name
*
* @ deprecated Use Group :: remove instead
*
2017-12-17 20:27:50 +00:00
* @ param int $uid
* @ param string $name
* @ return bool
2017-12-09 18:31:00 +00:00
*/
public static function removeByName ( $uid , $name ) {
$return = false ;
if ( x ( $uid ) && x ( $name )) {
$gid = self :: getIdByName ( $uid , $name );
$return = self :: remove ( $gid );
}
return $return ;
}
/**
* @ brief Adds a contact to a group
*
* @ param int $gid
* @ param int $cid
* @ return boolean
*/
public static function addMember ( $gid , $cid )
{
2017-12-10 06:06:12 +00:00
if ( ! $gid || ! $cid ) {
2017-12-09 18:31:00 +00:00
return false ;
}
2018-07-20 12:19:26 +00:00
$row_exists = DBA :: exists ( 'group_member' , [ 'gid' => $gid , 'contact-id' => $cid ]);
2017-12-09 18:31:00 +00:00
if ( $row_exists ) {
// Row already existing, nothing to do
$return = true ;
} else {
2018-07-20 12:19:26 +00:00
$return = DBA :: insert ( 'group_member' , [ 'gid' => $gid , 'contact-id' => $cid ]);
2017-12-09 18:31:00 +00:00
}
return $return ;
}
/**
* @ brief Removes a contact from a group
*
* @ param int $gid
* @ param int $cid
* @ return boolean
*/
public static function removeMember ( $gid , $cid )
{
2017-12-10 06:06:12 +00:00
if ( ! $gid || ! $cid ) {
2017-12-09 18:31:00 +00:00
return false ;
}
2018-07-20 12:19:26 +00:00
$return = DBA :: delete ( 'group_member' , [ 'gid' => $gid , 'contact-id' => $cid ]);
2017-12-09 18:31:00 +00:00
return $return ;
}
/**
* @ brief Removes a contact from a group based on its name
*
* @ deprecated Use Group :: removeMember instead
*
* @ param int $uid
* @ param string $name
* @ param int $cid
* @ return boolean
*/
public static function removeMemberByName ( $uid , $name , $cid )
{
$gid = self :: getIdByName ( $uid , $name );
$return = self :: removeMember ( $gid , $cid );
return $return ;
}
/**
* @ brief Returns the combined list of contact ids from a group id list
*
* @ param array $group_ids
* @ param boolean $check_dead
* @ param boolean $use_gcontact
* @ return array
*/
public static function expand ( $group_ids , $check_dead = false , $use_gcontact = false )
{
2017-12-10 06:06:12 +00:00
if ( ! is_array ( $group_ids ) || ! count ( $group_ids )) {
2017-12-09 18:31:00 +00:00
return [];
}
$condition = '`gid` IN (' . substr ( str_repeat ( " ?, " , count ( $group_ids )), 0 , - 2 ) . ')' ;
if ( $use_gcontact ) {
$sql = ' SELECT `gcontact` . `id` AS `contact-id` FROM `group_member`
INNER JOIN `contact` ON `contact` . `id` = `group_member` . `contact-id`
INNER JOIN `gcontact` ON `gcontact` . `nurl` = `contact` . `nurl`
WHERE ' . $condition ;
$param_arr = array_merge ([ $sql ], $group_ids );
$stmt = call_user_func_array ( 'dba::p' , $param_arr );
} else {
$condition_array = array_merge ([ $condition ], $group_ids );
2018-07-20 12:19:26 +00:00
$stmt = DBA :: select ( 'group_member' , [ 'contact-id' ], $condition_array );
2017-12-09 18:31:00 +00:00
}
2017-12-10 06:06:12 +00:00
$return = [];
2018-07-20 12:19:26 +00:00
while ( $group_member = DBA :: fetch ( $stmt )) {
2017-12-10 06:06:12 +00:00
$return [] = $group_member [ 'contact-id' ];
2017-12-09 18:31:00 +00:00
}
if ( $check_dead && ! $use_gcontact ) {
2018-02-26 00:58:23 +00:00
Contact :: pruneUnavailable ( $return );
2017-12-09 18:31:00 +00:00
}
return $return ;
}
/**
* @ brief Returns a templated group selection list
*
* @ param int $uid
* @ param int $gid An optional pre - selected group
* @ param string $label An optional label of the list
* @ return string
*/
public static function displayGroupSelection ( $uid , $gid = 0 , $label = '' )
{
$o = '' ;
2018-07-20 12:19:26 +00:00
$stmt = DBA :: select ( 'group' , [], [ 'deleted' => 0 , 'uid' => $uid ], [ 'order' => [ 'name' ]]);
2017-12-09 18:31:00 +00:00
$display_groups = [
[
'name' => '' ,
'id' => '0' ,
'selected' => ''
]
];
2018-07-20 12:19:26 +00:00
while ( $group = DBA :: fetch ( $stmt )) {
2017-12-09 18:31:00 +00:00
$display_groups [] = [
'name' => $group [ 'name' ],
'id' => $group [ 'id' ],
'selected' => $gid == $group [ 'id' ] ? 'true' : ''
];
}
logger ( 'groups: ' . print_r ( $display_groups , true ));
if ( $label == '' ) {
2018-01-22 14:54:13 +00:00
$label = L10n :: t ( 'Default privacy group for new contacts' );
2017-12-09 18:31:00 +00:00
}
2018-01-15 13:05:12 +00:00
$o = replace_macros ( get_markup_template ( 'group_selection.tpl' ), [
2017-12-09 18:31:00 +00:00
'$label' => $label ,
'$groups' => $display_groups
2018-01-15 13:05:12 +00:00
]);
2017-12-09 18:31:00 +00:00
return $o ;
}
/**
* @ brief Create group sidebar widget
*
* @ param string $every
* @ param string $each
* @ param string $editmode
* 'standard' => include link 'Edit groups'
* 'extended' => include link 'Create new group'
* 'full' => include link 'Create new group' and provide for each group a link to edit this group
* @ param int $group_id
* @ param int $cid
* @ return string
*/
2018-07-09 22:36:50 +00:00
public static function sidebarWidget ( $every = 'contacts' , $each = 'group' , $editmode = 'standard' , $group_id = '' , $cid = 0 )
2017-12-09 18:31:00 +00:00
{
$o = '' ;
if ( ! local_user ()) {
return '' ;
}
$display_groups = [
[
2018-01-22 14:54:13 +00:00
'text' => L10n :: t ( 'Everybody' ),
2017-12-09 18:31:00 +00:00
'id' => 0 ,
2018-07-09 22:36:50 +00:00
'selected' => (( $group_id === 'everyone' ) ? 'group-selected' : '' ),
2017-12-09 18:31:00 +00:00
'href' => $every ,
]
];
2018-07-20 12:19:26 +00:00
$stmt = DBA :: select ( 'group' , [], [ 'deleted' => 0 , 'uid' => local_user ()], [ 'order' => [ 'name' ]]);
2017-12-09 18:31:00 +00:00
2018-01-15 13:05:12 +00:00
$member_of = [];
2017-12-09 18:31:00 +00:00
if ( $cid ) {
2017-12-16 16:50:58 +00:00
$member_of = self :: getIdsByContactId ( $cid );
2017-12-09 18:31:00 +00:00
}
2018-07-20 12:19:26 +00:00
while ( $group = DBA :: fetch ( $stmt )) {
2017-12-10 06:06:12 +00:00
$selected = (( $group_id == $group [ 'id' ]) ? ' group-selected' : '' );
2017-12-09 18:31:00 +00:00
2017-12-10 06:06:12 +00:00
if ( $editmode == 'full' ) {
$groupedit = [
'href' => 'group/' . $group [ 'id' ],
2018-01-22 14:54:13 +00:00
'title' => L10n :: t ( 'edit' ),
2017-12-09 18:31:00 +00:00
];
2017-12-10 06:06:12 +00:00
} else {
$groupedit = null ;
2017-12-09 18:31:00 +00:00
}
2017-12-10 06:06:12 +00:00
$display_groups [] = [
'id' => $group [ 'id' ],
'cid' => $cid ,
'text' => $group [ 'name' ],
'href' => $each . '/' . $group [ 'id' ],
'edit' => $groupedit ,
'selected' => $selected ,
'ismember' => in_array ( $group [ 'id' ], $member_of ),
];
2017-12-09 18:31:00 +00:00
}
$tpl = get_markup_template ( 'group_side.tpl' );
$o = replace_macros ( $tpl , [
2018-01-22 14:54:13 +00:00
'$add' => L10n :: t ( 'add' ),
'$title' => L10n :: t ( 'Groups' ),
2017-12-09 18:31:00 +00:00
'$groups' => $display_groups ,
'newgroup' => $editmode == 'extended' || $editmode == 'full' ? 1 : '' ,
'grouppage' => 'group/' ,
2018-01-22 14:54:13 +00:00
'$edittext' => L10n :: t ( 'Edit group' ),
'$ungrouped' => $every === 'contacts' ? L10n :: t ( 'Contacts not in any group' ) : '' ,
2018-07-09 22:36:50 +00:00
'$ungrouped_selected' => (( $group_id === 'none' ) ? 'group-selected' : '' ),
2018-01-22 14:54:13 +00:00
'$createtext' => L10n :: t ( 'Create a new group' ),
'$creategroup' => L10n :: t ( 'Group Name: ' ),
'$editgroupstext' => L10n :: t ( 'Edit groups' ),
2017-12-09 18:31:00 +00:00
'$form_security_token' => get_form_security_token ( 'group_edit' ),
]);
return $o ;
}
}