SubMirror.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. /*
  3. * StatusNet - the distributed open-source microblogging tool
  4. * Copyright (C) 2010, StatusNet, Inc.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /**
  20. * @package SubMirrorPlugin
  21. * @maintainer Brion Vibber <brion@status.net>
  22. */
  23. class SubMirror extends Managed_DataObject
  24. {
  25. public $__table = 'submirror';
  26. public $subscriber;
  27. public $subscribed;
  28. public $style;
  29. public $created;
  30. public $modified;
  31. /**
  32. * return table definition for DB_DataObject
  33. *
  34. * DB_DataObject needs to know something about the table to manipulate
  35. * instances. This method provides all the DB_DataObject needs to know.
  36. *
  37. * @return array array of column definitions
  38. */
  39. function table()
  40. {
  41. return array('subscriber' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
  42. 'subscribed' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
  43. 'style' => DB_DATAOBJECT_STR,
  44. 'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL,
  45. 'modified' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
  46. }
  47. static function schemaDef()
  48. {
  49. // @fixme need a reverse key on (subscribed, subscriber) as well
  50. return array(new ColumnDef('subscriber', 'integer',
  51. null, false, 'PRI'),
  52. new ColumnDef('subscribed', 'integer',
  53. null, false, 'PRI'),
  54. new ColumnDef('style', 'varchar',
  55. 16, true),
  56. new ColumnDef('created', 'datetime',
  57. null, false),
  58. new ColumnDef('modified', 'datetime',
  59. null, false));
  60. }
  61. /**
  62. * Temporary hack to set up the compound index, since we can't do
  63. * it yet through regular Schema interface. (Coming for 1.0...)
  64. *
  65. * @param Schema $schema
  66. * @return void
  67. */
  68. static function fixIndexes($schema)
  69. {
  70. try {
  71. $schema->createIndex('submirror', array('subscribed', 'subscriber'));
  72. } catch (Exception $e) {
  73. common_log(LOG_ERR, __METHOD__ . ': ' . $e->getMessage());
  74. }
  75. }
  76. /**
  77. * return key definitions for DB_DataObject
  78. *
  79. * DB_DataObject needs to know about keys that the table has; this function
  80. * defines them.
  81. *
  82. * @return array key definitions
  83. */
  84. function keys()
  85. {
  86. return array_keys($this->keyTypes());
  87. }
  88. /**
  89. * return key definitions for Memcached_DataObject
  90. *
  91. * Our caching system uses the same key definitions, but uses a different
  92. * method to get them.
  93. *
  94. * @return array key definitions
  95. */
  96. function keyTypes()
  97. {
  98. // @todo FIXME keys
  99. // need a sane key for reverse lookup too
  100. return array('subscriber' => 'K', 'subscribed' => 'K');
  101. }
  102. function sequenceKey()
  103. {
  104. return array(false, false, false);
  105. }
  106. /**
  107. * @param Profile $subscribed
  108. * @param Profile $subscribed
  109. * @return SubMirror
  110. * @throws ServerException
  111. */
  112. public static function saveMirror($subscriber, $subscribed, $style='repeat')
  113. {
  114. // @fixme make sure they're subscribed!
  115. $mirror = new SubMirror();
  116. $mirror->subscriber = $subscriber->id;
  117. $mirror->subscribed = $subscribed->id;
  118. $mirror->style = $style;
  119. $mirror->created = common_sql_now();
  120. $mirror->modified = common_sql_now();
  121. $mirror->insert();
  122. return $mirror;
  123. }
  124. /**
  125. * @param Notice $notice
  126. * @return mixed Notice on successful mirroring, boolean if not
  127. */
  128. public function mirrorNotice(Notice $notice)
  129. {
  130. $profile = Profile::getKV('id', $this->subscriber);
  131. if (!($profile instanceof Profile)) {
  132. common_log(LOG_ERR, "SubMirror plugin skipping auto-repeat of notice $notice->id for missing user $profile->id");
  133. return false;
  134. }
  135. if ($this->style == 'copy') {
  136. return $this->copyNotice($profile, $notice);
  137. } else { // default to repeat mode
  138. return $this->repeatNotice($profile, $notice);
  139. }
  140. }
  141. /**
  142. * Mirror a notice using StatusNet's repeat functionality.
  143. * This retains attribution within the site, and other nice things,
  144. * but currently ends up looking like 'RT @foobar bla bla' when
  145. * bridged out over OStatus or TwitterBridge.
  146. *
  147. * @param Notice $notice
  148. * @return mixed Notice on successful repeat, true if already repeated, false on failure
  149. */
  150. protected function repeatNotice(Profile $profile, Notice $notice)
  151. {
  152. if($profile->hasRepeated($notice)) {
  153. common_log(LOG_INFO, "SubMirror plugin skipping auto-repeat of notice $notice->id for user $profile->id; already repeated.");
  154. return true;
  155. } else {
  156. common_log(LOG_INFO, "SubMirror plugin auto-repeating notice $notice->id for $profile->id");
  157. return $notice->repeat($profile, 'mirror');
  158. }
  159. }
  160. /**
  161. * Mirror a notice by emitting a new notice with the same contents.
  162. * Kind of dirty, but if pulling an external data feed into an account
  163. * that may be what you want.
  164. *
  165. * @param Notice $notice
  166. * @return mixed Notice on successful repeat, true if already repeated, false on failure
  167. */
  168. protected function copyNotice($profile, $notice)
  169. {
  170. $options = array('is_local' => Notice::LOCAL_PUBLIC,
  171. 'url' => $notice->getUrl(), // pass through the foreign link...
  172. 'rendered' => $notice->rendered);
  173. $saved = Notice::saveNew($profile->id,
  174. $notice->content,
  175. 'feed',
  176. $options);
  177. return $saved;
  178. }
  179. /**
  180. * Get the mirroring setting for a pair of profiles, if existing.
  181. *
  182. * @param Profile $subscriber
  183. * @param Profile $subscribed
  184. * @return mixed Profile or empty
  185. */
  186. public static function getMirror($subscriber, $subscribed)
  187. {
  188. return self::pkeyGet(array('subscriber' => $subscriber->id,
  189. 'subscribed' => $subscribed->id));
  190. }
  191. }