]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Sitemap/Sitemap_notice_count.php
Localisation updates from http://translatewiki.net.
[quix0rs-gnu-social.git] / plugins / Sitemap / Sitemap_notice_count.php
1 <?php
2 /**
3  * Data class for counting notice postings by date
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) 2010, 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
30 if (!defined('STATUSNET')) {
31     exit(1);
32 }
33
34 require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
35
36 /**
37  * Data class for counting notices by date
38  *
39  * We make a separate sitemap for each notice posted by date.
40  * To save ourselves some (not inconsiderable) processing effort,
41  * we cache this data in the sitemap_notice_count table. Each
42  * row represents a day since the site has been started, with a count
43  * of notices posted on that day. Since, after the end of the day,
44  * this number doesn't change, it's a good candidate for persistent caching.
45  *
46  * @category Data
47  * @package  StatusNet
48  * @author   Evan Prodromou <evan@status.net>
49  * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
50  * @link     http://status.net/
51  *
52  * @see      DB_DataObject
53  */
54 class Sitemap_notice_count extends Memcached_DataObject
55 {
56     public $__table = 'sitemap_notice_count'; // table name
57
58     public $notice_date;                       // date primary_key not_null
59     public $notice_count;                      // int(4)
60     public $created;
61     public $modified;
62
63     /**
64      * Get an instance by key
65      *
66      * This is a utility method to get a single instance with a given key value.
67      *
68      * @param string $k Key to use to lookup (usually 'notice_id' for this class)
69      * @param mixed  $v Value to lookup
70      *
71      * @return Sitemap_notice_count object found, or null for no hits
72      *
73      */
74     function staticGet($k, $v=null)
75     {
76         return Memcached_DataObject::staticGet('Sitemap_notice_count', $k, $v);
77     }
78
79     /**
80      * return table definition for DB_DataObject
81      *
82      * DB_DataObject needs to know something about the table to manipulate
83      * instances. This method provides all the DB_DataObject needs to know.
84      *
85      * @return array array of column definitions
86      */
87     function table()
88     {
89         return array('notice_date' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_NOTNULL,
90                      'notice_count' => DB_DATAOBJECT_INT,
91                      'created'   => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL,
92                      'modified'  => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
93     }
94
95     /**
96      * return key definitions for DB_DataObject
97      *
98      * DB_DataObject needs to know about keys that the table has; this function
99      * defines them.
100      *
101      * @return array key definitions
102      */
103     function keys()
104     {
105         return array('notice_date' => 'K');
106     }
107
108     /**
109      * return key definitions for Memcached_DataObject
110      *
111      * Our caching system uses the same key definitions, but uses a different
112      * method to get them.
113      *
114      * @return array key definitions
115      */
116     function keyTypes()
117     {
118         return $this->keys();
119     }
120
121     static function getAll()
122     {
123         $noticeCounts = self::cacheGet('sitemap:notice:counts');
124
125         if ($noticeCounts === false) {
126             $snc = new Sitemap_notice_count();
127             $snc->orderBy('notice_date DESC');
128
129             // Fetch the first one to check up-to-date-itude
130
131             $n = $snc->find(true);
132
133             $today = self::today();
134             $noticeCounts = array();
135
136             if (!$n) { // No counts saved yet
137                 $noticeCounts = self::initializeCounts();
138             } else if ($snc->notice_date < $today) { // There are counts but not up to today
139                 $noticeCounts = self::fillInCounts($snc->notice_date);
140             } else if ($snc->notice_date == $today) { // Refresh today's
141                 $noticeCounts[$today] = self::updateToday();
142             }
143
144             // starts with second-to-last date
145
146             while ($snc->fetch()) {
147                 $noticeCounts[$snc->notice_date] = $snc->notice_count;
148             }
149
150             // Cache notice counts for 4 hours.
151
152             self::cacheSet('sitemap:notice:counts', $noticeCounts, null, time() + 4 * 60 * 60);
153         }
154
155         return $noticeCounts;
156     }
157
158     static function initializeCounts()
159     {
160         $firstDate = self::getFirstDate(); // awww
161         $today     = self::today();
162
163         $counts = array();
164
165         for ($d = $firstDate; $d <= $today; $d = self::incrementDay($d)) {
166             $n = self::getCount($d);
167             self::insertCount($d, $n);
168             $counts[$d] = $n;
169         }
170
171         return $counts;
172     }
173
174     static function fillInCounts($lastDate)
175     {
176         $today = self::today();
177
178         $counts = array();
179
180         $n = self::getCount($lastDate);
181         self::updateCount($lastDate, $n);
182
183         $counts[$lastDate] = $n;
184
185         for ($d = self::incrementDay($lastDate); $d <= $today; $d = self::incrementDay($d)) {
186             $n = self::getCount($d);
187             self::insertCount($d, $n);
188         }
189
190         return $counts;
191     }
192
193     static function updateToday()
194     {
195         $today = self::today();
196
197         $n = self::getCount($today);
198         self::updateCount($today, $n);
199
200         return $n;
201     }
202
203     static function getCount($d)
204     {
205         $notice = new Notice();
206         $notice->whereAdd('created BETWEEN "'.$d.' 00:00:00" AND "'.self::incrementDay($d).' 00:00:00"');
207         $notice->whereAdd('is_local = ' . Notice::LOCAL_PUBLIC);
208         $n = $notice->count();
209
210         return $n;
211     }
212
213     static function insertCount($d, $n)
214     {
215         $snc = new Sitemap_notice_count();
216
217         $snc->notice_date = DB_DataObject_Cast::date($d);
218
219         $snc->notice_count      = $n;
220         $snc->created           = common_sql_now();
221         $snc->modified          = $snc->created;
222
223         if (!$snc->insert()) {
224             common_log(LOG_WARNING, "Could not save user counts for '$d'");
225         }
226     }
227
228     static function updateCount($d, $n)
229     {
230         $snc = Sitemap_notice_count::staticGet('notice_date', DB_DataObject_Cast::date($d));
231
232         if (empty($snc)) {
233             // TRANS: Exception
234             throw new Exception(_m("No such registration date: $d."));
235         }
236
237         $orig = clone($snc);
238
239         $snc->notice_date = DB_DataObject_Cast::date($d);
240
241         $snc->notice_count      = $n;
242         $snc->created           = common_sql_now();
243         $snc->modified          = $snc->created;
244
245         if (!$snc->update($orig)) {
246             common_log(LOG_WARNING, "Could not save user counts for '$d'");
247         }
248     }
249
250     static function incrementDay($d)
251     {
252         $dt = self::dateStrToInt($d);
253         return self::dateIntToStr($dt + 24 * 60 * 60);
254     }
255
256     static function dateStrToInt($d)
257     {
258         return strtotime($d.' 00:00:00');
259     }
260
261     static function dateIntToStr($dt)
262     {
263         return date('Y-m-d', $dt);
264     }
265
266     static function getFirstDate()
267     {
268         $n = new Notice();
269
270         $n->selectAdd();
271         $n->selectAdd('date(min(created)) as first_date');
272
273         if ($n->find(true)) {
274             return $n->first_date;
275         } else {
276             // Is this right?
277             return self::dateIntToStr(time());
278         }
279     }
280
281     static function today()
282     {
283         return self::dateIntToStr(time());
284     }
285 }