The official, canonical postActiv repository. http://www.postactiv.com

apisubscriptions.php 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <?php
  2. /* ============================================================================
  3. * Title: APISubscriptions
  4. * Base class for showing subscription information in the API
  5. *
  6. * postActiv:
  7. * the micro-blogging software
  8. *
  9. * Copyright:
  10. * Copyright (C) 2016-2018, Maiyannah Bishop
  11. *
  12. * Derived from code copyright various sources:
  13. * o GNU Social (C) 2013-2016, Free Software Foundation, Inc
  14. * o StatusNet (C) 2008-2012, StatusNet, Inc
  15. * ----------------------------------------------------------------------------
  16. * License:
  17. * This program is free software: you can redistribute it and/or modify
  18. * it under the terms of the GNU Affero General Public License as published by
  19. * the Free Software Foundation, either version 3 of the License, or
  20. * (at your option) any later version.
  21. *
  22. * This program is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. * GNU Affero General Public License for more details.
  26. *
  27. * You should have received a copy of the GNU Affero General Public License
  28. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  29. *
  30. * <https://www.gnu.org/licenses/agpl.html>
  31. * ----------------------------------------------------------------------------
  32. * About:
  33. * Base class for showing subscription information in the API
  34. *
  35. * PHP version:
  36. * Tested with PHP 7.0
  37. * ----------------------------------------------------------------------------
  38. * File Authors:
  39. * @author Dan Moore <dan@moore.cx>
  40. * @author Evan Prodromou
  41. * @author Zach Copley <zach@copley.name>
  42. * @author Maiyannah Bishop <maiyannah.bishop@postactiv.com>
  43. *
  44. * Web:
  45. * o postActiv <http://www.postactiv.com>
  46. * o GNU social <https://www.gnu.org/s/social/>
  47. * ============================================================================
  48. */
  49. // This file is formatted so that it provides useful documentation output in
  50. // NaturalDocs. Please be considerate of this before changing formatting.
  51. if (!defined('POSTACTIV')) { exit(1); }
  52. /**
  53. * This class outputs a list of profiles as Twitter-style user and status objects.
  54. * It is used by the API methods /api/statuses/(friends|followers). To support the
  55. * social graph methods it also can output a simple list of IDs.
  56. */
  57. abstract class ApiSubscriptionsAction extends ApiBareAuthAction
  58. {
  59. var $profiles = null;
  60. var $tag = null;
  61. var $lite = null;
  62. var $ids_only = null;
  63. /**
  64. * Take arguments for running
  65. *
  66. * @param array $args $_REQUEST args
  67. *
  68. * @return boolean success flag
  69. */
  70. protected function prepare(array $args=array())
  71. {
  72. parent::prepare($args);
  73. $this->tag = $this->arg('tag');
  74. // Note: Twitter no longer supports 'lite'
  75. $this->lite = $this->arg('lite');
  76. $this->ids_only = $this->arg('ids_only');
  77. // If called as a social graph method, show 5000 per page, otherwise 100
  78. $this->count = isset($this->ids_only) ?
  79. 5000 : (int)$this->arg('count', 100);
  80. $this->target = $this->getTargetProfile($this->arg('id'));
  81. if (!($this->target instanceof Profile)) {
  82. // TRANS: Client error displayed when requesting a list of followers for a non-existing user.
  83. $this->clientError(_('No such user.'), 404);
  84. }
  85. $this->profiles = $this->getProfiles();
  86. return true;
  87. }
  88. /**
  89. * Handle the request
  90. *
  91. * Show the profiles
  92. *
  93. * @return void
  94. */
  95. protected function handle()
  96. {
  97. parent::handle();
  98. if (!in_array($this->format, array('xml', 'json'))) {
  99. // TRANS: Client error displayed when coming across a non-supported API method.
  100. $this->clientError(_('API method not found.'), 404);
  101. }
  102. $this->initDocument($this->format);
  103. if (isset($this->ids_only)) {
  104. $this->showIds();
  105. } else {
  106. $this->showProfiles(isset($this->lite) ? false : true);
  107. }
  108. $this->endDocument($this->format);
  109. }
  110. /**
  111. * Get profiles related to the type of subscriber/subscription action
  112. *
  113. * @return array Profiles
  114. */
  115. abstract protected function getProfiles();
  116. /**
  117. * Is this action read only?
  118. *
  119. * @param array $args other arguments
  120. *
  121. * @return boolean true
  122. */
  123. function isReadOnly($args)
  124. {
  125. return true;
  126. }
  127. /**
  128. * When was this feed last modified?
  129. *
  130. * @return string datestamp of the latest profile in the stream
  131. */
  132. function lastModified()
  133. {
  134. if (!empty($this->profiles) && (count($this->profiles) > 0)) {
  135. return strtotime($this->profiles[0]->created);
  136. }
  137. return null;
  138. }
  139. /**
  140. * An entity tag for this action
  141. *
  142. * Returns an Etag based on the action name, language, user ID, and
  143. * timestamps of the first and last profiles in the subscriptions list
  144. * There's also an indicator to show whether this action is being called
  145. * as /api/statuses/(friends|followers) or /api/(friends|followers)/ids
  146. *
  147. * @return string etag
  148. */
  149. function etag()
  150. {
  151. if (!empty($this->profiles) && (count($this->profiles) > 0)) {
  152. $last = count($this->profiles) - 1;
  153. return '"' . implode(
  154. ':',
  155. array($this->arg('action'),
  156. common_user_cache_hash($this->auth_user),
  157. common_language(),
  158. $this->target->id,
  159. // Caching tags.
  160. isset($this->ids_only) ? 'IDs' : 'Profiles',
  161. strtotime($this->profiles[0]->created),
  162. strtotime($this->profiles[$last]->created))
  163. )
  164. . '"';
  165. }
  166. return null;
  167. }
  168. /**
  169. * Show the profiles as Twitter-style useres and statuses
  170. *
  171. * @param boolean $include_statuses Whether to include the latest status
  172. * with each user. Default true.
  173. *
  174. * @return void
  175. */
  176. function showProfiles($include_statuses = true)
  177. {
  178. switch ($this->format) {
  179. case 'xml':
  180. $this->elementStart('users', array('type' => 'array',
  181. 'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
  182. foreach ($this->profiles as $profile) {
  183. $this->showProfile(
  184. $profile,
  185. $this->format,
  186. null,
  187. $include_statuses
  188. );
  189. }
  190. $this->elementEnd('users');
  191. break;
  192. case 'json':
  193. $arrays = array();
  194. foreach ($this->profiles as $profile) {
  195. $arrays[] = $this->twitterUserArray(
  196. $profile,
  197. $include_statuses
  198. );
  199. }
  200. print json_encode($arrays);
  201. break;
  202. default:
  203. // TRANS: Client error displayed when requesting profiles of followers in an unsupported format.
  204. $this->clientError(_('Unsupported format.'));
  205. break;
  206. }
  207. }
  208. /**
  209. * Show the IDs of the profiles only. 5000 per page. To support
  210. * the 'social graph' methods: /api/(friends|followers)/ids
  211. *
  212. * @return void
  213. */
  214. function showIds()
  215. {
  216. switch ($this->format) {
  217. case 'xml':
  218. $this->elementStart('ids');
  219. foreach ($this->profiles as $profile) {
  220. $this->element('id', null, $profile->id);
  221. }
  222. $this->elementEnd('ids');
  223. break;
  224. case 'json':
  225. $ids = array();
  226. foreach ($this->profiles as $profile) {
  227. $ids[] = (int)$profile->id;
  228. }
  229. print json_encode($ids);
  230. break;
  231. default:
  232. // TRANS: Client error displayed when requesting IDs of followers in an unsupported format.
  233. $this->clientError(_('Unsupported format.'));
  234. break;
  235. }
  236. }
  237. }
  238. // END OF FILE
  239. // ============================================================================
  240. ?>