3 * StatusNet - the distributed open-source microblogging tool
4 * Copyright (C) 2011, StatusNet, Inc.
6 * A plugin to enable social-bookmarking functionality
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Affero General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 * @category PollPlugin
25 * @author Brion Vibber <brion@status.net>
26 * @copyright 2011 StatusNet, Inc.
27 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
28 * @link http://status.net/
31 if (!defined('STATUSNET')) {
36 * Poll plugin main class
38 * @category PollPlugin
40 * @author Brion Vibber <brionv@status.net>
41 * @author Evan Prodromou <evan@status.net>
42 * @copyright 2011 StatusNet, Inc.
43 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
44 * @link http://status.net/
47 class PollPlugin extends MicroAppPlugin
49 const VERSION = '0.1';
50 const POLL_OBJECT = 'http://apinamespace.org/activitystreams/object/poll';
53 * Database schema setup
58 * @return boolean hook value; true means continue processing, false means stop.
61 function onCheckSchema()
63 $schema = Schema::get();
64 $schema->ensureTable('poll', Poll::schemaDef());
65 $schema->ensureTable('poll_response', Poll_response::schemaDef());
70 * Show the CSS necessary for this plugin
72 * @param Action $action the action being run
74 * @return boolean hook value
77 function onEndShowStyles($action)
79 $action->cssLink($this->path('poll.css'));
84 * Load related modules when needed
86 * @param string $cls Name of the class to be loaded
88 * @return boolean hook value; true means continue processing, false means stop.
91 function onAutoload($cls)
93 $dir = dirname(__FILE__);
97 case 'ShowpollAction':
99 case 'RespondpollAction':
100 include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
103 case 'Poll_response':
104 include_once $dir.'/'.$cls.'.php';
107 case 'PollResponseForm':
108 case 'PollResultForm':
109 include_once $dir.'/'.strtolower($cls).'.php';
117 * Map URLs to actions
119 * @param Net_URL_Mapper $m path-to-action mapper
121 * @return boolean hook value; true means continue processing, false means stop.
124 function onRouterInitialized($m)
126 $m->connect('main/poll/new',
127 array('action' => 'newpoll'),
128 array('id' => '[0-9]+'));
130 $m->connect('main/poll/:id/respond',
131 array('action' => 'respondpoll'),
132 array('id' => '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'));
138 * Plugin version data
140 * @param array &$versions array of version data
145 function onPluginVersion(&$versions)
147 $versions[] = array('name' => 'Poll',
148 'version' => self::VERSION,
149 'author' => 'Brion Vibber',
150 'homepage' => 'http://status.net/wiki/Plugin:Poll',
152 _m('Simple extension for supporting basic polls.'));
158 return array(self::POLL_OBJECT);
162 * When a notice is deleted, delete the related Poll
164 * @param Notice $notice Notice being deleted
166 * @return boolean hook value
169 function deleteRelated($notice)
171 $p = Poll::getByNotice($notice);
181 * Save a poll from an activity
183 * @param Profile $profile Profile to use as author
184 * @param Activity $activity Activity to save
185 * @param array $options Options to pass to bookmark-saving code
187 * @return Notice resulting notice
190 function saveNoticeFromActivity($activity, $profile, $options=array())
195 function activityObjectFromNotice($notice)
197 assert($this->isMyNotice($notice));
199 $object = new ActivityObject();
200 $object->id = $notice->uri;
201 $object->type = self::POLL_OBJECT;
202 $object->title = 'Poll title';
203 $object->summary = 'Poll summary';
204 $object->link = $notice->bestUrl();
206 $poll = Poll::getByNotice($notice);
208 * Adding the poll-specific data. There's no standard in AS for polls,
209 * so we're making stuff up.
211 * For the moment, using a kind of icky-looking schema that happens to
212 * work with out code for generating both Atom and JSON forms, though
215 * <poll:data xmlns:poll="http://apinamespace.org/activitystreams/object/poll"
216 * question="Who wants a poll question?"
217 * option1="Option one"
218 * option2="Option two"
219 * option3="Option three"></poll:data>
222 * "xmlns:poll": http://apinamespace.org/activitystreams/object/poll
223 * "question": "Who wants a poll question?"
224 * "option1": "Option one"
225 * "option2": "Option two"
226 * "option3": "Option three"
230 // @fixme there's no way to specify an XML node tree here, like <poll><option/><option/></poll>
231 // @fixme there's no way to specify a JSON array or multi-level tree unless you break the XML attribs
232 // @fixme XML node contents don't get shown in JSON
233 $data = array('xmlns:poll' => self::POLL_OBJECT,
234 'question' => $poll->question);
235 foreach ($poll->getOptions() as $i => $opt) {
236 $data['option' . ($i + 1)] = $opt;
238 $object->extra[] = array('poll:data', $data, '');
243 * @fixme WARNING WARNING WARNING parent class closes the final div that we
244 * open here, but we probably shouldn't open it here. Check parent class
245 * and Bookmark plugin for if that's right.
247 function showNotice($notice, $out)
249 $user = common_current_user();
251 // @hack we want regular rendering, then just add stuff after that
252 $nli = new NoticeListItem($notice, $out);
255 $out->elementStart('div', array('class' => 'entry-content poll-content'));
256 $poll = Poll::getByNotice($notice);
259 $profile = $user->getProfile();
260 $response = $poll->getResponse($profile);
262 // User has already responded; show the results.
263 $form = new PollResultForm($poll, $out);
265 $form = new PollResponseForm($poll, $out);
270 $out->text('Poll data is missing');
272 $out->elementEnd('div');
275 $out->elementStart('div', array('class' => 'entry-content'));
278 function entryForm($out)
280 return new NewPollForm($out);
283 // @fixme is this from parent?