ILIAS  Release_4_1_x_branch Revision 61804
 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  $ilLog->write(__METHOD__.': ... update called.');
317  $remote->updateFromECSContent($content);
318  }
319  else
320  {
321  $ilLog->write(__METHOD__.': ... create called.');
322  include_once('./Modules/RemoteCourse/classes/class.ilObjRemoteCourse.php');
323  $remote_crs = ilObjRemoteCourse::_createFromECSEContent($content,$mid);
324  }
325  }
326  // deprecated mids
327  foreach(array_diff(ilECSImport::_lookupMIDs($content->getEContentId()),$content->getEligibleMembers()) as $deprecated)
328  {
329  $this->handleDelete($content->getEContentId(),$deprecated);
330  }
331  }
332  }
333 
340  private function handleDeprecatedAccounts()
341  {
342  global $ilDB;
343 
344  $query = "SELECT usr_id FROM usr_data WHERE auth_mode = 'ecs' ".
345  "AND time_limit_until < ".time()." ".
346  "AND time_limit_unlimited = 0 ".
347  "AND (time_limit_until - time_limit_from) < 7200";
348  $res = $ilDB->query($query);
349  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
350  {
351  if($user_obj = ilObjectFactory::getInstanceByObjId($row->usr_id,false))
352  {
353  $this->log->write(__METHOD__.': Deleting deprecated ECS user account '.$user_obj->getLogin());
354  $user_obj->delete();
355  }
356  // only one user
357  break;
358  }
359  return true;
360  }
361 
368  private function readMIDs()
369  {
370  try
371  {
372  $this->mids = array();
373 
374  include_once('./Services/WebServices/ECS/classes/class.ilECSCommunityReader.php');
376  foreach($reader->getCommunities() as $com)
377  {
378  foreach($com->getParticipants() as $part)
379  {
380  if($part->isSelf())
381  {
382  $this->mids[] = $part->getMID();
383  $this->log->write('Fetch MID: '.$part->getMID());
384  }
385  }
386  }
387  }
388  catch(ilException $exc)
389  {
390  throw $exc;
391  }
392  }
393 
394 
401  public function start()
402  {
403  global $ilLog;
404 
405  if(!$this->settings->isEnabled())
406  {
407  return false;
408  }
409 
410  if(!$this->settings->checkImportId())
411  {
412  $this->log->write(__METHOD__.': Import ID is deleted or not of type "category". Aborting');
413  return false;
414  }
415 
416  // check next task excecution time:
417  // If it's greater than time() directly increase this value with the polling time
418  // and exceute a new task.
419  // These operations should be thread-safe
420 
421  $sett = new ilSetting("ecs");
422  $time = $sett->get("next_execution");
423  if(time() < ($time + $this->settings->getPollingTime()))
424  {
425  return true;
426  // Nothing to do
427  }
428  // Set new execution time
429  $sett->set("next_execution", time() + $this->settings->getPollingTime());
430 
431  $this->log->write(__METHOD__.': Starting ECS tasks.');
432 
433  // Debug
434  //$this->startTaskExecution();
435  //return true;
436 
437  include_once 'Services/WebServices/SOAP/classes/class.ilSoapClient.php';
438 
439  $soap_client = new ilSoapClient();
440  $soap_client->setTimeout(1);
441  $soap_client->setResponseTimeout(1);
442  $soap_client->enableWSDL(true);
443 
444  $ilLog->write(__METHOD__.': Trying to call Soap client...');
445  $new_session_id = duplicate_session($_COOKIE['PHPSESSID']);
446  $client_id = $_COOKIE['ilClientId'];
447 
448  if($soap_client->init())
449  {
450  $ilLog->write(__METHOD__.': Calling soap handleECSTasks method...');
451  $res = $soap_client->call('handleECSTasks',array($new_session_id.'::'.$client_id));
452  }
453  else
454  {
455  $ilLog->write(__METHOD__.': SOAP call failed. Calling clone method manually. ');
456  include_once('./webservice/soap/include/inc.soap_functions.php');
457  $res = ilSoapFunctions::handleECSTasks($new_session_id.'::'.$client_id);
458  }
459  return true;
460  }
461 }
462 ?>