Happening.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <?php
  2. /**
  3. * Data class for happenings
  4. *
  5. * PHP version 5
  6. *
  7. * @category Data
  8. * @package StatusNet
  9. * @author Evan Prodromou <evan@status.net>
  10. * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
  11. * @link http://status.net/
  12. *
  13. * StatusNet - the distributed open-source microblogging tool
  14. * Copyright (C) 2011, StatusNet, Inc.
  15. *
  16. * This program is free software: you can redistribute it and/or modify
  17. * it under the terms of the GNU Affero General Public License as published by
  18. * the Free Software Foundation, either version 3 of the License, or
  19. * (at your option) any later version.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU Affero General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU Affero General Public License
  27. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  28. */
  29. if (!defined('STATUSNET')) {
  30. exit(1);
  31. }
  32. /**
  33. * Data class for happenings
  34. *
  35. * There's already an Event class in lib/event.php, so we couldn't
  36. * call this an Event without causing a hole in space-time.
  37. *
  38. * "Happening" seemed good enough.
  39. *
  40. * @category Event
  41. * @package StatusNet
  42. * @author Evan Prodromou <evan@status.net>
  43. * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
  44. * @link http://status.net/
  45. *
  46. * @see Managed_DataObject
  47. */
  48. class Happening extends Managed_DataObject
  49. {
  50. const OBJECT_TYPE = 'http://activitystrea.ms/schema/1.0/event';
  51. public $__table = 'happening'; // table name
  52. public $id; // varchar(36) UUID
  53. public $uri; // varchar(255)
  54. public $profile_id; // int
  55. public $start_time; // datetime
  56. public $end_time; // datetime
  57. public $title; // varchar(255)
  58. public $location; // varchar(255)
  59. public $url; // varchar(255)
  60. public $description; // text
  61. public $created; // datetime
  62. /**
  63. * The One True Thingy that must be defined and declared.
  64. */
  65. public static function schemaDef()
  66. {
  67. return array(
  68. 'description' => 'A real-world happening',
  69. 'fields' => array(
  70. 'id' => array('type' => 'char',
  71. 'length' => 36,
  72. 'not null' => true,
  73. 'description' => 'UUID'),
  74. 'uri' => array('type' => 'varchar',
  75. 'length' => 255,
  76. 'not null' => true),
  77. 'profile_id' => array('type' => 'int', 'not null' => true),
  78. 'start_time' => array('type' => 'datetime', 'not null' => true),
  79. 'end_time' => array('type' => 'datetime', 'not null' => true),
  80. 'title' => array('type' => 'varchar',
  81. 'length' => 255,
  82. 'not null' => true),
  83. 'location' => array('type' => 'varchar',
  84. 'length' => 255),
  85. 'url' => array('type' => 'varchar',
  86. 'length' => 255),
  87. 'description' => array('type' => 'text'),
  88. 'created' => array('type' => 'datetime',
  89. 'not null' => true),
  90. ),
  91. 'primary key' => array('id'),
  92. 'unique keys' => array(
  93. 'happening_uri_key' => array('uri'),
  94. ),
  95. 'foreign keys' => array('happening_profile_id__key' => array('profile', array('profile_id' => 'id'))),
  96. 'indexes' => array('happening_created_idx' => array('created'),
  97. 'happening_start_end_idx' => array('start_time', 'end_time')),
  98. );
  99. }
  100. static function saveNew($profile, $start_time, $end_time, $title, $location, $description, $url, $options=array())
  101. {
  102. if (array_key_exists('uri', $options)) {
  103. $other = Happening::getKV('uri', $options['uri']);
  104. if (!empty($other)) {
  105. // TRANS: Client exception thrown when trying to create an event that already exists.
  106. throw new ClientException(_m('Event already exists.'));
  107. }
  108. }
  109. $ev = new Happening();
  110. $ev->id = UUID::gen();
  111. $ev->profile_id = $profile->id;
  112. $ev->start_time = common_sql_date($start_time);
  113. $ev->end_time = common_sql_date($end_time);
  114. $ev->title = $title;
  115. $ev->location = $location;
  116. $ev->description = $description;
  117. $ev->url = $url;
  118. if (array_key_exists('created', $options)) {
  119. $ev->created = $options['created'];
  120. } else {
  121. $ev->created = common_sql_now();
  122. }
  123. if (array_key_exists('uri', $options)) {
  124. $ev->uri = $options['uri'];
  125. } else {
  126. $ev->uri = common_local_url('showevent',
  127. array('id' => $ev->id));
  128. }
  129. $ev->insert();
  130. // XXX: does this get truncated?
  131. // TRANS: Event description. %1$s is a title, %2$s is start time, %3$s is end time,
  132. // TRANS: %4$s is location, %5$s is a description.
  133. $content = sprintf(_m('"%1$s" %2$s - %3$s (%4$s): %5$s'),
  134. $title,
  135. common_exact_date($ev->start_time),
  136. common_exact_date($ev->end_time),
  137. $location,
  138. $description);
  139. // TRANS: Rendered microformats2 tagged event description.
  140. // TRANS: %1$s is a title, %2$s is start time, %3$s is start time,
  141. // TRANS: %4$s is end time, %5$s is end time, %6$s is location, %7$s is description.
  142. // TRANS: Class names should not be translated.
  143. $rendered = sprintf(_m('<div class="h-event">'.
  144. '<p class="p-name p-summary">%1$s</p> '.
  145. '<time class="dt-start" datetime="%2$s">%3$s</time> - '.
  146. '<time class="dt-end" datetime="%4$s">%5$s</time> '.
  147. '(<span class="p-location">%6$s</span>): '.
  148. '<div class="p-description">%7$s</div> '.
  149. '</div>'),
  150. htmlspecialchars($title),
  151. htmlspecialchars(common_date_iso8601($ev->start_time)),
  152. htmlspecialchars(common_exact_date($ev->start_time)),
  153. htmlspecialchars(common_date_iso8601($ev->end_time)),
  154. htmlspecialchars(common_exact_date($ev->end_time)),
  155. htmlspecialchars($location),
  156. htmlspecialchars($description));
  157. $options = array_merge(array('object_type' => Happening::OBJECT_TYPE),
  158. $options);
  159. if (!array_key_exists('uri', $options)) {
  160. $options['uri'] = $ev->uri;
  161. }
  162. if (!empty($url)) {
  163. $options['urls'] = array($url);
  164. }
  165. $saved = Notice::saveNew($profile->id,
  166. $content,
  167. array_key_exists('source', $options) ?
  168. $options['source'] : 'web',
  169. $options);
  170. return $saved;
  171. }
  172. /**
  173. * Returns the profile's canonical url, not necessarily a uri/unique id
  174. *
  175. * @return string $url
  176. */
  177. public function getUrl()
  178. {
  179. if (empty($this->url) ||
  180. !filter_var($this->url, FILTER_VALIDATE_URL)) {
  181. throw new InvalidUrlException($this->url);
  182. }
  183. return $this->url;
  184. }
  185. function getNotice()
  186. {
  187. return Notice::getKV('uri', $this->uri);
  188. }
  189. static function fromNotice($notice)
  190. {
  191. return Happening::getKV('uri', $notice->uri);
  192. }
  193. function getRSVPs()
  194. {
  195. return RSVP::forEvent($this);
  196. }
  197. function getRSVP($profile)
  198. {
  199. return RSVP::pkeyGet(array('profile_id' => $profile->id,
  200. 'event_id' => $this->id));
  201. }
  202. }