X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=lib%2Fnoticelist.php;h=83c8de9f6e0ac3b573846ea92016858d8cd3e187;hb=1c40e7c139af98e4fe9c73093da4183ad8d9e234;hp=004905056276acf142a87db0627e94fa35e221d5;hpb=7ae2ed7cfcc78992c6f6ad02be646fb935c7f6dc;p=quix0rs-gnu-social.git diff --git a/lib/noticelist.php b/lib/noticelist.php index 0049050562..83c8de9f6e 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -1,6 +1,6 @@ . * * @category UI - * @package Laconica - * @author Evan Prodromou - * @author Sarven Capadisli - * @copyright 2008 Control Yourself, Inc. + * @package StatusNet + * @author Evan Prodromou + * @author Sarven Capadisli + * @copyright 2008 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ + * @link http://status.net/ */ -if (!defined('LACONICA')) { +if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } require_once INSTALLDIR.'/lib/favorform.php'; require_once INSTALLDIR.'/lib/disfavorform.php'; +require_once INSTALLDIR.'/lib/attachmentlist.php'; /** * widget for displaying a list of notices @@ -44,12 +45,11 @@ require_once INSTALLDIR.'/lib/disfavorform.php'; * data for e.g. the profile page. * * @category UI - * @package Laconica - * @author Evan Prodromou + * @package StatusNet + * @author Evan Prodromou * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ + * @link http://status.net/ * @see Notice - * @see StreamAction * @see NoticeListItem * @see ProfileNoticeList */ @@ -85,7 +85,7 @@ class NoticeList extends Widget { $this->out->elementStart('div', array('id' =>'notices_primary')); $this->out->element('h2', null, _('Notices')); - $this->out->elementStart('ul', array('class' => 'notices')); + $this->out->elementStart('ol', array('class' => 'notices xoxo')); $cnt = 0; @@ -100,7 +100,7 @@ class NoticeList extends Widget $item->show(); } - $this->out->elementEnd('ul'); + $this->out->elementEnd('ol'); $this->out->elementEnd('div'); return $cnt; @@ -133,10 +133,10 @@ class NoticeList extends Widget * author info (since that's implicit by the data in the page). * * @category UI - * @package Laconica - * @author Evan Prodromou + * @package StatusNet + * @author Evan Prodromou * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ + * @link http://status.net/ * @see NoticeList * @see ProfileNoticeListItem */ @@ -147,6 +147,10 @@ class NoticeListItem extends Widget var $notice = null; + /** The notice that was repeated. */ + + var $repeat = null; + /** The profile of the author of the notice, extracted once for convenience. */ var $profile = null; @@ -162,8 +166,18 @@ class NoticeListItem extends Widget function __construct($notice, $out=null) { parent::__construct($out); - $this->notice = $notice; - $this->profile = $notice->getProfile(); + if (!empty($notice->repeat_of)) { + $original = Notice::staticGet('id', $notice->repeat_of); + if (empty($original)) { // could have been deleted + $this->notice = $notice; + } else { + $this->notice = $original; + $this->repeat = $notice; + } + } else { + $this->notice = $notice; + } + $this->profile = $this->notice->getProfile(); } /** @@ -177,91 +191,40 @@ class NoticeListItem extends Widget function show() { + if (empty($this->notice)) { + common_log(LOG_WARNING, "Trying to show missing notice; skipping."); + return; + } else if (empty($this->profile)) { + common_log(LOG_WARNING, "Trying to show missing profile (" . $this->notice->profile_id . "); skipping."); + return; + } + $this->showStart(); - $this->showNotice(); - $this->showNoticeAttachments(); - $this->showNoticeOptions(); - $this->showNoticeInfo(); + if (Event::handle('StartShowNoticeItem', array($this))) { + $this->showNotice(); + $this->showNoticeInfo(); + $this->showNoticeOptions(); + Event::handle('EndShowNoticeItem', array($this)); + } $this->showEnd(); } function showNotice() { -if(0) - $this->out->elementStart('entry-title'); -else - - if ('shownotice' === $this->out->args['action']) { - $width = '85%'; - } else { - $width = '90%'; - } - - - $this->out->elementStart('div', array('class' => 'entry-title', 'style' => "float: left; width: $width;")); + $this->out->elementStart('div', 'entry-title'); $this->showAuthor(); $this->showContent(); $this->out->elementEnd('div'); } - function showNoticeAttachments() - { - $f2p = new File_to_post; - $f2p->post_id = $this->notice->id; - $file = new File; - $file->joinAdd($f2p); - $file->selectAdd(); - $file->selectAdd('file.id as id'); - $count = $file->find(true); - if (!$count) return; - if (1 === $count) { - $href = common_local_url('attachment', array('attachment' => $file->id)); - $att_class = 'attachment'; - } else { - $href = common_local_url('attachments', array('notice' => $this->notice->id)); - $att_class = 'attachments'; - } - - $clip = theme_path('images/icons/clip', 'base'); - if ('shownotice' === $this->out->args['action']) { - $height = '96px'; - $width = '83%'; - $width_att = '15%'; - $clip .= '-big.png'; - $top = '70px'; - } else { - $height = '48px'; - $width = '90%'; - $width_att = '8%'; - $clip .= '.png'; - $top = '20px'; - } -if(0) - $this->out->elementStart('div', 'entry-attachments'); -else - $this->out->elementStart('p', array('class' => 'entry-attachments', 'style' => "float: right; width: $width_att; background: url($clip) no-repeat; text-align: right; height: $height;")); - $this->out->element('a', array('class' => $att_class, 'style' => "text-decoration: none; padding-top: $top; display: block; height: $height;", 'href' => $href, 'title' => "# of attachments: $count"), $count === 1 ? '' : $count); - - - $this->out->elementEnd('p'); - } - function showNoticeInfo() { -if(0) $this->out->elementStart('div', 'entry-content'); -else - - if ('shownotice' === $this->out->args['action']) { - $width = '85%'; - } else { - $width = '90%'; - } - - $this->out->elementStart('div', array('class' => 'entry-content', 'style' => "float: left; width: $width;")); $this->showNoticeLink(); $this->showNoticeSource(); + $this->showNoticeLocation(); $this->showContext(); + $this->showRepeat(); $this->out->elementEnd('div'); } @@ -269,12 +232,10 @@ else { $user = common_current_user(); if ($user) { -if(0) $this->out->elementStart('div', 'notice-options'); -else - $this->out->elementStart('div', array('class' => 'notice-options', 'style' => 'float: right; width: 16%;')); $this->showFaveForm(); $this->showReplyLink(); + $this->showRepeatForm(); $this->showDeleteLink(); $this->out->elementEnd('div'); } @@ -290,8 +251,9 @@ else { // XXX: RDFa // TODO: add notice_type class e.g., notice_video, notice_image + $id = (empty($this->repeat)) ? $this->notice->id : $this->repeat->id; $this->out->elementStart('li', array('class' => 'hentry notice', - 'id' => 'notice-' . $this->notice->id)); + 'id' => 'notice-' . $id)); } /** @@ -328,10 +290,11 @@ else $attrs = array('href' => $this->profile->profileurl, 'class' => 'url'); if (!empty($this->profile->fullname)) { - $attrs['title'] = $this->profile->fullname . ' (' . $this->profile->nickname . ') '; + $attrs['title'] = $this->profile->fullname . ' (' . $this->profile->nickname . ')'; } $this->out->elementStart('a', $attrs); $this->showAvatar(); + $this->out->text(' '); $this->showNickname(); $this->out->elementEnd('a'); $this->out->elementEnd('span'); @@ -377,8 +340,9 @@ else function showNickname() { - $this->out->element('span', array('class' => 'nickname fn'), - $this->profile->nickname); + $this->out->raw('' . + htmlspecialchars($this->profile->nickname) . + ''); } /** @@ -417,25 +381,92 @@ else function showNoticeLink() { - $noticeurl = common_local_url('shownotice', - array('notice' => $this->notice->id)); - // XXX: we need to figure this out better. Is this right? - if (strcmp($this->notice->uri, $noticeurl) != 0 && - preg_match('/^http/', $this->notice->uri)) { - $noticeurl = $this->notice->uri; - } - $this->out->elementStart('dl', 'timestamp'); - $this->out->element('dt', null, _('Published')); - $this->out->elementStart('dd', null); + $noticeurl = $this->notice->bestUrl(); + + // above should always return an URL + + assert(!empty($noticeurl)); + $this->out->elementStart('a', array('rel' => 'bookmark', + 'class' => 'timestamp', 'href' => $noticeurl)); $dt = common_date_iso8601($this->notice->created); $this->out->element('abbr', array('class' => 'published', 'title' => $dt), common_date_string($this->notice->created)); $this->out->elementEnd('a'); - $this->out->elementEnd('dd'); - $this->out->elementEnd('dl'); + } + + /** + * show the notice location + * + * shows the notice location in the correct language. + * + * If an URL is available, makes a link. Otherwise, just a span. + * + * @return void + */ + + function showNoticeLocation() + { + $id = $this->notice->id; + + $location = $this->notice->getLocation(); + + if (empty($location)) { + return; + } + + $name = $location->getName(); + + $lat = $this->notice->lat; + $lon = $this->notice->lon; + $latlon = (!empty($lat) && !empty($lon)) ? $lat.';'.$lon : ''; + + if (empty($name)) { + $latdms = $this->decimalDegreesToDMS(abs($lat)); + $londms = $this->decimalDegreesToDMS(abs($lon)); + $name = sprintf( + _('%1$u°%2$u\'%3$u"%4$s %5$u°%6$u\'%7$u"%8$s'), + $latdms['deg'],$latdms['min'], $latdms['sec'],($lat>0?_('N'):_('S')), + $londms['deg'],$londms['min'], $londms['sec'],($lon>0?_('E'):_('W'))); + } + + $url = $location->getUrl(); + + $this->out->text(' '); + $this->out->elementStart('span', array('class' => 'location')); + $this->out->text(_('at')); + $this->out->text(' '); + if (empty($url)) { + $this->out->element('abbr', array('class' => 'geo', + 'title' => $latlon), + $name); + } else { + $xstr = new XMLStringer(false); + $xstr->elementStart('a', array('href' => $url, + 'rel' => 'external')); + $xstr->element('abbr', array('class' => 'geo', + 'title' => $latlon), + $name); + $xstr->elementEnd('a'); + $this->out->raw($xstr->getString()); + } + $this->out->elementEnd('span'); + } + + function decimalDegreesToDMS($dec) + { + + $vars = explode(".",$dec); + $deg = $vars[0]; + $tempma = "0.".$vars[1]; + + $tempma = $tempma * 3600; + $min = floor($tempma / 60); + $sec = $tempma - ($min*60); + + return array("deg"=>$deg,"min"=>$min,"sec"=>$sec); } /** @@ -450,9 +481,11 @@ else function showNoticeSource() { if ($this->notice->source) { - $this->out->elementStart('dl', 'device'); - $this->out->element('dt', null, _('From')); + $this->out->text(' '); + $this->out->elementStart('span', 'source'); + $this->out->text(_('from')); $source_name = _($this->notice->source); + $this->out->text(' '); switch ($this->notice->source) { case 'web': case 'xmpp': @@ -460,22 +493,42 @@ else case 'omb': case 'system': case 'api': - $this->out->element('dd', null, $source_name); + $this->out->element('span', 'device', $source_name); break; default: - $ns = Notice_source::staticGet($this->notice->source); - if ($ns) { - $this->out->elementStart('dd', null); - $this->out->element('a', array('href' => $ns->url, - 'rel' => 'external'), - $ns->name); - $this->out->elementEnd('dd'); + + $name = $source_name; + $url = null; + + if (Event::handle('StartNoticeSourceLink', array($this->notice, &$name, &$url, &$title))) { + $ns = Notice_source::staticGet($this->notice->source); + + if ($ns) { + $name = $ns->name; + $url = $ns->url; + } else { + $app = Oauth_application::staticGet('name', $this->notice->source); + if ($app) { + $name = $app->name; + $url = $app->source_url; + } + } + } + Event::handle('EndNoticeSourceLink', array($this->notice, &$name, &$url, &$title)); + + if (!empty($name) && !empty($url)) { + $this->out->elementStart('span', 'device'); + $this->out->element('a', array('href' => $url, + 'rel' => 'external', + 'title' => $title), + $name); + $this->out->elementEnd('span'); } else { - $this->out->element('dd', null, $source_name); + $this->out->element('span', 'device', $name); } break; } - $this->out->elementEnd('dl'); + $this->out->elementEnd('span'); } } @@ -490,18 +543,72 @@ else function showContext() { - // XXX: also show context if there are replies to this notice - if (!empty($this->notice->conversation) - && $this->notice->conversation != $this->notice->id) { - $convurl = common_local_url('conversation', - array('id' => $this->notice->conversation)); - $this->out->elementStart('dl', 'response'); - $this->out->element('dt', null, _('To')); - $this->out->elementStart('dd'); - $this->out->element('a', array('href' => $convurl), - _('in context')); - $this->out->elementEnd('dd'); - $this->out->elementEnd('dl'); + $hasConversation = false; + if (!empty($this->notice->conversation)) { + $conversation = Notice::conversationStream( + $this->notice->conversation, + 1, + 1 + ); + if ($conversation->N > 0) { + $hasConversation = true; + } + } + if ($hasConversation) { + $conv = Conversation::staticGet( + 'id', + $this->notice->conversation + ); + $convurl = $conv->uri; + if (!empty($convurl)) { + $this->out->text(' '); + $this->out->element( + 'a', + array( + 'href' => $convurl.'#notice-'.$this->notice->id, + 'class' => 'response'), + _('in context') + ); + } else { + $msg = sprintf( + "Couldn't find Conversation ID %d to make 'in context'" + . "link for Notice ID %d", + $this->notice->conversation, + $this->notice->id + ); + common_log(LOG_WARNING, $msg); + } + } + } + + /** + * show a link to the author of repeat + * + * @return void + */ + + function showRepeat() + { + if (!empty($this->repeat)) { + + $repeater = Profile::staticGet('id', $this->repeat->profile_id); + + $attrs = array('href' => $repeater->profileurl, + 'class' => 'url'); + + if (!empty($repeater->fullname)) { + $attrs['title'] = $repeater->fullname . ' (' . $repeater->nickname . ')'; + } + + $this->out->elementStart('span', 'repeat vcard'); + + $this->out->raw(_('Repeated by')); + + $this->out->elementStart('a', $attrs); + $this->out->element('span', 'fn nickname', $repeater->nickname); + $this->out->elementEnd('a'); + + $this->out->elementEnd('span'); } } @@ -517,19 +624,16 @@ else function showReplyLink() { if (common_logged_in()) { + $this->out->text(' '); $reply_url = common_local_url('newnotice', - array('replyto' => $this->profile->nickname)); - - $this->out->elementStart('dl', 'notice_reply'); - $this->out->element('dt', null, _('Reply to this notice')); - $this->out->elementStart('dd'); + array('replyto' => $this->profile->nickname, 'inreplyto' => $this->notice->id)); $this->out->elementStart('a', array('href' => $reply_url, + 'class' => 'notice_reply', 'title' => _('Reply to this notice'))); $this->out->text(_('Reply')); + $this->out->text(' '); $this->out->element('span', 'notice_id', $this->notice->id); $this->out->elementEnd('a'); - $this->out->elementEnd('dd'); - $this->out->elementEnd('dl'); } } @@ -542,16 +646,40 @@ else function showDeleteLink() { $user = common_current_user(); - if ($user && $this->notice->profile_id == $user->id) { + + $todel = (empty($this->repeat)) ? $this->notice : $this->repeat; + + if (!empty($user) && + ($todel->profile_id == $user->id || $user->hasRight(Right::DELETEOTHERSNOTICE))) { + $this->out->text(' '); $deleteurl = common_local_url('deletenotice', - array('notice' => $this->notice->id)); - $this->out->elementStart('dl', 'notice_delete'); - $this->out->element('dt', null, _('Delete this notice')); - $this->out->elementStart('dd'); + array('notice' => $todel->id)); $this->out->element('a', array('href' => $deleteurl, + 'class' => 'notice_delete', 'title' => _('Delete this notice')), _('Delete')); - $this->out->elementEnd('dd'); - $this->out->elementEnd('dl'); + } + } + + /** + * show the form to repeat a notice + * + * @return void + */ + + function showRepeatForm() + { + $user = common_current_user(); + if ($user && $user->id != $this->notice->profile_id) { + $this->out->text(' '); + $profile = $user->getProfile(); + if ($profile->hasRepeated($this->notice->id)) { + $this->out->element('span', array('class' => 'repeated', + 'title' => _('Notice repeated')), + _('Repeated')); + } else { + $rf = new RepeatForm($this->out, $this->notice); + $rf->show(); + } } }