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