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