ILIAS  Release_4_2_x_branch Revision 61807
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilECSTaskScheduler.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2006 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
33 {
34  const MAX_TASKS = 30;
35 
36  private static $instances = array();
37 
38  private $event_reader = null;
39 
40  protected $settings = null;
41  protected $log = null;
42  protected $db;
43 
44  private $mids = array();
45  private $content = array();
46  private $to_create = array();
47  private $to_update = array();
48  private $to_delete = array();
49 
56  private function __construct(ilECSSetting $setting)
57  {
58  global $ilDB,$ilLog;
59 
60  $this->db = $ilDB;
61  $this->log = $ilLog;
62 
63  include_once('./Services/WebServices/ECS/classes/class.ilECSSetting.php');
64  $this->settings = $setting;
65  }
66 
79  public static function _getInstanceByServerId($a_server_id)
80  {
81  if(self::$instances[$a_server_id])
82  {
83  return self::$instances[$a_server_id];
84  }
85  return self::$instances[$a_server_id] =
88  );
89  }
90 
94  public static function start()
95  {
96  include_once './Services/WebServices/ECS/classes/class.ilECSServerSettings.php';
98  foreach($servers->getServers() as $server)
99  {
100  $sched = new ilECSTaskScheduler($server);
101  if($sched->checkNextExecution())
102  {
103  $sched->initNextExecution();
104  }
105  }
106  }
107 
111  public static function startExecution()
112  {
113  include_once './Services/WebServices/ECS/classes/class.ilECSServerSettings.php';
115  foreach($server->getServers() as $server)
116  {
117  $sched = new ilECSTaskScheduler($server);
118  $sched->startTaskExecution();
119  }
120 
121  }
122 
127  public function getServer()
128  {
129  return $this->settings;
130  }
131 
132 
139  public function startTaskExecution()
140  {
141  global $ilLog;
142 
143  try
144  {
145  $this->readMIDs();
146  $this->readEvents();
147  $this->handleEvents();
148 
149  $this->handleDeprecatedAccounts();
150  }
151  catch(ilException $exc)
152  {
153  $this->log->write(__METHOD__.': Caught exception: '.$exc->getMessage());
154  return false;
155  }
156  return true;
157  }
158 
165  private function readEvents()
166  {
167  try
168  {
169  include_once('./Services/WebServices/ECS/classes/class.ilECSEventQueueReader.php');
170  $this->event_reader = new ilECSEventQueueReader($this->getServer()->getServerId());
171  $this->event_reader->refresh();
172  }
173  catch(ilException $exc)
174  {
175  throw $exc;
176  }
177  }
178 
185  private function handleEvents()
186  {
187  include_once './Services/WebServices/ECS/classes/class.ilECSEvent.php';
188 
189  for($i = 0;$i < self::MAX_TASKS;$i++)
190  {
191  if(!$event = $this->event_reader->shift())
192  {
193  $this->log->write(__METHOD__.': No more pending events found. DONE');
194  break;
195  }
196  if($event['op'] == ilECSEvent::DESTROYED)
197  {
198  $this->handleDelete($event['id']);
199  $this->log->write(__METHOD__.': Handling delete. DONE');
200  continue;
201  }
202  if($event['op'] == ilECSEvent::NEW_EXPORT)
203  {
204  $this->handleNewlyCreate($event['id']);
205  $this->log->write(__METHOD__.': Handling new creation. DONE');
206  continue;
207  }
208 
209  // Operation is create or update
210  // get econtent
211  try
212  {
213  include_once('./Services/WebServices/ECS/classes/class.ilECSEContentReader.php');
214  $reader = new ilECSEContentReader($this->getServer()->getServerId(),$event['id']);
215  $reader->read();
216  $reader->read(true);
217  }
218  catch(Exception $e)
219  {
220  $this->log->write(__METHOD__.': Cannot read Econtent. '.$e->getMessage());
221  continue;
222  }
223  if(!$reader->getEContent() instanceof ilECSEContent)
224  {
225  $this->handleDelete($event['id']);
226  $this->log->write(__METHOD__.': Handling delete of deprecated remote courses. DONE');
227  }
228  else
229  {
230  $this->handleUpdate($reader->getEContent(),$reader->getEContentDetails());
231  $this->log->write(__METHOD__.': Handling update. DONE');
232  }
233  }
234  }
235 
236  private function handleNewlyCreate($a_obj_id)
237  {
238  global $ilLog;
239 
240  include_once('./Services/WebServices/ECS/classes/class.ilECSExport.php');
241  include_once('./Services/WebServices/ECS/classes/class.ilECSConnectorException.php');
242  include_once('./Services/WebServices/ECS/classes/class.ilECSEContentReader.php');
243  include_once('./Services/WebServices/ECS/classes/class.ilECSReaderException.php');
244  include_once('./Services/WebServices/ECS/classes/class.ilECSContentWriter.php');
245  include_once('./Services/WebServices/ECS/classes/class.ilECSContentWriterException.php');
246 
247 
248  $export = new ilECSExport($this->getServer()->getServerId(),$a_obj_id);
249  $econtent_id = $export->getEContentId();
250 
251  try
252  {
253  $reader = new ilECSEContentReader($this->getServer()->getServerId(),$econtent_id);
254  $reader->read();
255  $reader->read(true);
256 
257  $econtent = $reader->getEContent();
258  $details = $reader->getEContentDetails();
259 
260  if($econtent instanceof ilECSEContent and $details instanceof ilECSEContentDetails)
261  {
262  if(!$obj = ilObjectFactory::getInstanceByObjId($a_obj_id,false))
263  {
264  $ilLog->write(__METHOD__.': Cannot create object instance. Aborting...');
265  return false;
266  }
267  // Delete resource
268  $writer = new ilECSContentWriter($obj,$this->getServer()->getServerId());
269  $writer->setExportable(false);
270  $writer->setOwnerId($details->getFirstSender());
271  $writer->setParticipantIds($details->getReceivers());
272  $writer->refresh();
273 
274  // Create resource
275  $writer->setExportable(true);
276  $writer->refresh();
277  return true;
278  }
279  return false;
280 
281  }
282  catch(ilECSConnectorException $e1)
283  {
284  $ilLog->write(__METHOD__.': Cannot handle create event. Message: '.$e1->getMessage());
285  return false;
286  }
287  catch(ilECSReaderException $e2)
288  {
289  $ilLog->write(__METHOD__.': Cannot handle create event. Message: '.$e2->getMessage());
290  return false;
291  }
292  catch(ilECSContentWriterException $e3)
293  {
294  $ilLog->write(__METHOD__.': Cannot handle create event. Message: '.$e2->getMessage());
295  return false;
296  }
297 
298  }
299 
306  private function handleDelete($econtent_id,$a_mid = 0)
307  {
308  global $tree;
309 
310  include_once('./Services/WebServices/ECS/classes/class.ilECSImport.php');
311  // if mid is zero delete all obj_ids
312  if(!$a_mid)
313  {
314  $obj_ids = ilECSImport::_lookupObjIds($this->settings->getServerId(),$econtent_id);
315  }
316  else
317  {
318  $obj_ids = (array) ilECSImport::_lookupObjId($this->settings->getServerId(),$econtent_id,$a_mid);
319  }
320  $GLOBALS['ilLog']->write(__METHOD__.': Received obj_ids '.print_r($obj_ids,true));
321  foreach($obj_ids as $obj_id)
322  {
323  $references = ilObject::_getAllReferences($obj_id);
324  foreach($references as $ref_id)
325  {
326  if($tmp_obj = ilObjectFactory::getInstanceByRefId($ref_id,false))
327  {
328  $this->log->write(__METHOD__.': Deleting obsolete remote course: '.$tmp_obj->getTitle());
329  $tmp_obj->delete();
330  $tree->deleteTree($tree->getNodeData($ref_id));
331  }
332  unset($tmp_obj);
333  }
334  }
335  }
336 
345  {
346  global $ilLog;
347 
348 
349  $GLOBALS['ilLog']->write(__METHOD__.': Receivers are '. print_r($details->getReceivers(),true));
350 
351  include_once('./Services/WebServices/ECS/classes/class.ilECSParticipantSettings.php');
352  if(!ilECSParticipantSettings::getInstanceByServerId($this->getServer()->getServerId())->isImportAllowed($content->getOwner()))
353  {
354  $ilLog->write('Ignoring disabled participant. MID: '.$content->getOwner());
355  return false;
356  }
357 
358  include_once('Services/WebServices/ECS/classes/class.ilECSImport.php');
359 
360  // new mids
361  #foreach($this->mids as $mid)
362  foreach(array_intersect($this->mids,$details->getReceivers()) as $mid)
363  {
364  // Update existing
365  if($obj_id = ilECSImport::_isImported($this->settings->getServerId(),$content->getEContentId(),$mid))
366  {
367  $ilLog->write(__METHOD__.': Handling update for existing object');
368  $remote = ilObjectFactory::getInstanceByObjId($obj_id,false);
369  if($remote->getType() != 'rcrs')
370  {
371  $this->log->write(__METHOD__.': Cannot instantiate remote course. Got object type '.$remote->getType());
372  continue;
373  }
374  $remote->updateFromECSContent($this->getServer()->getServerId(),$content);
375  }
376  else
377  {
378  $ilLog->write(__METHOD__.': Handling create for non existing object');
379  include_once('./Modules/RemoteCourse/classes/class.ilObjRemoteCourse.php');
380  $remote_crs = ilObjRemoteCourse::_createFromECSEContent($this->settings->getServerId(),$content,$mid);
381  }
382 
383  /*
384  // deprecated mids
385  foreach(array_diff(ilECSImport::_lookupMIDs($this->settings->getServerId(),$content->getEContentId()),$details->getReceivers()) as $deprecated)
386  {
387  $this->handleDelete($content->getEContentId(),$deprecated);
388  }
389  */
390  }
391  }
392 
399  private function handleDeprecatedAccounts()
400  {
401  global $ilDB;
402 
403  $query = "SELECT usr_id FROM usr_data WHERE auth_mode = 'ecs' ".
404  "AND time_limit_until < ".time()." ".
405  "AND time_limit_unlimited = 0 ".
406  "AND (time_limit_until - time_limit_from) < 7200";
407  $res = $ilDB->query($query);
408  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
409  {
410  if($user_obj = ilObjectFactory::getInstanceByObjId($row->usr_id,false))
411  {
412  $this->log->write(__METHOD__.': Deleting deprecated ECS user account '.$user_obj->getLogin());
413  $user_obj->delete();
414  }
415  // only one user
416  break;
417  }
418  return true;
419  }
420 
427  private function readMIDs()
428  {
429  try
430  {
431  $this->mids = array();
432 
433  include_once('./Services/WebServices/ECS/classes/class.ilECSCommunityReader.php');
435  foreach($reader->getCommunities() as $com)
436  {
437  foreach($com->getParticipants() as $part)
438  {
439  if($part->isSelf())
440  {
441  $this->mids[] = $part->getMID();
442  $this->log->write('Fetch MID: '.$part->getMID());
443  }
444  }
445  }
446  }
447  catch(ilException $exc)
448  {
449  throw $exc;
450  }
451  }
452 
453 
460  public function checkNextExecution()
461  {
462  global $ilLog, $ilDB;
463 
464 
465  if(!$this->settings->isEnabled())
466  {
467  return false;
468  }
469 
470  if(!$this->settings->checkImportId())
471  {
472  $this->log->write(__METHOD__.': Import ID is deleted or not of type "category". Aborting');
473  return false;
474  }
475 
476  // check next task excecution time:
477  // If it's greater than time() directly increase this value with the polling time
478  /* synchronized { */
479  $query = 'UPDATE settings SET '.
480  'value = '.$ilDB->quote(time() + $this->settings->getPollingTime(),'text').' '.
481  'WHERE module = '.$ilDB->quote('ecs','text').' '.
482  'AND keyword = '.$ilDB->quote('next_execution_'.$this->settings->getServerId(),'text').' '.
483  'AND value < '.$ilDB->quote(time(),'text');
484  $affected_rows = $ilDB->manipulate($query);
485  /* } */
486 
487 
488  if(!$affected_rows)
489  {
490  // Nothing to do
491  return false;
492  }
493  return true;
494  }
495 
496 
500  protected function initNextExecution()
501  {
502  global $ilLog;
503 
504  // Start task execution as backend process
505  include_once 'Services/WebServices/SOAP/classes/class.ilSoapClient.php';
506 
507  $soap_client = new ilSoapClient();
508  $soap_client->setResponseTimeout(1);
509  $soap_client->enableWSDL(true);
510 
511  $ilLog->write(__METHOD__.': Trying to call Soap client...');
512  $new_session_id = duplicate_session($_COOKIE['PHPSESSID']);
513  $client_id = $_COOKIE['ilClientId'];
514 
515  if($soap_client->init() and 0)
516  {
517  $ilLog->write(__METHOD__.': Calling soap handleECSTasks method...');
518  $res = $soap_client->call('handleECSTasks',array($new_session_id.'::'.$client_id,$this->settings->getServerId()));
519  }
520  else
521  {
522  $ilLog->write(__METHOD__.': SOAP call failed. Calling clone method manually. ');
523  include_once('./webservice/soap/include/inc.soap_functions.php');
524  $res = ilSoapFunctions::handleECSTasks($new_session_id.'::'.$client_id,$this->settings->getServerId());
525  }
526  }
527 }
528 ?>