]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/AnonymousFave/AnonymousFavePlugin.php
Merge branch '0.9.x' of gitorious.org:statusnet/mainline into 1.0.x
[quix0rs-gnu-social.git] / plugins / AnonymousFave / AnonymousFavePlugin.php
1 <?php
2
3 /**
4  * StatusNet - the distributed open-source microblogging tool
5  * Copyright (C) 2010, StatusNet, Inc.
6  *
7  * A plugin to allow anonymous users to favorite notices
8  *
9  * PHP version 5
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Affero General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU Affero General Public License for more details.
20  *
21  * You should have received a copy of the GNU Affero General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  *
24  * @category  Plugin
25  * @package   StatusNet
26  * @author    Zach Copley <zach@status.net>
27  * @copyright 2010 StatusNet, Inc.
28  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
29  * @link      http://status.net/
30  */
31
32 if (!defined('STATUSNET')) {
33     // This check helps protect against security problems;
34     // your code file can't be executed directly from the web.
35     exit(1);
36 }
37
38 define('ANONYMOUS_FAVE_PLUGIN_VERSION', '0.1');
39
40 /**
41  * Anonymous Fave plugin to allow anonymous (not logged in) users
42  * to favorite notices
43  *
44  * @category  Plugin
45  * @package   StatusNet
46  * @author    Zach Copley <zach@status.net>
47  * @copyright 2010 StatusNet, Inc.
48  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
49  * @link      http://status.net/
50  */
51 class AnonymousFavePlugin extends Plugin {
52
53     function onArgsInitialize() {
54         // We always want a session because we're tracking anon users
55         common_ensure_session();
56     }
57
58     /**
59      * Hook for ensuring our tables are created
60      *
61      * Ensures the fave_tally table is there and has the right columns
62      *
63      * @return boolean hook return
64      */
65
66     function onCheckSchema()
67     {
68         $schema = Schema::get();
69
70         // For storing total number of times a notice has been faved
71
72         $schema->ensureTable('fave_tally',
73             array(
74                 new ColumnDef('notice_id', 'integer', null,  false, 'PRI'),
75                 new ColumnDef('count', 'integer', null, false),
76                 new ColumnDef(
77                     'modified',
78                     'timestamp',
79                     null,
80                     false,
81                     null,
82                     'CURRENT_TIMESTAMP',
83                     'on update CURRENT_TIMESTAMP'
84                 )
85             )
86         );
87
88         return true;
89     }
90
91     function onEndShowHTML($action)
92     {
93         if (!common_logged_in()) {
94             // Set a place to return to when submitting forms
95             common_set_returnto($action->selfUrl());
96         }
97     }
98
99     function onEndShowScripts($action)
100     {
101         // Setup ajax calls for favoriting. Usually this is only done when
102         // a user is logged in.
103         $action->inlineScript('SN.U.NoticeFavor();');
104     }
105
106     function onAutoload($cls)
107     {
108         $dir = dirname(__FILE__);
109
110         switch ($cls) {
111             case 'Fave_tally':
112                 include_once $dir . '/' . $cls . '.php';
113                 return false;
114             case 'AnonFavorAction':
115                 include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
116                 return false;
117             case 'AnonDisFavorAction':
118                 include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
119                 return false;
120             case 'AnonFavorForm':
121                 include_once $dir . '/anonfavorform.php';
122                 return false;
123             case 'AnonDisFavorForm':
124                 include_once $dir . '/anondisfavorform.php';
125                 return false;
126             default:
127                 return true;
128         }
129     }
130
131     function onStartInitializeRouter($m) {
132
133         $m->connect('main/anonfavor', array('action' => 'AnonFavor'));
134         $m->connect('main/anondisfavor', array('action' => 'AnonDisFavor'));
135
136         return true;
137     }
138
139     function onStartShowNoticeOptions($item) {
140
141         if (!common_logged_in()) {
142             $item->out->elementStart('div', 'notice-options');
143             $item->showFaveForm();
144             $item->out->elementEnd('div');
145         }
146
147         return true;
148     }
149
150     function onStartShowFaveForm($item) {
151
152         if (!common_logged_in()) {
153
154             $profile = AnonymousFavePlugin::getAnonProfile();
155             if (!empty($profile)) {
156                 if ($profile->hasFave($item->notice)) {
157                     $disfavor = new AnonDisFavorForm($item->out, $item->notice);
158                     $disfavor->show();
159                 } else {
160                     $favor = new AnonFavorForm($item->out, $item->notice);
161                     $favor->show();
162                 }
163             }
164         }
165
166         return true;
167     }
168
169     function onEndFavorNoticeForm($form, $notice)
170     {
171         $this->showTally($form->out, $notice);
172     }
173
174     function onEndDisFavorNoticeForm($form, $notice)
175     {
176         $this->showTally($form->out, $notice);
177     }
178
179     function showTally($out, $notice)
180     {
181         $tally = Fave_tally::ensureTally($notice->id);
182
183         if (!empty($tally)) {
184             $out->elementStart(
185                 'div',
186                 array(
187                     'id' => 'notice-' . $notice->id . '-tally',
188                     'class' => 'notice-tally'
189                 )
190             );
191             // TRANS: Tally for number of times a notice was favored.
192             // TRANS: %d is the number of times a notice was favored.
193             $out->raw(sprintf(_m("favored once", "favored %d times", $tally->count), $tally->count));
194             $out->elementEnd('div');
195         }
196     }
197
198     function onEndFavorNotice($profile, $notice)
199     {
200         $tally = Fave_tally::increment($notice->id);
201     }
202
203     function onEndDisfavorNotice($profile, $notice)
204     {
205         $tally = Fave_tally::decrement($notice->id);
206     }
207
208     static function createAnonProfile() {
209
210         // Get the anon user's IP, and turn it into a nickname
211         list($proxy, $ip) = common_client_ip();
212
213         // IP + time + random number should help to avoid collisions
214         $baseNickname = $ip . '-' . time() . '-' . common_good_rand(5);
215
216         $profile = new Profile();
217         $profile->nickname = $baseNickname;
218         $id = $profile->insert();
219
220         if (!$id) {
221             // TRANS: Server exception.
222             throw new ServerException(_m("Couldn't create anonymous user session."));
223         }
224
225         // Stick the Profile ID into the nickname
226         $orig = clone($profile);
227
228         $profile->nickname = 'anon-' . $id . '-' . $baseNickname;
229         $result = $profile->update($orig);
230
231         if (!$result) {
232             // TRANS: Server exception.
233             throw new ServerException(_m("Couldn't create anonymous user session."));
234         }
235
236         common_log(
237             LOG_INFO,
238             "AnonymousFavePlugin - created profile for anonymous user from IP: "
239             . $ip
240             . ', nickname = '
241             . $profile->nickname
242         );
243
244         return $profile;
245     }
246
247     static function getAnonProfile() {
248
249         $token = $_SESSION['anon_token'];
250         $anon = base64_decode($token);
251
252         $profile = null;
253
254         if (!empty($anon) && substr($anon, 0, 5) == 'anon-') {
255             $parts = explode('-', $anon);
256             $id = $parts[1];
257             // Do Profile lookup by ID instead of nickname for safety/performance
258             $profile = Profile::staticGet('id', $id);
259         } else {
260             $profile = AnonymousFavePlugin::createAnonProfile();
261             // Obfuscate so it's hard to figure out the Profile ID
262             $_SESSION['anon_token'] = base64_encode($profile->nickname);
263         }
264
265         return $profile;
266     }
267
268     /**
269      * Provide plugin version information.
270      *
271      * This data is used when showing the version page.
272      *
273      * @param array &$versions array of version data arrays; see EVENTS.txt
274      *
275      * @return boolean hook value
276      */
277     function onPluginVersion(&$versions)
278     {
279         $url = 'http://status.net/wiki/Plugin:AnonymousFave';
280
281         $versions[] = array('name' => 'AnonymousFave',
282             'version' => ANONYMOUS_FAVE_PLUGIN_VERSION,
283             'author' => 'Zach Copley',
284             'homepage' => $url,
285             'rawdescription' =>
286             // TRANS: Plugin description.
287             _m('Allow anonymous users to favorite notices.'));
288
289         return true;
290     }
291
292 }