X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=plugins%2FEvent%2FRSVP.php;h=1f47958e9a266b4e07fdd3828c614b6f0d46f813;hb=14f03a237e1a67a764a75cfa8e6fed34f0074a4b;hp=38d68c91ed35a473041874bc32d0c15cfa14048d;hpb=24fd39d6ab2c0bf72ba0dc970883fdd9fa751465;p=quix0rs-gnu-social.git
diff --git a/plugins/Event/RSVP.php b/plugins/Event/RSVP.php
index 38d68c91ed..1f47958e9a 100644
--- a/plugins/Event/RSVP.php
+++ b/plugins/Event/RSVP.php
@@ -1,6 +1,6 @@
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
- * @see DB_DataObject
+ * @see Managed_DataObject
*/
-
-class User_greeting_count extends Memcached_DataObject
+class RSVP extends Managed_DataObject
{
- public $__table = 'user_greeting_count'; // table name
- public $user_id; // int(4) primary_key not_null
- public $greeting_count; // int(4)
+ const POSITIVE = 'http://activitystrea.ms/schema/1.0/rsvp-yes';
+ const POSSIBLE = 'http://activitystrea.ms/schema/1.0/rsvp-maybe';
+ const NEGATIVE = 'http://activitystrea.ms/schema/1.0/rsvp-no';
+
+ public $__table = 'rsvp'; // table name
+ public $id; // varchar(36) UUID
+ public $uri; // varchar(255)
+ public $profile_id; // int
+ public $event_id; // varchar(36) UUID
+ public $response; // tinyint
+ 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 string $k Key to use to lookup (usually 'id' for this class)
* @param mixed $v Value to lookup
*
- * @return User_greeting_count object found, or null for no hits
- *
+ * @return RSVP object found, or null for no hits
*/
function staticGet($k, $v=null)
{
- return Memcached_DataObject::staticGet('User_greeting_count', $k, $v);
+ return Memcached_DataObject::staticGet('RSVP', $k, $v);
}
/**
- * return table definition for DB_DataObject
+ * Get an instance by compound key
*
- * DB_DataObject needs to know something about the table to manipulate
- * instances. This method provides all the DB_DataObject needs to know.
+ * @param array $kv array of key-value mappings
*
- * @return array array of column definitions
+ * @return Bookmark object found, or null for no hits
*/
- function table()
+
+ function pkeyGet($kv)
{
- return array('user_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
- 'greeting_count' => DB_DATAOBJECT_INT);
+ return Memcached_DataObject::pkeyGet('RSVP', $kv);
}
/**
- * return key definitions for DB_DataObject
- *
- * DB_DataObject needs to know about keys that the table has, since it
- * won't appear in StatusNet's own keys list. In most cases, this will
- * simply reference your keyTypes() function.
+ * Add the compound profile_id/event_id index to our cache keys
+ * since the DB_DataObject stuff doesn't understand compound keys
+ * except for the primary.
*
- * @return array list of key field names
+ * @return array
*/
- function keys()
- {
- return array_keys($this->keyTypes());
+ function _allCacheKeys() {
+ $keys = parent::_allCacheKeys();
+ $keys[] = self::multicacheKey('RSVP', array('profile_id' => $this->profile_id,
+ 'event_id' => $this->event_id));
+ return $keys;
}
/**
- * return key definitions for Memcached_DataObject
- *
- * Our caching system uses the same key definitions, but uses a different
- * method to get them. This key information is used to store and clear
- * cached data, so be sure to list any key that will be used for static
- * lookups.
- *
- * @return array associative array of key definitions, field name to type:
- * 'K' for primary key: for compound keys, add an entry for each component;
- * 'U' for unique keys: compound keys are not well supported here.
+ * The One True Thingy that must be defined and declared.
*/
- function keyTypes()
+ public static function schemaDef()
{
- return array('user_id' => 'K');
+ return array(
+ 'description' => 'Plan to attend event',
+ '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'),
+ 'event_id' => array('type' => 'char',
+ 'length' => 36,
+ 'not null' => true,
+ 'description' => 'UUID'),
+ 'response' => array('type' => 'char',
+ 'length' => '1',
+ 'description' => 'Y, N, or ? for three-state yes, no, maybe'),
+ 'created' => array('type' => 'datetime',
+ 'not null' => true),
+ ),
+ 'primary key' => array('id'),
+ 'unique keys' => array(
+ 'rsvp_uri_key' => array('uri'),
+ 'rsvp_profile_event_key' => array('profile_id', 'event_id'),
+ ),
+ 'foreign keys' => array('rsvp_event_id_key' => array('event', array('event_id' => 'id')),
+ 'rsvp_profile_id__key' => array('profile', array('profile_id' => 'id'))),
+ 'indexes' => array('rsvp_created_idx' => array('created')),
+ );
}
- /**
- * Magic formula for non-autoincrementing integer primary keys
- *
- * If a table has a single integer column as its primary key, DB_DataObject
- * assumes that the column is auto-incrementing and makes a sequence table
- * to do this incrementation. Since we don't need this for our class, we
- * overload this method and return the magic formula that DB_DataObject needs.
- *
- * @return array magic three-false array that stops auto-incrementing.
- */
- function sequenceKey()
+ function saveNew($profile, $event, $verb, $options=array())
{
- return array(false, false, false);
+ if (array_key_exists('uri', $options)) {
+ $other = RSVP::staticGet('uri', $options['uri']);
+ if (!empty($other)) {
+ // TRANS: Client exception thrown when trying to save an already existing RSVP ("please respond").
+ throw new ClientException(_m('RSVP already exists.'));
+ }
+ }
+
+ $other = RSVP::pkeyGet(array('profile_id' => $profile->id,
+ 'event_id' => $event->id));
+
+ if (!empty($other)) {
+ // TRANS: Client exception thrown when trying to save an already existing RSVP ("please respond").
+ throw new ClientException(_m('RSVP already exists.'));
+ }
+
+ $rsvp = new RSVP();
+
+ $rsvp->id = UUID::gen();
+ $rsvp->profile_id = $profile->id;
+ $rsvp->event_id = $event->id;
+ $rsvp->response = self::codeFor($verb);
+
+ if (array_key_exists('created', $options)) {
+ $rsvp->created = $options['created'];
+ } else {
+ $rsvp->created = common_sql_now();
+ }
+
+ if (array_key_exists('uri', $options)) {
+ $rsvp->uri = $options['uri'];
+ } else {
+ $rsvp->uri = common_local_url('showrsvp',
+ array('id' => $rsvp->id));
+ }
+
+ $rsvp->insert();
+
+ self::blow('rsvp:for-event:%s', $event->id);
+
+ // XXX: come up with something sexier
+
+ $content = $rsvp->asString();
+
+ $rendered = $rsvp->asHTML();
+
+ $options = array_merge(array('object_type' => $verb),
+ $options);
+
+ if (!array_key_exists('uri', $options)) {
+ $options['uri'] = $rsvp->uri;
+ }
+
+ $eventNotice = $event->getNotice();
+
+ if (!empty($eventNotice)) {
+ $options['reply_to'] = $eventNotice->id;
+ }
+
+ $saved = Notice::saveNew($profile->id,
+ $content,
+ array_key_exists('source', $options) ?
+ $options['source'] : 'web',
+ $options);
+
+ return $saved;
}
- /**
- * Increment a user's greeting count and return instance
- *
- * This method handles the ins and outs of creating a new greeting_count for a
- * user or fetching the existing greeting count and incrementing its value.
- *
- * @param integer $user_id ID of the user to get a count for
- *
- * @return User_greeting_count instance for this user, with count already incremented.
- */
- static function inc($user_id)
+ function codeFor($verb)
+ {
+ switch ($verb) {
+ case RSVP::POSITIVE:
+ return 'Y';
+ break;
+ case RSVP::NEGATIVE:
+ return 'N';
+ break;
+ case RSVP::POSSIBLE:
+ return '?';
+ break;
+ default:
+ // TRANS: Exception thrown when requesting an undefined verb for RSVP.
+ throw new Exception(sprintf(_m('Unknown verb "%s".'),$verb));
+ }
+ }
+
+ static function verbFor($code)
{
- $gc = User_greeting_count::staticGet('user_id', $user_id);
+ switch ($code) {
+ case 'Y':
+ return RSVP::POSITIVE;
+ break;
+ case 'N':
+ return RSVP::NEGATIVE;
+ break;
+ case '?':
+ return RSVP::POSSIBLE;
+ break;
+ default:
+ // TRANS: Exception thrown when requesting an undefined code for RSVP.
+ throw new Exception(sprintf(_m('Unknown code "%s".'),$code));
+ }
+ }
- if (empty($gc)) {
+ function getNotice()
+ {
+ $notice = Notice::staticGet('uri', $this->uri);
+ if (empty($notice)) {
+ // TRANS: Server exception thrown when requesting a non-exsting notice for an RSVP ("please respond").
+ // TRANS: %s is the RSVP with the missing notice.
+ throw new ServerException(sprintf(_m('RSVP %s does not correspond to a notice in the database.'),$this->id));
+ }
+ return $notice;
+ }
- $gc = new User_greeting_count();
+ static function fromNotice($notice)
+ {
+ return RSVP::staticGet('uri', $notice->uri);
+ }
- $gc->user_id = $user_id;
- $gc->greeting_count = 1;
+ static function forEvent($event)
+ {
+ $keypart = sprintf('rsvp:for-event:%s', $event->id);
- $result = $gc->insert();
+ $idstr = self::cacheGet($keypart);
- if (!$result) {
- // TRANS: Exception thrown when the user greeting count could not be saved in the database.
- // TRANS: %d is a user ID (number).
- throw Exception(sprintf(_m("Could not save new greeting count for %d."),
- $user_id));
- }
+ if ($idstr !== false) {
+ $ids = explode(',', $idstr);
} else {
- $orig = clone($gc);
+ $ids = array();
+
+ $rsvp = new RSVP();
- $gc->greeting_count++;
+ $rsvp->selectAdd();
+ $rsvp->selectAdd('id');
+
+ $rsvp->event_id = $event->id;
+
+ if ($rsvp->find()) {
+ while ($rsvp->fetch()) {
+ $ids[] = $rsvp->id;
+ }
+ }
+ self::cacheSet($keypart, implode(',', $ids));
+ }
- $result = $gc->update($orig);
+ $rsvps = array(RSVP::POSITIVE => array(),
+ RSVP::NEGATIVE => array(),
+ RSVP::POSSIBLE => array());
- if (!$result) {
- // TRANS: Exception thrown when the user greeting count could not be saved in the database.
- // TRANS: %d is a user ID (number).
- throw Exception(sprintf(_m("Could not increment greeting count for %d."),
- $user_id));
+ foreach ($ids as $id) {
+ $rsvp = RSVP::staticGet('id', $id);
+ if (!empty($rsvp)) {
+ $verb = self::verbFor($rsvp->response);
+ $rsvps[$verb][] = $rsvp;
}
}
- return $gc;
+ return $rsvps;
+ }
+
+ function getProfile()
+ {
+ $profile = Profile::staticGet('id', $this->profile_id);
+ if (empty($profile)) {
+ // TRANS: Exception thrown when requesting a non-existing profile.
+ // TRANS: %s is the ID of the non-existing profile.
+ throw new Exception(sprintf(_m('No profile with ID %s.'),$this->profile_id));
+ }
+ return $profile;
+ }
+
+ function getEvent()
+ {
+ $event = Happening::staticGet('id', $this->event_id);
+ if (empty($event)) {
+ // TRANS: Exception thrown when requesting a non-existing event.
+ // TRANS: %s is the ID of the non-existing event.
+ throw new Exception(sprintf(_m('No event with ID %s.'),$this->event_id));
+ }
+ return $event;
+ }
+
+ function asHTML()
+ {
+ $event = Happening::staticGet('id', $this->event_id);
+
+ return self::toHTML($this->getProfile(),
+ $event,
+ $this->response);
+ }
+
+ function asString()
+ {
+ $event = Happening::staticGet('id', $this->event_id);
+
+ return self::toString($this->getProfile(),
+ $event,
+ $this->response);
+ }
+
+ static function toHTML($profile, $event, $response)
+ {
+ $fmt = null;
+
+ switch ($response) {
+ case 'Y':
+ // TRANS: HTML version of an RSVP ("please respond") status for a user.
+ // TRANS: %1$s is a profile URL, %2$s a profile name,
+ // TRANS: %3$s is an event URL, %4$s an event title.
+ $fmt = _m("%2\$s is attending %4\$s.");
+ break;
+ case 'N':
+ // TRANS: HTML version of an RSVP ("please respond") status for a user.
+ // TRANS: %1$s is a profile URL, %2$s a profile name,
+ // TRANS: %3$s is an event URL, %4$s an event title.
+ $fmt = _m("%2\$s is not attending %4\$s.");
+ break;
+ case '?':
+ // TRANS: HTML version of an RSVP ("please respond") status for a user.
+ // TRANS: %1$s is a profile URL, %2$s a profile name,
+ // TRANS: %3$s is an event URL, %4$s an event title.
+ $fmt = _m("%2\$s might attend %4\$s.");
+ break;
+ default:
+ // TRANS: Exception thrown when requesting a user's RSVP status for a non-existing response code.
+ // TRANS: %s is the non-existing response code.
+ throw new Exception(sprintf(_m('Unknown response code %s.'),$response));
+ break;
+ }
+
+ if (empty($event)) {
+ $eventUrl = '#';
+ // TRANS: Used as event title when not event title is available.
+ // TRANS: Used as: Username [is [not ] attending|might attend] an unknown event.
+ $eventTitle = _m('an unknown event');
+ } else {
+ $notice = $event->getNotice();
+ $eventUrl = $notice->bestUrl();
+ $eventTitle = $event->title;
+ }
+
+ return sprintf($fmt,
+ htmlspecialchars($profile->profileurl),
+ htmlspecialchars($profile->getBestName()),
+ htmlspecialchars($eventUrl),
+ htmlspecialchars($eventTitle));
+ }
+
+ static function toString($profile, $event, $response)
+ {
+ $fmt = null;
+
+ switch ($response) {
+ case 'Y':
+ // TRANS: Plain text version of an RSVP ("please respond") status for a user.
+ // TRANS: %1$s is a profile name, %2$s is an event title.
+ $fmt = _m('%1$s is attending %2$s.');
+ break;
+ case 'N':
+ // TRANS: Plain text version of an RSVP ("please respond") status for a user.
+ // TRANS: %1$s is a profile name, %2$s is an event title.
+ $fmt = _m('%1$s is not attending %2$s.');
+ break;
+ case '?':
+ // TRANS: Plain text version of an RSVP ("please respond") status for a user.
+ // TRANS: %1$s is a profile name, %2$s is an event title.
+ $fmt = _m('%1$s might attend %2$s.');
+ break;
+ default:
+ // TRANS: Exception thrown when requesting a user's RSVP status for a non-existing response code.
+ // TRANS: %s is the non-existing response code.
+ throw new Exception(sprintf(_m('Unknown response code %s.'),$response));
+ break;
+ }
+
+ if (empty($event)) {
+ // TRANS: Used as event title when not event title is available.
+ // TRANS: Used as: Username [is [not ] attending|might attend] an unknown event.
+ $eventTitle = _m('an unknown event');
+ } else {
+ $notice = $event->getNotice();
+ $eventTitle = $event->title;
+ }
+
+ return sprintf($fmt,
+ $profile->getBestName(),
+ $eventTitle);
+ }
+
+ function delete()
+ {
+ self::blow('rsvp:for-event:%s', $event->id);
+ parent::delete();
}
}