1<?php 2 3/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */ 4 5require_once('./Modules/DataCollection/classes/class.ilObjDataCollectionAccess.php'); 6require_once('./Modules/DataCollection/classes/class.ilObjDataCollectionGUI.php'); 7require_once('./Modules/DataCollection/classes/Content/class.ilDclRecordListGUI.php'); 8require_once('./Modules/DataCollection/classes/Table/class.ilDclTable.php'); 9require_once('./Services/Export/classes/class.ilExport.php'); 10 11/** 12 * Hook-Class for exporting data-collections (used in SOAP-Class) 13 * This Class avoids duplicated code by routing the request to the right place 14 * 15 * @author Michael Herren <mh@studer-raimann.ch> 16 * @ingroup ModulesDataCollection 17 */ 18class ilDclContentExporter 19{ 20 const SOAP_FUNCTION_NAME = 'exportDataCollectionContent'; 21 const EXPORT_EXCEL = 'xlsx'; 22 const IN_PROGRESS_POSTFIX = '.prog'; 23 /** 24 * @var int $ref_id Ref-ID of DataCollection 25 */ 26 protected $ref_id; 27 /** 28 * @var int $table_id Table-Id for export 29 */ 30 protected $table_id; 31 /** 32 * @var array $filter Array with filters 33 */ 34 protected $filter; 35 /** 36 * @var ilObjDataCollection 37 */ 38 protected $dcl; 39 /** 40 * @var ilLanguage 41 */ 42 protected $lng; 43 /** 44 * @var ilDclTable 45 */ 46 protected $table; 47 48 49 public function __construct($ref_id, $table_id = null, $filter = array()) 50 { 51 global $DIC; 52 $lng = $DIC['lng']; 53 54 $this->ref_id = $ref_id; 55 $this->table_id = $table_id; 56 $this->filter = $filter; 57 58 $this->dcl = new ilObjDataCollection($ref_id); 59 $this->tables = ($table_id) ? array($this->dcl->getTableById($table_id)) : $this->dcl->getTables(); 60 61 $lng->loadLanguageModule('dcl'); 62 $this->lng = $lng; 63 } 64 65 66 /** 67 * Sanitize the given filename 68 * The ilUtil::_sanitizeFilemame() does not clean enough 69 * 70 * @param $filename 71 * 72 * @return string 73 */ 74 public function sanitizeFilename($filename) 75 { 76 $dangerous_filename_characters = array(" ", '"', "'", "&", "/", "\\", "?", "#", "`"); 77 78 return str_replace($dangerous_filename_characters, "_", iconv("utf-8", "ascii//TRANSLIT", $filename)); 79 } 80 81 82 /** 83 * Return export path 84 * 85 * @param $format 86 * 87 * @return string 88 */ 89 public function getExportContentPath($format) 90 { 91 return ilExport::_getExportDirectory($this->dcl->getId(), $format, 'dcl') . '/'; 92 } 93 94 95 /** 96 * Fill a excel row 97 * 98 * @param ilDclTable $table 99 * @param ilExcel $worksheet 100 * @param ilDclBaseRecordModel $record 101 * @param $row 102 */ 103 protected function fillRowExcel(ilDclTable $table, ilExcel $worksheet, ilDclBaseRecordModel $record, $row) 104 { 105 $col = 0; 106 foreach ($table->getFields() as $field) { 107 if ($field->getExportable()) { 108 $record->fillRecordFieldExcelExport($worksheet, $row, $col, $field->getId()); 109 } 110 } 111 } 112 113 114 /** 115 * Fill Excel header 116 * 117 * @param ilDclTable $table 118 * @param ilExcel $worksheet 119 * @param $row 120 */ 121 protected function fillHeaderExcel(ilDclTable $table, ilExcel $worksheet, $row) 122 { 123 $col = 0; 124 125 foreach ($table->getFields() as $field) { 126 if ($field->getExportable()) { 127 $field->fillHeaderExcel($worksheet, $row, $col); 128 } 129 } 130 } 131 132 133 /** 134 * Fill Excel meta-data 135 * 136 * @param $table 137 * @param $worksheet 138 * @param $row 139 */ 140 protected function fillMetaExcel($table, $worksheet, $row) 141 { 142 } 143 144 145 /** 146 * Creates an export of a specific datacollection table 147 * 148 * @param string $format 149 * @param null $filepath 150 * @param bool|false $send 151 * 152 * @return null|string|void 153 */ 154 public function export($format = self::EXPORT_EXCEL, $filepath = null, $send = false) 155 { 156 if (count($this->tables) == 0) { 157 return; 158 } 159 160 if (empty($filepath)) { 161 $filepath = $this->getExportContentPath($format); 162 ilUtil::makeDirParents($filepath); 163 164 $basename = (isset($this->table_id)) ? $this->tables[0]->getTitle() : 'complete'; 165 $filename = time() . '__' . $basename . "_" . date("Y-m-d_H-i"); 166 167 $filepath .= $this->sanitizeFilename($filename); 168 } else { 169 $filename = pathinfo($filepath, PATHINFO_FILENAME); 170 } 171 172 $in_progress_file = $filepath . self::IN_PROGRESS_POSTFIX; 173 file_put_contents($in_progress_file, ""); 174 175 $data_available = false; 176 $fields_available = false; 177 switch ($format) { 178 case self::EXPORT_EXCEL: 179 require_once "./Services/Excel/classes/class.ilExcel.php"; 180 181 $adapter = new ilExcel(); 182 foreach ($this->tables as $table) { 183 ilDclCache::resetCache(); 184 185 $list = $table->getPartialRecords(null, null, null, 0, $this->filter); 186 $data_available = $data_available || ($list['total'] > 0); 187 $fields_available = $fields_available || (count($table->getExportableFields()) > 0); 188 if ($list['total'] > 0 && count($table->getExportableFields()) > 0) { 189 // only 31 character-long table-titles are allowed 190 $title = substr($table->getTitle(), 0, 31); 191 $adapter->addSheet($title); 192 $row = 1; 193 194 $this->fillMetaExcel($table, $adapter, $row); 195 196 // #14813 197 $pre = $row; 198 $this->fillHeaderExcel($table, $adapter, $row); 199 if ($pre == $row) { 200 $row++; 201 } 202 203 foreach ($list['records'] as $set) { 204 $this->fillRowExcel($table, $adapter, $set, $row); 205 $row++; // #14760 206 } 207 208 $data_available = true; 209 } 210 } 211 break; 212 } 213 214 if (file_exists($in_progress_file)) { 215 unlink($in_progress_file); 216 } 217 218 if (!$data_available) { 219 ilUtil::sendInfo($this->lng->txt('dcl_no_export_content_available')); 220 221 return false; 222 } 223 224 if (!$fields_available) { 225 global $ilCtrl; 226 ilUtil::sendInfo( 227 sprintf( 228 $this->lng->txt('dcl_no_export_fields_available'), 229 $ilCtrl->getLinkTargetByClass(array('ilDclTableListGUI', 'ilDclTableEditGUI', 'ilDclFieldListGUI'), 'listFields') 230 ) 231 ); 232 233 return false; 234 } 235 236 if ($send) { 237 $adapter->sendToClient($filename); 238 exit; 239 } else { 240 $adapter->writeToFile($filepath); 241 } 242 } 243 244 245 /** 246 * Start Export async 247 * 248 * @param string $format 249 * @param null $filepath 250 * 251 * @return mixed 252 * @throws ilDclException 253 */ 254 public function exportAsync($format = self::EXPORT_EXCEL, $filepath = null) 255 { 256 global $DIC; 257 $ilLog = $DIC['ilLog']; 258 259 $method = self::SOAP_FUNCTION_NAME; 260 261 $soap_params = array($this->dcl->getRefId()); 262 array_push($soap_params, $this->table_id, $format, $filepath); 263 264 $new_session_id = ilSession::_duplicate($_COOKIE[session_name()]); 265 $client_id = $_COOKIE['ilClientId']; 266 267 // Start cloning process using soap call 268 include_once 'Services/WebServices/SOAP/classes/class.ilSoapClient.php'; 269 270 $soap_client = new ilSoapClient(); 271 $soap_client->setResponseTimeout(5); 272 $soap_client->enableWSDL(true); 273 274 $ilLog->write(__METHOD__ . ': Trying to call Soap client...'); 275 276 array_unshift($soap_params, $new_session_id . '::' . $client_id); 277 278 if ($soap_client->init()) { 279 $ilLog->info('Calling soap ' . $method . ' method with params ' . print_r($soap_params, true)); 280 $res = $soap_client->call($method, $soap_params); 281 } else { 282 $ilLog->warning('SOAP clone call failed. Calling clone method manually'); 283 require_once('./webservice/soap/include/inc.soap_functions.php'); 284 if (method_exists('ilSoapFunctions', $method)) { 285 $res = ilSoapFunctions::$method($new_session_id . '::' . $client_id, $this->dcl->getRefId(), $this->table_id, $format, $filepath); 286 } else { 287 throw new ilDclException("SOAP call " . $method . " does not exists!"); 288 } 289 } 290 291 return $res; 292 } 293} 294