]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - classes/Profile.php
Event upgraded to microformats2
[quix0rs-gnu-social.git] / classes / Profile.php
index c0af2635a7d0705563eba491f15874411e3d17cd..862e8ff11a4f34acecb8c982f116672b9a4b90d3 100644 (file)
@@ -92,18 +92,42 @@ class Profile extends Managed_DataObject
         return $user->getProfile();
     } 
 
-    protected $_user = -1;  // Uninitialized value distinct from null
+    protected $_user = array();
 
     public function getUser()
     {
-        if ($this->_user === -1) {
-            $this->_user = User::getKV('id', $this->id);
+        if (!isset($this->_user[$this->id])) {
+            $user = User::getKV('id', $this->id);
+            if (!$user instanceof User) {
+                throw new NoSuchUserException(array('id'=>$this->id));
+            }
+            $this->_user[$this->id] = $user;
         }
-        if (!($this->_user instanceof User)) {
-            throw new NoSuchUserException(array('id'=>$this->id));
+        return $this->_user[$this->id];
+    }
+
+    protected $_group = array();
+
+    public function getGroup()
+    {
+        if (!isset($this->_group[$this->id])) {
+            $group = User_group::getKV('profile_id', $this->id);
+            if (!$group instanceof User_group) {
+                throw new NoSuchGroupException(array('profile_id'=>$this->id));
+            }
+            $this->_group[$this->id] = $group;
         }
+        return $this->_group[$this->id];
+    }
 
-        return $this->_user;
+    public function isGroup()
+    {
+        try {
+            $this->getGroup();
+            return true;
+        } catch (NoSuchGroupException $e) {
+            return false;
+        }
     }
 
     public function isLocal()
@@ -116,8 +140,6 @@ class Profile extends Managed_DataObject
         return true;
     }
 
-    protected $_avatars = array();
-
     public function getAvatar($width, $height=null)
     {
         return Avatar::byProfile($this, $width, $height);
@@ -135,7 +157,7 @@ class Profile extends Managed_DataObject
         $avatar->filename = $filename;
         $avatar->original = true;
         $avatar->url = Avatar::url($filename);
-        $avatar->created = DB_DataObject_Cast::dateTime(); # current time
+        $avatar->created = common_sql_now();
 
         // XXX: start a transaction here
         if (!Avatar::deleteFromProfile($this, true) || !$avatar->insert()) {
@@ -144,17 +166,6 @@ class Profile extends Managed_DataObject
             return null;
         }
 
-        foreach (array(AVATAR_PROFILE_SIZE, AVATAR_STREAM_SIZE, AVATAR_MINI_SIZE) as $size) {
-            // We don't do a scaled one if original is our scaled size
-            if (!($avatar->width == $size && $avatar->height == $size)) {
-                try {
-                    Avatar::newSize($this, $size);
-                } catch (Exception $e) {
-                    // should we abort the generation and live without smaller avatars?
-                }
-            }
-        }
-
         return $avatar;
     }
 
@@ -168,6 +179,20 @@ class Profile extends Managed_DataObject
         return ($this->fullname) ? $this->fullname : $this->nickname;
     }
 
+    /**
+     * Takes the currently scoped profile into account to give a name 
+     * to list in notice streams. Preferences may differ between profiles.
+     */
+    function getStreamName()
+    {
+        $user = common_current_user();
+        if ($user instanceof User && $user->streamNicknames()) {
+            return $this->nickname;
+        }
+
+        return $this->getBestName();
+    }
+
     /**
      * Gets the full name (if filled) with nickname as a parenthetical, or the nickname alone
      * if no fullname is provided.
@@ -199,9 +224,9 @@ class Profile extends Managed_DataObject
                 return $notice->_items[0];
             }
             return $notice;
-        } else {
-            return null;
         }
+        
+        return null;
     }
 
     function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
@@ -211,26 +236,25 @@ class Profile extends Managed_DataObject
         return $stream->getNotices($offset, $limit, $since_id, $max_id);
     }
 
-    function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
+    function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, Profile $scoped=null)
     {
-        $stream = new ProfileNoticeStream($this);
+        $stream = new ProfileNoticeStream($this, $scoped);
 
         return $stream->getNotices($offset, $limit, $since_id, $max_id);
     }
 
-    function isMember($group)
+    function isMember(User_group $group)
     {
        $groups = $this->getGroups(0, null);
-       $gs = $groups->fetchAll();
-       foreach ($gs as $g) {
-           if ($group->id == $g->id) {
+        while ($groups instanceof User_group && $groups->fetch()) {
+           if ($groups->id == $group->id) {
                return true;
            }
        }
        return false;
     }
 
-    function isAdmin($group)
+    function isAdmin(User_group $group)
     {
         $gm = Group_member::pkeyGet(array('profile_id' => $this->id,
                                           'group_id' => $group->id));
@@ -272,7 +296,18 @@ class Profile extends Managed_DataObject
             $ids = array_slice($ids, $offset, $limit);
         }
 
-        return User_group::multiGet('id', $ids);
+        try {
+            return User_group::listFind('id', $ids);
+        } catch (NoResultException $e) {
+            return null;    // throw exception when we handle it everywhere
+        }
+    }
+
+    function getGroupCount() {
+        $groups = $this->getGroups(0, null);
+        return $groups instanceof User_group
+                ? $groups->N
+                : 0;
     }
 
     function isTagged($peopletag)
@@ -549,40 +584,69 @@ class Profile extends Managed_DataObject
     function getSubscribed($offset=0, $limit=null)
     {
         $subs = Subscription::getSubscribedIDs($this->id, $offset, $limit);
-        $profiles = Profile::listFind('id', $subs);
+        try {
+            $profiles = Profile::listFind('id', $subs);
+        } catch (NoResultException $e) {
+            return $e->obj;
+        }
         return $profiles;
     }
 
     function getSubscribers($offset=0, $limit=null)
     {
         $subs = Subscription::getSubscriberIDs($this->id, $offset, $limit);
-        $profiles = Profile::listFind('id', $subs);
+        try {
+            $profiles = Profile::listFind('id', $subs);
+        } catch (NoResultException $e) {
+            return $e->obj;
+        }
         return $profiles;
     }
 
-    function getTaggedSubscribers($tag)
+    function getTaggedSubscribers($tag, $offset=0, $limit=null)
     {
         $qry =
           'SELECT profile.* ' .
-          'FROM profile JOIN (subscription, profile_tag, profile_list) ' .
+          'FROM profile JOIN subscription ' .
           'ON profile.id = subscription.subscriber ' .
-          'AND profile.id = profile_tag.tagged ' .
-          'AND profile_tag.tagger = profile_list.tagger AND profile_tag.tag = profile_list.tag ' .
+          'JOIN profile_tag ON (profile_tag.tagged = subscription.subscriber ' .
+          'AND profile_tag.tagger = subscription.subscribed) ' .
           'WHERE subscription.subscribed = %d ' .
+          "AND profile_tag.tag = '%s' " .
           'AND subscription.subscribed != subscription.subscriber ' .
-          'AND profile_tag.tagger = %d AND profile_tag.tag = "%s" ' .
-          'AND profile_list.private = false ' .
-          'ORDER BY subscription.created DESC';
+          'ORDER BY subscription.created DESC ';
+
+        if ($offset) {
+            $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+        }
 
         $profile = new Profile();
-        $tagged = array();
 
-        $cnt = $profile->query(sprintf($qry, $this->id, $this->id, $profile->escape($tag)));
+        $cnt = $profile->query(sprintf($qry, $this->id, $profile->escape($tag)));
 
-        while ($profile->fetch()) {
-            $tagged[] = clone($profile);
-        }
-        return $tagged;
+        return $profile;
+    }
+
+    function getTaggedSubscriptions($tag, $offset=0, $limit=null)
+    {
+        $qry =
+          'SELECT profile.* ' .
+          'FROM profile JOIN subscription ' .
+          'ON profile.id = subscription.subscribed ' .
+          'JOIN profile_tag on (profile_tag.tagged = subscription.subscribed ' .
+          'AND profile_tag.tagger = subscription.subscriber) ' .
+          'WHERE subscription.subscriber = %d ' .
+          "AND profile_tag.tag = '%s' " .
+          'AND subscription.subscribed != subscription.subscriber ' .
+          'ORDER BY subscription.created DESC ';
+
+        $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+
+        $profile = new Profile();
+
+        $profile->query(sprintf($qry, $this->id, $profile->escape($tag)));
+
+        return $profile;
     }
 
     /**
@@ -668,7 +732,7 @@ class Profile extends Managed_DataObject
      * @param Profile $other
      * @return boolean
      */
-    function isSubscribed($other)
+    function isSubscribed(Profile $other)
     {
         return Subscription::exists($this, $other);
     }
@@ -679,7 +743,7 @@ class Profile extends Managed_DataObject
      * @param Profile $other
      * @return boolean
      */
-    function hasPendingSubscription($other)
+    function hasPendingSubscription(Profile $other)
     {
         return Subscription_queue::exists($this, $other);
     }
@@ -690,7 +754,7 @@ class Profile extends Managed_DataObject
      * @param Profile $other
      * @return boolean
      */
-    function mutuallySubscribed($other)
+    function mutuallySubscribed(Profile $other)
     {
         return $this->isSubscribed($other) &&
           $other->isSubscribed($this);
@@ -724,6 +788,11 @@ class Profile extends Managed_DataObject
         return $cnt;
     }
 
+    function favoriteNotices($own=false, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
+    {
+        return Fave::stream($this->id, $offset, $limit, $own, $since_id, $max_id);
+    }
+
     function noticeCount()
     {
         $c = Cache::instance();
@@ -808,13 +877,41 @@ class Profile extends Managed_DataObject
         return ($biolimit > 0 && !empty($bio) && (mb_strlen($bio) > $biolimit));
     }
 
-    function delete()
+    function update($dataObject=false)
+    {
+        if (is_object($dataObject) && $this->nickname != $dataObject->nickname) {
+            try {
+                $local = $this->getUser();
+                common_debug("Updating User ({$this->id}) nickname from {$dataObject->nickname} to {$this->nickname}");
+                $origuser = clone($local);
+                $local->nickname = $this->nickname;
+                $result = $local->updateKeys($origuser);
+                if ($result === false) {
+                    common_log_db_error($local, 'UPDATE', __FILE__);
+                    // TRANS: Server error thrown when user profile settings could not be updated.
+                    throw new ServerException(_('Could not update user nickname.'));
+                }
+
+                // Clear the site owner, in case nickname changed
+                if ($local->hasRole(Profile_role::OWNER)) {
+                    User::blow('user:site_owner');
+                }
+            } catch (NoSuchUserException $e) {
+                // Nevermind...
+            }
+        }
+
+        return parent::update($dataObject);
+    }
+
+    function delete($useWhere=false)
     {
         $this->_deleteNotices();
         $this->_deleteSubscriptions();
         $this->_deleteMessages();
         $this->_deleteTags();
         $this->_deleteBlocks();
+        $this->_deleteAttentions();
         Avatar::deleteFromProfile($this, true);
 
         // Warning: delete() will run on the batch objects,
@@ -830,7 +927,7 @@ class Profile extends Managed_DataObject
             $inst->delete();
         }
 
-        parent::delete();
+        return parent::delete($useWhere);
     }
 
     function _deleteNotices()
@@ -916,6 +1013,20 @@ class Profile extends Managed_DataObject
         $block->delete();
     }
 
+    function _deleteAttentions()
+    {
+        $att = new Attention();
+        $att->profile_id = $this->getID();
+
+        if ($att->find()) {
+            while ($att->fetch()) {
+                // Can't do delete() on the object directly since it won't remove all of it
+                $other = clone($att);
+                $other->delete();
+            }
+        }
+    }
+
     // XXX: identical to Notice::getLocation.
 
     public function getLocation()
@@ -1091,7 +1202,7 @@ class Profile extends Managed_DataObject
      * @param $right string Name of the right, usually a constant in class Right
      * @return boolean whether the user has the right in question
      */
-    function hasRight($right)
+    public function hasRight($right)
     {
         $result = false;
 
@@ -1157,12 +1268,13 @@ class Profile extends Managed_DataObject
         return $result;
     }
 
-    function hasRepeated($notice_id)
+    // FIXME: Can't put Notice typing here due to ArrayWrapper
+    public function hasRepeated($notice)
     {
         // XXX: not really a pkey, but should work
 
         $notice = Notice::pkeyGet(array('profile_id' => $this->id,
-                                        'repeat_of' => $notice_id));
+                                        'repeat_of' => $notice->id));
 
         return !empty($notice);
     }
@@ -1264,6 +1376,11 @@ class Profile extends Managed_DataObject
         return $this->profileurl;
     }
 
+    public function getNickname()
+    {
+        return $this->nickname;
+    }
+
     /**
      * Returns the best URI for a profile. Plugins may override.
      *
@@ -1278,9 +1395,8 @@ class Profile extends Managed_DataObject
 
             // check for a local user first
             $user = User::getKV('id', $this->id);
-
-            if (!empty($user)) {
-                $uri = $user->uri;
+            if ($user instanceof User) {
+                $uri = $user->getUri();
             }
 
             Event::handle('EndGetProfileUri', array($this, &$uri));
@@ -1289,6 +1405,26 @@ class Profile extends Managed_DataObject
         return $uri;
     }
 
+    /**
+     * Returns an assumed acct: URI for a profile. Plugins are required.
+     *
+     * @return string $uri
+     */
+    public function getAcctUri()
+    {
+        $acct = null;
+
+        if (Event::handle('StartGetProfileAcctUri', array($this, &$acct))) {
+            Event::handle('EndGetProfileAcctUri', array($this, &$acct));
+        }
+
+        if ($acct === null) {
+            throw new ProfileNoAcctUriException($this);
+        }
+
+        return $acct;
+    }
+
     function hasBlocked($other)
     {
         $block = Profile_block::exists($this, $other);
@@ -1311,19 +1447,29 @@ class Profile extends Managed_DataObject
         return $feed;
     }
 
-    static function fromURI($uri)
+    /*
+     * Get a Profile object by URI. Will call external plugins for help
+     * using the event StartGetProfileFromURI.
+     *
+     * @param string $uri A unique identifier for a resource (profile/group/whatever)
+     */
+    static function fromUri($uri)
     {
         $profile = null;
 
         if (Event::handle('StartGetProfileFromURI', array($uri, &$profile))) {
-            // Get a local user or remote (OMB 0.1) profile
+            // Get a local user when plugin lookup (like OStatus) fails
             $user = User::getKV('uri', $uri);
-            if (!empty($user)) {
+            if ($user instanceof User) {
                 $profile = $user->getProfile();
             }
             Event::handle('EndGetProfileFromURI', array($uri, $profile));
         }
 
+        if (!$profile instanceof Profile) {
+            throw new UnknownUriException($uri);
+        }
+
         return $profile;
     }
 
@@ -1391,7 +1537,7 @@ class Profile extends Managed_DataObject
     function __sleep()
     {
         $vars = parent::__sleep();
-        $skip = array('_user', '_avatars');
+        $skip = array('_user', '_group');
         return array_diff($vars, $skip);
     }
 
@@ -1399,4 +1545,20 @@ class Profile extends Managed_DataObject
     {
         return $this;
     }
+
+    /**
+     * This will perform shortenLinks with the connected User object.
+     *
+     * Won't work on remote profiles or groups, so expect a
+     * NoSuchUserException if you don't know it's a local User.
+     *
+     * @param string $text      String to shorten
+     * @param boolean $always   Disrespect minimum length etc.
+     *
+     * @return string link-shortened $text
+     */
+    public function shortenLinks($text, $always=false)
+    {
+        return $this->getUser()->shortenLinks($text, $always);
+    }
 }