]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/SchedulersJobs/SchedulersJob.php
Release 6.4.0
[Github/sugarcrm.git] / modules / SchedulersJobs / SchedulersJob.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-2011 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
41 class SchedulersJob extends SugarBean {
42         // schema attributes
43         var $id = '';
44         var $deleted = '';
45         var $date_entered = '';
46         var $date_modified = '';
47         var $scheduler_id = '';
48         var $execute_time = '';
49         var $status;
50         // standard SugarBean child attrs
51         var $table_name         = "schedulers_times";
52         var $object_name                = "SchedulersJob";
53         var $module_dir         = "SchedulersJobs";
54         var $new_schema         = true;
55         var $process_save_dates = true;
56         // related fields
57         var $job_name;  // the Scheduler's 'name' field
58         var $job;               // the Scheduler's 'job' field
59         // object specific attributes
60         var $user; // User object
61         var $scheduler; // Scheduler parent
62
63         /**
64          * Sole constructor.
65          */
66         function SchedulersJob($init=true) {
67         parent::SugarBean();
68         if($init) {
69             $user = new User();
70             //check is default admin exists
71             $adminId = $this->db->getOne(
72                 'SELECT id FROM users WHERE id='.$this->db->quoted('1').' AND is_admin=1 AND deleted=0 AND status='.$this->db->quoted('Active'),
73                 true,
74                 'Error retrieving Admin account info'
75             );
76             if (false === $adminId) {//retrive other admin
77                 $adminId = $this->db->getOne(
78                     'SELECT id FROM users WHERE is_admin=1 AND deleted=0 AND status='.$this->db->quoted('Active'),
79                     true,
80                     'Error retrieving Admin account info'
81                 );
82                 if ($adminId) {
83                     $user->retrieve($adminId);
84                 } else {
85                     $GLOBALS['log']->fatal('No Admin account found!');
86                     return false;
87                 }
88                 
89             } else {
90                 $user->retrieve('1'); // Scheduler jobs run as default Admin
91             }
92             $this->user = $user;
93         }
94     }
95         
96
97         ///////////////////////////////////////////////////////////////////////////
98         ////    SCHEDULERSJOB HELPER FUNCTIONS
99
100         function fireSelf($id) {
101
102                 $sched = new Scheduler();
103                 $sched->retrieve($id);
104
105                 $exJob = explode('::', $sched->job);
106
107                 if(is_array($exJob)) {
108                         $this->scheduler_id     = $sched->id;
109                         $this->scheduler                = $sched;
110                         $this->execute_time     = $this->handleDateFormat('now');
111                         $this->save();
112
113                         if($exJob[0] == 'function') {
114                                 $GLOBALS['log']->debug('----->Scheduler found a job of type FUNCTION');
115                                 require_once('modules/Schedulers/_AddJobsHere.php');
116
117                                 $this->setJobFlag(1);
118
119                                 $func = $exJob[1];
120                                 $GLOBALS['log']->debug('----->SchedulersJob firing '.$func);
121
122                                 $res = call_user_func($func);
123                                 if($res) {
124                                         $this->setJobFlag(2);
125                                         $this->finishJob();
126                                         return true;
127                                 } else {
128                                         $this->setJobFlag(3);
129                                         return false;
130                                 }
131                         } elseif($exJob[0] == 'url') {
132                                 if(function_exists('curl_init')) {
133                                         $GLOBALS['log']->debug('----->SchedulersJob found a job of type URL');
134                                         $this->setJobFlag(1);
135
136                                         $GLOBALS['log']->debug('----->SchedulersJob firing URL job: '.$exJob[1]);
137                                         if($this->fireUrl($exJob[1])) {
138                                                 $this->setJobFlag(2);
139                                                 $this->finishJob();
140                                                 return true;
141                                         } else {
142                                                 $this->setJobFlag(3);
143                                                 return false;
144                                         }
145                                 } else {
146                                         $this->setJobFlag(4);
147                                         return false;
148                                 }
149                         }
150                 }
151                 return false;
152         }
153
154         /**
155          * handles some date/time foramtting
156          * @param string time Time (usually "now")
157          * @param object user User, usually admin (id = '1')
158          * @param boolean to_local, convert to user's time format
159          * @return string formatted time.
160          */
161         function handleDateFormat($time, $user=null, $to_local=true) {
162                 global $timedate;
163                 
164                 if(!isset($timedate) || empty($timedate)) {
165                         $timedate = new TimeDate();
166                 }
167                 
168                 // get proper user
169                 $user = (empty($user)) ? $this->user : $user;
170                 $dbTime = $timedate->nowDb();
171
172                 if ($to_local) {
173                     $ret = $timedate->to_display_date_time($dbTime, true, true, $user);
174                     return $ret;
175                 }
176                 
177                 return $dbTime;
178         }
179
180         function setJobFlag($flag) {
181                 $trackerManager = TrackerManager::getInstance();
182                 $trackerManager->pause();
183                 $status = array (0 => 'ready', 1 => 'in progress', 2 => 'completed', 3 => 'failed', 4 => 'no curl');
184                 $statusScheduler = array (0 => 'Active', 1 => 'In Progress', 2 => 'Active', 3 => 'Active', 4 => 'Active');
185                 $GLOBALS['log']->info('-----> SchedulersJob setting Job flag: '.$status[$flag].' AND setting Scheduler status to: '.$statusScheduler[$flag]);
186
187                 $time = $this->handleDateFormat('now');
188                 $this->status = $status[$flag];
189                 $this->scheduler->retrieve($this->scheduler_id);
190                 $this->scheduler->status = $statusScheduler[$flag];
191                 $this->scheduler->save();
192                 $this->save();
193                 $this->retrieve($this->id);
194                 $trackerManager->unPause();
195         }
196
197         /**
198          * This function takes a job_id, and updates schedulers last_run as well as
199          * soft delete the job instance from schedulers_times
200          * @return      boolean         Success
201          */
202         function finishJob() {
203                 $trackerManager = TrackerManager::getInstance();
204                 $trackerManager->pause();
205                 $GLOBALS['log']->debug('----->SchedulersJob updating Job Status and finishing Job execution.');
206                 $this->scheduler->retrieve($this->scheduler->id);
207                 $this->scheduler->last_run = gmdate($GLOBALS['timedate']->get_db_date_time_format());
208                 if($this->scheduler->last_run == gmdate($GLOBALS['timedate']->get_db_date_time_format(), strtotime('Jan 01 2000 00:00:00'))) {
209                         $this->scheduler->last_run = $this->handleDateFormat('now');
210                         $GLOBALS['log']->fatal('Scheduler applying bogus date for "Last Run": '.$this->scheduler->last_run);
211                 }
212                 $this->scheduler->save();
213                 $trackerManager->unPause();
214         }
215
216         /**
217          * This function takes a passed URL and cURLs it to fake multi-threading with another httpd instance
218          * @param       $job            String in URI-clean format
219          * @param       $timeout        Int value in secs for cURL to timeout. 30 default.
220          */
221         //TODO: figure out what error is thrown when no more apache instances can be spun off
222         function fireUrl($job, $timeout=30) {
223                 // cURL inits
224                 $ch = curl_init();
225                 curl_setopt($ch, CURLOPT_URL, $job); // set url
226                 curl_setopt($ch, CURLOPT_FAILONERROR, true); // silent failure (code >300);
227                 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // do not follow location(); inits - we always use the current
228                 curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
229                 curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false);  // not thread-safe
230                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // return into a variable to continue program execution
231                 curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); // never times out - bad idea?
232                 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); // 5 secs for connect timeout
233                 curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);  // open brand new conn
234                 curl_setopt($ch, CURLOPT_HEADER, true); // do not return header info with result
235                 curl_setopt($ch, CURLOPT_NOPROGRESS, true); // do not have progress bar
236                 $urlparts = parse_url($job);
237                 if(empty($urlparts['port'])) {
238                     if($urlparts['scheme'] == 'https'){
239                                 $urlparts['port'] = 443;
240                         } else {
241                                 $urlparts['port'] = 80;
242                         }
243                 }
244                 curl_setopt($ch, CURLOPT_PORT, $urlparts['port']); // set port as reported by Server
245                 //TODO make the below configurable
246                 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // most customers will not have Certificate Authority account
247                 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // most customers will not have Certificate Authority account
248
249                 if(constant('PHP_VERSION') > '5.0.0') {
250                         curl_setopt($ch, CURLOPT_NOSIGNAL, true); // ignore any cURL signals to PHP (for multi-threading)
251                 }
252                 $result = curl_exec($ch);
253                 $cInfo = curl_getinfo($ch);     //url,content_type,header_size,request_size,filetime,http_code
254                                                                         //ssl_verify_result,total_time,namelookup_time,connect_time
255                                                                         //pretransfer_time,size_upload,size_download,speed_download,
256                                                                         //speed_upload,download_content_length,upload_content_length
257                                                                         //starttransfer_time,redirect_time
258                 curl_close($ch);
259
260                 if($result !== FALSE && $cInfo['http_code'] < 400) {
261                         $GLOBALS['log']->debug('----->Firing was successful: ('.$job.') at '.$this->handleDateFormat('now'));
262                         $GLOBALS['log']->debug('----->WTIH RESULT: '.strip_tags($result).' AND '.strip_tags(print_r($cInfo, true)));
263                         return true;
264                 } else {
265                         $GLOBALS['log']->fatal('Job errored: ('.$job.') at '.$this->handleDateFormat('now'));
266                         return false;
267                 }
268         }
269         ////    END SCHEDULERSJOB HELPER FUNCTIONS
270         ///////////////////////////////////////////////////////////////////////////
271
272
273         ///////////////////////////////////////////////////////////////////////////
274         ////    STANDARD SUGARBEAN OVERRIDES
275         /**
276          * This function gets DB data and preps it for ListViews
277          */
278         function get_list_view_data(){
279                 global $mod_strings;
280
281                 $temp_array = $this->get_list_view_array();
282                 $temp_array['JOB_NAME'] = $this->job_name;
283                 $temp_array['JOB']              = $this->job;
284
285         return $temp_array;
286         }
287
288         /** method stub for future customization
289          *
290          */
291         function fill_in_additional_list_fields() {
292                 $this->fill_in_additional_detail_fields();
293         }
294
295         function fill_in_additional_detail_fields() {
296                 // get the Job Name and Job fields from schedulers table
297 //              $q = "SELECT name, job FROM schedulers WHERE id = '".$this->job_id."'";
298 //              $result = $this->db->query($q);
299 //              $row = $this->db->fetchByAssoc($result);
300 //              $this->job_name = $row['name'];
301 //              $this->job = $row['job'];
302 //              $GLOBALS['log']->info('Assigned Name('.$this->job_name.') and Job('.$this->job.') to Job');
303 //
304 //              $this->created_by_name = get_assigned_user_name($this->created_by);
305 //              $this->modified_by_name = get_assigned_user_name($this->modified_user_id);
306
307     }
308
309         /**
310          * returns the bean name - overrides SugarBean's
311          */
312         function get_summary_text() {
313         if(isset($this->name))
314                 return $this->name;
315         }
316
317         /**
318          * function overrides the one in SugarBean.php
319          */
320
321 }  // end class Job
322 ?>