]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - lib/util.php
Do proper Activity-plugin based mention notification
[quix0rs-gnu-social.git] / lib / util.php
index 5f6f03295868f2ca8c7cd1851fa7f53f48c58996..dd4be87849510dd7027e1d992ae05b8445c7a39b 100644 (file)
@@ -244,13 +244,11 @@ function common_check_user($nickname, $password)
             $user = User::getKV('nickname', Nickname::normalize($nickname));
         }
 
-        if (!empty($user)) {
-            if (!empty($password)) { // never allow login with blank password
-                if (0 == strcmp(common_munge_password($password, $user->id),
-                                $user->password)) {
-                    //internal checking passed
-                    $authenticatedUser = $user;
-                }
+        if ($user instanceof User && !empty($password)) {
+            if (0 == strcmp(common_munge_password($password, $user->id),
+                            $user->password)) {
+                //internal checking passed
+                $authenticatedUser = $user;
             }
         }
         Event::handle('EndCheckPassword', array($nickname, $password, $authenticatedUser));
@@ -320,7 +318,7 @@ function common_set_user($user)
     } else if (is_string($user)) {
         $nickname = $user;
         $user = User::getKV('nickname', $nickname);
-    } else if (!($user instanceof User)) {
+    } else if (!$user instanceof User) {
         return false;
     }
 
@@ -433,7 +431,7 @@ function common_remembered_user()
 
     $user = User::getKV('id', $rm->user_id);
 
-    if (!$user) {
+    if (!$user instanceof User) {
         common_log(LOG_WARNING, 'No such user for rememberme: ' . $rm->user_id);
         common_forgetme();
         return null;
@@ -488,8 +486,8 @@ function common_current_user()
             common_ensure_session();
             $id = isset($_SESSION['userid']) ? $_SESSION['userid'] : false;
             if ($id) {
-                $user = User::getKV($id);
-                if ($user) {
+                $user = User::getKV('id', $id);
+                if ($user instanceof User) {
                        $_cur = $user;
                        return $_cur;
                 }
@@ -584,13 +582,10 @@ function common_canonical_email($email)
  * @param Notice $notice in whose context we're working
  * @return string partially rendered HTML
  */
-function common_render_content($text, $notice)
+function common_render_content($text, Notice $notice)
 {
     $r = common_render_text($text);
-    $id = $notice->profile_id;
     $r = common_linkify_mentions($r, $notice);
-    $r = preg_replace_callback('/(^|[\s\.\,\:\;]+)!(' . Nickname::DISPLAY_FMT . ')/',
-                      function ($m) { return "{$m[1]}!".common_group_link($id, $m[2]); }, $r);
     return $r;
 }
 
@@ -640,17 +635,13 @@ function common_linkify_mention($mention)
         $xs = new XMLStringer(false);
 
         $attrs = array('href' => $mention['url'],
-                       'class' => 'url');
+                       'class' => 'h-card '.$mention['type']);
 
         if (!empty($mention['title'])) {
             $attrs['title'] = $mention['title'];
         }
 
-        $xs->elementStart('span', 'vcard');
-        $xs->elementStart('a', $attrs);
-        $xs->element('span', 'fn nickname mention', $mention['text']);
-        $xs->elementEnd('a');
-        $xs->elementEnd('span');
+        $xs->element('a', $attrs, $mention['text']);
 
         $output = $xs->getString();
 
@@ -677,35 +668,41 @@ function common_linkify_mention($mention)
  */
 function common_find_mentions($text, $notice)
 {
-    $mentions = array();
-
-    $sender = Profile::getKV('id', $notice->profile_id);
-
-    if (empty($sender)) {
-        return $mentions;
+    try {
+        $sender = Profile::getKV('id', $notice->profile_id);
+    } catch (NoProfileException $e) {
+        return array();
     }
 
+    $mentions = array();
+
     if (Event::handle('StartFindMentions', array($sender, $text, &$mentions))) {
         // Get the context of the original notice, if any
-        $originalAuthor   = null;
-        $originalNotice   = null;
-        $originalMentions = array();
+        $origAuthor   = null;
+        $origNotice   = null;
+        $origMentions = array();
 
         // Is it a reply?
 
-        if (!empty($notice) && !empty($notice->reply_to)) {
-            $originalNotice = Notice::getKV('id', $notice->reply_to);
-            if (!empty($originalNotice)) {
-                $originalAuthor = Profile::getKV('id', $originalNotice->profile_id);
+        if ($notice instanceof Notice) {
+            try {
+                $origNotice = $notice->getParent();
+                $origAuthor = $origNotice->getProfile();
 
-                $ids = $originalNotice->getReplies();
+                $ids = $origNotice->getReplies();
 
                 foreach ($ids as $id) {
                     $repliedTo = Profile::getKV('id', $id);
-                    if (!empty($repliedTo)) {
-                        $originalMentions[$repliedTo->nickname] = $repliedTo;
+                    if ($repliedTo instanceof Profile) {
+                        $origMentions[$repliedTo->nickname] = $repliedTo;
                     }
                 }
+            } catch (NoProfileException $e) {
+                common_log(LOG_WARNING, sprintf('Notice %d author profile id %d does not exist', $origNotice->id, $origNotice->profile_id));
+            } catch (ServerException $e) {
+                // Probably just no parent. Should get a specific NoParentException
+            } catch (Exception $e) {
+                common_log(LOG_WARNING, __METHOD__ . ' got exception ' . get_class($e) . ' : ' . $e->getMessage());
             }
         }
 
@@ -723,25 +720,26 @@ function common_find_mentions($text, $notice)
             // Start with conversation context, then go to
             // sender context.
 
-            if (!empty($originalAuthor) && $originalAuthor->nickname == $nickname) {
-                $mentioned = $originalAuthor;
-            } else if (!empty($originalMentions) &&
-                       array_key_exists($nickname, $originalMentions)) {
-                $mentioned = $originalMentions[$nickname];
+            if ($origAuthor instanceof Profile && $origAuthor->nickname == $nickname) {
+                $mentioned = $origAuthor;
+            } else if (!empty($origMentions) &&
+                       array_key_exists($nickname, $origMentions)) {
+                $mentioned = $origMentions[$nickname];
             } else {
                 $mentioned = common_relative_profile($sender, $nickname);
             }
 
-            if (!empty($mentioned)) {
+            if ($mentioned instanceof Profile) {
                 $user = User::getKV('id', $mentioned->id);
 
-                if ($user) {
+                if ($user instanceof User) {
                     $url = common_local_url('userbyid', array('id' => $user->id));
                 } else {
                     $url = $mentioned->profileurl;
                 }
 
                 $mention = array('mentioned' => array($mentioned),
+                                 'type' => 'mention',
                                  'text' => $match[0],
                                  'position' => $match[1],
                                  'url' => $url);
@@ -757,26 +755,44 @@ function common_find_mentions($text, $notice)
         // @#tag => mention of all subscriptions tagged 'tag'
 
         preg_match_all('/(?:^|[\s\.\,\:\;]+)@#([\pL\pN_\-\.]{1,64})/',
-                       $text,
-                       $hmatches,
-                       PREG_OFFSET_CAPTURE);
-
+                       $text, $hmatches, PREG_OFFSET_CAPTURE);
         foreach ($hmatches[1] as $hmatch) {
-
             $tag = common_canonical_tag($hmatch[0]);
             $plist = Profile_list::getByTaggerAndTag($sender->id, $tag);
-            if (!empty($plist) && !$plist->private) {
-                $tagged = $sender->getTaggedSubscribers($tag);
+            if (!$plist instanceof Profile_list || $plist->private) {
+                continue;
+            }
+            $tagged = $sender->getTaggedSubscribers($tag);
 
-                $url = common_local_url('showprofiletag',
-                                        array('tagger' => $sender->nickname,
-                                              'tag' => $tag));
+            $url = common_local_url('showprofiletag',
+                                    array('tagger' => $sender->nickname,
+                                          'tag' => $tag));
+
+            $mentions[] = array('mentioned' => $tagged,
+                                'type'      => 'list',
+                                'text' => $hmatch[0],
+                                'position' => $hmatch[1],
+                                'url' => $url);
+        }
 
-                $mentions[] = array('mentioned' => $tagged,
-                                    'text' => $hmatch[0],
-                                    'position' => $hmatch[1],
-                                    'url' => $url);
+        preg_match_all('/(?:^|[\s\.\,\:\;]+)!(' . Nickname::DISPLAY_FMT . ')/',
+                       $text, $hmatches, PREG_OFFSET_CAPTURE);
+        foreach ($hmatches[1] as $hmatch) {
+            $nickname = Nickname::normalize($hmatch[0]);
+            $group = User_group::getForNickname($nickname, $sender);
+
+            if (!$group instanceof User_group || !$sender->isMember($group)) {
+                continue;
             }
+
+            $profile = $group->getProfile();
+
+            $mentions[] = array('mentioned' => array($profile),
+                                'type'      => 'group',
+                                'text'      => $hmatch[0],
+                                'position'  => $hmatch[1],
+                                'url'       => $group->permalink(),
+                                'title'     => $group->getFancyName());
         }
 
         Event::handle('EndFindMentions', array($sender, $text, &$mentions));
@@ -812,7 +828,7 @@ function common_find_mentions_raw($text)
 
 function common_render_text($text)
 {
-    $r = htmlspecialchars($text);
+    $r = nl2br(htmlspecialchars($text));
 
     $r = preg_replace('/[\x{0}-\x{8}\x{b}-\x{c}\x{e}-\x{19}]/', '', $r);
     $r = common_replace_urls_callback($r, 'common_linkify');
@@ -931,24 +947,7 @@ function callback_helper($matches, $callback, $arg=null) {
     return substr($matches[0],0,$left) . $result . substr($matches[0],$right);
 }
 
-if (version_compare(PHP_VERSION, '5.3.0', 'ge')) {
-    // lambda implementation in a separate file; PHP 5.2 won't parse it.
-    require_once INSTALLDIR . "/lib/curry.php";
-} else {
-    function curry($fn) {
-        $args = func_get_args();
-        array_shift($args);
-        $id = uniqid('_partial');
-        $GLOBALS[$id] = array($fn, $args);
-        return create_function('',
-                               '$args = func_get_args(); '.
-                               'return call_user_func_array('.
-                               '$GLOBALS["'.$id.'"][0],'.
-                               'array_merge('.
-                               '$args,'.
-                               '$GLOBALS["'.$id.'"][1]));');
-    }
-}
+require_once INSTALLDIR . "/lib/curry.php";
 
 function common_linkify($url) {
     // It comes in special'd, so we unspecial it before passing to the stringifying
@@ -986,22 +985,27 @@ function common_linkify($url) {
 
     $f = File::getKV('url', $longurl);
 
-    if (empty($f)) {
+    if (!$f instanceof File) {
         if (common_config('attachments', 'process_links')) {
             // XXX: this writes to the database. :<
-            $f = File::processNew($longurl);
+            try {
+                $f = File::processNew($longurl);
+            } catch (ServerException $e) {
+                $f = null;
+            }
         }
     }
 
-    if (!empty($f)) {
-        if ($f->getEnclosure()) {
+    if ($f instanceof File) {
+        try {
+            $enclosure = $f->getEnclosure();
             $is_attachment = true;
             $attachment_id = $f->id;
 
             $thumb = File_thumbnail::getKV('file_id', $f->id);
-            if (!empty($thumb)) {
-                $has_thumb = true;
-            }
+            $has_thumb = ($thumb instanceof File_thumbnail);
+        } catch (ServerException $e) {
+            // There was not enough metadata available
         }
     }
 
@@ -1146,35 +1150,6 @@ function common_valid_profile_tag($str)
     return preg_match('/^[A-Za-z0-9_\-\.]{1,64}$/', $str);
 }
 
-/**
- *
- * @param <type> $sender_id
- * @param <type> $nickname
- * @return <type>
- * @access private
- */
-function common_group_link($sender_id, $nickname)
-{
-    $sender = Profile::getKV($sender_id);
-    $group = User_group::getForNickname($nickname, $sender);
-    if ($sender && $group && $sender->isMember($group)) {
-        $attrs = array('href' => $group->permalink(),
-                       'class' => 'url');
-        if (!empty($group->fullname)) {
-            $attrs['title'] = $group->getFancyName();
-        }
-        $xs = new XMLStringer();
-        $xs->elementStart('span', 'vcard');
-        $xs->elementStart('a', $attrs);
-        $xs->element('span', 'fn nickname group', $nickname);
-        $xs->elementEnd('a');
-        $xs->elementEnd('span');
-        return $xs->getString();
-    } else {
-        return $nickname;
-    }
-}
-
 /**
  * Resolve an ambiguous profile nickname reference, checking in following order:
  * - profiles that $sender subscribes to
@@ -1222,10 +1197,10 @@ function common_relative_profile($sender, $nickname, $dt=null)
         return $recipient;
     }
     // If this is a local user, try to find a local user with that nickname.
-    $sender = User::getKV($sender->id);
-    if ($sender) {
+    $sender = User::getKV('id', $sender->id);
+    if ($sender instanceof User) {
         $recipient_user = User::getKV('nickname', $nickname);
-        if ($recipient_user) {
+        if ($recipient_user instanceof User) {
             return $recipient_user->getProfile();
         }
     }
@@ -1314,26 +1289,26 @@ function common_path($relative, $ssl=false, $addSession=true)
 
 function common_inject_session($url, $serverpart = null)
 {
-    if (common_have_session()) {
+    if (!common_have_session()) {
+        return $url;
+    }
 
-        if (empty($serverpart)) {
-            $serverpart = parse_url($url, PHP_URL_HOST);
-        }
+    if (empty($serverpart)) {
+        $serverpart = parse_url($url, PHP_URL_HOST);
+    }
 
-        $currentServer = (array_key_exists('HTTP_HOST', $_SERVER)) ? $_SERVER['HTTP_HOST'] : null;
+    $currentServer = (array_key_exists('HTTP_HOST', $_SERVER)) ? $_SERVER['HTTP_HOST'] : null;
 
-        // Are we pointing to another server (like an SSL server?)
+    // Are we pointing to another server (like an SSL server?)
 
-        if (!empty($currentServer) &&
-            0 != strcasecmp($currentServer, $serverpart)) {
-            // Pass the session ID as a GET parameter
-            $sesspart = session_name() . '=' . session_id();
-            $i = strpos($url, '?');
-            if ($i === false) { // no GET params, just append
-                $url .= '?' . $sesspart;
-            } else {
-                $url = substr($url, 0, $i + 1).$sesspart.'&'.substr($url, $i + 1);
-            }
+    if (!empty($currentServer) && 0 != strcasecmp($currentServer, $serverpart)) {
+        // Pass the session ID as a GET parameter
+        $sesspart = session_name() . '=' . session_id();
+        $i = strpos($url, '?');
+        if ($i === false) { // no GET params, just append
+            $url .= '?' . $sesspart;
+        } else {
+            $url = substr($url, 0, $i + 1).$sesspart.'&'.substr($url, $i + 1);
         }
     }
 
@@ -1402,7 +1377,8 @@ function common_exact_date($dt)
     $dateStr = date('d F Y H:i:s', strtotime($dt));
     $d = new DateTime($dateStr, $_utc);
     $d->setTimezone($_siteTz);
-    return $d->format(DATE_RFC850);
+    // TRANS: Human-readable full date-time specification (formatting on http://php.net/date)
+    return $d->format(_('l, d-M-Y H:i:s T'));
 }
 
 function common_date_w3dtf($dt)
@@ -1543,7 +1519,7 @@ function common_random_hexstr($bytes)
 
     $hexstr = '';
     for ($i = 0; $i < $bytes; $i++) {
-        $hexstr .= sprintf("%02x", ord($str{$i}));
+        $hexstr .= sprintf("%02x", ord($str[$i]));
     }
     return $hexstr;
 }
@@ -1678,8 +1654,10 @@ function common_debug($msg, $filename=null)
 
 function common_log_db_error(&$object, $verb, $filename=null)
 {
+    global $_PEAR;
+
     $objstr = common_log_objstring($object);
-    $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
+    $last_error = &$_PEAR->getStaticProperty('DB_DataObject','lastError');
     if (is_object($last_error)) {
         $msg = $last_error->message;
     } else {
@@ -1804,6 +1782,44 @@ function common_accept_to_prefs($accept, $def = '*/*')
     return $prefs;
 }
 
+// Match by our supported file extensions
+function common_supported_ext_to_mime($fileext)
+{
+    // Accept a filename and take out the extension
+    if (strpos($fileext, '.') !== false) {
+        $fileext = substr(strrchr($fileext, '.'), 1);
+    }
+
+    $supported = common_config('attachments', 'supported');
+    foreach($supported as $type => $ext) {
+        if ($ext === $fileext) {
+            return $type;
+        }
+    }
+
+    throw new ServerException('Unsupported file extension');
+}
+
+// Match by our supported mime types
+function common_supported_mime_to_ext($mimetype)
+{
+    $supported = common_config('attachments', 'supported');
+    foreach($supported as $type => $ext) {
+        if ($mimetype === $type) {
+            return $ext;
+        }
+    }
+
+    throw new ServerException('Unsupported MIME type');
+}
+
+// The MIME "media" is the part before the slash (video in video/webm)
+function common_get_mime_media($type)
+{
+    $tmp = explode('/', $type);
+    return strtolower($tmp[0]);
+}
+
 function common_mime_type_match($type, $avail)
 {
     if(array_key_exists($type, $avail)) {
@@ -1935,13 +1951,6 @@ function common_user_uri(&$user)
                             null, null, false);
 }
 
-function common_notice_uri(&$notice)
-{
-    return common_local_url('shownotice',
-                            array('notice' => $notice->id),
-                            null, null, false);
-}
-
 // 36 alphanums - lookalikes (0, O, 1, I) = 32 chars = 5 bits
 
 function common_confirmation_code($bits)
@@ -1961,9 +1970,12 @@ function common_confirmation_code($bits)
 }
 
 // convert markup to HTML
-
 function common_markup_to_html($c, $args=null)
 {
+    if ($c === null) {
+        return '';
+    }
+
     if (is_null($args)) {
         $args = array();
     }
@@ -1978,7 +1990,8 @@ function common_markup_to_html($c, $args=null)
     $c = preg_replace_callback('/%%action.(\w+)%%/', function ($m) { return common_local_url($m[1]); }, $c);
     $c = preg_replace_callback('/%%doc.(\w+)%%/', function ($m) { return common_local_url('doc', array('title'=>$m[1])); }, $c);
     $c = preg_replace_callback('/%%(\w+).(\w+)%%/', function ($m) { return common_config($m[1], $m[2]); }, $c);
-    return Markdown($c);
+
+    return \Michelf\Markdown::defaultTransform($c);
 }
 
 function common_user_property($property)
@@ -2018,9 +2031,9 @@ function common_profile_uri($profile)
 
     if (!empty($profile)) {
         if (Event::handle('StartCommonProfileURI', array($profile, &$uri))) {
-            $user = User::getKV($profile->id);
-            if (!empty($user)) {
-                $uri = $user->uri;
+            $user = User::getKV('id', $profile->id);
+            if ($user instanceof User) {
+                $uri = $user->getUri();
             }
             Event::handle('EndCommonProfileURI', array($profile, &$uri));
         }
@@ -2157,17 +2170,16 @@ function common_shorten_url($long_url, User $user=null, $force = false)
     if (Event::handle('StartShortenUrl',
                       array($long_url, $shortenerName, &$shortenedUrl))) {
         if ($shortenerName == 'internal') {
-            $f = File::processNew($long_url);
-            if (empty($f)) {
-                return $long_url;
-            } else {
-                $shortenedUrl = common_local_url('redirecturl',
-                                                 array('id' => $f->id));
+            try {
+                $f = File::processNew($long_url);
+                $shortenedUrl = common_local_url('redirecturl', array('id' => $f->id));
                 if ((mb_strlen($shortenedUrl) < mb_strlen($long_url)) || $force) {
                     return $shortenedUrl;
                 } else {
                     return $long_url;
                 }
+            } catch (ServerException $e) {
+                return $long_url;
             }
         } else {
             return $long_url;