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