import_csv.php 115 KB

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