import_csv.php 94 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CourseBundle\Entity\CCalendarEvent;
  4. use Chamilo\CourseBundle\Entity\CItemProperty;
  5. if (PHP_SAPI != 'cli') {
  6. die('Run this script through the command line or comment this line in the code');
  7. }
  8. if (file_exists('multiple_url_fix.php')) {
  9. require 'multiple_url_fix.php';
  10. }
  11. require_once __DIR__.'/../inc/global.inc.php';
  12. ini_set('memory_limit', -1);
  13. ini_set('max_execution_time', 0);
  14. ini_set('log_errors', '1');
  15. /**
  16. * Class ImportCsv
  17. */
  18. class ImportCsv
  19. {
  20. private $logger;
  21. private $dumpValues;
  22. public $test;
  23. public $defaultLanguage = 'dutch';
  24. public $extraFieldIdNameList = array(
  25. 'session' => 'external_session_id',
  26. 'course' => 'external_course_id',
  27. 'user' => 'external_user_id',
  28. 'calendar_event' => 'external_calendar_event_id',
  29. );
  30. public $defaultAdminId = 1;
  31. public $defaultSessionVisibility = 1;
  32. /**
  33. * When creating a user the expiration date is set to registration date + this value
  34. * @var int number of years
  35. */
  36. public $expirationDateInUserCreation = 1;
  37. public $batchSize = 20;
  38. /**
  39. * When updating a user the expiration date is set to update date + this value
  40. * @var int number of years
  41. */
  42. public $expirationDateInUserUpdate = 1;
  43. public $daysCoachAccessBeforeBeginning = 14;
  44. public $daysCoachAccessAfterBeginning = 14;
  45. public $conditions;
  46. private $updateEmailToDummy;
  47. /**
  48. * @param Monolog\Logger $logger
  49. * @param array
  50. */
  51. public function __construct($logger, $conditions)
  52. {
  53. $this->logger = $logger;
  54. $this->conditions = $conditions;
  55. $this->updateEmailToDummy = false;
  56. }
  57. /**
  58. * @param bool $dump
  59. */
  60. public function setDumpValues($dump)
  61. {
  62. $this->dumpValues = $dump;
  63. }
  64. /**
  65. * @return boolean
  66. */
  67. public function getDumpValues()
  68. {
  69. return $this->dumpValues;
  70. }
  71. /**
  72. * Runs the import process
  73. */
  74. public function run()
  75. {
  76. global $_configuration;
  77. $value = api_get_configuration_value('import_csv_custom_url_id');
  78. if (!empty($value)) {
  79. $_configuration['access_url'] = $value;
  80. }
  81. $path = api_get_path(SYS_CODE_PATH).'cron/incoming/';
  82. if (!is_dir($path)) {
  83. echo "The folder! $path does not exits";
  84. return 0;
  85. }
  86. if ($this->getDumpValues()) {
  87. $this->dumpDatabaseTables();
  88. }
  89. echo "Reading files: ".PHP_EOL.PHP_EOL;
  90. $files = scandir($path);
  91. $fileToProcess = array();
  92. $fileToProcessStatic = array();
  93. $teacherBackup = array();
  94. $groupBackup = array();
  95. if (!empty($files)) {
  96. foreach ($files as $file) {
  97. $fileInfo = pathinfo($file);
  98. if (isset($fileInfo['extension']) && $fileInfo['extension'] === 'csv') {
  99. // Checking teachers_yyyymmdd.csv, courses_yyyymmdd.csv, students_yyyymmdd.csv and sessions_yyyymmdd.csv
  100. $parts = explode('_', $fileInfo['filename']);
  101. $preMethod = ucwords($parts[1]);
  102. $preMethod = str_replace('-static', 'Static', $preMethod);
  103. $method = 'import'.$preMethod;
  104. $isStatic = strpos($method, 'Static');
  105. if ($method == 'importSessionsextidStatic') {
  106. $method = 'importSessionsExtIdStatic';
  107. }
  108. if ($method == 'importCourseinsertStatic') {
  109. $method = 'importSubscribeUserToCourse';
  110. }
  111. if ($method == 'importUnsubsessionsextidStatic') {
  112. $method = 'importUnsubsessionsExtidStatic';
  113. }
  114. if ($method == 'importSubsessionsextidStatic') {
  115. $method = 'importSubscribeUserToCourseSessionExtStatic';
  116. }
  117. if (method_exists($this, $method)) {
  118. if (
  119. (
  120. $method == 'importSubscribeStatic' ||
  121. $method == 'importSubscribeUserToCourse'
  122. ) ||
  123. empty($isStatic)
  124. ) {
  125. $fileToProcess[$parts[1]][] = array(
  126. 'method' => $method,
  127. 'file' => $path.$fileInfo['basename']
  128. );
  129. } else {
  130. $fileToProcessStatic[$parts[1]][] = array(
  131. 'method' => $method,
  132. 'file' => $path.$fileInfo['basename']
  133. );
  134. }
  135. } else {
  136. echo "Error - This file '$file' can't be processed.".PHP_EOL;
  137. echo "Trying to call $method".PHP_EOL;
  138. echo "The file have to has this format:".PHP_EOL;
  139. echo "prefix_students_ddmmyyyy.csv, prefix_teachers_ddmmyyyy.csv, prefix_courses_ddmmyyyy.csv, prefix_sessions_ddmmyyyy.csv ".PHP_EOL;
  140. exit;
  141. }
  142. }
  143. }
  144. if (empty($fileToProcess) && empty($fileToProcessStatic)) {
  145. echo 'Error - no files to process.';
  146. return 0;
  147. }
  148. $this->prepareImport();
  149. $sections = array(
  150. 'students',
  151. 'teachers',
  152. 'courses',
  153. 'sessions',
  154. 'subscribe-static',
  155. 'courseinsert-static',
  156. 'unsubscribe-static'
  157. );
  158. foreach ($sections as $section) {
  159. $this->logger->addInfo("-- Import $section --");
  160. if (isset($fileToProcess[$section]) && !empty($fileToProcess[$section])) {
  161. $files = $fileToProcess[$section];
  162. foreach ($files as $fileInfo) {
  163. $method = $fileInfo['method'];
  164. $file = $fileInfo['file'];
  165. echo 'File: '.$file.PHP_EOL;
  166. $this->logger->addInfo("Reading file: $file");
  167. if ($method == 'importSessions') {
  168. $this->$method(
  169. $file,
  170. true,
  171. $teacherBackup,
  172. $groupBackup
  173. );
  174. } else {
  175. $this->$method($file, true);
  176. }
  177. $this->logger->addInfo("--Finish reading file--");
  178. }
  179. }
  180. }
  181. $sections = array(
  182. 'students-static',
  183. 'teachers-static',
  184. 'courses-static',
  185. 'sessions-static',
  186. 'calendar-static',
  187. 'sessionsextid-static',
  188. 'unsubscribe-static',
  189. 'unsubsessionsextid-static',
  190. 'subsessionsextid-static'
  191. );
  192. foreach ($sections as $section) {
  193. $this->logger->addInfo("-- Import static files $section --");
  194. if (isset($fileToProcessStatic[$section]) &&
  195. !empty($fileToProcessStatic[$section])
  196. ) {
  197. $files = $fileToProcessStatic[$section];
  198. foreach ($files as $fileInfo) {
  199. $method = $fileInfo['method'];
  200. $file = $fileInfo['file'];
  201. echo 'Static file: '.$file.PHP_EOL;
  202. $this->logger->addInfo("Reading static file: $file");
  203. $this->$method(
  204. $file,
  205. true,
  206. $teacherBackup,
  207. $groupBackup
  208. );
  209. $this->logger->addInfo("--Finish reading file--");
  210. }
  211. }
  212. }
  213. $this->logger->addInfo("teacher backup");
  214. $this->logger->addInfo(print_r($teacherBackup, 1));
  215. }
  216. }
  217. /**
  218. * Prepares extra fields before the import
  219. */
  220. private function prepareImport()
  221. {
  222. // Create user extra field: extra_external_user_id
  223. UserManager::create_extra_field(
  224. $this->extraFieldIdNameList['user'],
  225. 1,
  226. 'External user id',
  227. null
  228. );
  229. // Create course extra field: extra_external_course_id
  230. CourseManager::create_course_extra_field(
  231. $this->extraFieldIdNameList['course'],
  232. 1,
  233. 'External course id',
  234. ''
  235. );
  236. // Create session extra field extra_external_session_id
  237. SessionManager::create_session_extra_field(
  238. $this->extraFieldIdNameList['session'],
  239. 1,
  240. 'External session id'
  241. );
  242. // Create calendar_event extra field extra_external_session_id
  243. $extraField = new ExtraField('calendar_event');
  244. $extraField->save(
  245. array(
  246. 'field_type' => ExtraField::FIELD_TYPE_TEXT,
  247. 'variable' => $this->extraFieldIdNameList['calendar_event'],
  248. 'display_text' => 'External calendar event id',
  249. )
  250. );
  251. }
  252. /**
  253. * @param string $file
  254. */
  255. private function moveFile($file)
  256. {
  257. $moved = str_replace('incoming', 'treated', $file);
  258. if ($this->test) {
  259. $result = 1;
  260. } else {
  261. $result = rename($file, $moved);
  262. }
  263. if ($result) {
  264. $this->logger->addInfo("Moving file to the treated folder: $file");
  265. } else {
  266. $this->logger->addError(
  267. "Error - Cant move file to the treated folder: $file"
  268. );
  269. }
  270. }
  271. /**
  272. * @param array $row
  273. *
  274. * @return array
  275. */
  276. private function cleanUserRow($row)
  277. {
  278. $row['lastname'] = $row['LastName'];
  279. $row['firstname'] = $row['FirstName'];
  280. $row['email'] = $row['Email'];
  281. $row['username'] = $row['UserName'];
  282. $row['password'] = $row['Password'];
  283. $row['auth_source'] = isset($row['AuthSource']) ? $row['AuthSource'] : PLATFORM_AUTH_SOURCE;
  284. $row['official_code'] = $row['OfficialCode'];
  285. $row['phone'] = isset($row['PhoneNumber']) ? $row['PhoneNumber'] : '';
  286. if (isset($row['StudentID'])) {
  287. $row['extra_'.$this->extraFieldIdNameList['user']] = $row['StudentID'];
  288. }
  289. if (isset($row['TeacherID'])) {
  290. $row['extra_'.$this->extraFieldIdNameList['user']] = $row['TeacherID'];
  291. }
  292. return $row;
  293. }
  294. /**
  295. * @param array $row
  296. *
  297. * @return array
  298. */
  299. private function cleanCourseRow($row)
  300. {
  301. $row['title'] = $row['Title'];
  302. $row['course_code'] = $row['Code'];
  303. $row['course_category'] = $row['CourseCategory'];
  304. $row['email'] = $row['Teacher'];
  305. $row['language'] = $row['Language'];
  306. $row['teachers'] = array();
  307. if (isset($row['Teacher']) && !empty($row['Teacher'])) {
  308. $this->logger->addInfo("Teacher list found: ".$row['Teacher']);
  309. $teachers = explode(',', $row['Teacher']);
  310. if (!empty($teachers)) {
  311. foreach ($teachers as $teacherUserName) {
  312. $teacherUserName = trim($teacherUserName);
  313. $userInfo = api_get_user_info_from_username($teacherUserName);
  314. if (!empty($userInfo)) {
  315. $this->logger->addInfo("Username found: $teacherUserName");
  316. $row['teachers'][] = $userInfo['user_id'];
  317. }
  318. }
  319. }
  320. }
  321. if (isset($row['CourseID'])) {
  322. $row['extra_'.$this->extraFieldIdNameList['course']] = $row['CourseID'];
  323. }
  324. return $row;
  325. }
  326. /**
  327. * File to import
  328. * @param string $file
  329. */
  330. private function importTeachersStatic($file)
  331. {
  332. $this->importTeachers($file, true);
  333. }
  334. /**
  335. * File to import
  336. * @param string $file
  337. * @param bool $moveFile
  338. */
  339. private function importTeachers($file, $moveFile = true)
  340. {
  341. $this->fixCSVFile($file);
  342. $data = Import::csvToArray($file);
  343. /* Unique identifier: official-code username.
  344. Email address and password should never get updated. *ok
  345. The only fields that I can think of that should update if the data changes in the csv file are FirstName and LastName. *ok
  346. A slight edit of these fields should be taken into account. ???
  347. Adding teachers is no problem, but deleting them shouldn’t be automated, but we should get a log of “to delete teachers”.
  348. We’ll handle that manually if applicable.
  349. No delete!
  350. */
  351. $language = $this->defaultLanguage;
  352. if (!empty($data)) {
  353. $this->logger->addInfo(count($data)." records found.");
  354. $expirationDateOnCreation = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserCreation)."years"));
  355. $expirationDateOnUpdate = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserUpdate)."years"));
  356. $batchSize = $this->batchSize;
  357. $em = Database::getManager();
  358. $counter = 1;
  359. foreach ($data as $row) {
  360. $row = $this->cleanUserRow($row);
  361. $user_id = UserManager::get_user_id_from_original_id(
  362. $row['extra_'.$this->extraFieldIdNameList['user']],
  363. $this->extraFieldIdNameList['user']
  364. );
  365. $userInfo = array();
  366. $userInfoByOfficialCode = null;
  367. if (!empty($user_id)) {
  368. $userInfo = api_get_user_info($user_id);
  369. $userInfoByOfficialCode = api_get_user_info_from_official_code($row['official_code']);
  370. }
  371. if (empty($userInfo) && empty($userInfoByOfficialCode)) {
  372. // Create user
  373. $userId = UserManager::create_user(
  374. $row['firstname'],
  375. $row['lastname'],
  376. COURSEMANAGER,
  377. $row['email'],
  378. $row['username'],
  379. $row['password'],
  380. $row['official_code'],
  381. $language, //$row['language'],
  382. $row['phone'],
  383. null, //$row['picture'], //picture
  384. $row['auth_source'], // ?
  385. $expirationDateOnCreation, //'0000-00-00 00:00:00', //$row['expiration_date'], //$expiration_date = '0000-00-00 00:00:00',
  386. 1, //active
  387. 0,
  388. null, // extra
  389. null, //$encrypt_method = '',
  390. false //$send_mail = false
  391. );
  392. if ($userId) {
  393. foreach ($row as $key => $value) {
  394. if (substr($key, 0, 6) == 'extra_') {
  395. //an extra field
  396. UserManager::update_extra_field_value(
  397. $userId,
  398. substr($key, 6),
  399. $value
  400. );
  401. }
  402. }
  403. $this->logger->addInfo("Teachers - User created: ".$row['username']);
  404. } else {
  405. $this->logger->addError("Teachers - User NOT created: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
  406. $this->logger->addError(strip_tags(Display::getFlashToString()));
  407. Display::cleanFlashMessages();
  408. }
  409. } else {
  410. if (empty($userInfo)) {
  411. $this->logger->addError("Teachers - Can't update user :".$row['username']);
  412. continue;
  413. }
  414. // Update user
  415. $result = UserManager::update_user(
  416. $userInfo['user_id'],
  417. $row['firstname'], // <<-- changed
  418. $row['lastname'], // <<-- changed
  419. $userInfo['username'],
  420. null, //$password = null,
  421. $row['auth_source'],
  422. $userInfo['email'],
  423. COURSEMANAGER,
  424. $userInfo['official_code'],
  425. $userInfo['phone'],
  426. $userInfo['picture_uri'],
  427. $expirationDateOnUpdate,
  428. $userInfo['active'],
  429. null, //$creator_id = null,
  430. 0, //$hr_dept_id = 0,
  431. null, // $extra = null,
  432. null, //$language = 'english',
  433. null, //$encrypt_method = '',
  434. false, //$send_email = false,
  435. 0 //$reset_password = 0
  436. );
  437. if ($result) {
  438. foreach ($row as $key => $value) {
  439. if (substr($key, 0, 6) == 'extra_') {
  440. //an extra field
  441. UserManager::update_extra_field_value(
  442. $userInfo['user_id'],
  443. substr($key, 6),
  444. $value
  445. );
  446. }
  447. }
  448. $this->logger->addInfo("Teachers - User updated: ".$row['username']);
  449. } else {
  450. $this->logger->addError("Teachers - User not updated: ".$row['username']);
  451. }
  452. }
  453. if (($counter % $batchSize) === 0) {
  454. $em->flush();
  455. $em->clear(); // Detaches all objects from Doctrine!
  456. }
  457. $counter++;
  458. }
  459. $em->clear(); // Detaches all objects from Doctrine!
  460. }
  461. if ($moveFile) {
  462. $this->moveFile($file);
  463. }
  464. $this->updateUsersEmails();
  465. }
  466. /**
  467. * @param string $file
  468. */
  469. private function importStudentsStatic($file)
  470. {
  471. $this->importStudents($file, true);
  472. }
  473. /**
  474. * @param string $file
  475. * @param bool $moveFile
  476. */
  477. private function importStudents($file, $moveFile = true)
  478. {
  479. $this->fixCSVFile($file);
  480. $data = Import::csvToArray($file);
  481. /*
  482. * Another users import.
  483. Unique identifier: official code and username . ok
  484. Password should never get updated. ok
  485. If an update should need to occur (because it changed in the .csv),
  486. we’ll want that logged. We will handle this manually in that case.
  487. All other fields should be updateable, though passwords should of course not get updated. ok
  488. If a user gets deleted (not there anymore),
  489. He should be set inactive one year after the current date.
  490. So I presume you’ll just update the expiration date.
  491. We want to grant access to courses up to a year after deletion.
  492. */
  493. $timeStart = microtime(true);
  494. $batchSize = $this->batchSize;
  495. $em = Database::getManager();
  496. if (!empty($data)) {
  497. $language = $this->defaultLanguage;
  498. $this->logger->addInfo(count($data)." records found.");
  499. $expirationDateOnCreate = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserCreation)."years"));
  500. $expirationDateOnUpdate = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserUpdate)."years"));
  501. $counter = 1;
  502. foreach ($data as $row) {
  503. $row = $this->cleanUserRow($row);
  504. $user_id = UserManager::get_user_id_from_original_id(
  505. $row['extra_'.$this->extraFieldIdNameList['user']],
  506. $this->extraFieldIdNameList['user']
  507. );
  508. $userInfo = array();
  509. $userInfoByOfficialCode = null;
  510. if (!empty($user_id)) {
  511. $userInfo = api_get_user_info($user_id, false, true);
  512. $userInfoByOfficialCode = api_get_user_info_from_official_code($row['official_code']);
  513. }
  514. if (empty($userInfo) && empty($userInfoByOfficialCode)) {
  515. // Create user
  516. $result = UserManager::create_user(
  517. $row['firstname'],
  518. $row['lastname'],
  519. STUDENT,
  520. $row['email'],
  521. $row['username'],
  522. $row['password'],
  523. $row['official_code'],
  524. $language, //$row['language'],
  525. $row['phone'],
  526. null, //$row['picture'], //picture
  527. $row['auth_source'], // ?
  528. $expirationDateOnCreate, //'0000-00-00 00:00:00', //$row['expiration_date'], //$expiration_date = '0000-00-00 00:00:00',
  529. 1, //active
  530. 0,
  531. null, // extra
  532. null, //$encrypt_method = '',
  533. false //$send_mail = false
  534. );
  535. if ($result) {
  536. foreach ($row as $key => $value) {
  537. if (substr($key, 0, 6) === 'extra_') {
  538. //an extra field
  539. UserManager::update_extra_field_value(
  540. $result,
  541. substr($key, 6),
  542. $value
  543. );
  544. }
  545. }
  546. $this->logger->addInfo("Students - User created: ".$row['username']);
  547. } else {
  548. $this->logger->addError("Students - User NOT created: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
  549. $this->logger->addError(strip_tags(Display::getFlashToString()));
  550. Display::cleanFlashMessages();
  551. }
  552. } else {
  553. if (empty($userInfo)) {
  554. $this->logger->addError("Students - Can't update user :".$row['username']);
  555. continue;
  556. }
  557. if (isset($row['action']) && $row['action'] === 'delete') {
  558. // Inactive one year later
  559. $userInfo['expiration_date'] = api_get_utc_datetime(api_strtotime(time() + 365 * 24 * 60 * 60));
  560. }
  561. $password = $row['password']; // change password
  562. $email = $row['email']; // change email
  563. $resetPassword = 2; // allow password change
  564. // Conditions that disables the update of password and email:
  565. if (isset($this->conditions['importStudents'])) {
  566. if (isset($this->conditions['importStudents']['update']) &&
  567. isset($this->conditions['importStudents']['update']['avoid'])
  568. ) {
  569. // Blocking email update -
  570. // 1. Condition
  571. $avoidUsersWithEmail = $this->conditions['importStudents']['update']['avoid']['email'];
  572. if ($userInfo['email'] != $row['email'] && in_array($row['email'], $avoidUsersWithEmail)) {
  573. $this->logger->addInfo("Students - User email is not updated : ".$row['username']." because the avoid conditions (email).");
  574. // Do not change email keep the old email.
  575. $email = $userInfo['email'];
  576. }
  577. // 2. Condition
  578. if (!in_array($userInfo['email'], $avoidUsersWithEmail) && !in_array($row['email'], $avoidUsersWithEmail)) {
  579. $email = $userInfo['email'];
  580. }
  581. // 3. Condition
  582. if (in_array($userInfo['email'], $avoidUsersWithEmail) && !in_array($row['email'], $avoidUsersWithEmail)) {
  583. $email = $row['email'];
  584. }
  585. // Blocking password update
  586. //$avoidUsersWithPassword = $this->conditions['importStudents']['update']['avoid']['password'];
  587. /*if (isset($row['password'])) {
  588. $user = api_get_user_entity($userInfo['id']);
  589. $encoded = UserManager::encryptPassword(
  590. $row['password'],
  591. $user
  592. );
  593. if ($userInfo['password'] != $encoded &&
  594. in_array($row['password'], $avoidUsersWithPassword)
  595. ) {
  596. $this->logger->addInfo(
  597. "Students - User password is not updated: ".$row['username']." because the avoid conditions (password)."
  598. );
  599. $password = null;
  600. $resetPassword = 0; // disallow password change
  601. }
  602. }*/
  603. }
  604. }
  605. // Always disallow password change during update
  606. $password = null;
  607. $resetPassword = 0; // disallow password change
  608. // Update user
  609. $result = UserManager::update_user(
  610. $userInfo['user_id'],
  611. $row['firstname'], // <<-- changed
  612. $row['lastname'], // <<-- changed
  613. $row['username'], // <<-- changed
  614. $password, //$password = null,
  615. $row['auth_source'],
  616. $email,
  617. STUDENT,
  618. $userInfo['official_code'],
  619. $userInfo['phone'],
  620. $userInfo['picture_uri'],
  621. $expirationDateOnUpdate,
  622. $userInfo['active'],
  623. null, //$creator_id = null,
  624. 0, //$hr_dept_id = 0,
  625. null, // $extra = null,
  626. null, //$language = 'english',
  627. null, //$encrypt_method = '',
  628. false, //$send_email = false,
  629. $resetPassword //$reset_password = 0
  630. );
  631. if ($result) {
  632. if ($row['username'] != $userInfo['username']) {
  633. $this->logger->addInfo("Students - Username was changes from '".$userInfo['username']."' to '".$row['username']."' ");
  634. }
  635. foreach ($row as $key => $value) {
  636. if (substr($key, 0, 6) === 'extra_') {
  637. //an extra field
  638. UserManager::update_extra_field_value(
  639. $userInfo['user_id'],
  640. substr($key, 6),
  641. $value
  642. );
  643. }
  644. }
  645. $this->logger->addInfo("Students - User updated: ".$row['username']);
  646. } else {
  647. $this->logger->addError("Students - User NOT updated: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
  648. }
  649. }
  650. if (($counter % $batchSize) === 0) {
  651. $em->flush();
  652. $em->clear(); // Detaches all objects from Doctrine!
  653. $this->logger->addInfo("Detaches all objects");
  654. }
  655. $counter++;
  656. }
  657. $em->clear(); // Detaches all objects from Doctrine!
  658. }
  659. $timeEnd = microtime(true);
  660. $executionTime = round(($timeEnd - $timeStart) / 60, 2);
  661. $this->logger->addInfo("Execution Time for process students: $executionTime Min");
  662. if ($moveFile) {
  663. $this->moveFile($file);
  664. }
  665. $this->updateUsersEmails();
  666. }
  667. /**
  668. * @param string $file
  669. */
  670. private function importCoursesStatic($file, $moveFile, &$teacherBackup = array(), &$groupBackup = array())
  671. {
  672. $this->importCourses($file, true, $teacherBackup, $groupBackup);
  673. }
  674. /**
  675. * @param string $file
  676. * @param bool $moveFile
  677. *
  678. * @return int
  679. */
  680. private function importCalendarStatic($file, $moveFile = true)
  681. {
  682. $this->fixCSVFile($file);
  683. $this->updateUsersEmails();
  684. $data = Import::csvToArray($file);
  685. if (!empty($data)) {
  686. $this->logger->addInfo(count($data)." records found.");
  687. $eventsToCreate = array();
  688. $errorFound = false;
  689. foreach ($data as $row) {
  690. $sessionId = null;
  691. $externalSessionId = null;
  692. if (isset($row['external_sessionID'])) {
  693. $externalSessionId = $row['external_sessionID'];
  694. $sessionId = SessionManager::getSessionIdFromOriginalId(
  695. $externalSessionId,
  696. $this->extraFieldIdNameList['session']
  697. );
  698. }
  699. $courseCode = null;
  700. if (isset($row['coursecode'])) {
  701. $courseCode = $row['coursecode'];
  702. }
  703. $courseInfo = api_get_course_info($courseCode);
  704. if (empty($courseInfo)) {
  705. $this->logger->addInfo("Course '$courseCode' does not exists");
  706. }
  707. if (empty($sessionId)) {
  708. $this->logger->addInfo("external_sessionID: ".$externalSessionId." does not exists.");
  709. }
  710. $teacherId = null;
  711. if (!empty($sessionId) && !empty($courseInfo)) {
  712. $courseIncluded = SessionManager::relation_session_course_exist(
  713. $sessionId,
  714. $courseInfo['real_id']
  715. );
  716. if ($courseIncluded == false) {
  717. $this->logger->addInfo(
  718. "Course '$courseCode' is not included in session: $sessionId"
  719. );
  720. $errorFound = true;
  721. } else {
  722. $teachers = CourseManager::get_coach_list_from_course_code(
  723. $courseInfo['code'],
  724. $sessionId
  725. );
  726. // Getting first teacher.
  727. if (!empty($teachers)) {
  728. $teacher = current($teachers);
  729. $teacherId = $teacher['user_id'];
  730. } else {
  731. $sessionInfo = api_get_session_info($sessionId);
  732. $teacherId = $sessionInfo['id_coach'];
  733. }
  734. }
  735. } else {
  736. $errorFound = true;
  737. }
  738. if (empty($teacherId)) {
  739. $errorFound = true;
  740. $this->logger->addInfo(
  741. "No teacher found in course code : '$courseCode' and session: '$sessionId'"
  742. );
  743. }
  744. $date = $row['date'];
  745. $startTime = $row['time_start'];
  746. $endTime = $row['time_end'];
  747. $title = $row['title'];
  748. $comment = $row['comment'];
  749. $color = isset($row['color']) ? $row['color'] : '';
  750. $startDateYear = substr($date, 0, 4);
  751. $startDateMonth = substr($date, 4, 2);
  752. $startDateDay = substr($date, 6, 8);
  753. $startDate = $startDateYear.'-'.$startDateMonth.'-'.$startDateDay.' '.$startTime.":00";
  754. $endDate = $startDateYear.'-'.$startDateMonth.'-'.$startDateDay.' '.$endTime.":00";
  755. if (!api_is_valid_date($startDate) || !api_is_valid_date($endDate)) {
  756. $this->logger->addInfo(
  757. "Verify your dates: '$startDate' : '$endDate' "
  758. );
  759. $errorFound = true;
  760. }
  761. if ($errorFound == false) {
  762. $eventsToCreate[] = array(
  763. 'start' => $startDate,
  764. 'end' => $endDate,
  765. 'title' => $title,
  766. 'sender_id' => $teacherId,
  767. 'course_id' => $courseInfo['real_id'],
  768. 'session_id' => $sessionId,
  769. 'comment' => $comment,
  770. 'color' => $color,
  771. $this->extraFieldIdNameList['calendar_event'] => $row['external_calendar_itemID'],
  772. );
  773. }
  774. $errorFound = false;
  775. }
  776. if (empty($eventsToCreate)) {
  777. $this->logger->addInfo(
  778. "No events to add"
  779. );
  780. return 0;
  781. }
  782. $extraFieldValue = new ExtraFieldValue('calendar_event');
  783. $extraFieldName = $this->extraFieldIdNameList['calendar_event'];
  784. $externalEventId = null;
  785. $extraField = new ExtraField('calendar_event');
  786. $extraFieldInfo = $extraField->get_handler_field_info_by_field_variable(
  787. $extraFieldName
  788. );
  789. if (empty($extraFieldInfo)) {
  790. $this->logger->addInfo(
  791. "No calendar event extra field created: $extraFieldName"
  792. );
  793. return 0;
  794. }
  795. $this->logger->addInfo('Ready to insert # '.count($eventsToCreate).' events');
  796. $batchSize = $this->batchSize;
  797. $counter = 1;
  798. $em = Database::getManager();
  799. $eventStartDateList = [];
  800. $eventEndDateList = [];
  801. $report = [
  802. 'mail_sent' => 0,
  803. 'mail_not_sent_announcement_exists' => 0,
  804. 'mail_not_sent_because_date' => 0
  805. ];
  806. $eventsToCreateFinal = [];
  807. foreach ($eventsToCreate as $event) {
  808. $update = false;
  809. $item = null;
  810. if (!isset($event[$extraFieldName])) {
  811. $this->logger->addInfo(
  812. "No external_calendar_itemID found. Skipping ..."
  813. );
  814. continue;
  815. } else {
  816. $externalEventId = $event[$extraFieldName];
  817. if (empty($externalEventId)) {
  818. $this->logger->addInfo(
  819. "external_calendar_itemID was set but empty. Skipping ..."
  820. );
  821. continue;
  822. }
  823. $item = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
  824. $extraFieldName,
  825. $externalEventId,
  826. false,
  827. false,
  828. false
  829. );
  830. if (!empty($item)) {
  831. $update = true;
  832. }
  833. }
  834. $courseInfo = api_get_course_info_by_id($event['course_id']);
  835. $event['course_info'] = $courseInfo;
  836. $event['update'] = $update;
  837. $event['item'] = $item;
  838. $calendarEvent = null;
  839. /* Check if event changed of course code */
  840. if (!empty($item) && isset($item['item_id']) && !empty($item['item_id'])) {
  841. /** @var CCalendarEvent $calendarEvent */
  842. $calendarEvent = $em->getRepository('ChamiloCourseBundle:CCalendarEvent')->find($item['item_id']);
  843. }
  844. if ($calendarEvent) {
  845. $this->logger->addInfo('Calendar event found '.$item['item_id']);
  846. if ($calendarEvent->getCId() != $courseInfo['real_id']) {
  847. $this->logger->addInfo('Move from course #'.$calendarEvent->getCId().' to #'.$courseInfo['real_id']);
  848. // Seems that the course id changed in the csv
  849. $calendarEvent->setCId($courseInfo['real_id']);
  850. $em->persist($calendarEvent);
  851. $em->flush();
  852. $criteria = [
  853. 'tool' => 'calendar_event',
  854. 'ref' => $item['item_id']
  855. ];
  856. /** @var CItemProperty $itemProperty */
  857. $itemProperty = $em->getRepository('ChamiloCourseBundle:CItemProperty')->findOneBy($criteria);
  858. $courseEntity = $em->getRepository('ChamiloCoreBundle:Course')->find($courseInfo['real_id']);
  859. if ($itemProperty && $courseEntity) {
  860. $itemProperty->setCourse($courseEntity);
  861. $em->persist($itemProperty);
  862. $em->flush();
  863. }
  864. }
  865. } else {
  866. $this->logger->addInfo('Calendar event not found '.$item['item_id']);
  867. }
  868. $event['external_event_id'] = $externalEventId;
  869. if (isset($eventStartDateList[$courseInfo['real_id']]) &&
  870. isset($eventStartDateList[$courseInfo['real_id']][$event['session_id']])
  871. ) {
  872. $currentItemDate = api_strtotime($event['start']);
  873. $firstDate = $eventStartDateList[$courseInfo['real_id']][$event['session_id']];
  874. if ($currentItemDate < api_strtotime($firstDate)) {
  875. $eventStartDateList[$courseInfo['real_id']][$event['session_id']] = $event['start'];
  876. $eventEndDateList[$courseInfo['real_id']][$event['session_id']] = $event['end'];
  877. }
  878. } else {
  879. // First time
  880. $eventStartDateList[$courseInfo['real_id']][$event['session_id']] = $event['start'];
  881. $eventEndDateList[$courseInfo['real_id']][$event['session_id']] = $event['end'];
  882. }
  883. $eventsToCreateFinal[] = $event;
  884. }
  885. $eventAlreadySent = [];
  886. foreach ($eventsToCreateFinal as $event) {
  887. $courseInfo = $event['course_info'];
  888. $item = $event['item'];
  889. $update = $event['update'];
  890. $externalEventId = $event['external_event_id'];
  891. $info = 'Course: '.$courseInfo['real_id'].' ('.$courseInfo['code'].') - Session: '.$event['session_id'];
  892. $agenda = new Agenda(
  893. 'course',
  894. $event['sender_id'],
  895. $courseInfo['real_id'],
  896. $event['session_id']
  897. );
  898. $agenda->set_course($courseInfo);
  899. $agenda->setSessionId($event['session_id']);
  900. $agenda->setSenderId($event['sender_id']);
  901. $agenda->setIsAllowedToEdit(true);
  902. $eventComment = $event['comment'];
  903. $color = $event['color'];
  904. // To use the event comment you need
  905. // ALTER TABLE c_calendar_event ADD COLUMN comment TEXT;
  906. // add in configuration.php allow_agenda_event_comment = true
  907. if (empty($courseInfo)) {
  908. $this->logger->addInfo(
  909. "No course found for event #$externalEventId Course #".$event['course_id']." Skipping ..."
  910. );
  911. continue;
  912. }
  913. if (empty($event['sender_id'])) {
  914. $this->logger->addInfo(
  915. "No sender found for event #$externalEventId Send #".$event['sender_id']." Skipping ..."
  916. );
  917. continue;
  918. }
  919. // Taking first element of course-session event
  920. $alreadyAdded = false;
  921. $firstDate = $eventStartDateList[$courseInfo['real_id']][$event['session_id']];
  922. $firstEndDate = $eventEndDateList[$courseInfo['real_id']][$event['session_id']];
  923. if (isset($eventAlreadySent[$courseInfo['real_id']]) &&
  924. isset($eventAlreadySent[$courseInfo['real_id']][$event['session_id']])
  925. ) {
  926. $alreadyAdded = true;
  927. } else {
  928. $eventAlreadySent[$courseInfo['real_id']][$event['session_id']] = true;
  929. }
  930. // Working days (Mon-Fri)see BT#12156#note-16
  931. $days = 5;
  932. $startDatePlusDays = api_strtotime("$days weekdays");
  933. $this->logger->addInfo(
  934. "startDatePlusDays: ".api_get_utc_datetime($startDatePlusDays).' - First date: '.$firstDate
  935. );
  936. // Send
  937. if ($startDatePlusDays > api_strtotime($firstDate)) {
  938. $sendMail = true;
  939. } else {
  940. $sendMail = false;
  941. }
  942. // Send announcement to users
  943. if ($sendMail && $alreadyAdded == false) {
  944. $start = $firstDate;
  945. $end = $firstEndDate;
  946. if (!empty($end) &&
  947. api_format_date($start, DATE_FORMAT_LONG) == api_format_date($end, DATE_FORMAT_LONG)
  948. ) {
  949. $date = api_format_date($start, DATE_FORMAT_LONG).' ('.
  950. api_format_date($start, TIME_NO_SEC_FORMAT).' '.
  951. api_format_date($end, TIME_NO_SEC_FORMAT).')';
  952. } else {
  953. $date = api_format_date($start, DATE_TIME_FORMAT_LONG_24H).' - '.
  954. api_format_date($end, DATE_TIME_FORMAT_LONG_24H);
  955. }
  956. $sessionName = '';
  957. if (!empty($event['session_id'])) {
  958. $sessionName = ' ('.api_get_session_name($event['session_id']).')';
  959. }
  960. $courseTitle = $courseInfo['title'].$sessionName;
  961. $emailBody = get_lang('Dear').' ((user_firstname)) <br />'.
  962. sprintf(
  963. get_lang('YouHaveBeenSubscribedToCourseXTheStartDateXAndCommentX'),
  964. $courseTitle,
  965. $date,
  966. $event['comment']
  967. );
  968. $subject = sprintf(
  969. get_lang('AgendaAvailableInCourseX'),
  970. $courseInfo['title']
  971. );
  972. $coaches = SessionManager::getCoachesByCourseSession(
  973. $courseInfo['real_id'],
  974. $event['session_id']
  975. );
  976. // Search if an announcement exists:
  977. $announcementsWithTitleList = AnnouncementManager::getAnnouncementsByTitle(
  978. $subject,
  979. $courseInfo['real_id'],
  980. $event['session_id'],
  981. 1
  982. );
  983. if (count($announcementsWithTitleList) === 0) {
  984. $this->logger->addInfo(
  985. "Mail to be sent because start date: ".$event['start']." and no announcement found."
  986. );
  987. $announcementId = AnnouncementManager::add_announcement(
  988. $courseInfo,
  989. $event['session_id'],
  990. $subject,
  991. $emailBody,
  992. [
  993. 'everyone',
  994. 'users' => $coaches
  995. ],
  996. [],
  997. null,
  998. null,
  999. false,
  1000. $this->defaultAdminId
  1001. );
  1002. if ($announcementId) {
  1003. $this->logger->addInfo(
  1004. "Announcement added: ".(int) ($announcementId)." in $info"
  1005. );
  1006. $this->logger->addInfo(
  1007. "<<--SENDING MAIL-->>"
  1008. );
  1009. $report['mail_sent']++;
  1010. AnnouncementManager::sendEmail(
  1011. $courseInfo,
  1012. $event['session_id'],
  1013. $announcementId,
  1014. false
  1015. );
  1016. }
  1017. } else {
  1018. $report['mail_not_sent_announcement_exists']++;
  1019. $this->logger->addInfo(
  1020. "Mail NOT sent. An announcement seems to be already saved in '$info'"
  1021. );
  1022. }
  1023. } else {
  1024. if ($sendMail == false) {
  1025. $report['mail_not_sent_because_date']++;
  1026. }
  1027. }
  1028. $content = '';
  1029. if ($update && isset($item['item_id'])) {
  1030. //the event already exists, just update
  1031. $eventResult = $agenda->editEvent(
  1032. $item['item_id'],
  1033. $event['start'],
  1034. $event['end'],
  1035. false,
  1036. $event['title'],
  1037. $content,
  1038. array('everyone'), // $usersToSend
  1039. array(), //$attachmentArray = array(),
  1040. [], //$attachmentCommentList
  1041. $eventComment,
  1042. $color,
  1043. false,
  1044. false,
  1045. $this->defaultAdminId
  1046. );
  1047. if ($eventResult !== false) {
  1048. $this->logger->addInfo(
  1049. "Event updated #".$item['item_id']." External cal Id: (".$externalEventId.") $info"
  1050. );
  1051. } else {
  1052. $this->logger->addInfo(
  1053. "Error while updating event with external id: $externalEventId"
  1054. );
  1055. }
  1056. } else {
  1057. // New event. Create it.
  1058. $eventId = $agenda->addEvent(
  1059. $event['start'],
  1060. $event['end'],
  1061. false,
  1062. $event['title'],
  1063. $content,
  1064. array('everyone'), // $usersToSend
  1065. false, //$addAsAnnouncement = false
  1066. null, // $parentEventId
  1067. array(), //$attachmentArray = array(),
  1068. [], //$attachmentCommentList
  1069. $eventComment,
  1070. $color
  1071. );
  1072. if (!empty($eventId)) {
  1073. $extraFieldValue->save(
  1074. array(
  1075. 'value' => $externalEventId,
  1076. 'field_id' => $extraFieldInfo['id'],
  1077. 'item_id' => $eventId
  1078. )
  1079. );
  1080. $this->logger->addInfo(
  1081. "Event added: #$eventId External cal id: (".$externalEventId.") $info"
  1082. );
  1083. } else {
  1084. $this->logger->addInfo(
  1085. "Error while creating event external id: $externalEventId"
  1086. );
  1087. }
  1088. }
  1089. if (($counter % $batchSize) === 0) {
  1090. $em->flush();
  1091. $em->clear(); // Detaches all objects from Doctrine!
  1092. }
  1093. $counter++;
  1094. }
  1095. $em->clear(); // Detaches all objects from Doctrine!
  1096. $this->logger->addInfo('------Summary------');
  1097. foreach ($report as $title => $count) {
  1098. $this->logger->addInfo("$title: $count");
  1099. }
  1100. $this->logger->addInfo('------End Summary------');
  1101. }
  1102. if ($moveFile) {
  1103. $this->moveFile($file);
  1104. }
  1105. }
  1106. /**
  1107. * @param string $file
  1108. * @param bool $moveFile
  1109. * @param array $teacherBackup
  1110. * @param array $groupBackup
  1111. */
  1112. private function importCourses(
  1113. $file,
  1114. $moveFile = true,
  1115. &$teacherBackup = array(),
  1116. &$groupBackup = array()
  1117. ) {
  1118. $this->fixCSVFile($file);
  1119. $data = Import::csvToArray($file);
  1120. if (!empty($data)) {
  1121. $this->logger->addInfo(count($data)." records found.");
  1122. foreach ($data as $row) {
  1123. $row = $this->cleanCourseRow($row);
  1124. $courseId = CourseManager::get_course_id_from_original_id(
  1125. $row['extra_'.$this->extraFieldIdNameList['course']],
  1126. $this->extraFieldIdNameList['course']
  1127. );
  1128. $courseInfo = api_get_course_info_by_id($courseId);
  1129. if (empty($courseInfo)) {
  1130. // Create
  1131. $params = array();
  1132. $params['title'] = $row['title'];
  1133. $params['exemplary_content'] = false;
  1134. $params['wanted_code'] = $row['course_code'];
  1135. $params['course_category'] = $row['course_category'];
  1136. $params['course_language'] = $row['language'];
  1137. $params['teachers'] = $row['teachers'];
  1138. $courseInfo = CourseManager::create_course(
  1139. $params,
  1140. $this->defaultAdminId
  1141. );
  1142. if (!empty($courseInfo)) {
  1143. CourseManager::update_course_extra_field_value(
  1144. $courseInfo['code'],
  1145. 'external_course_id',
  1146. $row['extra_'.$this->extraFieldIdNameList['course']]
  1147. );
  1148. $this->logger->addInfo("Courses - Course created ".$courseInfo['code']);
  1149. } else {
  1150. $this->logger->addError("Courses - Can't create course:".$row['title']);
  1151. }
  1152. } else {
  1153. // Update
  1154. $params = array(
  1155. 'title' => $row['title'],
  1156. 'category_code' => $row['course_category']
  1157. );
  1158. $result = CourseManager::update_attributes(
  1159. $courseInfo['real_id'],
  1160. $params
  1161. );
  1162. $addTeacherToSession = isset($courseInfo['add_teachers_to_sessions_courses']) && !empty($courseInfo['add_teachers_to_sessions_courses']) ? true : false;
  1163. $teachers = $row['teachers'];
  1164. if (!is_array($teachers)) {
  1165. $teachers = array($teachers);
  1166. }
  1167. if ($addTeacherToSession) {
  1168. $this->logger->addInfo("Add teacher to all course sessions");
  1169. CourseManager::updateTeachers(
  1170. $courseInfo,
  1171. $row['teachers'],
  1172. false,
  1173. true,
  1174. false,
  1175. $teacherBackup,
  1176. $this->logger
  1177. );
  1178. } else {
  1179. CourseManager::updateTeachers(
  1180. $courseInfo,
  1181. $row['teachers'],
  1182. true,
  1183. false,
  1184. false,
  1185. $teacherBackup,
  1186. $this->logger
  1187. );
  1188. }
  1189. foreach ($teachers as $teacherId) {
  1190. if (isset($groupBackup['tutor'][$teacherId]) &&
  1191. isset($groupBackup['tutor'][$teacherId][$courseInfo['code']])
  1192. ) {
  1193. foreach ($groupBackup['tutor'][$teacherId][$courseInfo['code']] as $data) {
  1194. $groupInfo = GroupManager::get_group_properties($data['group_id']);
  1195. GroupManager::subscribe_tutors(
  1196. array($teacherId),
  1197. $groupInfo,
  1198. $data['c_id']
  1199. );
  1200. }
  1201. }
  1202. if (isset($groupBackup['user'][$teacherId]) &&
  1203. isset($groupBackup['user'][$teacherId][$courseInfo['code']]) &&
  1204. !empty($groupBackup['user'][$teacherId][$courseInfo['code']])
  1205. ) {
  1206. foreach ($groupBackup['user'][$teacherId][$courseInfo['code']] as $data) {
  1207. $groupInfo = GroupManager::get_group_properties($data['group_id']);
  1208. GroupManager::subscribe_users(
  1209. array($teacherId),
  1210. $groupInfo,
  1211. $data['c_id']
  1212. );
  1213. }
  1214. }
  1215. }
  1216. if ($result) {
  1217. $this->logger->addInfo("Courses - Course updated ".$courseInfo['code']);
  1218. } else {
  1219. $this->logger->addError("Courses - Course NOT updated ".$courseInfo['code']);
  1220. }
  1221. }
  1222. }
  1223. }
  1224. if ($moveFile) {
  1225. $this->moveFile($file);
  1226. }
  1227. }
  1228. /**
  1229. * Parse filename: encora_subsessionsextid-static_31082016.csv
  1230. * @param string $file
  1231. */
  1232. private function importSubscribeUserToCourseSessionExtStatic($file, $moveFile = true)
  1233. {
  1234. $data = Import::csv_reader($file);
  1235. if (!empty($data)) {
  1236. $this->logger->addInfo(count($data)." records found.");
  1237. $userIdList = [];
  1238. foreach ($data as $row) {
  1239. $chamiloUserName = $row['UserName'];
  1240. $chamiloCourseCode = $row['CourseCode'];
  1241. $externalSessionId = $row['ExtSessionID'];
  1242. $status = $row['Status'];
  1243. $chamiloSessionId = null;
  1244. if (!empty($externalSessionId)) {
  1245. $chamiloSessionId = SessionManager::getSessionIdFromOriginalId(
  1246. $externalSessionId,
  1247. $this->extraFieldIdNameList['session']
  1248. );
  1249. }
  1250. $sessionInfo = api_get_session_info($chamiloSessionId);
  1251. if (empty($sessionInfo)) {
  1252. $this->logger->addError('Session does not exists: '.$chamiloSessionId);
  1253. continue;
  1254. }
  1255. $courseInfo = api_get_course_info($chamiloCourseCode);
  1256. if (empty($courseInfo)) {
  1257. $this->logger->addError('Course does not exists: '.$courseInfo);
  1258. continue;
  1259. }
  1260. $userId = UserManager::get_user_id_from_username($chamiloUserName);
  1261. if (empty($userId)) {
  1262. $this->logger->addError('User does not exists: '.$chamiloUserName);
  1263. continue;
  1264. }
  1265. switch ($status) {
  1266. case 'student':
  1267. SessionManager::subscribe_users_to_session_course(
  1268. array($userId),
  1269. $chamiloSessionId,
  1270. $courseInfo['code']
  1271. );
  1272. break;
  1273. case 'teacher':
  1274. SessionManager::set_coach_to_course_session(
  1275. $userId,
  1276. $chamiloSessionId,
  1277. $courseInfo['code']
  1278. );
  1279. break;
  1280. case 'drh':
  1281. $removeAllSessionsFromUser = true;
  1282. if (in_array($userId, $userIdList)) {
  1283. $removeAllSessionsFromUser = false;
  1284. } else {
  1285. $userIdList[] = $userId;
  1286. }
  1287. $userInfo = api_get_user_info($userId);
  1288. SessionManager::subscribeSessionsToDrh(
  1289. $userInfo,
  1290. [$chamiloSessionId],
  1291. false,
  1292. $removeAllSessionsFromUser
  1293. );
  1294. break;
  1295. }
  1296. $this->logger->addError(
  1297. "User '$chamiloUserName' was added as '$status' to Session: #$chamiloSessionId - Course: ".$courseInfo['code']
  1298. );
  1299. }
  1300. }
  1301. if ($moveFile) {
  1302. $this->moveFile($file);
  1303. }
  1304. }
  1305. /**
  1306. * @param $file
  1307. * @param bool $moveFile
  1308. */
  1309. private function importUnsubSessionsExtIdStatic($file, $moveFile = true)
  1310. {
  1311. $data = Import::csv_reader($file);
  1312. if (!empty($data)) {
  1313. $this->logger->addInfo(count($data)." records found.");
  1314. foreach ($data as $row) {
  1315. $chamiloUserName = $row['UserName'];
  1316. $chamiloCourseCode = $row['CourseCode'];
  1317. $externalSessionId = $row['ExtSessionID'];
  1318. $dateStop = $row['DateStop'];
  1319. $chamiloSessionId = null;
  1320. if (!empty($externalSessionId)) {
  1321. $chamiloSessionId = SessionManager::getSessionIdFromOriginalId(
  1322. $externalSessionId,
  1323. $this->extraFieldIdNameList['session']
  1324. );
  1325. }
  1326. $sessionInfo = api_get_session_info($chamiloSessionId);
  1327. if (empty($sessionInfo)) {
  1328. $this->logger->addError('Session does not exists: '.$chamiloSessionId);
  1329. continue;
  1330. }
  1331. $courseInfo = api_get_course_info($chamiloCourseCode);
  1332. if (empty($courseInfo)) {
  1333. $this->logger->addError('Course does not exists: '.$courseInfo);
  1334. continue;
  1335. }
  1336. $userId = UserManager::get_user_id_from_username($chamiloUserName);
  1337. if (empty($userId)) {
  1338. $this->logger->addError('User does not exists: '.$chamiloUserName);
  1339. continue;
  1340. }
  1341. SessionManager::removeUsersFromCourseSession(
  1342. array($userId),
  1343. $chamiloSessionId,
  1344. $courseInfo
  1345. );
  1346. $this->logger->addError(
  1347. "User '$chamiloUserName' was remove from Session: #$chamiloSessionId - Course: ".$courseInfo['code']
  1348. );
  1349. }
  1350. }
  1351. if ($moveFile) {
  1352. $this->moveFile($file);
  1353. }
  1354. }
  1355. /**
  1356. *
  1357. * @param string $file
  1358. */
  1359. private function importSessionsExtIdStatic($file, $moveFile = true)
  1360. {
  1361. $data = Import::csv_reader($file);
  1362. if (!empty($data)) {
  1363. $this->logger->addInfo(count($data)." records found.");
  1364. foreach ($data as $row) {
  1365. $chamiloUserName = $row['UserName'];
  1366. $chamiloCourseCode = $row['CourseCode'];
  1367. $externalSessionId = $row['ExtSessionID'];
  1368. $type = $row['Type'];
  1369. $chamiloSessionId = null;
  1370. if (!empty($externalSessionId)) {
  1371. $chamiloSessionId = SessionManager::getSessionIdFromOriginalId(
  1372. $externalSessionId,
  1373. $this->extraFieldIdNameList['session']
  1374. );
  1375. }
  1376. $sessionInfo = api_get_session_info($chamiloSessionId);
  1377. if (empty($sessionInfo)) {
  1378. $this->logger->addError('Session does not exists: '.$chamiloSessionId);
  1379. continue;
  1380. }
  1381. $courseInfo = api_get_course_info($chamiloCourseCode);
  1382. if (empty($courseInfo)) {
  1383. $this->logger->addError('Course does not exists: '.$courseInfo);
  1384. continue;
  1385. }
  1386. $userId = UserManager::get_user_id_from_username($chamiloUserName);
  1387. if (empty($userId)) {
  1388. $this->logger->addError('User does not exists: '.$chamiloUserName);
  1389. continue;
  1390. }
  1391. switch ($type) {
  1392. case 'student':
  1393. SessionManager::subscribe_users_to_session_course(
  1394. array($userId),
  1395. $chamiloSessionId,
  1396. $courseInfo['code'],
  1397. null,
  1398. false
  1399. );
  1400. break;
  1401. case 'teacher':
  1402. SessionManager::set_coach_to_course_session(
  1403. $userId,
  1404. $chamiloSessionId,
  1405. $courseInfo['code']
  1406. );
  1407. break;
  1408. }
  1409. $this->logger->addError(
  1410. "User '$chamiloUserName' with status $type was added to session: #$chamiloSessionId - Course: ".$courseInfo['code']
  1411. );
  1412. }
  1413. }
  1414. if ($moveFile) {
  1415. $this->moveFile($file);
  1416. }
  1417. }
  1418. /**
  1419. * Updates the session synchronize with the csv file.
  1420. * @param bool $moveFile
  1421. * @param string $file
  1422. */
  1423. private function importSessionsStatic($file, $moveFile = true)
  1424. {
  1425. $content = file($file);
  1426. $sessions = array();
  1427. $tag_names = array();
  1428. foreach ($content as $key => $enreg) {
  1429. $enreg = explode(';', trim($enreg));
  1430. if ($key) {
  1431. foreach ($tag_names as $tag_key => $tag_name) {
  1432. if (isset($enreg[$tag_key])) {
  1433. $sessions[$key - 1][$tag_name] = $enreg[$tag_key];
  1434. }
  1435. }
  1436. } else {
  1437. foreach ($enreg as $tag_name) {
  1438. $tag_names[] = api_preg_replace(
  1439. '/[^a-zA-Z0-9_\-]/',
  1440. '',
  1441. $tag_name
  1442. );
  1443. }
  1444. if (!in_array('SessionName', $tag_names) ||
  1445. !in_array('DateStart', $tag_names) || !in_array('DateEnd', $tag_names)
  1446. ) {
  1447. $error_message = get_lang('NoNeededData');
  1448. break;
  1449. }
  1450. }
  1451. }
  1452. if (!empty($sessions)) {
  1453. // Looping the sessions.
  1454. foreach ($sessions as $session) {
  1455. if (!empty($session['SessionID'])) {
  1456. $sessionId = SessionManager::getSessionIdFromOriginalId(
  1457. $session['SessionID'],
  1458. $this->extraFieldIdNameList['session']
  1459. );
  1460. $coachUserName = isset($session['Coach']) ? $session['Coach'] : null;
  1461. $categoryId = isset($session['category_id']) ? $session['category_id'] : null;
  1462. // 2014-06-30
  1463. $dateStart = explode('/', $session['DateStart']);
  1464. $dateEnd = explode('/', $session['DateEnd']);
  1465. $visibility = $this->defaultSessionVisibility;
  1466. $coachId = null;
  1467. if (!empty($coachUserName)) {
  1468. $coachInfo = api_get_user_info_from_username($coachUserName);
  1469. $coachId = $coachInfo['user_id'];
  1470. }
  1471. $dateStart = $dateStart[0].'-'.$dateStart[1].'-'.$dateStart[2].' 00:00:00';
  1472. $dateEnd = $dateEnd[0].'-'.$dateEnd[1].'-'.$dateEnd[2].' 23:59:59';
  1473. $date = new \DateTime($dateStart);
  1474. $interval = new DateInterval('P'.$this->daysCoachAccessBeforeBeginning.'D');
  1475. $date->sub($interval);
  1476. $coachBefore = $date->format('Y-m-d h:i');
  1477. $date = new \DateTime($dateEnd);
  1478. $interval = new DateInterval('P'.$this->daysCoachAccessAfterBeginning.'D');
  1479. $date->add($interval);
  1480. $coachAfter = $date->format('Y-m-d h:i');
  1481. /*$dateStart = api_get_utc_datetime($dateStart);
  1482. $dateEnd = api_get_utc_datetime($dateEnd);
  1483. $coachBefore = api_get_utc_datetime($coachBefore);
  1484. $coachAfter = api_get_utc_datetime($coachAfter);*/
  1485. if (empty($sessionId)) {
  1486. $result = SessionManager::create_session(
  1487. $session['SessionName'],
  1488. $dateStart,
  1489. $dateEnd,
  1490. $dateStart,
  1491. $dateEnd,
  1492. $coachBefore,
  1493. $coachAfter,
  1494. $coachId,
  1495. $categoryId,
  1496. $visibility
  1497. );
  1498. if (is_numeric($result)) {
  1499. $sessionId = $result;
  1500. $this->logger->addInfo("Session #$sessionId created: ".$session['SessionName']);
  1501. SessionManager::update_session_extra_field_value(
  1502. $sessionId,
  1503. $this->extraFieldIdNameList['session'],
  1504. $session['SessionID']
  1505. );
  1506. } else {
  1507. $this->logger->addInfo("Failed creating session: ".$session['SessionName']);
  1508. }
  1509. } else {
  1510. $sessionInfo = api_get_session_info($sessionId);
  1511. $accessBefore = null;
  1512. $accessAfter = null;
  1513. if (empty($sessionInfo['nb_days_access_before_beginning']) ||
  1514. (!empty($sessionInfo['nb_days_access_before_beginning']) &&
  1515. $sessionInfo['nb_days_access_before_beginning'] < $this->daysCoachAccessBeforeBeginning)
  1516. ) {
  1517. $accessBefore = $coachBefore;
  1518. }
  1519. $accessAfter = null;
  1520. if (empty($sessionInfo['nb_days_access_after_end']) ||
  1521. (!empty($sessionInfo['nb_days_access_after_end']) &&
  1522. $sessionInfo['nb_days_access_after_end'] < $this->daysCoachAccessAfterBeginning)
  1523. ) {
  1524. $accessAfter = $coachAfter;
  1525. }
  1526. $showDescription = isset($sessionInfo['show_description']) ? $sessionInfo['show_description'] : 1;
  1527. $result = SessionManager::edit_session(
  1528. $sessionId,
  1529. $session['SessionName'],
  1530. $dateStart,
  1531. $dateEnd,
  1532. $dateStart,
  1533. $dateEnd,
  1534. $accessBefore,
  1535. $accessAfter,
  1536. $coachId,
  1537. $categoryId,
  1538. $visibility,
  1539. null, //$description = null,
  1540. $showDescription
  1541. );
  1542. if (is_numeric($result)) {
  1543. $this->logger->addInfo("Session #$sessionId updated: ".$session['SessionName']);
  1544. $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
  1545. $params = array(
  1546. 'description' => $session['SessionDescription']
  1547. );
  1548. Database::update(
  1549. $tbl_session,
  1550. $params,
  1551. array('id = ?' => $sessionId)
  1552. );
  1553. }
  1554. }
  1555. if (!empty($sessionId)) {
  1556. // Courses
  1557. $courses = explode('|', $session['Courses']);
  1558. $courseList = [];
  1559. $courseListWithCoach = [];
  1560. foreach ($courses as $course) {
  1561. $courseArray = bracketsToArray($course);
  1562. $courseCode = $courseArray[0];
  1563. if (CourseManager::course_exists($courseCode)) {
  1564. $courseInfo = api_get_course_info($courseCode);
  1565. $courseList[] = $courseInfo['real_id'];
  1566. // Extracting course coaches
  1567. $courseCoaches = isset($courseArray[1]) ? $courseArray[1] : null;
  1568. $courseCoaches = explode(',', $courseCoaches);
  1569. // Extracting students
  1570. $courseUsers = isset($courseArray[2]) ? $courseArray[2] : null;
  1571. $courseUsers = explode(',', $courseUsers);
  1572. $courseListWithCoach[] = [
  1573. 'course_info' => $courseInfo,
  1574. 'coaches' => $courseCoaches,
  1575. 'course_users' => $courseUsers
  1576. ];
  1577. }
  1578. }
  1579. SessionManager::add_courses_to_session(
  1580. $sessionId,
  1581. $courseList,
  1582. true
  1583. );
  1584. $this->logger->addInfo("Session #$sessionId: Courses added: '".implode(', ', $courseList)."'");
  1585. if (empty($courseListWithCoach)) {
  1586. $this->logger->addInfo("No users/coaches to update");
  1587. continue;
  1588. }
  1589. foreach ($courseListWithCoach as $courseData) {
  1590. $courseInfo = $courseData['course_info'];
  1591. $courseCode = $courseInfo['code'];
  1592. $courseId = $courseInfo['real_id'];
  1593. $courseCoaches = $courseData['coaches'];
  1594. $courseUsers = $courseData['course_users'];
  1595. // Coaches
  1596. if (!empty($courseCoaches)) {
  1597. $coachList = array();
  1598. foreach ($courseCoaches as $courseCoach) {
  1599. $courseCoachId = UserManager::get_user_id_from_username(
  1600. $courseCoach
  1601. );
  1602. if ($courseCoachId !== false) {
  1603. // Just insert new coaches
  1604. $coachList[] = $courseCoachId;
  1605. }
  1606. }
  1607. $this->logger->addInfo("Session #$sessionId: course '$courseCode' coaches added: '".implode(', ', $coachList)."'");
  1608. SessionManager::updateCoaches(
  1609. $sessionId,
  1610. $courseId,
  1611. $coachList,
  1612. true
  1613. );
  1614. } else {
  1615. $this->logger->addInfo("No coaches added");
  1616. }
  1617. // Students
  1618. if (!empty($courseUsers)) {
  1619. $userList = array();
  1620. foreach ($courseUsers as $username) {
  1621. $userInfo = api_get_user_info_from_username(trim($username));
  1622. if (!empty($userInfo)) {
  1623. $userList[] = $userInfo['user_id'];
  1624. }
  1625. }
  1626. $this->logger->addInfo("Session #$sessionId: course '$courseCode': Students added '".implode(', ', $userList)."'");
  1627. SessionManager::subscribe_users_to_session_course(
  1628. $userList,
  1629. $sessionId,
  1630. $courseCode,
  1631. SESSION_VISIBLE_READ_ONLY,
  1632. true
  1633. );
  1634. } else {
  1635. $this->logger->addInfo("No users to register.");
  1636. }
  1637. }
  1638. } else {
  1639. $this->logger->addInfo(
  1640. 'SessionID not found in system.'
  1641. );
  1642. }
  1643. } else {
  1644. $this->logger->addInfo('SessionID does not exists');
  1645. }
  1646. }
  1647. } else {
  1648. $this->logger->addInfo($error_message);
  1649. }
  1650. if ($moveFile) {
  1651. $this->moveFile($file);
  1652. }
  1653. }
  1654. /**
  1655. * @param string $file
  1656. * @param bool $moveFile
  1657. * @param array $teacherBackup
  1658. * @param array $groupBackup
  1659. */
  1660. private function importSessions(
  1661. $file,
  1662. $moveFile = true,
  1663. &$teacherBackup = array(),
  1664. &$groupBackup = array()
  1665. ) {
  1666. $avoid = null;
  1667. if (isset($this->conditions['importSessions']) &&
  1668. isset($this->conditions['importSessions']['update'])
  1669. ) {
  1670. $avoid = $this->conditions['importSessions']['update'];
  1671. }
  1672. $result = SessionManager::importCSV(
  1673. $file,
  1674. true,
  1675. $this->defaultAdminId,
  1676. $this->logger,
  1677. array('SessionID' => 'extra_'.$this->extraFieldIdNameList['session']),
  1678. $this->extraFieldIdNameList['session'],
  1679. $this->daysCoachAccessBeforeBeginning,
  1680. $this->daysCoachAccessAfterBeginning,
  1681. $this->defaultSessionVisibility,
  1682. $avoid,
  1683. false, // deleteUsersNotInList
  1684. false, // updateCourseCoaches
  1685. true, // sessionWithCoursesModifier
  1686. true, //$addOriginalCourseTeachersAsCourseSessionCoaches
  1687. false, //$removeAllTeachersFromCourse
  1688. 1, // $showDescription,
  1689. $teacherBackup,
  1690. $groupBackup
  1691. );
  1692. if (!empty($result['error_message'])) {
  1693. $this->logger->addError($result['error_message']);
  1694. }
  1695. $this->logger->addInfo("Sessions - Sessions parsed: ".$result['session_counter']);
  1696. if ($moveFile) {
  1697. $this->moveFile($file);
  1698. }
  1699. }
  1700. /**
  1701. * @param string $file
  1702. * @param bool $moveFile
  1703. */
  1704. private function importSubscribeStatic($file, $moveFile = true)
  1705. {
  1706. $data = Import::csv_reader($file);
  1707. if (!empty($data)) {
  1708. $this->logger->addInfo(count($data)." records found.");
  1709. foreach ($data as $row) {
  1710. $chamiloUserName = $row['UserName'];
  1711. $chamiloCourseCode = $row['CourseCode'];
  1712. $chamiloSessionId = $row['SessionID'];
  1713. $type = $row['Type'];
  1714. $sessionInfo = api_get_session_info($chamiloSessionId);
  1715. if (empty($sessionInfo)) {
  1716. $this->logger->addError('Session does not exists: '.$chamiloSessionId);
  1717. continue;
  1718. }
  1719. $courseInfo = api_get_course_info($chamiloCourseCode);
  1720. if (empty($courseInfo)) {
  1721. $this->logger->addError('Course does not exists: '.$courseInfo);
  1722. continue;
  1723. }
  1724. $userId = UserManager::get_user_id_from_username($chamiloUserName);
  1725. if (empty($userId)) {
  1726. $this->logger->addError('User does not exists: '.$chamiloUserName);
  1727. continue;
  1728. }
  1729. switch ($type) {
  1730. case 'student':
  1731. SessionManager::subscribe_users_to_session_course(
  1732. array($userId),
  1733. $chamiloSessionId,
  1734. $courseInfo['code'],
  1735. null,
  1736. false
  1737. );
  1738. break;
  1739. case 'teacher':
  1740. SessionManager::set_coach_to_course_session(
  1741. $userId,
  1742. $chamiloSessionId,
  1743. $courseInfo['real_id']
  1744. );
  1745. break;
  1746. }
  1747. $this->logger->addError(
  1748. "User '$chamiloUserName' with status $type was added to session: #$chamiloSessionId - Course: ".$courseInfo['code']
  1749. );
  1750. }
  1751. }
  1752. if ($moveFile) {
  1753. $this->moveFile($file);
  1754. }
  1755. }
  1756. /**
  1757. * @param $file
  1758. * @param bool $moveFile
  1759. */
  1760. private function importSubscribeUserToCourse($file, $moveFile = false, &$teacherBackup = [])
  1761. {
  1762. $data = Import::csv_reader($file);
  1763. if (!empty($data)) {
  1764. $this->logger->addInfo(count($data)." records found.");
  1765. foreach ($data as $row) {
  1766. $chamiloUserName = $row['UserName'];
  1767. $chamiloCourseCode = $row['CourseCode'];
  1768. $status = $row['Status'];
  1769. $courseInfo = api_get_course_info($chamiloCourseCode);
  1770. if (empty($courseInfo)) {
  1771. $this->logger->addError(
  1772. 'Course does not exists: '.$chamiloCourseCode
  1773. );
  1774. continue;
  1775. }
  1776. $userId = UserManager::get_user_id_from_username(
  1777. $chamiloUserName
  1778. );
  1779. if (empty($userId)) {
  1780. $this->logger->addError(
  1781. 'User does not exists: '.$chamiloUserName
  1782. );
  1783. continue;
  1784. }
  1785. $userCourseCategory = '';
  1786. if (isset($teacherBackup[$userId]) &&
  1787. isset($teacherBackup[$userId][$courseInfo['code']])
  1788. ) {
  1789. $courseUserData = $teacherBackup[$userId][$courseInfo['code']];
  1790. $userCourseCategory = $courseUserData['user_course_cat'];
  1791. }
  1792. CourseManager::subscribe_user(
  1793. $userId,
  1794. $courseInfo['code'],
  1795. $status,
  1796. 0,
  1797. $userCourseCategory
  1798. );
  1799. $this->logger->addInfo(
  1800. "User $userId added to course ".$courseInfo['code']." with status '$status' with course category: '$userCourseCategory'"
  1801. );
  1802. }
  1803. }
  1804. if ($moveFile) {
  1805. $this->moveFile($file);
  1806. }
  1807. }
  1808. /**
  1809. * @param string $file
  1810. * @param bool $moveFile
  1811. * @param array $teacherBackup
  1812. * @param array $groupBackup
  1813. */
  1814. private function importUnsubscribeStatic(
  1815. $file,
  1816. $moveFile = false,
  1817. &$teacherBackup = array(),
  1818. &$groupBackup = array()
  1819. ) {
  1820. $data = Import::csv_reader($file);
  1821. if (!empty($data)) {
  1822. $this->logger->addInfo(count($data)." records found.");
  1823. foreach ($data as $row) {
  1824. $chamiloUserName = $row['UserName'];
  1825. $chamiloCourseCode = $row['CourseCode'];
  1826. $chamiloSessionId = $row['SessionID'];
  1827. $sessionInfo = api_get_session_info($chamiloSessionId);
  1828. if (empty($sessionInfo)) {
  1829. $this->logger->addError('Session does not exists: '.$chamiloSessionId);
  1830. continue;
  1831. }
  1832. $courseInfo = api_get_course_info($chamiloCourseCode);
  1833. if (empty($courseInfo)) {
  1834. $this->logger->addError('Course does not exists: '.$courseInfo);
  1835. continue;
  1836. }
  1837. $userId = UserManager::get_user_id_from_username($chamiloUserName);
  1838. if (empty($userId)) {
  1839. $this->logger->addError('User does not exists: '.$chamiloUserName);
  1840. continue;
  1841. }
  1842. $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
  1843. WHERE
  1844. user_id = ".$userId." AND
  1845. c_id = '".$courseInfo['real_id']."'
  1846. ";
  1847. $result = Database::query($sql);
  1848. $rows = Database::num_rows($result);
  1849. if ($rows > 0) {
  1850. $userCourseData = Database::fetch_array($result, 'ASSOC');
  1851. if (!empty($userCourseData)) {
  1852. $teacherBackup[$userId][$courseInfo['code']] = $userCourseData;
  1853. }
  1854. }
  1855. $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_USER)."
  1856. WHERE
  1857. user_id = ".$userId." AND
  1858. c_id = '".$courseInfo['real_id']."'
  1859. ";
  1860. $result = Database::query($sql);
  1861. while ($groupData = Database::fetch_array($result, 'ASSOC')) {
  1862. $groupBackup['user'][$userId][$courseInfo['code']][$groupData['group_id']] = $groupData;
  1863. }
  1864. $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
  1865. WHERE
  1866. user_id = ".$userId." AND
  1867. c_id = '".$courseInfo['real_id']."'
  1868. ";
  1869. $result = Database::query($sql);
  1870. while ($groupData = Database::fetch_array($result, 'ASSOC')) {
  1871. $groupBackup['tutor'][$userId][$courseInfo['code']][$groupData['group_id']] = $groupData;
  1872. }
  1873. CourseManager::unsubscribe_user(
  1874. $userId,
  1875. $courseInfo['code'],
  1876. $chamiloSessionId
  1877. );
  1878. $this->logger->addError(
  1879. "User '$chamiloUserName' was removed from session: #$chamiloSessionId, Course: ".$courseInfo['code']
  1880. );
  1881. }
  1882. }
  1883. if ($moveFile) {
  1884. $this->moveFile($file);
  1885. }
  1886. }
  1887. /**
  1888. * Dump database tables
  1889. */
  1890. private function dumpDatabaseTables()
  1891. {
  1892. echo 'Dumping tables'.PHP_EOL;
  1893. // User
  1894. $table = Database::get_main_table(TABLE_MAIN_USER);
  1895. $tableAdmin = Database::get_main_table(TABLE_MAIN_ADMIN);
  1896. $sql = "DELETE FROM $table
  1897. WHERE user_id not in (select user_id from $tableAdmin) and status <> ".ANONYMOUS;
  1898. Database::query($sql);
  1899. echo $sql.PHP_EOL;
  1900. // Truncate tables
  1901. $truncateTables = array(
  1902. Database::get_main_table(TABLE_MAIN_COURSE),
  1903. Database::get_main_table(TABLE_MAIN_COURSE_USER),
  1904. Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE),
  1905. Database::get_main_table(TABLE_MAIN_CATEGORY),
  1906. Database::get_main_table(TABLE_MAIN_COURSE_MODULE),
  1907. Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER),
  1908. Database::get_main_table(TABLE_MAIN_SESSION),
  1909. Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY),
  1910. Database::get_main_table(TABLE_MAIN_SESSION_COURSE),
  1911. Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER),
  1912. Database::get_main_table(TABLE_MAIN_SESSION_USER),
  1913. Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION),
  1914. Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES),
  1915. Database::get_main_table(TABLE_MAIN_COURSE_FIELD_VALUES),
  1916. Database::get_main_table(TABLE_MAIN_USER_FIELD_VALUES),
  1917. Database::get_main_table(TABLE_MAIN_USER_FIELD),
  1918. Database::get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS),
  1919. Database::get_main_table(TABLE_MAIN_COURSE_FIELD),
  1920. Database::get_main_table(TABLE_MAIN_COURSE_FIELD_VALUES),
  1921. Database::get_main_table(TABLE_MAIN_SESSION_FIELD),
  1922. Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES),
  1923. Database::get_course_table(TABLE_AGENDA),
  1924. Database::get_course_table(TABLE_AGENDA_ATTACHMENT),
  1925. Database::get_course_table(TABLE_AGENDA_REPEAT),
  1926. Database::get_course_table(TABLE_AGENDA_REPEAT_NOT),
  1927. Database::get_main_table(TABLE_PERSONAL_AGENDA),
  1928. Database::get_main_table(TABLE_PERSONAL_AGENDA_REPEAT_NOT),
  1929. Database::get_main_table(TABLE_PERSONAL_AGENDA_REPEAT),
  1930. Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_VALUES),
  1931. Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS),
  1932. Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS),
  1933. Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN),
  1934. Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS),
  1935. Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES),
  1936. Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT),
  1937. Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING),
  1938. Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT),
  1939. Database::get_main_table(TABLE_STATISTIC_TRACK_E_UPLOADS),
  1940. Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT),
  1941. Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY),
  1942. Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY),
  1943. Database::get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION),
  1944. Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINKEVAL_LOG),
  1945. Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT),
  1946. Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT_LOG),
  1947. Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK),
  1948. Database::get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY),
  1949. Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE),
  1950. Database::get_course_table(TABLE_STUDENT_PUBLICATION),
  1951. Database::get_course_table(TABLE_QUIZ_QUESTION),
  1952. Database::get_course_table(TABLE_QUIZ_TEST),
  1953. Database::get_course_table(TABLE_QUIZ_ORDER),
  1954. Database::get_course_table(TABLE_QUIZ_ANSWER),
  1955. Database::get_course_table(TABLE_QUIZ_TEST_QUESTION),
  1956. Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION),
  1957. Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY),
  1958. Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY),
  1959. Database::get_course_table(TABLE_LP_MAIN),
  1960. Database::get_course_table(TABLE_LP_ITEM),
  1961. Database::get_course_table(TABLE_LP_VIEW),
  1962. Database::get_course_table(TABLE_LP_ITEM_VIEW),
  1963. Database::get_course_table(TABLE_DOCUMENT),
  1964. Database::get_course_table(TABLE_ITEM_PROPERTY),
  1965. Database::get_course_table(TABLE_TOOL_LIST),
  1966. Database::get_course_table(TABLE_TOOL_INTRO),
  1967. Database::get_course_table(TABLE_COURSE_SETTING),
  1968. Database::get_course_table(TABLE_SURVEY),
  1969. Database::get_course_table(TABLE_SURVEY_QUESTION),
  1970. Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION),
  1971. Database::get_course_table(TABLE_SURVEY_INVITATION),
  1972. Database::get_course_table(TABLE_SURVEY_ANSWER),
  1973. Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP),
  1974. Database::get_course_table(TABLE_SURVEY_REPORT),
  1975. Database::get_course_table(TABLE_GLOSSARY),
  1976. Database::get_course_table(TABLE_LINK),
  1977. Database::get_course_table(TABLE_LINK_CATEGORY),
  1978. Database::get_course_table(TABLE_GROUP),
  1979. Database::get_course_table(TABLE_GROUP_USER),
  1980. Database::get_course_table(TABLE_GROUP_TUTOR),
  1981. Database::get_course_table(TABLE_GROUP_CATEGORY),
  1982. Database::get_course_table(TABLE_DROPBOX_CATEGORY),
  1983. Database::get_course_table(TABLE_DROPBOX_FEEDBACK),
  1984. Database::get_course_table(TABLE_DROPBOX_POST),
  1985. Database::get_course_table(TABLE_DROPBOX_FILE),
  1986. Database::get_course_table(TABLE_DROPBOX_PERSON)
  1987. );
  1988. foreach ($truncateTables as $table) {
  1989. $sql = "TRUNCATE $table";
  1990. Database::query($sql);
  1991. echo $sql.PHP_EOL;
  1992. }
  1993. $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
  1994. $sql = "DELETE FROM $table WHERE tool = 'calendar_event'";
  1995. Database::query($sql);
  1996. echo $sql.PHP_EOL;
  1997. }
  1998. /**
  1999. * If csv file ends with '"' character then a '";' is added
  2000. * @param string $file
  2001. */
  2002. private function fixCSVFile($file)
  2003. {
  2004. /*$f = fopen($file, 'r+');
  2005. $cursor = -1;
  2006. fseek($f, $cursor, SEEK_END);
  2007. $char = fgetc($f);
  2008. while ($char === "\n" || $char === "\r") {
  2009. fseek($f, $cursor--, SEEK_END);
  2010. $char = fgetc($f);
  2011. }
  2012. if ($char === "\"") {
  2013. fseek($f, -1, SEEK_CUR);
  2014. fwrite($f, '";');
  2015. }*/
  2016. }
  2017. /**
  2018. * @return mixed
  2019. */
  2020. public function getUpdateEmailToDummy()
  2021. {
  2022. return $this->updateEmailToDummy;
  2023. }
  2024. /**
  2025. * @param mixed $updateEmailToDummy
  2026. */
  2027. public function setUpdateEmailToDummy($updateEmailToDummy)
  2028. {
  2029. $this->updateEmailToDummy = $updateEmailToDummy;
  2030. }
  2031. /**
  2032. * Change emails of all users except admins
  2033. *
  2034. */
  2035. public function updateUsersEmails()
  2036. {
  2037. if ($this->getUpdateEmailToDummy() === true) {
  2038. $sql = "UPDATE user SET email = CONCAT(username,'@example.com') WHERE id NOT IN (SELECT user_id FROM admin)";
  2039. Database::query($sql);
  2040. }
  2041. }
  2042. }
  2043. use Monolog\Logger;
  2044. use Monolog\Handler\StreamHandler;
  2045. use Monolog\Handler\NativeMailerHandler;
  2046. use Monolog\Handler\RotatingFileHandler;
  2047. use Monolog\Handler\BufferHandler;
  2048. $logger = new Logger('cron');
  2049. $emails = isset($_configuration['cron_notification_mails']) ? $_configuration['cron_notification_mails'] : null;
  2050. $minLevel = Logger::DEBUG;
  2051. if (!is_array($emails)) {
  2052. $emails = array($emails);
  2053. }
  2054. $subject = "Cron main/cron/import_csv.php ".date('Y-m-d h:i:s');
  2055. $from = api_get_setting('emailAdministrator');
  2056. /*
  2057. if (!empty($emails)) {
  2058. foreach ($emails as $email) {
  2059. $stream = new NativeMailerHandler($email, $subject, $from, $minLevel);
  2060. $logger->pushHandler(new BufferHandler($stream, 0, $minLevel));
  2061. }
  2062. }*/
  2063. $stream = new StreamHandler(
  2064. api_get_path(SYS_ARCHIVE_PATH).'import_csv.log',
  2065. $minLevel
  2066. );
  2067. $logger->pushHandler(new BufferHandler($stream, 0, $minLevel));
  2068. $logger->pushHandler(new RotatingFileHandler('import_csv', 5, $minLevel));
  2069. $cronImportCSVConditions = isset($_configuration['cron_import_csv_conditions']) ? $_configuration['cron_import_csv_conditions'] : null;
  2070. echo 'See the error log here: '.api_get_path(SYS_ARCHIVE_PATH).'import_csv.log'."\n";
  2071. $import = new ImportCsv($logger, $cronImportCSVConditions);
  2072. if (isset($_configuration['default_admin_user_id_for_cron'])) {
  2073. $import->defaultAdminId = $_configuration['default_admin_user_id_for_cron'];
  2074. }
  2075. // @todo in production disable the dump option
  2076. $dump = false;
  2077. if (isset($argv[1]) && $argv[1] = '--dump') {
  2078. $dump = true;
  2079. }
  2080. if (isset($_configuration['import_csv_disable_dump']) &&
  2081. $_configuration['import_csv_disable_dump'] == true
  2082. ) {
  2083. $import->setDumpValues(false);
  2084. } else {
  2085. $import->setDumpValues($dump);
  2086. }
  2087. $import->setUpdateEmailToDummy(api_get_configuration_value('update_users_email_to_dummy_except_admins'));
  2088. // Do not moves the files to treated
  2089. if (isset($_configuration['import_csv_test'])) {
  2090. $import->test = $_configuration['import_csv_test'];
  2091. } else {
  2092. $import->test = true;
  2093. }
  2094. $timeStart = microtime(true);
  2095. $import->run();
  2096. $timeEnd = microtime(true);
  2097. $executionTime = round(($timeEnd - $timeStart) / 60, 2);
  2098. $logger->addInfo("Total execution Time $executionTime Min");
  2099. if (isset($_configuration['import_csv_fix_permissions']) &&
  2100. $_configuration['import_csv_fix_permissions'] == true
  2101. ) {
  2102. $command = "sudo find ".api_get_path(SYS_COURSE_PATH)." -type d -exec chmod 777 {} \; ";
  2103. echo "Executing: ".$command.PHP_EOL;
  2104. system($command);
  2105. $command = "sudo find ".api_get_path(SYS_CODE_PATH)."upload/users -type d -exec chmod 777 {} \;";
  2106. echo "Executing: ".$command.PHP_EOL;
  2107. system($command);
  2108. }