ILIAS  Release_3_10_x_branch Revision 61812
 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 $instance = null;
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  public function __construct()
57  {
58  global $ilDB,$ilLog;
59 
60  $this->db = $ilDB;
61  $this->log = $ilLog;
62 
63  include_once('./Services/WebServices/ECS/classes/class.ilECSSettings.php');
64  $this->settings = ilECSSettings::_getInstance();
65  }
66 
74  public static function _getInstance()
75  {
76  if(self::$instance)
77  {
78  return self::$instance;
79  }
80  return self::$instance = new ilECSTaskScheduler();
81  }
82 
89  public function startTaskExecution()
90  {
91  global $ilLog;
92 
93  try
94  {
95  $this->readMIDs();
96  $this->readEvents();
97  $this->handleEvents();
98 
99  $this->handleDeprecatedAccounts();
100  }
101  catch(ilException $exc)
102  {
103  $this->log->write(__METHOD__.': Caught exception: '.$exc->getMessage());
104  return false;
105  }
106  return true;
107  }
108 
115  private function readEvents()
116  {
117  try
118  {
119  include_once('./Services/WebServices/ECS/classes/class.ilECSEventQueueReader.php');
120  $this->event_reader = new ilECSEventQueueReader();
121  $this->event_reader->refresh();
122  }
123  catch(ilException $exc)
124  {
125  throw $exc;
126  }
127  }
128 
135  private function handleEvents()
136  {
137  #return true;
138 
139  for($i = 0;$i < self::MAX_TASKS;$i++)
140  {
141  if(!$event = $this->event_reader->shift())
142  {
143  $this->log->write(__METHOD__.': No more pending events found.');
144  break;
145  }
146 
147  // Delete events
148  if($event['op'] == ilECSEventQueueReader::OPERATION_DELETE)
149  {
150  $this->handleDelete($event['id']);
151  continue;
152  }
153  elseif($event['op'] == ilECSEventQueueReader::OPERATION_NEWLY_CREATED)
154  {
155  // That was command queue 'reset_all'
156  // Stop export and then start export.
157  $this->handleNewlyCreate($event['id']);
158  }
159 
160  // Operation is create or update
161  // get econtent
162  try
163  {
164  include_once('./Services/WebServices/ECS/classes/class.ilECSEContentReader.php');
165  $reader = new ilECSEContentReader($event['id']);
166  }
167  catch(Exception $e)
168  {
169  $this->log->write(__METHOD__.': Cannot read Econtent. '.$e->getMessage());
170  continue;
171  }
172 
173  if(!$reader->read())
174  {
175  $this->log->write(__METHOD__.': Deleting deprecated remote course.');
176  $this->handleDelete($event['id']);
177 
178  }
179  else
180  {
181  $this->log->write(__METHOD__.': Starting update of remote courses.');
182  $this->handleUpdate($reader->getEContent());
183  }
184  }
185  }
186 
187  private function handleNewlyCreate($a_obj_id)
188  {
189  global $ilLog;
190 
191  include_once('./Services/WebServices/ECS/classes/class.ilECSExport.php');
192  include_once('./Services/WebServices/ECS/classes/class.ilECSConnectorException.php');
193  include_once('./Services/WebServices/ECS/classes/class.ilECSEContentReader.php');
194  include_once('./Services/WebServices/ECS/classes/class.ilECSReaderException.php');
195  include_once('./Services/WebServices/ECS/classes/class.ilECSContentWriter.php');
196  include_once('./Services/WebServices/ECS/classes/class.ilECSContentWriterException.php');
197 
198 
199  $export = new ilECSExport($a_obj_id);
200  $econtent_id = $export->getEContentId();
201  try
202  {
203  $reader = new ilECSEContentReader($econtent_id);
204  $reader->read();
205 
206  foreach($reader->getEContent() as $econtent)
207  {
208  if(!$obj = ilObjectFactory::getInstanceByObjId($a_obj_id,false))
209  {
210  $ilLog->write(__METHOD__.': Cannot create object instance. Aborting...');
211  }
212  // Delete resource
213  $writer = new ilECSContentWriter($obj);
214  $writer->setExportable(false);
215  $writer->setOwnerId($econtent->getOwner());
216  $writer->setParticipantIds($econtent->getEligibleMembers());
217  $writer->refresh();
218 
219  // Create resource
220  $writer->setExportable(true);
221  $writer->refresh();
222  return true;
223  }
224  return false;
225 
226  }
227  catch(ilECSConnectorException $e1)
228  {
229  $ilLog->write(__METHOD__.': Cannot handle create event. Message: '.$e1->getMessage());
230  return false;
231  }
232  catch(ilECSReaderException $e2)
233  {
234  $ilLog->write(__METHOD__.': Cannot handle create event. Message: '.$e2->getMessage());
235  return false;
236  }
237  catch(ilECSContentWriterException $e3)
238  {
239  $ilLog->write(__METHOD__.': Cannot handle create event. Message: '.$e2->getMessage());
240  return false;
241  }
242 
243  }
244 
251  private function handleDelete($econtent_id,$a_mid = 0)
252  {
253  global $tree;
254 
255  include_once('./Services/WebServices/ECS/classes/class.ilECSImport.php');
256  // if mid is zero delete all obj_ids
257  if(!$a_mid)
258  {
259  $obj_ids = ilECSImport::_lookupObjIds($econtent_id);
260  }
261  else
262  {
263  $obj_ids = (array) ilECSImport::_lookupObjId($econtent_id,$a_mid);
264  }
265  foreach($obj_ids as $obj_id)
266  {
267  $references = ilObject::_getAllReferences($obj_id);
268  foreach($references as $ref_id)
269  {
270  if($tmp_obj = ilObjectFactory::getInstanceByRefId($ref_id,false))
271  {
272  $this->log->write(__METHOD__.': Deleting obsolete remote course: '.$tmp_obj->getTitle());
273  $tmp_obj->delete();
274  $tree->deleteTree($tree->getNodeData($ref_id));
275  }
276  unset($tmp_obj);
277  }
278  }
279  }
280 
288  private function handleUpdate($ecscontent)
289  {
290  global $ilLog;
291 
292 
293  foreach($ecscontent as $content)
294  {
295  include_once('./Services/WebServices/ECS/classes/class.ilECSParticipantSettings.php');
296  if(!ilECSParticipantSettings::_getInstance()->isEnabled($content->getOwner()))
297  {
298  $ilLog->write('Ignoring disabled participant. MID: '.$content->getOwner());
299  continue;
300  }
301 
302  include_once('Services/WebServices/ECS/classes/class.ilECSImport.php');
303 
304  // new mids
305  foreach(array_intersect($this->mids,$content->getEligibleMembers()) as $mid)
306  {
307  // Update existing
308  if($obj_id = ilECSImport::_isImported($content->getEContentId(),$mid))
309  {
310  $remote = ilObjectFactory::getInstanceByObjId($obj_id,false);
311  if($remote->getType() != 'rcrs')
312  {
313  $this->log->write(__METHOD__.': Cannot instantiate remote course. Got object type '.$remote->getType());
314  continue;
315  }
316  $remote->updateFromECSContent($content);
317  }
318  else
319  {
320  include_once('./Modules/RemoteCourse/classes/class.ilObjRemoteCourse.php');
321  $remote_crs = ilObjRemoteCourse::_createFromECSEContent($content,$mid);
322  }
323  }
324  // deprecated mids
325  foreach(array_diff(ilECSImport::_lookupMIDs($content->getEContentId()),$content->getEligibleMembers()) as $deprecated)
326  {
327  $this->handleDelete($content->getEContentId(),$deprecated);
328  }
329  }
330  }
331 
338  private function handleDeprecatedAccounts()
339  {
340  global $ilDB;
341 
342  $query = "SELECT usr_id FROM usr_data WHERE auth_mode = 'ecs' ".
343  "AND time_limit_until < ".time()." ".
344  "AND time_limit_unlimited = 0 ".
345  "AND (time_limit_until - time_limit_from) < 7200";
346  $res = $ilDB->query($query);
347  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
348  {
349  if($user_obj = ilObjectFactory::getInstanceByObjId($row->usr_id,false))
350  {
351  $this->log->write(__METHOD__.': Deleting deprecated ECS user account '.$user_obj->getLogin());
352  $user_obj->delete();
353  }
354  // only one user
355  break;
356  }
357  return true;
358  }
359 
366  private function readMIDs()
367  {
368  try
369  {
370  $this->mids = array();
371 
372  include_once('./Services/WebServices/ECS/classes/class.ilECSCommunityReader.php');
374  foreach($reader->getCommunities() as $com)
375  {
376  foreach($com->getParticipants() as $part)
377  {
378  if($part->isSelf())
379  {
380  $this->mids[] = $part->getMID();
381  $this->log->write('Fetch MID: '.$part->getMID());
382  }
383  }
384  }
385  }
386  catch(ilException $exc)
387  {
388  throw $exc;
389  }
390  }
391 
392 
399  public function start()
400  {
401  global $ilLog;
402 
403  if(!$this->settings->isEnabled())
404  {
405  return false;
406  }
407 
408  if(!$this->settings->checkImportId())
409  {
410  $this->log->write(__METHOD__.': Import ID is deleted or not of type "category". Aborting');
411  return false;
412  }
413 
414  // check next task excecution time:
415  // If it's greater than time() directly increase this value with the polling time
416  // and exceute a new task.
417  // These operations should be thread-safe
418  $query = "SELECT value FROM settings WHERE module = 'ecs' ".
419  "AND keyword = 'next_execution'";
420  $res = $this->db->query($query);
421  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
422  {
423  $time = $row->value;
424  }
425  if(time() < ($time + $this->settings->getPollingTime()))
426  {
427  return true;
428  // Nothing to do
429  }
430  // Set new execution time
431  $query = "REPLACE INTO settings SET ".
432  "module = 'ecs', ".
433  "keyword = 'next_execution', ".
434  "value = ".$this->db->quote(time() + $this->settings->getPollingTime());
435  $this->db->query($query);
436 
437  $this->log->write(__METHOD__.': Starting ECS tasks.');
438 
439 
440  include_once 'Services/WebServices/SOAP/classes/class.ilSoapClient.php';
441 
442  $soap_client = new ilSoapClient();
443  $soap_client->setTimeout(1);
444  $soap_client->setResponseTimeout(1);
445  $soap_client->enableWSDL(true);
446 
447  $ilLog->write(__METHOD__.': Trying to call Soap client...');
448  $new_session_id = duplicate_session($_COOKIE['PHPSESSID']);
449  $client_id = $_COOKIE['ilClientId'];
450 
451  if($soap_client->init())
452  {
453  $ilLog->write(__METHOD__.': Calling soap handleECSTasks method...');
454  $res = $soap_client->call('handleECSTasks',array($new_session_id.'::'.$client_id));
455  }
456  else
457  {
458  $ilLog->write(__METHOD__.': SOAP call failed. Calling clone method manually. ');
459  include_once('./webservice/soap/include/inc.soap_functions.php');
460  $res = ilSoapFunctions::handleECSTasks($new_session_id.'::'.$client_id);
461  }
462  return true;
463  }
464 }
465 ?>