]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - actions/apitimelinepublic.php
Use array_merge instead of array_replace (same effect, and array_merge works with...
[quix0rs-gnu-social.git] / actions / apitimelinepublic.php
1 <?php
2 /**
3  * StatusNet, the distributed open-source microblogging tool
4  *
5  * Show the public timeline
6  *
7  * PHP version 5
8  *
9  * LICENCE: This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU Affero General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Affero General Public License for more details.
18  *
19  * You should have received a copy of the GNU Affero General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  * @category  API
23  * @package   StatusNet
24  * @author    Craig Andrews <candrews@integralblue.com>
25  * @author    Evan Prodromou <evan@status.net>
26  * @author    Jeffery To <jeffery.to@gmail.com>
27  * @author    mac65 <mac65@mac65.com>
28  * @author    Mike Cochrane <mikec@mikenz.geek.nz>
29  * @author    Robin Millette <robin@millette.info>
30  * @author    Zach Copley <zach@status.net>
31  * @copyright 2009 StatusNet, Inc.
32  * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
33  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
34  * @link      http://status.net/
35  */
36
37 if (!defined('STATUSNET')) {
38     exit(1);
39 }
40
41 require_once INSTALLDIR . '/lib/apiprivateauth.php';
42
43 /**
44  * Returns the most recent notices (default 20) posted by everybody
45  *
46  * @category API
47  * @package  StatusNet
48  * @author   Craig Andrews <candrews@integralblue.com>
49  * @author   Evan Prodromou <evan@status.net>
50  * @author   Jeffery To <jeffery.to@gmail.com>
51  * @author   mac65 <mac65@mac65.com>
52  * @author   Mike Cochrane <mikec@mikenz.geek.nz>
53  * @author   Robin Millette <robin@millette.info>
54  * @author   Zach Copley <zach@status.net>
55  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
56  * @link     http://status.net/
57  */
58
59 /* External API usage documentation. Please update when you change how this method works. */
60
61 /*! @page publictimeline statuses/public_timeline
62
63     @section Description
64     Returns the 20 most recent notices from users throughout the system who have
65     uploaded their own avatars. Depending on configuration, it may or may not
66     not include notices from automatic posting services.
67
68     @par URL patterns
69     @li /api/statuses/public_timeline.:format
70
71     @par Formats (:format)
72     xml, json, rss, atom
73
74     @par HTTP Method(s)
75     GET
76
77     @par Requires Authentication
78     No
79
80     @param since_id (Optional) Returns only statuses with an ID greater
81     than (that is, more recent than) the specified ID.
82     @param max_id (Optional) Returns only statuses with an ID less than
83     (that is, older than) or equal to the specified ID.
84     @param count (Optional) Specifies the number of statuses to retrieve.
85     @param page (Optional) Specifies the page of results to retrieve.
86
87     @sa @ref apiroot
88
89     @subsection usagenotes Usage notes
90     @li The URL pattern is relative to the @ref apiroot.
91     @li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
92     to encode the latitude and longitude (see example response below <georss:point>).
93
94     @subsection exampleusage Example usage
95
96     @verbatim
97     curl http://identi.ca/api/statuses/friends_timeline/evan.xml?count=1&page=2
98     @endverbatim
99
100     @subsection exampleresponse Example response
101
102     @verbatim
103     <?xml version="1.0" encoding="UTF-8"?>
104     <statuses type="array">
105      <status>
106       <text>@skwashd oh, commbank reenabled me super quick both times. but disconcerting when you don't expect it though</text>
107       <truncated>false</truncated>
108       <created_at>Sat Apr 17 00:49:12 +0000 2010</created_at>
109       <in_reply_to_status_id>28838393</in_reply_to_status_id>
110       <source>xmpp</source>
111       <id>28838456</id>
112       <in_reply_to_user_id>39303</in_reply_to_user_id>
113       <in_reply_to_screen_name>skwashd</in_reply_to_screen_name>
114       <geo></geo>
115       <favorited>false</favorited>
116       <user>
117        <id>44517</id>
118        <name>joshua may</name>
119        <screen_name>notjosh</screen_name>
120        <location></location>
121        <description></description>
122        <profile_image_url>http://avatar.identi.ca/44517-48-20090321004106.jpeg</profile_image_url>
123        <url></url>
124        <protected>false</protected>
125        <followers_count>17</followers_count>
126        <profile_background_color></profile_background_color>
127        <profile_text_color></profile_text_color>
128        <profile_link_color></profile_link_color>
129        <profile_sidebar_fill_color></profile_sidebar_fill_color>
130        <profile_sidebar_border_color></profile_sidebar_border_color>
131        <friends_count>20</friends_count>
132        <created_at>Sat Mar 21 00:40:25 +0000 2009</created_at>
133        <favourites_count>0</favourites_count>
134        <utc_offset>0</utc_offset>
135        <time_zone>UTC</time_zone>
136        <profile_background_image_url></profile_background_image_url>
137        <profile_background_tile>false</profile_background_tile>
138        <statuses_count>100</statuses_count>
139        <following>false</following>
140        <notifications>false</notifications>
141     </user>
142     </status>
143     [....]
144     </statuses>
145 @endverbatim
146 */
147 class ApiTimelinePublicAction extends ApiPrivateAuthAction
148 {
149     var $notices = null;
150
151     /**
152      * Take arguments for running
153      *
154      * @param array $args $_REQUEST args
155      *
156      * @return boolean success flag
157      *
158      */
159     function prepare($args)
160     {
161         parent::prepare($args);
162
163         $this->notices = $this->getNotices();
164
165         return true;
166     }
167
168     /**
169      * Handle the request
170      *
171      * Just show the notices
172      *
173      * @param array $args $_REQUEST data (unused)
174      *
175      * @return void
176      */
177     function handle($args)
178     {
179         parent::handle($args);
180         $this->showTimeline();
181     }
182
183     /**
184      * Show the timeline of notices
185      *
186      * @return void
187      */
188     function showTimeline()
189     {
190         $sitename   = common_config('site', 'name');
191         $sitelogo   = (common_config('site', 'logo')) ? common_config('site', 'logo') : Theme::path('logo.png');
192         // TRANS: Title for site timeline. %s is the StatusNet sitename.
193         $title      = sprintf(_("%s public timeline"), $sitename);
194         $taguribase = TagURI::base();
195         $id         = "tag:$taguribase:PublicTimeline";
196         $link       = common_local_url('public');
197         $self       = $this->getSelfUri();
198         // TRANS: Subtitle for site timeline. %s is the StatusNet sitename.
199         $subtitle   = sprintf(_("%s updates from everyone!"), $sitename);
200
201         switch($this->format) {
202         case 'xml':
203             $this->showXmlTimeline($this->notices);
204             break;
205         case 'rss':
206             $this->showRssTimeline(
207                 $this->notices,
208                 $title,
209                 $link,
210                 $subtitle,
211                 null,
212                 $sitelogo,
213                 $self
214             );
215             break;
216         case 'atom':
217
218             header('Content-Type: application/atom+xml; charset=utf-8');
219
220             $atom = new AtomNoticeFeed($this->auth_user);
221
222             $atom->setId($id);
223             $atom->setTitle($title);
224             $atom->setSubtitle($subtitle);
225             $atom->setLogo($sitelogo);
226             $atom->setUpdated('now');
227             $atom->addLink(common_local_url('public'));
228             $atom->setSelfLink($self);
229             $atom->addEntryFromNotices($this->notices);
230
231             $this->raw($atom->getString());
232
233             break;
234         case 'json':
235             $this->showJsonTimeline($this->notices);
236             break;
237         case 'as':
238             header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
239             $doc = new ActivityStreamJSONDocument($this->auth_user);
240             $doc->setTitle($title);
241             $doc->addLink($link, 'alternate', 'text/html');
242             $doc->addItemsFromNotices($this->notices);
243             $this->raw($doc->asString());
244             break;
245         default:
246             // TRANS: Client error displayed when coming across a non-supported API method.
247             $this->clientError(_('API method not found.'), $code = 404);
248             break;
249         }
250     }
251
252     /**
253      * Get notices
254      *
255      * @return array notices
256      */
257     function getNotices()
258     {
259         $notices = array();
260
261         $profile = ($this->auth_user) ? $this->auth_user->getProfile() : null;
262
263         $stream = new PublicNoticeStream($profile);
264
265         $notice = $stream->getNotices(($this->page - 1) * $this->count,
266                                       $this->count,
267                                       $this->since_id,
268                                       $this->max_id);
269
270         $notices = $notice->fetchAll();
271
272         NoticeList::prefill($notices);
273
274         return $notices;
275     }
276
277     /**
278      * Is this action read only?
279      *
280      * @param array $args other arguments
281      *
282      * @return boolean true
283      */
284     function isReadOnly($args)
285     {
286         return true;
287     }
288
289     /**
290      * When was this feed last modified?
291      *
292      * @return string datestamp of the latest notice in the stream
293      */
294     function lastModified()
295     {
296         if (!empty($this->notices) && (count($this->notices) > 0)) {
297             return strtotime($this->notices[0]->created);
298         }
299
300         return null;
301     }
302
303     /**
304      * An entity tag for this stream
305      *
306      * Returns an Etag based on the action name, language, and
307      * timestamps of the first and last notice in the timeline
308      *
309      * @return string etag
310      */
311     function etag()
312     {
313         if (!empty($this->notices) && (count($this->notices) > 0)) {
314
315             $last = count($this->notices) - 1;
316
317             return '"' . implode(
318                 ':',
319                 array($this->arg('action'),
320                       common_user_cache_hash($this->auth_user),
321                       common_language(),
322                       strtotime($this->notices[0]->created),
323                       strtotime($this->notices[$last]->created))
324             )
325             . '"';
326         }
327
328         return null;
329     }
330 }