123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888 |
- <?php
- defined('GNUSOCIAL') || die();
- class User_group extends Managed_DataObject
- {
- const JOIN_POLICY_OPEN = 0;
- const JOIN_POLICY_MODERATE = 1;
- const CACHE_WINDOW = 201;
-
-
- public $__table = 'user_group';
- public $id;
- public $profile_id;
- public $nickname;
- public $fullname;
- public $homepage;
- public $description;
- public $location;
- public $original_logo;
- public $homepage_logo;
- public $stream_logo;
- public $mini_logo;
- public $created;
- public $modified;
- public $uri;
- public $mainpage;
- public $join_policy;
- public $force_scope;
-
-
- public function getObjectType()
- {
- return ActivityObject::GROUP;
- }
- public static function schemaDef()
- {
- return array(
- 'fields' => array(
- 'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
- 'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
- 'nickname' => array('type' => 'varchar', 'length' => 64, 'description' => 'nickname for addressing'),
- 'fullname' => array('type' => 'varchar', 'length' => 191, 'description' => 'display name'),
- 'homepage' => array('type' => 'varchar', 'length' => 191, 'description' => 'URL, cached so we dont regenerate'),
- 'description' => array('type' => 'text', 'description' => 'group description'),
- 'location' => array('type' => 'varchar', 'length' => 191, 'description' => 'related physical location, if any'),
- 'original_logo' => array('type' => 'varchar', 'length' => 191, 'description' => 'original size logo'),
- 'homepage_logo' => array('type' => 'varchar', 'length' => 191, 'description' => 'homepage (profile) size logo'),
- 'stream_logo' => array('type' => 'varchar', 'length' => 191, 'description' => 'stream-sized logo'),
- 'mini_logo' => array('type' => 'varchar', 'length' => 191, 'description' => 'mini logo'),
- 'created' => array('type' => 'datetime', 'description' => 'date this record was created'),
- 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
- 'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universal identifier'),
- 'mainpage' => array('type' => 'varchar', 'length' => 191, 'description' => 'page for group info to link to'),
- 'join_policy' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=open; 1=requires admin approval'),
- 'force_scope' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=never,1=sometimes,-1=always'),
- ),
- 'primary key' => array('id'),
- 'unique keys' => array(
- 'user_group_uri_key' => array('uri'),
- ),
- 'foreign keys' => array(
- 'user_group_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
- ),
- 'indexes' => array(
- 'user_group_nickname_idx' => array('nickname'),
- 'user_group_created_id_idx' => array('created', 'id'),
- 'user_group_profile_id_idx' => array('profile_id'),
- ),
- );
- }
- protected $_profile = array();
-
- public function getProfile()
- {
- if (!isset($this->_profile[$this->profile_id])) {
- $profile = Profile::getKV('id', $this->profile_id);
- if (!$profile instanceof Profile) {
- throw new GroupNoProfileException($this);
- }
- $this->_profile[$this->profile_id] = $profile;
- }
- return $this->_profile[$this->profile_id];
- }
- public function getNickname()
- {
- return $this->getProfile()->getNickname();
- }
- public function getFullname()
- {
- return $this->getProfile()->getFullname();
- }
- public static function defaultLogo($size)
- {
- static $sizenames = array(AVATAR_PROFILE_SIZE => 'profile',
- AVATAR_STREAM_SIZE => 'stream',
- AVATAR_MINI_SIZE => 'mini');
- return Theme::path('default-avatar-'.$sizenames[$size].'.png');
- }
- public function homeUrl()
- {
- return $this->getProfile()->getUrl();
- }
- public function getUri()
- {
- $uri = null;
- if (Event::handle('StartUserGroupGetUri', array($this, &$uri))) {
- if (!empty($this->uri)) {
- $uri = $this->uri;
- } elseif ($this->isLocal()) {
- $uri = common_local_url('groupbyid', ['id' => $this->id]);
- }
- }
- Event::handle('EndUserGroupGetUri', array($this, &$uri));
- return $uri;
- }
- public function permalink()
- {
- $url = null;
- if (Event::handle('StartUserGroupPermalink', array($this, &$url))) {
- if ($this->isLocal()) {
- $url = common_local_url('groupbyid', ['id' => $this->id]);
- }
- }
- Event::handle('EndUserGroupPermalink', array($this, &$url));
- return $url;
- }
- public function getNotices($offset, $limit, $since_id = null, $max_id = null)
- {
-
-
- $stream = new GroupNoticeStream($this, Profile::current());
- return $stream->getNotices($offset, $limit, $since_id, $max_id);
- }
- public function getMembers($offset = 0, $limit = null)
- {
- $ids = null;
- if (is_null($limit) || $offset + $limit > User_group::CACHE_WINDOW) {
- $ids = $this->getMemberIDs($offset, $limit);
- } else {
- $key = sprintf('group:member_ids:%d', $this->id);
- $window = self::cacheGet($key);
- if ($window === false) {
- $window = $this->getMemberIDs(0, User_group::CACHE_WINDOW);
- self::cacheSet($key, $window);
- }
- $ids = array_slice($window, $offset, $limit);
- }
- return Profile::multiGet('id', $ids);
- }
- public function getMemberIDs($offset = 0, $limit = null)
- {
- $gm = new Group_member();
- $gm->selectAdd();
- $gm->selectAdd('profile_id');
- $gm->group_id = $this->id;
- $gm->orderBy('created DESC, profile_id DESC');
- if (!is_null($limit)) {
- $gm->limit($offset, $limit);
- }
- $ids = array();
- if ($gm->find()) {
- while ($gm->fetch()) {
- $ids[] = $gm->profile_id;
- }
- }
- return $ids;
- }
-
- public function getRequests($offset = 0, $limit = null)
- {
- $rq = new Group_join_queue();
- $rq->group_id = $this->id;
- $members = new Profile();
- $members->joinAdd(['id', $rq, 'profile_id']);
- if ($limit != null) {
- $members->limit($offset, $limit);
- }
- $members->find();
- return $members;
- }
- public function getAdminCount()
- {
- $block = new Group_member();
- $block->group_id = $this->id;
- $block->is_admin = true;
- return $block->count();
- }
- public function getMemberCount()
- {
- $key = sprintf("group:member_count:%d", $this->id);
- $cnt = self::cacheGet($key);
- if (is_integer($cnt)) {
- return (int) $cnt;
- }
- $mem = new Group_member();
- $mem->group_id = $this->id;
-
- $cnt = (int) $mem->count('distinct profile_id');
- self::cacheSet($key, $cnt);
- return $cnt;
- }
- public function getBlockedCount()
- {
-
- $block = new Group_block();
- $block->group_id = $this->id;
- return $block->count();
- }
- public function getQueueCount()
- {
-
- $queue = new Group_join_queue();
- $queue->group_id = $this->id;
- return $queue->count();
- }
-
- public function getAdmins($offset = null, $limit = null)
- {
- $admins = new Profile();
- $admins->joinAdd(['id', 'group_member:profile_id']);
- $admins->whereAdd(sprintf(
- 'group_member.group_id = %d AND group_member.is_admin IS TRUE',
- $this->getID()
- ));
- $admins->orderBy('group_member.modified, group_member.profile_id');
- $admins->limit($offset, $limit);
- $admins->find();
- return $admins;
- }
-
- public function getBlocked($offset = null, $limit = null)
- {
- $blocked = new Profile();
- $blocked->joinAdd(array('id', 'group_block:blocked'));
- $blocked->whereAdd(sprintf('group_block.group_id = %u', $this->id));
- $blocked->orderBy('group_block.modified DESC, group_block.blocked DESC');
- $blocked->limit($offset, $limit);
- $blocked->find();
- return $blocked;
- }
- public function setOriginal($filename)
- {
-
- $imagefile = new ImageFile(null, Avatar::path($filename));
- $sizes = array('homepage_logo' => AVATAR_PROFILE_SIZE,
- 'stream_logo' => AVATAR_STREAM_SIZE,
- 'mini_logo' => AVATAR_MINI_SIZE);
- $orig = clone($this);
- $this->original_logo = Avatar::url($filename);
- foreach ($sizes as $name=>$size) {
- $filename = Avatar::filename(
- $this->profile_id,
- image_type_to_extension($imagefile->preferredType()),
- $size,
- common_timestamp()
- );
- $imagefile->resizeTo(Avatar::path($filename), array('width'=>$size, 'height'=>$size));
- $this->$name = Avatar::url($filename);
- }
- common_debug(common_log_objstring($this));
- return $this->update($orig);
- }
- public function getBestName()
- {
- return ($this->fullname) ? $this->fullname : $this->nickname;
- }
-
- public function getFancyName()
- {
- if ($this->fullname) {
-
- return sprintf(_m('FANCYNAME', '%1$s (%2$s)'), $this->fullname, $this->nickname);
- } else {
- return $this->nickname;
- }
- }
- public function getAliases()
- {
- $aliases = array();
-
- $alias = new Group_alias();
- $alias->group_id = $this->id;
- if ($alias->find()) {
- while ($alias->fetch()) {
- $aliases[] = $alias->alias;
- }
- }
- $alias->free();
- return $aliases;
- }
- public function setAliases($newaliases)
- {
- $newaliases = array_unique($newaliases);
- $oldaliases = $this->getAliases();
-
- $to_delete = array_diff($oldaliases, $newaliases);
-
- $to_insert = array_diff($newaliases, $oldaliases);
- $alias = new Group_alias();
- $alias->group_id = $this->id;
- foreach ($to_delete as $delalias) {
- $alias->alias = $delalias;
- $result = $alias->delete();
- if (!$result) {
- common_log_db_error($alias, 'DELETE', __FILE__);
- return false;
- }
- }
- foreach ($to_insert as $insalias) {
- if ($insalias === $this->nickname) {
- continue;
- }
- $alias->alias = Nickname::normalize($insalias, true);
- $result = $alias->insert();
- if (!$result) {
- common_log_db_error($alias, 'INSERT', __FILE__);
- return false;
- }
- }
- return true;
- }
- public static function getForNickname($nickname, Profile $profile = null)
- {
- $nickname = Nickname::normalize($nickname);
-
- if ($profile instanceof Profile) {
- $group = $profile->getGroups(0, null);
- while ($group instanceof User_group && $group->fetch()) {
- if ($group->nickname == $nickname) {
-
- return clone($group);
- }
- }
- }
-
- $group = Local_group::getKV('nickname', $nickname);
- if ($group instanceof Local_group) {
- return User_group::getKV('id', $group->group_id);
- }
- $alias = Group_alias::getKV('alias', $nickname);
- if ($alias instanceof Group_alias) {
- return User_group::getKV('id', $alias->group_id);
- }
- return null;
- }
- public function getUserMembers()
- {
-
- $user = new User();
- $user->query(sprintf(
- 'SELECT id FROM %1$s INNER JOIN group_member ' .
- 'ON %1$s.id = group_member.profile_id ' .
- 'WHERE group_member.group_id = %2$d ',
- $user->escapedTableName(),
- $this->id
- ));
- $ids = [];
- while ($user->fetch()) {
- $ids[] = $user->id;
- }
- $user->free();
- return $ids;
- }
- public static function maxDescription()
- {
- $desclimit = common_config('group', 'desclimit');
-
- if (is_null($desclimit)) {
- $desclimit = common_config('site', 'textlimit');
- }
- return $desclimit;
- }
- public static function descriptionTooLong($desc)
- {
- $desclimit = self::maxDescription();
- return ($desclimit > 0 && !empty($desc) && (mb_strlen($desc) > $desclimit));
- }
- public function asAtomEntry($namespace = false, $source = false)
- {
- $xs = new XMLStringer(true);
- if ($namespace) {
- $attrs = array('xmlns' => 'http://www.w3.org/2005/Atom',
- 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0');
- } else {
- $attrs = array();
- }
- $xs->elementStart('entry', $attrs);
- if ($source) {
- $xs->elementStart('source');
- $xs->element('id', null, $this->permalink());
- $xs->element('title', null, $profile->nickname . " - " . common_config('site', 'name'));
- $xs->element('link', array('href' => $this->permalink()));
- $xs->element('updated', null, $this->modified);
- $xs->elementEnd('source');
- }
- $xs->element('title', null, $this->nickname);
- $xs->element('summary', null, common_xml_safe_str($this->description));
- $xs->element('link', array('rel' => 'alternate',
- 'href' => $this->permalink()));
- $xs->element('id', null, $this->permalink());
- $xs->element('published', null, common_date_w3dtf($this->created));
- $xs->element('updated', null, common_date_w3dtf($this->modified));
- $xs->element(
- 'content',
- array('type' => 'html'),
- common_xml_safe_str($this->description)
- );
- $xs->elementEnd('entry');
- return $xs->getString();
- }
- public function asAtomAuthor()
- {
- $xs = new XMLStringer(true);
- $xs->elementStart('author');
- $xs->element('name', null, $this->nickname);
- $xs->element('uri', null, $this->permalink());
- $xs->elementEnd('author');
- return $xs->getString();
- }
-
- public function asActivityNoun($element)
- {
- $noun = ActivityObject::fromGroup($this);
- return $noun->asString('activity:' . $element);
- }
- public function getAvatar()
- {
- return empty($this->homepage_logo)
- ? User_group::defaultLogo(AVATAR_PROFILE_SIZE)
- : $this->homepage_logo;
- }
- public static function register($fields)
- {
- if (!empty($fields['userid'])) {
- $profile = Profile::getKV('id', $fields['userid']);
- if ($profile && !$profile->hasRight(Right::CREATEGROUP)) {
- common_log(LOG_WARNING, "Attempted group creation from banned user: " . $profile->nickname);
-
- throw new ClientException(_('You are not allowed to create groups on this site.'), 403);
- }
- }
- $fields['nickname'] = Nickname::normalize($fields['nickname']);
-
-
- $defaults = [
- 'nickname' => null,
- 'fullname' => null,
- 'homepage' => null,
- 'description' => null,
- 'location' => null,
- 'uri' => null,
- 'mainpage' => null,
- 'aliases' => [],
- 'userid' => null,
- ];
- $fields = array_merge($defaults, $fields);
- extract($fields);
- $group = new User_group();
- if (empty($uri)) {
-
- $uri = null;
- }
- if (empty($mainpage)) {
- $mainpage = common_local_url('showgroup', array('nickname' => $nickname));
- }
-
- $profile = new Profile();
- $profile->nickname = $nickname;
- $profile->fullname = $fullname;
- $profile->profileurl = $mainpage;
- $profile->homepage = $homepage;
- $profile->bio = $description;
- $profile->location = $location;
- $profile->created = common_sql_now();
- $group->nickname = $profile->nickname;
- $group->fullname = $profile->fullname;
- $group->homepage = $profile->homepage;
- $group->description = $profile->bio;
- $group->location = $profile->location;
- $group->mainpage = $profile->profileurl;
- $group->created = $profile->created;
- $profile->query('START TRANSACTION');
- $id = $profile->insert();
- if ($id === false) {
- $profile->query('ROLLBACK');
- throw new ServerException(_('Profile insertion failed'));
- }
- $group->profile_id = $id;
- $group->uri = $uri;
- if (isset($fields['join_policy'])) {
- $group->join_policy = intval($fields['join_policy']);
- } else {
- $group->join_policy = 0;
- }
- if (isset($fields['force_scope'])) {
- $group->force_scope = intval($fields['force_scope']);
- } else {
- $group->force_scope = 0;
- }
- if (Event::handle('StartGroupSave', array(&$group))) {
- $result = $group->insert();
- if ($result === false) {
- common_log_db_error($group, 'INSERT', __FILE__);
-
- throw new ServerException(_('Could not create group.'));
- }
- if (!isset($uri) || empty($uri)) {
- $orig = clone($group);
- $group->uri = common_local_url('groupbyid', array('id' => $group->id));
- $result = $group->update($orig);
- if (!$result) {
- common_log_db_error($group, 'UPDATE', __FILE__);
-
- throw new ServerException(_('Could not set group URI.'));
- }
- }
- $result = $group->setAliases($aliases);
- if (!$result) {
-
- throw new ServerException(_('Could not create aliases.'));
- }
- $member = new Group_member();
- $member->group_id = $group->id;
- $member->profile_id = $userid;
- $member->is_admin = true;
- $member->created = $group->created;
- $result = $member->insert();
- if (!$result) {
- common_log_db_error($member, 'INSERT', __FILE__);
-
- throw new ServerException(_('Could not set group membership.'));
- }
- self::blow('profile:groups:%d', $userid);
-
- if ($local) {
- $local_group = new Local_group();
- $local_group->group_id = $group->id;
- $local_group->nickname = $nickname;
- $local_group->created = common_sql_now();
- $result = $local_group->insert();
- if (!$result) {
- common_log_db_error($local_group, 'INSERT', __FILE__);
-
- throw new ServerException(_('Could not save local group info.'));
- }
- }
- Event::handle('EndGroupSave', array($group));
- }
- $profile->query('COMMIT');
- return $group;
- }
-
- public function delete($useWhere = false)
- {
- if (empty($this->id)) {
- common_log(LOG_WARNING, "Ambiguous User_group->delete(); skipping related tables.");
- return parent::delete($useWhere);
- }
-
- $related = array('Group_inbox',
- 'Group_block',
- 'Group_member',
- 'Related_group');
- Event::handle('UserGroupDeleteRelated', array($this, &$related));
- foreach ($related as $cls) {
- $inst = new $cls();
- $inst->group_id = $this->id;
- if ($inst->find()) {
- while ($inst->fetch()) {
- $dup = clone($inst);
- $dup->delete();
- }
- }
- }
-
- $inst = new Related_group();
- $inst->related_group_id = $this->id;
- $inst->delete();
-
-
-
- $this->setAliases(array());
-
- $local = Local_group::getKV('group_id', $this->id);
- if ($local instanceof Local_group) {
- $local->delete();
- }
- $result = parent::delete($useWhere);
- try {
- $profile = $this->getProfile();
- $profile->delete();
- } catch (GroupNoProfileException $unp) {
- common_log(
- LOG_INFO,
- "Group {$this->nickname} has no profile; continuing deletion."
- );
- }
-
- self::blow('user_group:notice_ids:%d', $this->id);
- return $result;
- }
- public function update($dataObject=false)
- {
-
-
- if ($this->nickname != $dataObject->nickname) {
- $local = Local_group::getKV('group_id', $this->id);
- if ($local instanceof Local_group) {
- common_debug("Updating Local_group ({$this->id}) nickname from {$dataObject->nickname} to {$this->nickname}");
- $local->setNickname($this->nickname);
- }
- }
-
- $fields = array(
- 'nickname' => 'nickname',
- 'fullname' => 'fullname',
- 'mainpage' => 'profileurl',
- 'homepage' => 'homepage',
- 'description' => 'bio',
- 'location' => 'location',
- 'created' => 'created',
- 'modified' => 'modified',
- );
- $profile = $this->getProfile();
- $origpro = clone($profile);
- foreach ($fields as $gf=>$pf) {
- $profile->$pf = $this->$gf;
- }
- if ($profile->update($origpro) === false) {
- throw new ServerException(_('Unable to update profile'));
- }
- return parent::update($dataObject);
- }
- public function isPrivate()
- {
- return ($this->join_policy == self::JOIN_POLICY_MODERATE &&
- intval($this->force_scope) === 1);
- }
- public function isLocal()
- {
- $local = Local_group::getKV('group_id', $this->id);
- return ($local instanceof Local_group);
- }
- public static function groupsFromText($text, Profile $profile)
- {
- $groups = array();
-
- $count = preg_match_all(
- '/(?:^|\s)!(' . Nickname::DISPLAY_FMT . ')/',
- strtolower($text),
- $match
- );
- if (!$count) {
- return $groups;
- }
- foreach (array_unique($match[1]) as $nickname) {
- $group = self::getForNickname($nickname, $profile);
- if ($group instanceof User_group && $profile->isMember($group)) {
- $groups[] = clone($group);
- }
- }
- return $groups;
- }
- public static function idsFromText($text, Profile $profile)
- {
- $ids = array();
- $groups = self::groupsFromText($text, $profile);
- foreach ($groups as $group) {
- $ids[$group->id] = true;
- }
- return array_keys($ids);
- }
- }
|