X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=plugins%2FBookmark%2FBookmarkPlugin.php;h=9ea83c4caf1f2263f43ff3952b5e550093b585fc;hb=bb31394cce356677c835717f775ee795ef700087;hp=f8db77e2b701d9ca0274704e0b9ba5b5726c046d;hpb=19b965d99188fde59cdd39b668df8951bc0f180c;p=quix0rs-gnu-social.git diff --git a/plugins/Bookmark/BookmarkPlugin.php b/plugins/Bookmark/BookmarkPlugin.php index f8db77e2b7..9ea83c4caf 100644 --- a/plugins/Bookmark/BookmarkPlugin.php +++ b/plugins/Bookmark/BookmarkPlugin.php @@ -48,6 +48,8 @@ class BookmarkPlugin extends MicroAppPlugin const VERSION = '0.1'; const IMPORTDELICIOUS = 'BookmarkPlugin:IMPORTDELICIOUS'; + var $oldSaveNew = true; + /** * Authorization for importing delicious bookmarks * @@ -80,39 +82,7 @@ class BookmarkPlugin extends MicroAppPlugin { $schema = Schema::get(); - // For storing user-submitted flags on profiles - - $schema->ensureTable('bookmark', - array(new ColumnDef('id', - 'char', - 36, - false, - 'PRI'), - new ColumnDef('profile_id', - 'integer', - null, - false, - 'MUL'), - new ColumnDef('url', - 'varchar', - 255, - false, - 'MUL'), - new ColumnDef('title', - 'varchar', - 255), - new ColumnDef('description', - 'text'), - new ColumnDef('uri', - 'varchar', - 255, - false, - 'UNI'), - new ColumnDef('created', - 'datetime', - null, - false, - 'MUL'))); + $schema->ensureTable('bookmark', Bookmark::schemaDef()); return true; } @@ -126,7 +96,7 @@ class BookmarkPlugin extends MicroAppPlugin */ function onEndShowStyles($action) { - $action->cssLink($this->path('bookmark.css')); + $action->cssLink($this->path('css/bookmark.css')); return true; } @@ -135,51 +105,36 @@ class BookmarkPlugin extends MicroAppPlugin $action->script($this->path('js/bookmark.js')); return true; } - /** - * Load related modules when needed - * - * @param string $cls Name of the class to be loaded - * - * @return boolean hook value; true means continue processing, false means stop. - */ - function onAutoload($cls) - { - $dir = dirname(__FILE__); - - switch ($cls) - { - case 'ShowbookmarkAction': - case 'NewbookmarkAction': - case 'BookmarkpopupAction': - case 'NoticebyurlAction': - case 'BookmarkforurlAction': - case 'ImportdeliciousAction': - include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; - return false; - case 'Bookmark': - include_once $dir.'/'.$cls.'.php'; - return false; - case 'BookmarkListItem': - case 'BookmarkForm': - case 'InitialBookmarkForm': - case 'DeliciousBackupImporter': - case 'DeliciousBookmarkImporter': - include_once $dir.'/'.strtolower($cls).'.php'; - return false; - default: - return true; - } - } /** * Map URLs to actions * - * @param Net_URL_Mapper $m path-to-action mapper + * @param URLMapper $m path-to-action mapper * * @return boolean hook value; true means continue processing, false means stop. */ - function onRouterInitialized($m) + public function onRouterInitialized(URLMapper $m) { + if (common_config('singleuser', 'enabled')) { + $nickname = User::singleUserNickname(); + $m->connect('bookmarks', + array('action' => 'bookmarks', 'nickname' => $nickname)); + $m->connect('bookmarks/rss', + array('action' => 'bookmarksrss', 'nickname' => $nickname)); + } else { + $m->connect(':nickname/bookmarks', + array('action' => 'bookmarks'), + array('nickname' => Nickname::DISPLAY_FMT)); + $m->connect(':nickname/bookmarks/rss', + array('action' => 'bookmarksrss'), + array('nickname' => Nickname::DISPLAY_FMT)); + } + + $m->connect('api/bookmarks/:id.:format', + array('action' => 'ApiTimelineBookmarks', + 'id' => Nickname::INPUT_FMT, + 'format' => '(xml|json|rss|atom|as)')); + $m->connect('main/bookmark/new', array('action' => 'newbookmark'), array('id' => '[0-9]+')); @@ -230,11 +185,13 @@ class BookmarkPlugin extends MicroAppPlugin { $versions[] = array('name' => 'Bookmark', 'version' => self::VERSION, - 'author' => 'Evan Prodromou', + 'author' => 'Evan Prodromou, Stephane Berube, Jean Baptiste Favre', 'homepage' => 'http://status.net/wiki/Plugin:Bookmark', 'description' => // TRANS: Plugin description. - _m('Simple extension for supporting bookmarks.')); + _m('Simple extension for supporting bookmarks. ') . + 'BookmarkList feature has been developped by Stephane Berube. ' . + 'Integration has been done by Jean Baptiste Favre.'); return true; } @@ -283,62 +240,30 @@ class BookmarkPlugin extends MicroAppPlugin } /** - * Output our CSS class for bookmark notice list elements + * Modify the default menu to link to our custom action * - * @param NoticeListItem $nli The item being shown + * Using event handlers, it's possible to modify the default UI for pages + * almost without limit. In this method, we add a menu item to the default + * primary menu for the interface to link to our action. * - * @return boolean hook value - */ - - function onStartOpenNoticeListItemElement($nli) - { - $nb = Bookmark::getByNotice($nli->notice); - if (!empty($nb)) { - $id = (empty($nli->repeat)) ? $nli->notice->id : $nli->repeat->id; - $class = 'hentry notice bookmark'; - if ($nli->notice->scope != 0 && $nli->notice->scope != 1) { - $class .= ' limited-scope'; - } - $nli->out->elementStart('li', array('class' => $class, - 'id' => 'notice-' . $id)); - Event::handle('EndOpenNoticeListItemElement', array($nli)); - return false; - } - return true; - } - - /** - * Save a remote bookmark (from Salmon or PuSH) + * The Action class provides a rich set of events to hook, as well as output + * methods. * - * @param Ostatus_profile $author Author of the bookmark - * @param Activity $activity Activity to save - * - * @return Notice resulting notice. - */ - static private function _postRemoteBookmark(Ostatus_profile $author, - Activity $activity) - { - $bookmark = $activity->objects[0]; - - $options = array('uri' => $bookmark->id, - 'url' => $bookmark->link, - 'is_local' => Notice::REMOTE_OMB, - 'source' => 'ostatus'); - - return self::_postBookmark($author->localProfile(), $activity, $options); - } - - /** - * Test if an activity represents posting a bookmark + * @param Action $action The current action handler. Use this to + * do any output. * - * @param Activity $activity Activity to test + * @return boolean hook value; true means continue processing, false means stop. * - * @return true if it's a Post of a Bookmark, else false + * @see Action */ - static private function _isPostBookmark($activity) + function onEndPersonalGroupNav(Menu $menu, Profile $target, Profile $scoped=null) { - return ($activity->verb == ActivityVerb::POST && - $activity->objects[0]->type == ActivityObject::BOOKMARK); + $menu->menuItem(common_local_url('bookmarks', array('nickname' => $target->getNickname())), + // TRANS: Menu item in sample plugin. + _m('Bookmarks'), + // TRANS: Menu item title in sample plugin. + _m('A list of your bookmarks'), false, 'nav_timeline_bookmarks'); + return true; } function types() @@ -353,14 +278,17 @@ class BookmarkPlugin extends MicroAppPlugin * * @return boolean hook value */ - function deleteRelated($notice) + function deleteRelated(Notice $notice) { - $nb = Bookmark::getByNotice($notice); - - if (!empty($nb)) { - $nb->delete(); - } - + if ($this->isMyNotice($notice)) { + + $nb = Bookmark::getByNotice($notice); + + if (!empty($nb)) { + $nb->delete(); + } + } + return true; } @@ -368,12 +296,12 @@ class BookmarkPlugin extends MicroAppPlugin * Save a bookmark from an activity * * @param Activity $activity Activity to save - * @param Profile $profile Profile to use as author + * @param Profile $actor Profile to use as author * @param array $options Options to pass to bookmark-saving code * * @return Notice resulting notice */ - function saveNoticeFromActivity($activity, $profile, $options=array()) + function saveNoticeFromActivity(Activity $activity, Profile $actor, array $options=array()) { $bookmark = $activity->objects[0]; @@ -417,20 +345,19 @@ class BookmarkPlugin extends MicroAppPlugin } } - $replies = $activity->context->attention; - $options['groups'] = array(); - $options['replies'] = array(); - - foreach ($replies as $replyURI) { - $other = Profile::fromURI($replyURI); - if (!empty($other)) { - $options['replies'][] = $replyURI; - } else { - $group = User_group::staticGet('uri', $replyURI); - if (!empty($group)) { - $options['groups'][] = $replyURI; + $options['replies'] = array(); // TODO: context->attention + + foreach ($activity->context->attention as $attnUrl=>$type) { + try { + $other = Profile::fromUri($attnUrl); + if ($other->isGroup()) { + $options['groups'][] = $other->id; + } else { + $options['replies'][] = $attnUrl; } + } catch (UnknownUriException $e) { + // We simply don't know this URI, despite lookup attempts. } } @@ -438,14 +365,14 @@ class BookmarkPlugin extends MicroAppPlugin // @fixme what about conversation ID? if (!empty($activity->context->replyToID)) { - $orig = Notice::staticGet('uri', + $orig = Notice::getKV('uri', $activity->context->replyToID); if (!empty($orig)) { $options['reply_to'] = $orig->id; } } - return Bookmark::saveNew($profile, + return Bookmark::saveNew($actor, $bookmark->title, $url, $tags, @@ -453,7 +380,7 @@ class BookmarkPlugin extends MicroAppPlugin $options); } - function activityObjectFromNotice($notice) + function activityObjectFromNotice(Notice $notice) { assert($this->isMyNotice($notice)); @@ -467,7 +394,7 @@ class BookmarkPlugin extends MicroAppPlugin $object->type = ActivityObject::BOOKMARK; $object->title = $nb->title; $object->summary = $nb->description; - $object->link = $notice->bestUrl(); + $object->link = $notice->getUrl(); // Attributes of the URL @@ -492,9 +419,8 @@ class BookmarkPlugin extends MicroAppPlugin // Attributes of the thumbnail, if any - $thumbnail = $target->getThumbnail(); - - if (!empty($thumbnail)) { + try { + $thumbnail = $target->getThumbnail(); $tattrs = array('rel' => 'preview', 'href' => $thumbnail->url); @@ -506,25 +432,14 @@ class BookmarkPlugin extends MicroAppPlugin $tattrs['media:height'] = $thumbnail->height; } - $object->extra[] = array('link', $attrs, null); + $object->extra[] = array('link', $tattrs, null); + } catch (UnsupportedMediaException $e) { + // No image thumbnail metadata available } return $object; } - /** - * Given a notice list item, returns an adapter specific - * to this plugin. - * - * @param NoticeListItem $nli item to adapt - * - * @return NoticeListItemAdapter adapter or null - */ - function adaptNoticeListItem($nli) - { - return new BookmarkListItem($nli); - } - function entryForm($out) { return new InitialBookmarkForm($out); @@ -540,4 +455,124 @@ class BookmarkPlugin extends MicroAppPlugin // TRANS: Application title. return _m('TITLE','Bookmark'); } + + function onEndUpgrade() + { + // Version 0.9.x of the plugin didn't stamp notices + // with verb and object-type (for obvious reasons). Update + // those notices here. + + $notice = new Notice(); + + $notice->whereAdd('exists (select uri from bookmark where bookmark.uri = notice.uri)'); + $notice->whereAdd('((object_type is null) or (object_type = "' .ActivityObject::NOTE.'"))'); + + $notice->find(); + + while ($notice->fetch()) { + $original = clone($notice); + $notice->verb = ActivityVerb::POST; + $notice->object_type = ActivityObject::BOOKMARK; + $notice->update($original); + } + } + + public function activityObjectOutputJson(ActivityObject $obj, array &$out) + { + assert($obj->type == ActivityObject::BOOKMARK); + + $bm = Bookmark::getKV('uri', $obj->id); + + if (empty($bm)) { + throw new ServerException("Unknown bookmark: " . $obj->id); + } + + $out['displayName'] = $bm->title; + $out['targetUrl'] = $bm->url; + + return true; + } + + protected function showNoticeItemNotice(NoticeListItem $nli) + { + $nli->out->elementStart('div', 'entry-title'); + $nli->showAuthor(); + $nli->showContent(); + $nli->out->elementEnd('div'); + } + + protected function showNoticeContent(Notice $stored, HTMLOutputter $out, Profile $scoped=null) + { + $nb = Bookmark::getByNotice($stored); + + if (empty($nb)) { + common_log(LOG_ERR, "No bookmark for notice {$stored->id}"); + parent::showContent(); + return; + } else if (empty($nb->url)) { + common_log(LOG_ERR, "No url for bookmark {$nb->id} for notice {$stored->id}"); + parent::showContent(); + return; + } + + $profile = $stored->getProfile(); + + // Whether to nofollow + $attrs = array('href' => $nb->url, 'class' => 'bookmark-title'); + + $nf = common_config('nofollow', 'external'); + + if ($nf == 'never' || ($nf == 'sometimes' and $out instanceof ShowstreamAction)) { + $attrs['rel'] = 'external'; + } else { + $attrs['rel'] = 'nofollow external'; + } + + $out->elementStart('h3'); + $out->element('a', $attrs, $nb->title); + $out->elementEnd('h3'); + + // Replies look like "for:" tags + $replies = $stored->getReplies(); + $tags = $stored->getTags(); + + if (!empty($replies) || !empty($tags)) { + + $out->elementStart('ul', array('class' => 'bookmark-tags')); + + foreach ($replies as $reply) { + $other = Profile::getKV('id', $reply); + if (!empty($other)) { + $out->elementStart('li'); + $out->element('a', array('rel' => 'tag', + 'href' => $other->profileurl, + 'title' => $other->getBestName()), + sprintf('for:%s', $other->nickname)); + $out->elementEnd('li'); + $out->text(' '); + } + } + + foreach ($tags as $tag) { + $tag = trim($tag); + if (!empty($tag)) { + $out->elementStart('li'); + $out->element('a', + array('rel' => 'tag', + 'href' => Notice_tag::url($tag)), + $tag); + $out->elementEnd('li'); + $out->text(' '); + } + } + + $out->elementEnd('ul'); + } + + if (!empty($nb->description)) { + $out->element('p', + array('class' => 'bookmark-description'), + $nb->description); + } + } }