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