]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/Schedulers/_AddJobsHere.php
Release 6.5.15
[Github/sugarcrm.git] / modules / Schedulers / _AddJobsHere.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38
39 /**
40  * Set up an array of Jobs with the appropriate metadata
41  * 'jobName' => array (
42  *              'X' => 'name',
43  * )
44  * 'X' should be an increment of 1
45  * 'name' should be the EXACT name of your function
46  *
47  * Your function should not be passed any parameters
48  * Always  return a Boolean. If it does not the Job will not terminate itself
49  * after completion, and the webserver will be forced to time-out that Job instance.
50  * DO NOT USE sugar_cleanup(); in your function flow or includes.  this will
51  * break Schedulers.  That function is called at the foot of cron.php
52  */
53
54 /**
55  * This array provides the Schedulers admin interface with values for its "Job"
56  * dropdown menu.
57  */
58 $job_strings = array (
59         0 => 'refreshJobs',
60         1 => 'pollMonitoredInboxes',
61         2 => 'runMassEmailCampaign',
62     5 => 'pollMonitoredInboxesForBouncedCampaignEmails',
63         3 => 'pruneDatabase',
64         4 => 'trimTracker',
65         /*4 => 'securityAudit()',*/
66     12 => 'sendEmailReminders',
67     14 => 'cleanJobQueue',
68     15 => 'removeDocumentsFromFS',
69
70 );
71
72 /**
73  * Job 0 refreshes all job schedulers at midnight
74  * DEPRECATED
75  */
76 function refreshJobs() {
77         return true;
78 }
79
80
81 /**
82  * Job 1
83  */
84 function pollMonitoredInboxes() {
85
86     $_bck_up = array('team_id' => $GLOBALS['current_user']->team_id, 'team_set_id' => $GLOBALS['current_user']->team_set_id);
87         $GLOBALS['log']->info('----->Scheduler fired job of type pollMonitoredInboxes()');
88         global $dictionary;
89         global $app_strings;
90
91
92         require_once('modules/Emails/EmailUI.php');
93
94         $ie = new InboundEmail();
95         $emailUI = new EmailUI();
96         $r = $ie->db->query('SELECT id, name FROM inbound_email WHERE is_personal = 0 AND deleted=0 AND status=\'Active\' AND mailbox_type != \'bounce\'');
97         $GLOBALS['log']->debug('Just got Result from get all Inbounds of Inbound Emails');
98
99         while($a = $ie->db->fetchByAssoc($r)) {
100                 $GLOBALS['log']->debug('In while loop of Inbound Emails');
101                 $ieX = new InboundEmail();
102                 $ieX->retrieve($a['id']);
103         $GLOBALS['current_user']->team_id = $ieX->team_id;
104         $GLOBALS['current_user']->team_set_id = $ieX->team_set_id;
105                 $mailboxes = $ieX->mailboxarray;
106                 foreach($mailboxes as $mbox) {
107                         $ieX->mailbox = $mbox;
108                         $newMsgs = array();
109                         $msgNoToUIDL = array();
110                         $connectToMailServer = false;
111                         if ($ieX->isPop3Protocol()) {
112                                 $msgNoToUIDL = $ieX->getPop3NewMessagesToDownloadForCron();
113                                 // get all the keys which are msgnos;
114                                 $newMsgs = array_keys($msgNoToUIDL);
115                         }
116                         if($ieX->connectMailserver() == 'true') {
117                                 $connectToMailServer = true;
118                         } // if
119
120                         $GLOBALS['log']->debug('Trying to connect to mailserver for [ '.$a['name'].' ]');
121                         if($connectToMailServer) {
122                                 $GLOBALS['log']->debug('Connected to mailserver');
123                                 if (!$ieX->isPop3Protocol()) {
124                                         $newMsgs = $ieX->getNewMessageIds();
125                                 }
126                                 if(is_array($newMsgs)) {
127                                         $current = 1;
128                                         $total = count($newMsgs);
129                                         require_once("include/SugarFolders/SugarFolders.php");
130                                         $sugarFolder = new SugarFolder();
131                                         $groupFolderId = $ieX->groupfolder_id;
132                                         $isGroupFolderExists = false;
133                                         $users = array();
134                                         if ($groupFolderId != null && $groupFolderId != "") {
135                                                 $sugarFolder->retrieve($groupFolderId);
136                                                 $isGroupFolderExists = true;
137                                         } // if
138                                         $messagesToDelete = array();
139                                         if ($ieX->isMailBoxTypeCreateCase()) {
140                                                 $users[] = $sugarFolder->assign_to_id;
141                                                 $distributionMethod = $ieX->get_stored_options("distrib_method", "");
142                                                 if ($distributionMethod != 'roundRobin') {
143                                                         $counts = $emailUI->getAssignedEmailsCountForUsers($users);
144                                                 } else {
145                                                         $lastRobin = $emailUI->getLastRobin($ieX);
146                                                 }
147                                                 $GLOBALS['log']->debug('distribution method id [ '.$distributionMethod.' ]');
148                                         }
149                                         foreach($newMsgs as $k => $msgNo) {
150                                                 $uid = $msgNo;
151                                                 if ($ieX->isPop3Protocol()) {
152                                                         $uid = $msgNoToUIDL[$msgNo];
153                                                 } else {
154                                                         $uid = imap_uid($ieX->conn, $msgNo);
155                                                 } // else
156                                                 if ($isGroupFolderExists) {
157                                                         if ($ieX->importOneEmail($msgNo, $uid)) {
158                                                                 // add to folder
159                                                                 $sugarFolder->addBean($ieX->email);
160                                                                 if ($ieX->isPop3Protocol()) {
161                                                                         $messagesToDelete[] = $msgNo;
162                                                                 } else {
163                                                                         $messagesToDelete[] = $uid;
164                                                                 }
165                                                                 if ($ieX->isMailBoxTypeCreateCase()) {
166                                                                         $userId = "";
167                                                                         if ($distributionMethod == 'roundRobin') {
168                                                                                 if (sizeof($users) == 1) {
169                                                                                         $userId = $users[0];
170                                                                                         $lastRobin = $users[0];
171                                                                                 } else {
172                                                                                         $userIdsKeys = array_flip($users); // now keys are values
173                                                                                         $thisRobinKey = $userIdsKeys[$lastRobin] + 1;
174                                                                                         if(!empty($users[$thisRobinKey])) {
175                                                                                                 $userId = $users[$thisRobinKey];
176                                                                                                 $lastRobin = $users[$thisRobinKey];
177                                                                                         } else {
178                                                                                                 $userId = $users[0];
179                                                                                                 $lastRobin = $users[0];
180                                                                                         }
181                                                                                 } // else
182                                                                         } else {
183                                                                                 if (sizeof($users) == 1) {
184                                                                                         foreach($users as $k => $value) {
185                                                                                                 $userId = $value;
186                                                                                         } // foreach
187                                                                                 } else {
188                                                                                         asort($counts); // lowest to highest
189                                                                                         $countsKeys = array_flip($counts); // keys now the 'count of items'
190                                                                                         $leastBusy = array_shift($countsKeys); // user id of lowest item count
191                                                                                         $userId = $leastBusy;
192                                                                                         $counts[$leastBusy] = $counts[$leastBusy] + 1;
193                                                                                 }
194                                                                         } // else
195                                                                         $GLOBALS['log']->debug('userId [ '.$userId.' ]');
196                                                                         $ieX->handleCreateCase($ieX->email, $userId);
197                                                                 } // if
198                                                         } // if
199                                                 } else {
200                                                                 if($ieX->isAutoImport()) {
201                                                                         $ieX->importOneEmail($msgNo, $uid);
202                                                                 } else {
203                                                                         /*If the group folder doesn't exist then download only those messages
204                                                                          which has caseid in message*/
205                                                                         $ieX->getMessagesInEmailCache($msgNo, $uid);
206                                                                         $email = new Email();
207                                                                         $header = imap_headerinfo($ieX->conn, $msgNo);
208                                                                         $email->name = $ieX->handleMimeHeaderDecode($header->subject);
209                                                                         $email->from_addr = $ieX->convertImapToSugarEmailAddress($header->from);
210                                                                         $email->reply_to_email  = $ieX->convertImapToSugarEmailAddress($header->reply_to);
211                                                                         if(!empty($email->reply_to_email)) {
212                                                                                 $contactAddr = $email->reply_to_email;
213                                                                         } else {
214                                                                                 $contactAddr = $email->from_addr;
215                                                                         }
216                                                                         $mailBoxType = $ieX->mailbox_type;
217                                                                                 $ieX->handleAutoresponse($email, $contactAddr);
218                                                                 } // else
219                                                 } // else
220                                                 $GLOBALS['log']->debug('***** On message [ '.$current.' of '.$total.' ] *****');
221                                                 $current++;
222                                         } // foreach
223                                         // update Inbound Account with last robin
224                                         if ($ieX->isMailBoxTypeCreateCase() && $distributionMethod == 'roundRobin') {
225                                                 $emailUI->setLastRobin($ieX, $lastRobin);
226                                         } // if
227
228                                 } // if
229                                 if ($isGroupFolderExists)        {
230                                         $leaveMessagesOnMailServer = $ieX->get_stored_options("leaveMessagesOnMailServer", 0);
231                                         if (!$leaveMessagesOnMailServer) {
232                                                 if ($ieX->isPop3Protocol()) {
233                                                         $ieX->deleteMessageOnMailServerForPop3(implode(",", $messagesToDelete));
234                                                 } else {
235                                                         $ieX->deleteMessageOnMailServer(implode($app_strings['LBL_EMAIL_DELIMITER'], $messagesToDelete));
236                                                 }
237                                         }
238                                 }
239                         } else {
240                                 $GLOBALS['log']->fatal("SCHEDULERS: could not get an IMAP connection resource for ID [ {$a['id']} ]. Skipping mailbox [ {$a['name']} ].");
241                                 // cn: bug 9171 - continue while
242                         } // else
243                 } // foreach
244                 imap_expunge($ieX->conn);
245                 imap_close($ieX->conn, CL_EXPUNGE);
246         } // while
247     $GLOBALS['current_user']->team_id = $_bck_up['team_id'];
248     $GLOBALS['current_user']->team_set_id = $_bck_up['team_set_id'];
249         return true;
250 }
251
252 /**
253  * Job 2
254  */
255 function runMassEmailCampaign() {
256         if (!class_exists('LoggerManager')){
257
258         }
259         $GLOBALS['log'] = LoggerManager::getLogger('emailmandelivery');
260         $GLOBALS['log']->debug('Called:runMassEmailCampaign');
261
262         if (!class_exists('DBManagerFactory')){
263                 require('include/database/DBManagerFactory.php');
264         }
265
266         global $beanList;
267         global $beanFiles;
268         require("config.php");
269         require('include/modules.php');
270         if(!class_exists('AclController')) {
271                 require('modules/ACL/ACLController.php');
272         }
273
274         require('modules/EmailMan/EmailManDelivery.php');
275         return true;
276 }
277
278 /**
279  *  Job 3
280  */
281 function pruneDatabase() {
282         $GLOBALS['log']->info('----->Scheduler fired job of type pruneDatabase()');
283         $backupDir      = sugar_cached('backups');
284         $backupFile     = 'backup-pruneDatabase-GMT0_'.gmdate('Y_m_d-H_i_s', strtotime('now')).'.php';
285
286         $db = DBManagerFactory::getInstance();
287         $tables = $db->getTablesArray();
288     $queryString = array();
289
290         if(!empty($tables)) {
291                 foreach($tables as $kTable => $table) {
292                         // find tables with deleted=1
293                         $columns = $db->get_columns($table);
294                         // no deleted - won't delete
295                         if(empty($columns['deleted'])) continue;
296
297                         $custom_columns = array();
298                         if(array_search($table.'_cstm', $tables)) {
299                             $custom_columns = $db->get_columns($table.'_cstm');
300                             if(empty($custom_columns['id_c'])) {
301                                 $custom_columns = array();
302                             }
303                         }
304
305                         $qDel = "SELECT * FROM $table WHERE deleted = 1";
306                         $rDel = $db->query($qDel);
307
308                         // make a backup INSERT query if we are deleting.
309                         while($aDel = $db->fetchByAssoc($rDel, false)) {
310                                 // build column names
311
312                                 $queryString[] = $db->insertParams($table, $columns, $aDel, null, false);
313
314                                 if(!empty($custom_columns) && !empty($aDel['id'])) {
315                     $qDelCstm = 'SELECT * FROM '.$table.'_cstm WHERE id_c = '.$db->quoted($aDel['id']);
316                     $rDelCstm = $db->query($qDelCstm);
317
318                     // make a backup INSERT query if we are deleting.
319                     while($aDelCstm = $db->fetchByAssoc($rDelCstm)) {
320                         $queryString[] = $db->insertParams($table, $custom_columns, $aDelCstm, null, false);
321                     } // end aDel while()
322
323                     $db->query('DELETE FROM '.$table.'_cstm WHERE id_c = '.$db->quoted($aDel['id']));
324                 }
325                         } // end aDel while()
326                         // now do the actual delete
327                         $db->query('DELETE FROM '.$table.' WHERE deleted = 1');
328                 } // foreach() tables
329
330                 if(!file_exists($backupDir) || !file_exists($backupDir.'/'.$backupFile)) {
331                         // create directory if not existent
332                         mkdir_recursive($backupDir, false);
333                 }
334                 // write cache file
335
336                 write_array_to_file('pruneDatabase', $queryString, $backupDir.'/'.$backupFile);
337                 return true;
338         }
339         return false;
340 }
341
342
343 ///**
344 // * Job 4
345 // */
346
347 //function securityAudit() {
348 //      // do something
349 //      return true;
350 //}
351
352 function trimTracker()
353 {
354     global $sugar_config, $timedate;
355         $GLOBALS['log']->info('----->Scheduler fired job of type trimTracker()');
356         $db = DBManagerFactory::getInstance();
357
358         $admin = new Administration();
359         $admin->retrieveSettings('tracker');
360         require('modules/Trackers/config.php');
361         $trackerConfig = $tracker_config;
362
363     require_once('include/utils/db_utils.php');
364     $prune_interval = !empty($admin->settings['tracker_prune_interval']) ? $admin->settings['tracker_prune_interval'] : 30;
365         foreach($trackerConfig as $tableName=>$tableConfig) {
366
367                 //Skip if table does not exist
368                 if(!$db->tableExists($tableName)) {
369                    continue;
370                 }
371
372             $timeStamp = db_convert("'". $timedate->asDb($timedate->getNow()->get("-".$prune_interval." days")) ."'" ,"datetime");
373                 if($tableName == 'tracker_sessions') {
374                    $query = "DELETE FROM $tableName WHERE date_end < $timeStamp";
375                 } else {
376                    $query = "DELETE FROM $tableName WHERE date_modified < $timeStamp";
377                 }
378
379             $GLOBALS['log']->info("----->Scheduler is about to trim the $tableName table by running the query $query");
380                 $db->query($query);
381         } //foreach
382     return true;
383 }
384
385 /* Job 5
386  *
387  */
388 function pollMonitoredInboxesForBouncedCampaignEmails() {
389         $GLOBALS['log']->info('----->Scheduler job of type pollMonitoredInboxesForBouncedCampaignEmails()');
390         global $dictionary;
391
392
393         $ie = new InboundEmail();
394         $r = $ie->db->query('SELECT id FROM inbound_email WHERE deleted=0 AND status=\'Active\' AND mailbox_type=\'bounce\'');
395
396         while($a = $ie->db->fetchByAssoc($r)) {
397                 $ieX = new InboundEmail();
398                 $ieX->retrieve($a['id']);
399                 $ieX->connectMailserver();
400         $ieX->importMessages();
401         }
402
403         return true;
404 }
405
406
407
408
409 /**
410  * Job 12
411  */
412 function sendEmailReminders(){
413         $GLOBALS['log']->info('----->Scheduler fired job of type sendEmailReminders()');
414         require_once("modules/Activities/EmailReminder.php");
415         $reminder = new EmailReminder();
416         return $reminder->process();
417 }
418
419 function removeDocumentsFromFS()
420 {
421     $GLOBALS['log']->info('Starting removal of documents if they are not present in DB');
422
423     /**
424      * @var DBManager $db
425      * @var SugarBean $bean
426      */
427     global $db;
428
429     // temp table to store id of files without memory leak
430     $tableName = 'cron_remove_documents';
431
432     $resource = $db->limitQuery("SELECT * FROM cron_remove_documents WHERE 1=1 ORDER BY date_modified ASC", 0, 100);
433     $return = true;
434     while ($row = $db->fetchByAssoc($resource)) {
435         $bean = BeanFactory::getBean($row['module']);
436         $bean->retrieve($row['bean_id'], true, false);
437         if (empty($bean->id)) {
438             $isSuccess = true;
439             $bean->id = $row['bean_id'];
440             $directory = $bean->deleteFileDirectory();
441             if (!empty($directory) && is_dir('upload://deleted/' . $directory)) {
442                 if ($isSuccess = rmdir_recursive('upload://deleted/' . $directory)) {
443                     $directory = explode('/', $directory);
444                     while (!empty($directory)) {
445                         $path = 'upload://deleted/' . implode('/', $directory);
446                         if (is_dir($path)) {
447                             $directoryIterator = new DirectoryIterator($path);
448                             $empty = true;
449                             foreach ($directoryIterator as $item) {
450                                 if ($item->getFilename() == '.' || $item->getFilename() == '..') {
451                                     continue;
452                                 }
453                                 $empty = false;
454                                 break;
455                             }
456                             if ($empty) {
457                                 rmdir($path);
458                             }
459                         }
460                         array_pop($directory);
461                     }
462                 }
463             }
464             if ($isSuccess) {
465                 $db->query('DELETE FROM ' . $tableName . ' WHERE id=' . $db->quoted($row['id']));
466             } else {
467                 $return = false;
468             }
469         } else {
470             $db->query('UPDATE ' . $tableName . ' SET date_modified=' . $db->convert($db->quoted(TimeDate::getInstance()->nowDb()), 'datetime') . ' WHERE id=' . $db->quoted($row['id']));
471         }
472     }
473
474     return $return;
475 }
476
477
478 function cleanJobQueue($job)
479 {
480     $td = TimeDate::getInstance();
481     // soft delete all jobs that are older than cutoff
482     $soft_cutoff = 7;
483     if(isset($GLOBALS['sugar_config']['jobs']['soft_lifetime'])) {
484         $soft_cutoff = $GLOBALS['sugar_config']['jobs']['soft_lifetime'];
485     }
486     $soft_cutoff_date = $job->db->quoted($td->getNow()->modify("- $soft_cutoff days")->asDb());
487     $job->db->query("UPDATE {$job->table_name} SET deleted=1 WHERE status='done' AND date_modified < ".$job->db->convert($soft_cutoff_date, 'datetime'));
488     // hard delete all jobs that are older than hard cutoff
489     $hard_cutoff = 21;
490     if(isset($GLOBALS['sugar_config']['jobs']['hard_lifetime'])) {
491         $hard_cutoff = $GLOBALS['sugar_config']['jobs']['hard_lifetime'];
492     }
493     $hard_cutoff_date = $job->db->quoted($td->getNow()->modify("- $hard_cutoff days")->asDb());
494     $job->db->query("DELETE FROM {$job->table_name} WHERE status='done' AND date_modified < ".$job->db->convert($hard_cutoff_date, 'datetime'));
495     return true;
496 }
497
498 if (file_exists('custom/modules/Schedulers/_AddJobsHere.php')) {
499         require('custom/modules/Schedulers/_AddJobsHere.php');
500 }
501
502 if (file_exists('custom/modules/Schedulers/Ext/ScheduledTasks/scheduledtasks.ext.php'))
503 {
504         require('custom/modules/Schedulers/Ext/ScheduledTasks/scheduledtasks.ext.php');
505 }
506 ?>