forked from GNUsocial/gnu-social
3438a78c02
This version is fairly basic; votes do not (yet) show a reply, they just got in the table. No pretty graphs for the results yet, just text. The ActivityStream output is temporary and probably should be replaced; the current structures for adding custom data aren't really ready yet (especially since we need to cover JSON and Atom formats, probably pretty differently) Uses similar system as Bookmark for attaching to notices -- saves a custom URI for an alternate action, which we can then pass in and hook back up to our poll object. This can probably do with a little more simplification in the parent MicroAppPlugin class. Currently adds two tables: - poll holds the main poll info: id and URI to associate with the notice, then the question and a text blob with the options. - poll_response records the selections picked by our nice fellows. Hopefully no off-by-one bugs left in the selection, but I give no guarantees. ;) Some todo notes in the README and in doc comments.
251 lines
7.0 KiB
PHP
251 lines
7.0 KiB
PHP
<?php
|
|
/**
|
|
* Data class to mark notices as bookmarks
|
|
*
|
|
* PHP version 5
|
|
*
|
|
* @category PollPlugin
|
|
* @package StatusNet
|
|
* @author Brion Vibber <brion@status.net>
|
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
|
* @link http://status.net/
|
|
*
|
|
* StatusNet - the distributed open-source microblogging tool
|
|
* Copyright (C) 2011, StatusNet, Inc.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
if (!defined('STATUSNET')) {
|
|
exit(1);
|
|
}
|
|
|
|
/**
|
|
* For storing the poll options and such
|
|
*
|
|
* @category PollPlugin
|
|
* @package StatusNet
|
|
* @author Brion Vibber <brion@status.net>
|
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
|
* @link http://status.net/
|
|
*
|
|
* @see DB_DataObject
|
|
*/
|
|
|
|
class Poll extends Managed_DataObject
|
|
{
|
|
public $__table = 'poll'; // table name
|
|
public $id; // char(36) primary key not null -> UUID
|
|
public $profile_id; // int -> profile.id
|
|
public $question; // text
|
|
public $options; // text; newline(?)-delimited
|
|
public $created; // datetime
|
|
|
|
/**
|
|
* Get an instance by key
|
|
*
|
|
* This is a utility method to get a single instance with a given key value.
|
|
*
|
|
* @param string $k Key to use to lookup (usually 'user_id' for this class)
|
|
* @param mixed $v Value to lookup
|
|
*
|
|
* @return User_greeting_count object found, or null for no hits
|
|
*
|
|
*/
|
|
|
|
function staticGet($k, $v=null)
|
|
{
|
|
return Memcached_DataObject::staticGet('Poll', $k, $v);
|
|
}
|
|
|
|
/**
|
|
* Get an instance by compound key
|
|
*
|
|
* This is a utility method to get a single instance with a given set of
|
|
* key-value pairs. Usually used for the primary key for a compound key; thus
|
|
* the name.
|
|
*
|
|
* @param array $kv array of key-value mappings
|
|
*
|
|
* @return Bookmark object found, or null for no hits
|
|
*
|
|
*/
|
|
|
|
function pkeyGet($kv)
|
|
{
|
|
return Memcached_DataObject::pkeyGet('Poll', $kv);
|
|
}
|
|
|
|
/**
|
|
* The One True Thingy that must be defined and declared.
|
|
*/
|
|
public static function schemaDef()
|
|
{
|
|
return array(
|
|
'description' => 'Per-notice poll data for Poll plugin',
|
|
'fields' => array(
|
|
'id' => array('type' => 'char', 'length' => 36, 'not null' => true, 'description' => 'UUID'),
|
|
'uri' => array('type' => 'varchar', 'length' => 255, 'not null' => true),
|
|
'profile_id' => array('type' => 'int'),
|
|
'question' => array('type' => 'text'),
|
|
'options' => array('type' => 'text'),
|
|
'created' => array('type' => 'datetime', 'not null' => true),
|
|
),
|
|
'primary key' => array('id'),
|
|
'unique keys' => array(
|
|
'poll_uri_key' => array('uri'),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get a bookmark based on a notice
|
|
*
|
|
* @param Notice $notice Notice to check for
|
|
*
|
|
* @return Poll found poll or null
|
|
*/
|
|
|
|
function getByNotice($notice)
|
|
{
|
|
return self::staticGet('uri', $notice->uri);
|
|
}
|
|
|
|
function getOptions()
|
|
{
|
|
return explode("\n", $this->options);
|
|
}
|
|
|
|
function getNotice()
|
|
{
|
|
return Notice::staticGet('uri', $this->uri);
|
|
}
|
|
|
|
function bestUrl()
|
|
{
|
|
return $this->getNotice()->bestUrl();
|
|
}
|
|
|
|
/**
|
|
* Get the response of a particular user to this poll, if any.
|
|
*
|
|
* @param Profile $profile
|
|
* @return Poll_response object or null
|
|
*/
|
|
function getResponse(Profile $profile)
|
|
{
|
|
$pr = new Poll_response();
|
|
$pr->poll_id = $this->id;
|
|
$pr->profile_id = $profile->id;
|
|
$pr->find();
|
|
if ($pr->fetch()) {
|
|
return $pr;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function countResponses()
|
|
{
|
|
$pr = new Poll_response();
|
|
$pr->poll_id = $this->id;
|
|
$pr->groupBy('selection');
|
|
$pr->selectAdd('count(profile_id) as votes');
|
|
$pr->find();
|
|
|
|
$raw = array();
|
|
while ($pr->fetch()) {
|
|
$raw[$pr->selection] = $pr->votes;
|
|
}
|
|
|
|
$counts = array();
|
|
foreach (array_keys($this->getOptions()) as $key) {
|
|
if (isset($raw[$key])) {
|
|
$counts[$key] = $raw[$key];
|
|
} else {
|
|
$counts[$key] = 0;
|
|
}
|
|
}
|
|
return $counts;
|
|
}
|
|
|
|
/**
|
|
* Save a new poll notice
|
|
*
|
|
* @param Profile $profile
|
|
* @param string $question
|
|
* @param array $opts (poll responses)
|
|
*
|
|
* @return Notice saved notice
|
|
*/
|
|
|
|
static function saveNew($profile, $question, $opts, $options=null)
|
|
{
|
|
if (empty($options)) {
|
|
$options = array();
|
|
}
|
|
|
|
$p = new Poll();
|
|
|
|
$p->id = UUID::gen();
|
|
$p->profile_id = $profile->id;
|
|
$p->question = $question;
|
|
$p->options = implode("\n", $opts);
|
|
|
|
if (array_key_exists('created', $options)) {
|
|
$p->created = $options['created'];
|
|
} else {
|
|
$p->created = common_sql_now();
|
|
}
|
|
|
|
if (array_key_exists('uri', $options)) {
|
|
$p->uri = $options['uri'];
|
|
} else {
|
|
$p->uri = common_local_url('showpoll',
|
|
array('id' => $p->id));
|
|
}
|
|
|
|
$p->insert();
|
|
|
|
$content = sprintf(_m('Poll: %s %s'),
|
|
$question,
|
|
$p->uri);
|
|
$rendered = sprintf(_m('Poll: <a href="%s">%s</a>'),
|
|
htmlspecialchars($p->uri),
|
|
htmlspecialchars($question));
|
|
|
|
$tags = array('poll');
|
|
$replies = array();
|
|
|
|
$options = array_merge(array('urls' => array(),
|
|
'rendered' => $rendered,
|
|
'tags' => $tags,
|
|
'replies' => $replies,
|
|
'object_type' => PollPlugin::POLL_OBJECT),
|
|
$options);
|
|
|
|
if (!array_key_exists('uri', $options)) {
|
|
$options['uri'] = $p->uri;
|
|
}
|
|
|
|
$saved = Notice::saveNew($profile->id,
|
|
$content,
|
|
array_key_exists('source', $options) ?
|
|
$options['source'] : 'web',
|
|
$options);
|
|
|
|
return $saved;
|
|
}
|
|
}
|