]> git.mxchange.org Git - friendica.git/blob - include/cronjobs.php
Merge pull request #3284 from annando/issue-3278
[friendica.git] / include / cronjobs.php
1 <?php
2 use \Friendica\Core\Config;
3
4 function cronjobs_run(&$argv, &$argc){
5         global $a;
6
7         require_once('include/datetime.php');
8         require_once('include/ostatus.php');
9         require_once('include/post_update.php');
10         require_once('mod/nodeinfo.php');
11         require_once('include/photos.php');
12         require_once('include/user.php');
13         require_once('include/socgraph.php');
14         require_once('include/Probe.php');
15
16         // No parameter set? So return
17         if ($argc <= 1) {
18                 return;
19         }
20
21         logger("Starting cronjob ".$argv[1], LOGGER_DEBUG);
22
23         // Check OStatus conversations
24         // Check only conversations with mentions (for a longer time)
25         if ($argv[1] == 'ostatus_mentions') {
26                 ostatus::check_conversations(true);
27                 return;
28         }
29
30         // Check every conversation
31         if ($argv[1] == 'ostatus_conversations') {
32                 ostatus::check_conversations(false);
33                 return;
34         }
35
36         // Call possible post update functions
37         // see include/post_update.php for more details
38         if ($argv[1] == 'post_update') {
39                 post_update();
40                 return;
41         }
42
43         // update nodeinfo data
44         if ($argv[1] == 'nodeinfo') {
45                 nodeinfo_cron();
46                 return;
47         }
48
49         // Expire and remove user entries
50         if ($argv[1] == 'expire_and_remove_users') {
51                 cron_expire_and_remove_users();
52                 return;
53         }
54
55         if ($argv[1] == 'update_contact_birthdays') {
56                 update_contact_birthdays();
57                 return;
58         }
59
60         if ($argv[1] == 'update_photo_albums') {
61                 cron_update_photo_albums();
62                 return;
63         }
64
65         // Clear cache entries
66         if ($argv[1] == 'clear_cache') {
67                 cron_clear_cache($a);
68                 return;
69         }
70
71         // Repair missing Diaspora values in contacts
72         if ($argv[1] == 'repair_diaspora') {
73                 cron_repair_diaspora($a);
74                 return;
75         }
76
77         // Repair entries in the database
78         if ($argv[1] == 'repair_database') {
79                 cron_repair_database();
80                 return;
81         }
82
83         logger("Xronjob ".$argv[1]." is unknown.", LOGGER_DEBUG);
84
85         return;
86 }
87
88 /**
89  * @brief Update the cached values for the number of photo albums per user
90  */
91 function cron_update_photo_albums() {
92         $r = q("SELECT `uid` FROM `user` WHERE NOT `account_expired` AND NOT `account_removed`");
93         if (!dbm::is_result($r)) {
94                 return;
95         }
96
97         foreach ($r AS $user) {
98                 photo_albums($user['uid'], true);
99         }
100 }
101
102 /**
103  * @brief Expire and remove user entries
104  */
105 function cron_expire_and_remove_users() {
106         // expire any expired accounts
107         q("UPDATE user SET `account_expired` = 1 where `account_expired` = 0
108                 AND `account_expires_on` > '%s'
109                 AND `account_expires_on` < UTC_TIMESTAMP()", dbesc(NULL_DATE));
110
111         // delete user and contact records for recently removed accounts
112         $r = q("SELECT * FROM `user` WHERE `account_removed` AND `account_expires_on` < UTC_TIMESTAMP() - INTERVAL 3 DAY");
113         if (dbm::is_result($r)) {
114                 foreach ($r as $user) {
115                         q("DELETE FROM `contact` WHERE `uid` = %d", intval($user['uid']));
116                         q("DELETE FROM `user` WHERE `uid` = %d", intval($user['uid']));
117                 }
118         }
119 }
120
121 /**
122  * @brief Clear cache entries
123  *
124  * @param App $a
125  */
126 function cron_clear_cache(App $a) {
127
128         $last = get_config('system','cache_last_cleared');
129
130         if ($last) {
131                 $next = $last + (3600); // Once per hour
132                 $clear_cache = ($next <= time());
133         } else {
134                 $clear_cache = true;
135         }
136
137         if (!$clear_cache) {
138                 return;
139         }
140
141         // clear old cache
142         Cache::clear();
143
144         // clear old item cache files
145         clear_cache();
146
147         // clear cache for photos
148         clear_cache($a->get_basepath(), $a->get_basepath()."/photo");
149
150         // clear smarty cache
151         clear_cache($a->get_basepath()."/view/smarty3/compiled", $a->get_basepath()."/view/smarty3/compiled");
152
153         // clear cache for image proxy
154         if (!get_config("system", "proxy_disabled")) {
155                 clear_cache($a->get_basepath(), $a->get_basepath()."/proxy");
156
157                 $cachetime = get_config('system','proxy_cache_time');
158                 if (!$cachetime) {
159                         $cachetime = PROXY_DEFAULT_TIME;
160                 }
161                 q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%" AND `created` < NOW() - INTERVAL %d SECOND', $cachetime);
162         }
163
164         // Delete the cached OEmbed entries that are older than one year
165         q("DELETE FROM `oembed` WHERE `created` < NOW() - INTERVAL 3 MONTH");
166
167         // Delete the cached "parse_url" entries that are older than one year
168         q("DELETE FROM `parsed_url` WHERE `created` < NOW() - INTERVAL 3 MONTH");
169
170         // Maximum table size in megabyte
171         $max_tablesize = intval(get_config('system','optimize_max_tablesize')) * 1000000;
172         if ($max_tablesize == 0) {
173                 $max_tablesize = 100 * 1000000; // Default are 100 MB
174         }
175         if ($max_tablesize > 0) {
176                 // Minimum fragmentation level in percent
177                 $fragmentation_level = intval(get_config('system','optimize_fragmentation')) / 100;
178                 if ($fragmentation_level == 0) {
179                         $fragmentation_level = 0.3; // Default value is 30%
180                 }
181
182                 // Optimize some tables that need to be optimized
183                 $r = q("SHOW TABLE STATUS");
184                 foreach ($r as $table) {
185
186                         // Don't optimize tables that are too large
187                         if ($table["Data_length"] > $max_tablesize) {
188                                 continue;
189                         }
190
191                         // Don't optimize empty tables
192                         if ($table["Data_length"] == 0) {
193                                 continue;
194                         }
195
196                         // Calculate fragmentation
197                         $fragmentation = $table["Data_free"] / ($table["Data_length"] + $table["Index_length"]);
198
199                         logger("Table ".$table["Name"]." - Fragmentation level: ".round($fragmentation * 100, 2), LOGGER_DEBUG);
200
201                         // Don't optimize tables that needn't to be optimized
202                         if ($fragmentation < $fragmentation_level) {
203                                 continue;
204                         }
205
206                         // So optimize it
207                         logger("Optimize Table ".$table["Name"], LOGGER_DEBUG);
208                         q("OPTIMIZE TABLE `%s`", dbesc($table["Name"]));
209                 }
210         }
211
212         set_config('system','cache_last_cleared', time());
213 }
214
215 /**
216  * @brief Repair missing values in Diaspora contacts
217  *
218  * @param App $a
219  */
220 function cron_repair_diaspora(App $a) {
221
222         $starttime = time();
223
224         $r = q("SELECT `id`, `url` FROM `contact`
225                 WHERE `network` = '%s' AND (`batch` = '' OR `notify` = '' OR `poll` = '' OR pubkey = '')
226                         ORDER BY RAND() LIMIT 50", dbesc(NETWORK_DIASPORA));
227         if (!dbm::is_result($r)) {
228                 return;
229         }
230
231         foreach ($r AS $contact) {
232                 // Quit the loop after 3 minutes
233                 if (time() > ($starttime + 180)) {
234                         return;
235                 }
236
237                 if (!poco_reachable($contact["url"])) {
238                         continue;
239                 }
240
241                 $data = Probe::uri($contact["url"]);
242                 if ($data["network"] != NETWORK_DIASPORA) {
243                         continue;
244                 }
245
246                 logger("Repair contact ".$contact["id"]." ".$contact["url"], LOGGER_DEBUG);
247                 q("UPDATE `contact` SET `batch` = '%s', `notify` = '%s', `poll` = '%s', pubkey = '%s' WHERE `id` = %d",
248                         dbesc($data["batch"]), dbesc($data["notify"]), dbesc($data["poll"]), dbesc($data["pubkey"]),
249                         intval($contact["id"]));
250         }
251 }
252
253 /**
254  * @brief Do some repairs in database entries
255  *
256  */
257 function cron_repair_database() {
258
259         // Sometimes there seem to be issues where the "self" contact vanishes.
260         // We haven't found the origin of the problem by now.
261         $r = q("SELECT `uid` FROM `user` WHERE NOT EXISTS (SELECT `uid` FROM `contact` WHERE `contact`.`uid` = `user`.`uid` AND `contact`.`self`)");
262         if (dbm::is_result($r)) {
263                 foreach ($r AS $user) {
264                         logger('Create missing self contact for user '.$user['uid']);
265                         user_create_self_contact($user['uid']);
266                 }
267         }
268
269         // Set the parent if it wasn't set. (Shouldn't happen - but does sometimes)
270         // This call is very "cheap" so we can do it at any time without a problem
271         q("UPDATE `item` INNER JOIN `item` AS `parent` ON `parent`.`uri` = `item`.`parent-uri` AND `parent`.`uid` = `item`.`uid` SET `item`.`parent` = `parent`.`id` WHERE `item`.`parent` = 0");
272
273         // There was an issue where the nick vanishes from the contact table
274         q("UPDATE `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` SET `nick` = `nickname` WHERE `self` AND `nick`=''");
275
276         // Update the global contacts for local users
277         $r = q("SELECT `uid` FROM `user` WHERE `verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired`");
278         if (dbm::is_result($r)) {
279                 foreach ($r AS $user) {
280                         update_gcontact_for_user($user["uid"]);
281                 }
282         }
283
284         /// @todo
285         /// - remove thread entries without item
286         /// - remove sign entries without item
287         /// - remove children when parent got lost
288         /// - set contact-id in item when not present
289 }