From 46167d6b3567d49f052a372fc97e43eefbd064d7 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 30 Sep 2010 18:02:02 -0700 Subject: [PATCH] ShareNotice plugin -- basic buttons per-notice to share the text & a link to the notice on other sites. Default settings list Twitter, Facebook, and Identi.ca as targets. Using icons built-in, and no magic offsite JS or anything so it won't slow down or break if third-party site goes down. Default styles are a little limited, but can be customized in theme should one be so inclined. --- plugins/ShareNotice/ShareNoticePlugin.php | 194 +++++++++++++++++++++ plugins/ShareNotice/css/README | 9 + plugins/ShareNotice/css/icon-facebook.png | Bin 0 -> 312 bytes plugins/ShareNotice/css/icon-share.png | Bin 0 -> 3838 bytes plugins/ShareNotice/css/icon-statusnet.png | Bin 0 -> 488 bytes plugins/ShareNotice/css/icon-twitter.png | Bin 0 -> 469 bytes plugins/ShareNotice/css/sharenotice.css | 23 +++ 7 files changed, 226 insertions(+) create mode 100644 plugins/ShareNotice/ShareNoticePlugin.php create mode 100644 plugins/ShareNotice/css/README create mode 100644 plugins/ShareNotice/css/icon-facebook.png create mode 100644 plugins/ShareNotice/css/icon-share.png create mode 100644 plugins/ShareNotice/css/icon-statusnet.png create mode 100644 plugins/ShareNotice/css/icon-twitter.png create mode 100644 plugins/ShareNotice/css/sharenotice.css diff --git a/plugins/ShareNotice/ShareNoticePlugin.php b/plugins/ShareNotice/ShareNoticePlugin.php new file mode 100644 index 0000000000..d44e234529 --- /dev/null +++ b/plugins/ShareNotice/ShareNoticePlugin.php @@ -0,0 +1,194 @@ +. + */ + +/** + * @package ShareNoticePlugin + * @maintainer Brion Vibber + */ + +if (!defined('STATUSNET')) { exit(1); } + +class ShareNoticePlugin extends Plugin +{ + public $targets = array( + array('Twitter'), + array('Facebook'), + array('StatusNet', array('baseurl' => 'http://identi.ca')) + ); + + function onEndShowStatusNetStyles($action) { + $action->cssLink('plugins/ShareNotice/css/sharenotice.css'); + return true; + } + + function onStartShowNoticeItem($item) + { + $notice = $item->notice; + $out = $item->out; + + $out->elementStart('ul', array('class' => 'notice-share')); + foreach ($this->targets as $data) { + $type = $data[0]; + $args = (count($data) > 1) ? $data[1] : array(); + $target = $this->getShareTarget($type, $notice, $args); + $this->showShareTarget($out, $target); + } + $out->elementEnd('ul'); + } + + private function getShareTarget($type, $notice, $args) + { + $class = ucfirst($type) . 'ShareTarget'; + + return new $class($notice, $args); + } + + private function showShareTarget(HTMLOutputter $out, NoticeShareTarget $target) + { + $class = $target->getClass(); + $text = $target->getText(); + $url = $target->targetUrl(); + + $out->elementStart('li', array('class' => 'notice-share-' . $class)); + $out->elementStart('a', array( + 'href' => $url, + 'title' => $text, + 'target' => '_blank' + )); + $out->element('span', array(), $text); + $out->elementEnd('a'); + $out->elementEnd('li'); + } +} + +abstract class NoticeShareTarget +{ + protected $notice; + + public function __construct($notice) + { + $this->notice = $notice; + } + + public abstract function getClass(); + + public abstract function getText(); + + public abstract function targetUrl(); +} + +abstract class GenericNoticeShareTarget extends NoticeShareTarget +{ + protected function maxLength() + { + return 140; // typical + } + + protected function statusText() + { + $pattern = _m('"%s"'); + $url = $this->notice->bestUrl(); + $suffix = ' ' . $url; + $room = $this->maxLength() - mb_strlen($suffix) - (mb_strlen($pattern) - mb_strlen('%s')); + + $content = $this->notice->content; + if (mb_strlen($content) > $room) { + $content = mb_substr($content, 0, $room - 1) . '…'; + } + + return sprintf($pattern, $content) . $suffix; + } +} + +class TwitterShareTarget extends GenericNoticeShareTarget +{ + public function getClass() + { + return 'twitter'; + } + + public function getText() + { + return _m('Share on Twitter'); + } + + public function targetUrl() + { + $args = array( + 'status' => $this->statusText() + ); + return 'http://twitter.com/home?' . + http_build_query($args, null, '&'); + } +} + +class StatusNetShareTarget extends GenericNoticeShareTarget +{ + protected $baseurl; + + public function __construct($notice, $args) + { + parent::__construct($notice); + $this->baseurl = $args['baseurl']; + } + + public function getClass() + { + return 'statusnet'; + } + + public function getText() + { + $host = parse_url($this->baseurl, PHP_URL_HOST); + return sprintf(_m('Share on %s'), $host); + } + + public function targetUrl() + { + $args = array( + 'status_textarea' => $this->statusText() + ); + return $this->baseurl . '/notice/new?' . + http_build_query($args, null, '&'); + } + +} + +class FacebookShareTarget extends NoticeShareTarget +{ + public function getClass() + { + return 'facebook'; + } + + public function getText() + { + return _m('Share on Facebook'); + } + + public function targetUrl() + { + $args = array( + 'u' => $this->notice->bestUrl(), + 't' => sprintf(_m('"%s"'), $this->notice->content), + ); + return 'http://www.facebook.com/sharer.php?' . + http_build_query($args, null, '&'); + } +} \ No newline at end of file diff --git a/plugins/ShareNotice/css/README b/plugins/ShareNotice/css/README new file mode 100644 index 0000000000..a3f4661973 --- /dev/null +++ b/plugins/ShareNotice/css/README @@ -0,0 +1,9 @@ +icon-sharing.png is from http://www.openshareicons.com/ + +Shareaholic has made the Open Share Icon freely available for use by others under the +Creative Commons Attribution-Share Alike 3.0 Unported License. + + +icon-twitter.png is from http://twitter.com/favicon.ico and distributed under fair use +icon-facebook.png is from http://facebook.com/favicon.ico and distributed under fair use +icon-statusnet.png is from http://status.net/favicon.ico and distributed under fair use diff --git a/plugins/ShareNotice/css/icon-facebook.png b/plugins/ShareNotice/css/icon-facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..3105e306963f11c32534a935b5984446dbee0768 GIT binary patch literal 312 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPgg4E=C3oW=~B~TcD6qiEBiObAE1a zYF-J0b5UwyNotBhd1gt5g1e`0fI@zrLZX6iVsiV6a%Z6GE>9Q75R22v2@3=aj0_A6 zB3#e@^6z_=eEO2aOpQ`TZo@7U5f%w6uNny#77Gaw$Vqy3;Auw@rMraS)o}V9>k8&H>UDV?^5!sYv+~a@MV1b{)r-BUz87n*lLUI-@5iUd{D)_1`xj^(n%1y_jp0b8a-80b3u}R{V(@hJb6Mw<&;$VT%w?+p literal 0 HcmV?d00001 diff --git a/plugins/ShareNotice/css/icon-share.png b/plugins/ShareNotice/css/icon-share.png new file mode 100644 index 0000000000000000000000000000000000000000..5be2b46c8a41d3485555bc5cdf686b03a35fcd45 GIT binary patch literal 3838 zcmeHKX;4#F7`=IthzJ^xMW~%VBgHifLBYhtfF>%kh=3Y*9?1n_LK2gQ1aO0@P^cme zs8vA`QCk$oDX7Q@1!@&nbX>+2sUR-HrU6Bu=}Vw!r@xq~|F|=6-uv!7-#Pa?_xo|* z_d$X4ZLD0Z001_=3xvVMn`(M2DFBe73^(5sfio@=;~}aDJQmYH;3HLqL)14Ki-f@t zlg6#Dfjj`LPRc^XxH!O{D^W!=FcXHMi&hia0PqAlH71cm91Vw&G9{nZT2?_rWl}zE z*^B^IfO;;Bk}ZhWz>xUBP)WR8!jaMhv#oeKE)Vt#APAkS(m-@N!<{Z+d3d7JJsE5-PcJrW8XBNdqVr%l>drygES49_W^<>r zxU89I|DesbLU|f#1UFbXuV0af__Qb-S96)n*w|P`tOrA-iDbHSI2S zcnFT+X4L^|l^QCwQN(e}Bq~D2Bw#KM{7`3+0D^E^gQOj#QUJ1IZfpB%@HR^^bd2O zf%-RR+V2+}Wpd1(!c&NLE>>88R2hz_6FTLZ49G!|>u7c7(0Hr1a*qM`3?`5Kw^yH7_>%fy8m?JhvUs0-qai z*73VWQ@yRxjQyo?#@6z4oq~v8YPPuTHsl?e=v=<3`$k*Oi!GF`00=>uk+dM*^M(Z( zI3NfKG{5Xg0X}jMV^43l@%7sVhU)e=Z(K5Aea)&dy-#v2`GGZ5beU*@4zKAHXpC$zwmb zxRU+4I*g#P=?&;I08ms}0NPsLfl*ErfCPE}F>S;)64+GtB=UGf&c#G3g=}++>M&k3 zw>~&g@8@~O@y_jFp-?~fnO$+QFt6h9s+CEW!^cOl?2uea>!|d?vX=8J>kLoF+}hcD zFgFK~kZn}qM0NHvc^Fy5`Eg0%$(-RM4&iQzwX1$OJ+21X-twq54bK*AeATAz@-M1` zQv}tOPbhm{9nQ~M4CN*M&yUo!H#0iZYh-z;57MV@tfDqNf5Tst?Z$3&7nIt`EN52; z#QWFet(Yp>C>GsC?loOe+;{q^Hj-0UdJI43z4@`Xn+L)`~A#!7q*bNZV9!Mk|ymkZrHHleG89ux>nd46xuV> z*2mRx&xWL<)FN92l3E$|vuOWT%PEr`Y$(MGB$&%co0P;iw=F_WG_<8%ewEvP?b6f2 z2TzvQJ!Vx~r(a4ic3s~xEm=N`VyHeUPazj+@{b%3TCwjO<-WFU)6Q=uanhpdDyROo zZdP6|-T5xEeq&xX>geqkoVjD%Q|-2TkC=7cfnoKGvwQX#SyzkN3hdj2qFqa}nr~bx zIqY@C1K02F&2ky7yw;Y`Jn?;`>TU6QC#HJl3jU4CE91G>9dAXX`evcmYHa2uw^KTP z-OKU9Z6{=uUUcFeIMmRYKXF_^PSvjTQzEyVwc`UC;w@a)GfI~irD!+*X-F-~PNnLV z3ti`Ubyp`Qx^(2a`%}`_Jjtyn*4Jb>m-j@yExjwnN-GcK@2xA*C5JD^V)3MsrVI7= ztvj0`?9iXOYUtqHtEzas-zC4jg-%}LSlwv5%WoK)Rj*D8?T;Bo$1hzyKMgJ_Uz<|2=WIbnm1l`xA-p_e#d-ARi`NGak2Pdo lw$EP(CpUKldeRdw8A+*5+lxc7FfY>|sjnzdSU4vv>2KGf(H{T+ literal 0 HcmV?d00001 diff --git a/plugins/ShareNotice/css/icon-statusnet.png b/plugins/ShareNotice/css/icon-statusnet.png new file mode 100644 index 0000000000000000000000000000000000000000..a7b39090d0d723228699030e242d099fe029aa9d GIT binary patch literal 488 zcmVP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igh& z04Ex%+MzN400C%8L_t(I%Z-yUZo)tiMW0QiAVoq>5s63?E2T>XojY7bbod646C^$X zzJbLFa83}rbmvqlV;ZCsC@v@>(U??FM5M6ST8MG-rImJOcmB-I{?Sn2fdM=MBS0ue zDG&ftC*POQlwcc}k&~Q41~?A*2Lwg%GyliEB+-hpKh(?}%i?x4q9p|DBw-nbtm62% zlAZ%89=IOt<$879eHEhdc(2~`^5>!#4J$L7lSyUGce5EC%TisoBq+Pxdw8gQ_|0&r znuZ5LS3T#3QA=>u?H;=h33gdlOYoJZzrIy3Itsut3~LG2^Z9}8K%y5417P9%EPVeY zL8sqW%>bY=fO#R`vWnei!&$RQO9)nR%rXeLXt%jGP2Q$czPDR|&j_BR5?x^Om;72n zu*)*FSCTB8Ud?0(60PMSKEmkB3dG%H-wZ5`YE7Kq|+$ eIJ1F1VE+JesE2#dVa!_q0000QL70(Y)*K0-AbW|YuPgg4E=C45tB&;>b_0c!N?apKobz*Y zQ}ap~oQqNuOHxx5$}>wc6x=<10~GS}6cQDD6O-Fllsg0MRQGgo46!)9bn-?&CP#s` z{mFZubp+mfz$Gl4`_%K?yzqtz5lqw6)E)@0*lTlgX28UR9KBm}Tg7BJi*`E~vNPUM zcAt~=FXj8~ne}B4=0D8oQn*sPAhP&jHRFMVi14*ROBAmBJ$K}UiD>6@rOP2pj14C_ zdo!lY>e_NVswu#`dd^FQE1TZmySQwHR!3T-+*zZy)si;$pO|fUUav}Lz47SZqD|+7 z&t`r^_R?gd3BPK3P;HJ@k8@u0d=JF~HK_s62G zXZ=lVYPk+P@MjGTUDs6+XK>6#K50>eZ_mEEho5fT%zotKe0J;XAAf!*-kD?BDsZ3K zf9>}pzvjA^zju4IGve?z`99W5%u)^SH6xzPzfrpBQ@MEwr^L>Mp2wrFE(ZoMgQu&X J%Q~loCICc+#CZS! literal 0 HcmV?d00001 diff --git a/plugins/ShareNotice/css/sharenotice.css b/plugins/ShareNotice/css/sharenotice.css new file mode 100644 index 0000000000..f4f847e66c --- /dev/null +++ b/plugins/ShareNotice/css/sharenotice.css @@ -0,0 +1,23 @@ +.notice-share { + width: 24px; + float: right; +} + +.notice-share li a { + display: block; + width: 16px; + height: 16px; + background: url(icon-share.png) no-repeat; +} +.notice-share li.notice-share-twitter a { + background-image: url(icon-twitter.png); +} +.notice-share li.notice-share-facebook a { + background-image: url(icon-facebook.png); +} +.notice-share li.notice-share-statusnet a { + background-image: url(icon-statusnet.png); +} +.notice-share li a span { + display: none; +}