]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Sitemap/Sitemap_notice_count.php
9e523dfbc7dda8792af18c2c77633cd8d9119e31
[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 Managed_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;                           // datetime()   not_null
61     public $modified;                          // datetime   not_null default_0000-00-00%2000%3A00%3A00
62
63     public static function schemaDef()
64     {
65         return array(
66             'fields' => array(
67                 'notice_date' => array('type' => 'date', 'not null' => true, 'description' => 'record date'),
68                 'notice_count' => array('type' => 'int', 'not null' => true, 'description' => 'the notice count'),
69                 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
70                 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
71             ),
72             'primary key' => array('notice_date'),
73         );
74     }
75
76     static function getAll()
77     {
78         $noticeCounts = self::cacheGet('sitemap:notice:counts');
79
80         if ($noticeCounts === false) {
81             $snc = new Sitemap_notice_count();
82             $snc->orderBy('notice_date DESC');
83
84             // Fetch the first one to check up-to-date-itude
85
86             $n = $snc->find(true);
87
88             $today = self::today();
89             $noticeCounts = array();
90
91             if (!$n) { // No counts saved yet
92                 $noticeCounts = self::initializeCounts();
93             } else if ($snc->notice_date < $today) { // There are counts but not up to today
94                 $noticeCounts = self::fillInCounts($snc->notice_date);
95             } else if ($snc->notice_date == $today) { // Refresh today's
96                 $noticeCounts[$today] = self::updateToday();
97             }
98
99             // starts with second-to-last date
100
101             while ($snc->fetch()) {
102                 $noticeCounts[$snc->notice_date] = $snc->notice_count;
103             }
104
105             // Cache notice counts for 4 hours.
106
107             self::cacheSet('sitemap:notice:counts', $noticeCounts, null, time() + 4 * 60 * 60);
108         }
109
110         return $noticeCounts;
111     }
112
113     static function initializeCounts()
114     {
115         $firstDate = self::getFirstDate(); // awww
116         $today     = self::today();
117
118         $counts = array();
119
120         for ($d = $firstDate; $d <= $today; $d = self::incrementDay($d)) {
121             $n = self::getCount($d);
122             self::insertCount($d, $n);
123             $counts[$d] = $n;
124         }
125
126         return $counts;
127     }
128
129     static function fillInCounts($lastDate)
130     {
131         $today = self::today();
132
133         $counts = array();
134
135         $n = self::getCount($lastDate);
136         self::updateCount($lastDate, $n);
137
138         $counts[$lastDate] = $n;
139
140         for ($d = self::incrementDay($lastDate); $d <= $today; $d = self::incrementDay($d)) {
141             $n = self::getCount($d);
142             self::insertCount($d, $n);
143         }
144
145         return $counts;
146     }
147
148     static function updateToday()
149     {
150         $today = self::today();
151
152         $n = self::getCount($today);
153         self::updateCount($today, $n);
154
155         return $n;
156     }
157
158     static function getCount($d)
159     {
160         $notice = new Notice();
161         $notice->whereAdd('created BETWEEN "'.$d.' 00:00:00" AND "'.self::incrementDay($d).' 00:00:00"');
162         $notice->whereAdd('is_local = ' . Notice::LOCAL_PUBLIC);
163         $n = $notice->count();
164
165         return $n;
166     }
167
168     static function insertCount($d, $n)
169     {
170         $snc = new Sitemap_notice_count();
171
172         $snc->notice_date = DB_DataObject_Cast::date($d);
173
174         $snc->notice_count      = $n;
175         $snc->created           = common_sql_now();
176         $snc->modified          = $snc->created;
177
178         if (!$snc->insert()) {
179             common_log(LOG_WARNING, "Could not save user counts for '$d'");
180         }
181     }
182
183     static function updateCount($d, $n)
184     {
185         $snc = Sitemap_notice_count::getKV('notice_date', DB_DataObject_Cast::date($d));
186
187         if (empty($snc)) {
188             // TRANS: Exception
189             throw new Exception(_m("No such registration date: $d."));
190         }
191
192         $orig = clone($snc);
193
194         $snc->notice_date = DB_DataObject_Cast::date($d);
195
196         $snc->notice_count      = $n;
197         $snc->created           = common_sql_now();
198         $snc->modified          = $snc->created;
199
200         if (!$snc->update($orig)) {
201             common_log(LOG_WARNING, "Could not save user counts for '$d'");
202         }
203     }
204
205     static function incrementDay($d)
206     {
207         $dt = self::dateStrToInt($d);
208         return self::dateIntToStr($dt + 24 * 60 * 60);
209     }
210
211     static function dateStrToInt($d)
212     {
213         return strtotime($d.' 00:00:00');
214     }
215
216     static function dateIntToStr($dt)
217     {
218         return date('Y-m-d', $dt);
219     }
220
221     static function getFirstDate()
222     {
223         $n = new Notice();
224
225         $n->selectAdd();
226         $n->selectAdd('date(min(created)) as first_date');
227
228         if ($n->find(true)) {
229             return $n->first_date;
230         } else {
231             // Is this right?
232             return self::dateIntToStr(time());
233         }
234     }
235
236     static function today()
237     {
238         return self::dateIntToStr(time());
239     }
240 }