PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.1
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.1
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
← All changes | back/Helpers/ImportHelper.php +0 -1304 11.0.4 → 11.1.1 View file →
@@ -1,1304 +1,0 @@
1 -<?php
2 -
3 -namespace AcyMailing\Helpers;
4 -
5 -use AcyMailing\Classes\ListClass;
6 -use AcyMailing\Classes\UserClass;
7 -use AcyMailing\Core\AcymObject;
8 -
9 -class ImportHelper extends AcymObject
10 -{
11 - //Handle messages to say that X users have been subscribed to list Y
12 - private array $subscribedUsers = [];
13 - private array $importUserInLists = [];
14 - private array $allUserIds = [];
15 - private array $columns = [];
16 - private int $totalTry = 0;
17 - private int $totalValid = 0;
18 - private int $separatorsToRemove = 0;
19 - private bool $forceConfirm = false;
20 - private bool $generateName = true;
21 - private bool $overwrite = false;
22 - private string $header = '';
23 - private string $separator = ',';
24 -
25 - //Variables used to handle the import on filter
26 - public string $tableName = '';
27 - public array $dbWhere = [];
28 - public array $fieldsMap = [];
29 - public array $subscriptionHistory = [];
30 - public array $importedUsersByEmail = [];
31 -
32 - public function __construct()
33 - {
34 - parent::__construct();
35 - //We do an import... so it might take a lot of times and it also might take some memory... so we increase those limits if we can!
36 - acym_increasePerf();
37 - }
38 -
39 - public function file(): bool
40 - {
41 - //Step 1 : we copy the file in the correct directory
42 - $importFile = acym_getVar('array', 'import_file', [], 'files');
43 -
44 - if (empty($importFile['name'])) {
45 - acym_enqueueMessage(acym_translation('ACYM_PLEASE_BROWSE_FILE_IMPORT'), 'error');
46 -
47 - return false;
48 - }
49 -
50 - $extension = strtolower(acym_fileGetExt($importFile['name']));
51 -
52 - if (!preg_match('#^(csv)$#Ui', $extension) || preg_match('#\.(php.?|.?htm.?|pl|py|jsp|asp|sh|cgi)$#Ui', $importFile['name'])) {
53 - acym_enqueueMessage(acym_translationSprintf('ACYM_ACCEPTED_TYPE', esc_html($extension), $this->config->get('allowed_files')), 'error');
54 -
55 - return false;
56 - }
57 -
58 - // Checking error upload
59 - $fileError = $importFile['error'];
60 - if ($fileError > 0) {
61 - switch ($fileError) {
62 - case 1:
63 - case 2:
64 - acym_enqueueMessage(acym_translation('ACYM_UPLOADED_FILE_EXCEED_MAX_FILESIZE_PHP'), 'error');
65 -
66 - return false;
67 - case 3:
68 - acym_enqueueMessage(acym_translation('ACYM_FILE_UPLOADED_PARTIALLY'), 'error');
69 -
70 - return false;
71 - case 4:
72 - acym_enqueueMessage(acym_translation('ACYM_NO_FILE_WAS_UPLOADED'), 'error');
73 -
74 - return false;
75 - default:
76 - acym_enqueueMessage(acym_translationSprintf('ACYM_UNKNOWN_ERROR_UPLOADING_FILE', $fileError), 'error');
77 -
78 - return false;
79 - }
80 - }
81 -
82 - $uploadPath = $this->createUploadFolder();
83 -
84 - $filename = uniqid('import_').'.csv';
85 - acym_setVar('acym_import_filename', $filename);
86 -
87 - if (!acym_uploadFile($importFile['tmp_name'], $uploadPath.$filename)) {
88 - acym_enqueueMessage(
89 - acym_translationSprintf(
90 - 'ACYM_FAIL_UPLOAD',
91 - '<b><i>'.esc_html($importFile['tmp_name']).'</i></b>',
92 - '<b><i>'.esc_html($uploadPath.$filename).'</i></b>'
93 - ),
94 - 'error'
95 - );
96 - }
97 -
98 - return true;
99 - }
100 -
101 - public function textarea(): bool
102 - {
103 - $content = acym_getVar('string', 'acym__users__import__from_text__textarea');
104 - $path = $this->createUploadFolder();
105 - $filename = uniqid('import_').'.csv';
106 -
107 - acym_writeFile($path.$filename, $content);
108 - acym_setVar('acym_import_filename', $filename);
109 -
110 - return true;
111 - }
112 -
113 - public function cms(): bool
114 - {
115 - global $acymCmsUserVars;
116 -
117 - //Update the users which already have a userid
118 - $query = 'UPDATE IGNORE '.$acymCmsUserVars->table.' as b, #__acym_user as a SET a.email = b.'.$acymCmsUserVars->email.', a.name = b.'.$acymCmsUserVars->name.', a.active = 1 - b.'.$acymCmsUserVars->blocked.' WHERE a.cms_id = b.'.$acymCmsUserVars->id.' AND a.cms_id IS NOT NULL';
119 - $nbUpdated = acym_query($query);
120 -
121 - //Step 1 : update the existing ones.
122 - //Update the users to give them a userid
123 - $query = 'UPDATE IGNORE '.$acymCmsUserVars->table.' as b, #__acym_user as a SET a.cms_id = b.'.$acymCmsUserVars->id.' WHERE a.email = b.'.$acymCmsUserVars->email;
124 - $affected = acym_query($query);
125 - $nbUpdated += intval($affected);
126 -
127 - acym_enqueueMessage(acym_translationSprintf('ACYM_IMPORT_UPDATE', $nbUpdated), 'success');
128 -
129 - //Step 2 : delete the ones which don't exist any more
130 - $query = 'SELECT a.id FROM #__acym_user as a LEFT JOIN '.$acymCmsUserVars->table.' as b on a.cms_id = b.'.$acymCmsUserVars->id.' WHERE b.'.$acymCmsUserVars->id.' IS NULL AND a.cms_id > 0';
131 - $deletedSubid = acym_loadResultArray($query);
132 -
133 - $query = 'SELECT a.id FROM #__acym_user as a LEFT JOIN '.$acymCmsUserVars->table.' as b on a.email = b.'.$acymCmsUserVars->email.' WHERE b.'.$acymCmsUserVars->id.' IS NULL AND a.cms_id > 0';
134 - $deletedSubid = array_merge(acym_loadResultArray($query), $deletedSubid);
135 -
136 - if (!empty($deletedSubid)) {
137 - $userClass = new UserClass();
138 - $deletedUsers = $userClass->delete($deletedSubid);
139 - acym_enqueueMessage(acym_translationSprintf('ACYM_IMPORT_DELETE', $deletedUsers));
140 - }
141 -
142 - //Step 3 : insert the new ones
143 - $time = time();
144 - $formattedTime = acym_date($time, 'Y-m-d H:i:s');
145 - $sourceImport = 'Import on '.$formattedTime;
146 - $query = 'INSERT IGNORE INTO #__acym_user (`name`,`email`,`creation_date`,`active`,`cms_id`, `source`) SELECT `user`.`'.$acymCmsUserVars->name.'`,`user`.`'.$acymCmsUserVars->email.'`,`user`.`'.$acymCmsUserVars->registered.'`,1 - `user`.'.$acymCmsUserVars->blocked.',`user`.`'.$acymCmsUserVars->id.'`,\''.$sourceImport.'\' FROM '.$acymCmsUserVars->table.' AS `user` ';
147 -
148 - $queryJoin = [];
149 - $queryWhere = [];
150 - if (ACYM_CMS === 'wordpress' && is_multisite()) {
151 - $queryJoin[] = 'JOIN #__usermeta AS `meta` ON `user`.'.$acymCmsUserVars->id.'=`meta`.`user_id`';
152 - $queryWhere[] = '`meta`.`meta_key`=\'#__capabilities\'';
153 - }
154 - $groups = acym_getVar('array', 'groups', []);
155 - $this->config->saveConfig(['import_groups' => implode(',', $groups)]);
156 - if (!empty($groups)) {
157 - if (ACYM_CMS === 'joomla') {
158 - acym_arrayToInteger($groups);
159 - $queryJoin[] = ' JOIN #__user_usergroup_map AS `map` ON map.user_id = `user`.`'.$acymCmsUserVars->id.'`';
160 - $queryWhere[] = '`map`.`group_id` IN ('.implode(', ', $groups).')';
161 - } else {
162 - if (!is_multisite()) {
163 - $queryJoin[] = 'JOIN #__usermeta AS `meta` ON meta.user_id = `user`.`'.$acymCmsUserVars->id.'` AND `meta`.`meta_key` = "#__capabilities"';
164 - }
165 -
166 - foreach ($groups as $i => $oneGroup) {
167 - $groups[$i] = acym_escapeDB('%'.strlen($oneGroup).':"'.$oneGroup.'"%');
168 - }
169 - $queryWhere[] = '`meta`.`meta_value` LIKE '.implode(' OR `meta`.`meta_value` LIKE ', $groups);
170 - }
171 - }
172 -
173 - $query .= implode(' ', $queryJoin);
174 - if (!empty($queryWhere)) {
175 - $query .= ' WHERE ('.implode(') AND (', $queryWhere).')';
176 - }
177 -
178 - $insertedUsers = acym_query($query);
179 -
180 - acym_query('UPDATE #__acym_configuration SET `value` = '.intval($time).' WHERE `name` = \'last_import\'');
181 -
182 - acym_trigger('onAcymAfterCMSUserImport', [$sourceImport]);
183 -
184 - acym_enqueueMessage(acym_translationSprintf('ACYM_IMPORT_NEW_SUBS', $insertedUsers), 'info');
185 -
186 - //Step 4 : subscribe all the registered users to one or several lists
187 - $lists = $this->getImportedLists();
188 - $listsSubscribe = [];
189 - if (!empty($lists)) {
190 - foreach ($lists as $listid => $val) {
191 - if (!empty($val)) {
192 - $listsSubscribe[] = intval($listid);
193 - }
194 - }
195 - }
196 -
197 - if (empty($listsSubscribe)) {
198 - return true;
199 - }
200 -
201 - $query = 'INSERT IGNORE INTO #__acym_user_has_list (`user_id`,`list_id`,`status`,`subscription_date`) ';
202 - $query .= 'SELECT user.`id`, list.`id`, 1, '.acym_escapeDB(gmdate('Y-m-d H:i:s', time())).'
203 - FROM #__acym_list AS list, #__acym_user AS user ';
204 - $conditions = [];
205 - $conditions[] = 'list.`id` IN ('.implode(',', $listsSubscribe).')';
206 - $conditions[] = 'user.`cms_id` > 0';
207 -
208 - if (!empty($groups)) {
209 - if (ACYM_CMS === 'joomla') {
210 - $query .= ' JOIN #__user_usergroup_map AS `map` ON map.user_id = `user`.`cms_id`';
211 - $conditions[] = '`map`.`group_id` IN ('.implode(', ', $groups).')';
212 - } else {
213 - $query .= ' JOIN #__usermeta AS `meta` ON meta.user_id = `user`.`cms_id` AND `meta`.`meta_key` = "#__capabilities"';
214 - $conditions[] = '(`meta`.`meta_value` LIKE '.implode(' OR `meta`.`meta_value` LIKE ', $groups).')';
215 - }
216 - }
217 -
218 - $query .= ' WHERE '.implode(' AND ', $conditions);
219 - $nbsubscribed = acym_query($query);
220 - acym_enqueueMessage(acym_translationSprintf('ACYM_IMPORT_SUBSCRIPTION', $nbsubscribed));
221 -
222 - return true;
223 - }
224 -
225 -
226 - public function database(bool $onlyImport = false): bool
227 - {
228 - $this->forceConfirm = acym_getVar('bool', 'import_confirmed_database', true);
229 -
230 - $table = empty($this->tableName) ? trim(acym_getVar('string', 'tablename')) : $this->tableName;
231 - $time = time();
232 - $formattedTime = acym_date($time, 'Y-m-d H:i:s');
233 -
234 - if (empty($table)) {
235 - acym_enqueueMessage(acym_translation('ACYM_SPECIFYTABLE'), 'warning');
236 -
237 - return false;
238 - }
239 -
240 - //We got a table... let's load the fields from this table
241 - $fields = acym_getColumns($table, false, false);
242 - if (empty($fields)) {
243 - //there is no field... so we consider it was the wrong table
244 - acym_enqueueMessage(acym_translation('ACYM_SPECIFYTABLE'), 'warning');
245 -
246 - return false;
247 - }
248 -
249 - //Ok now we have some fields and now we have a table selected.
250 - $equivalentFields = empty($this->fieldsMap) ? acym_getVar('array', 'fields', []) : $this->fieldsMap;
251 -
252 - if (empty($equivalentFields['email'])) {
253 - acym_enqueueMessage(acym_translation('ACYM_SPECIFYFIELDEMAIL'), 'warning');
254 -
255 - return false;
256 - }
257 -
258 - $select = [];
259 - //We check the data and create the query
260 - foreach ($equivalentFields as $acyField => $tableField) {
261 - $tableField = trim($tableField);
262 - if (empty($tableField)) {
263 - continue;
264 - }
265 - if (!in_array($tableField, $fields)) {
266 - acym_enqueueMessage(acym_translationSprintf('ACYM_SPECIFYFIELD', $tableField, implode(' <br> ', $fields)), 'warning');
267 -
268 - return false;
269 - }
270 - $select['`'.acym_secureDBColumn($acyField).'`'] = acym_secureDBColumn($tableField);
271 - }
272 -
273 - if (empty($select['`creation_date`'])) {
274 - $select['`creation_date`'] = acym_escapeDB(acym_date('now', 'Y-m-d H:i:s'));
275 - }
276 -
277 - if ($this->forceConfirm && empty($select['`confirmed`'])) {
278 - $select['`confirmed`'] = 1;
279 - }
280 -
281 - $sourceTxt = 'Import on '.$formattedTime;
282 - $select['`source`'] = acym_escapeDB($sourceTxt);
283 -
284 - $query = 'INSERT IGNORE INTO #__acym_user ('.implode(' , ', array_keys($select)).') SELECT '.implode(' , ', $select);
285 - $query .= ' FROM '.acym_secureDBColumn($table).' WHERE '.acym_secureDBColumn($select['`email`']).' LIKE "%@%"';
286 - if (!empty($this->dbWhere)) {
287 - $query .= ' AND ( '.implode(' ) AND (', $this->dbWhere).' )';
288 - }
289 -
290 - $affectedRows = acym_query($query);
291 -
292 - acym_query('UPDATE #__acym_configuration SET `value` = '.intval($time).' WHERE `name` = "last_import"');
293 -
294 - acym_trigger('onAcymAfterDatabaseUserImport', [$sourceTxt]);
295 -
296 - if ($onlyImport) {
297 - return true;
298 - }
299 -
300 - acym_enqueueMessage(acym_translationSprintf('ACYM_IMPORT_NEW_SUBS', $affectedRows), 'info');
301 -
302 -
303 - //Step 4 : subscribe all the registered users to one or several lists
304 - $lists = $this->getImportedLists();
305 - $listsSubscribe = [];
306 - if (!empty($lists)) {
307 - foreach ($lists as $listid => $val) {
308 - if (!empty($val)) {
309 - $listsSubscribe[] = intval($listid);
310 - }
311 - }
312 - }
313 -
314 - if (empty($listsSubscribe)) {
315 - return true;
316 - }
317 -
318 - $query = 'INSERT IGNORE INTO #__acym_user_has_list (`user_id`,`list_id`,`status`,`subscription_date`) ';
319 - $query .= 'SELECT user.`id`, list.`id`, 1, '.acym_escapeDB(gmdate('Y-m-d H:i:s', time())).'
320 - FROM #__acym_list AS list, #__acym_user AS user
321 - WHERE list.`id` IN ('.implode(',', $listsSubscribe).')
322 - AND user.`email` IN (SELECT '.acym_secureDBColumn($select['`email`']).' FROM '.acym_secureDBColumn($table).')';
323 -
324 - $nbsubscribed = acym_query($query);
325 - acym_enqueueMessage(acym_translationSprintf('ACYM_IMPORT_SUBSCRIPTION', $nbsubscribed));
326 -
327 - return true;
328 - }
329 -
330 - public function mailpoet(): bool
331 - {
332 - // Step 1 : import subscriber from mailpoet
333 - $time = time();
334 - $formattedTime = acym_date($time, 'Y-m-d H:i:s');
335 - $sourceImport = 'import_on_'.$formattedTime.'_mailpoet';
336 -
337 - $query = 'INSERT IGNORE INTO #__acym_user (`name`,`email`,`creation_date`,`active`, `confirmed`,`cms_id`, `source`)
338 - SELECT CONCAT(`subscriber`.`first_name`, `subscriber`.`last_name`),
339 - `subscriber`.`email`,
340 - `subscriber`.`created_at`,
341 - IF(`subscriber`.`status` = "inactive", 0, 1),
342 - IF(`subscriber`.`status` = "subscribed", 1, 0),
343 - `subscriber`.`wp_user_id`,
344 - \''.$sourceImport.'\'
345 - FROM #__mailpoet_subscribers AS `subscriber` ';
346 - $listsMailpoet = acym_getVar('array', 'mailpoet_lists', []);
347 - if (!empty($listsMailpoet)) {
348 - acym_arrayToInteger($listsMailpoet);
349 - $query .= ' JOIN #__mailpoet_subscriber_segment AS sub_segment ON `subscriber`.`id` = `sub_segment`.`subscriber_id` AND `sub_segment`.`segment_id` IN ('.implode(
350 - ',',
351 - $listsMailpoet
352 - ).')';
353 - }
354 - $query .= ' WHERE `subscriber`.`deleted_at` IS NULL ON DUPLICATE KEY UPDATE `source`='.acym_escapeDB($sourceImport);
355 -
356 - $insertedUsers = acym_query($query);
357 -
358 - acym_query('UPDATE #__acym_configuration SET `value` = '.intval($time).' WHERE `name` = \'last_import\'');
359 -
360 - acym_enqueueMessage(acym_translationSprintf('ACYM_IMPORT_NEW_SUBS', $insertedUsers), 'info');
361 -
362 - // Step 2 : subscribe all the registered users to one or several lists
363 - $lists = $this->getImportedLists();
364 - $listsSubscribe = [];
365 - if (!empty($lists)) {
366 - foreach ($lists as $listid => $val) {
367 - if (!empty($val)) {
368 - $listsSubscribe[] = intval($listid);
369 - }
370 - }
371 - }
372 -
373 - if (empty($listsSubscribe)) {
374 - return true;
375 - }
376 -
377 - $query = 'INSERT IGNORE INTO #__acym_user_has_list (`user_id`,`list_id`,`status`,`subscription_date`) ';
378 - $query .= 'SELECT user.`id`, list.`id`, 1, '.acym_escapeDB(gmdate('Y-m-d H:i:s', time())).'
379 - FROM #__acym_list AS list, #__acym_user AS user ';
380 - $conditions = [];
381 - $conditions[] = 'list.`id` IN ('.implode(',', $listsSubscribe).')';
382 - $conditions[] = 'user.`source` = '.acym_escapeDB($sourceImport);
383 -
384 - if (!empty($listsMailpoet)) {
385 - $query .= ' JOIN #__mailpoet_subscribers AS subscriber ON subscriber.email = user.email';
386 - $query .= ' JOIN #__mailpoet_subscriber_segment AS subscriber_segment ON subscriber.id = subscriber_segment.subscriber_id AND subscriber_segment.segment_id IN ('.implode(
387 - ',',
388 - $listsMailpoet
389 - ).')';
390 - }
391 -
392 - $query .= ' WHERE '.implode(' AND ', $conditions);
393 - $nbsubscribed = acym_query($query);
394 - acym_enqueueMessage(acym_translationSprintf('ACYM_IMPORT_SUBSCRIPTION', $nbsubscribed));
395 -
396 - return true;
397 - }
398 -
399 - public function finalizeImport(): bool
400 - {
401 - $filename = strtolower(acym_getVar('cmd', 'acym_import_filename'));
402 - $extension = '.'.acym_fileGetExt($filename);
403 - $this->forceConfirm = acym_getVar('bool', 'import_confirmed_generic', true);
404 - $this->generateName = acym_getVar('bool', 'import_generate_generic', true);
405 - $this->overwrite = acym_getVar('bool', 'import_overwrite_generic', true);
406 -
407 - // Remember user's choices
408 - $this->config->saveConfig(
409 - [
410 - 'import_confirmed' => $this->forceConfirm,
411 - 'import_generate' => $this->generateName,
412 - 'import_overwrite' => $this->overwrite,
413 - ]
414 - );
415 -
416 - $filename = str_replace(['.', ' '], '_', substr($filename, 0, strpos($filename, $extension))).$extension;
417 - $uploadPath = ACYM_MEDIA.'import'.DS.$filename;
418 -
419 - if (!file_exists($uploadPath) || !is_file($uploadPath)) {
420 - acym_enqueueMessage(acym_translation('ACYM_UPLOADED_FILE_NOT_FOUND').' '.$uploadPath, 'error');
421 -
422 - return false;
423 - }
424 -
425 - $importColumns = acym_getVar('string', 'import_columns');
426 - if (empty($importColumns)) {
427 - acym_enqueueMessage(acym_translation('ACYM_COLUMNS_NOT_FOUND'), 'error');
428 -
429 - return false;
430 - }
431 -
432 - $contentFile = file_get_contents($uploadPath);
433 -
434 - //We convert into the correct charset
435 - if (acym_getVar('cmd', 'acyencoding', '') != '') {
436 - $encodingHelper = new EncodingHelper();
437 - $contentFile = $encodingHelper->change($contentFile, acym_getVar('cmd', 'acyencoding'), 'UTF-8');
438 - }
439 -
440 - $cutContent = str_replace(["\r\n", "\r"], "\n", $contentFile);
441 - $allLines = explode("\n", $cutContent);
442 -
443 - $listSeparators = ["\t", ';', ','];
444 - $separator = ',';
445 - foreach ($listSeparators as $sep) {
446 - if (strpos($allLines[0], $sep) !== false) {
447 - $separator = $sep;
448 - break;
449 - }
450 - }
451 -
452 - if (!empty($listsId)) {
453 - $allLines[0] .= $sep;
454 - }
455 -
456 - $importColumns = str_replace(',', $separator, $importColumns);
457 -
458 - if (strpos($allLines[0], '@')) {
459 - $contentFile = $importColumns."\n".$contentFile;
460 - } else {
461 - $allLines[0] = $importColumns;
462 - $contentFile = implode("\n", $allLines);
463 - }
464 -
465 - $this->handleContent($contentFile);
466 -
467 - //We can now delete the file
468 - acym_deleteFile($uploadPath);
469 - $this->cleanImportFolder();
470 -
471 - return true;
472 - }
473 -
474 - public function getImportedLists(): array
475 - {
476 - $listClass = new ListClass();
477 - $listsId = json_decode(acym_getVar('string', 'acym__entity_select__selected'), true);
478 - $newListName = acym_getVar('string', 'new_list');
479 -
480 - if (empty($listsId) && empty($newListName)) {
481 - return [];
482 - }
483 -
484 - $lists = [];
485 -
486 - if (!empty($newListName)) {
487 - $newList = new \stdClass();
488 - $newList->name = $newListName;
489 - $newList->active = 1;
490 - $colors = '#'.substr(str_shuffle('ABCDEF0123456789'), 0, 6);
491 - $newList->color = $colors;
492 - $listid = $listClass->save($newList);
493 - $lists[$listid] = 1;
494 - }
495 -
496 - if (!empty($listsId)) {
497 - foreach ($listsId as $id) {
498 - $lists[$id] = 1;
499 - }
500 - }
501 -
502 - return $lists;
503 - }
504 -
505 - public function additionalDataUsersImport(bool $isGeneric): string
506 - {
507 - $buttonAddListId = $isGeneric ? 'acym__users__generic__import__create-list__button' : 'acym__users__import__create-list__button';
508 - $buttonImportClass = $isGeneric ? 'acym__users__import__generic__import__button' : 'acym__users__import__button';
509 - $buttonSkipId = $isGeneric ? 'acym__users__generic__import__skip__button' : 'acym__users__import__skip__button';
510 - $buttonImportDataTask = $isGeneric ? 'listing' : '';
511 -
512 - return '<div class="cell align-right grid-x margin-bottom-2">
513 - <div id="acym__users__import__create-list" class="grid-x" style="display: none;">
514 - <label for="acym__users__import__create-list__field" class="margin-right-1 acym_vcenter">'.acym_translation('ACYM_LIST_NAME').' : </label>
515 - <div>
516 - <input id="acym__users__import__create-list__field" type="text">
517 - </div>
518 - </div>
519 - <button type="button" class="button button-secondary margin-left-1 acym_vcenter margin-right-2" id="'.$buttonAddListId.'">'.acym_translation(
520 - 'ACYM_CREATE_NEW_LIST'
521 - ).'</button>
522 - <i style="display: none;" class="acym_vcenter acymicon-circle-o-notch acymicon-spin" id="acym__users__import__create-list__loading-logo"></i>
523 - </div>
524 - <div class="cell align-right grid-x">
525 - <button type="button" class="button-secondary button cell shrink margin-right-1" id="'.$buttonSkipId.'">'.acym_translation('ACYM_SKIP').'</button>
526 - <button
527 - type="button"
528 - class="button-primary button acy_button_submit cell shrink margin-right-2 '.$buttonImportClass.'"
529 - id="acym__entity_select__button__submit" data-task="'.$buttonImportDataTask.'">'.acym_translation('ACYM_SUBSCRIBE_USERS_TO_THESE_LISTS').'</button>
530 - </div>';
531 - }
532 -
533 - private function createUploadFolder(): string
534 - {
535 - $folderPath = acym_cleanPath(ACYM_ROOT.trim(html_entity_decode(ACYM_MEDIA_FOLDER.'import'))).DS;
536 - if ('wordpress' === ACYM_CMS) {
537 - $folderPath = acym_cleanPath(WP_PLUGIN_DIR.DS.ACYM_COMPONENT.DS.'media'.DS.'import').DS;
538 - }
539 - if (!is_dir($folderPath)) {
540 - acym_createDir($folderPath, true, true);
541 - }
542 -
543 - if (!acym_isWritable($folderPath)) {
544 - acym_chmod($folderPath, 0755);
545 - if (!acym_isWritable($folderPath)) {
546 - acym_enqueueMessage(acym_translationSprintf('ACYM_WRITABLE_FOLDER', $folderPath), 'warning');
547 - }
548 - }
549 -
550 - return $folderPath;
551 - }
552 -
553 - private function handleContent(string $contentFile): void
554 - {
555 - $timestamp = time();
556 -
557 - //We convert the file into something valid so that mac or not will be Ok!
558 - $contentFile = str_replace(["\r\n", "\r"], "\n", $contentFile);
559 - $importLines = explode("\n", $contentFile);
560 -
561 - //A little trick to take the second line if the first line is empty...
562 - $i = 0;
563 - $this->header = '';
564 - $this->allUserIds = [];
565 - while (empty($this->header) && $i < 10) {
566 - $this->header = trim($importLines[$i]);
567 - $i++;
568 - }
569 -
570 - if (strpos($this->header, '@') && !strpos($this->header, ',') && !strpos($this->header, ';') && !strpos($this->header, "\t")) {
571 - //We have an @ in the first line so there is definitely an issue there and the first line is not the right one!
572 - //And we don't have separators so we know the format
573 - $this->header = 'email';
574 - $i--;
575 - }
576 -
577 - //Step 3 : we make sure the header of the file is correct (so it does correspond to columns from the database)
578 - if (!$this->autoDetectHeader()) {
579 - acym_enqueueMessage(acym_translationSprintf('ACYM_IMPORT_HEADER', esc_html($this->header)), 'error');
580 - acym_enqueueMessage(acym_translation('ACYM_IMPORT_EMAIL'), 'error');
581 -
582 - return;
583 - }
584 -
585 - $encodingHelper = new EncodingHelper();
586 - $userClass = new UserClass();
587 - $listClass = new ListClass();
588 -
589 - $allLists = $listClass->getAll('name');
590 - $numberColumns = count($this->columns);
591 - $countUsersBeforeImport = $userClass->getCountTotalUsers();
592 - $importUsers = [];
593 - $errorLines = [];
594 -
595 - //Step 4 : we start importing the file as everything is OK
596 - while (isset($importLines[$i])) {
597 - // If there are quotes in the line, check if it is a broken line or not
598 - if (strpos($importLines[$i], '"') !== false) {
599 - $data = [];
600 - $j = $i + 1;
601 - // The position is the separator's one, -1 for the beginning as the line does not start by a separator
602 - $position = -1;
603 -
604 - // Concatenate 30 lines max
605 - while ($j < ($i + 30)) {
606 - // Test if the value is encapsulated by quotes
607 - $quoteOpened = substr($importLines[$i], $position + 1, 1) == '"';
608 -
609 - // If encapsulated, search the end of the value
610 - if ($quoteOpened) {
611 - $nextQuotePosition = strpos($importLines[$i], '"', $position + 2);
612 - // If quotes in the value encapsulated by quotes... find the real closing quote...
613 - while (
614 - $nextQuotePosition !== false
615 - && $nextQuotePosition + 1 != strlen($importLines[$i])
616 - && substr($importLines[$i], $nextQuotePosition + 1, 1) != $this->separator
617 - ) {
618 - $nextQuotePosition = strpos($importLines[$i], '"', $nextQuotePosition + 1);
619 - }
620 -
621 - // If we didn't find the whole value, then concatenate the current line with the next one
622 - if ($nextQuotePosition === false) {
623 - // If end of import file, error...
624 - if (!isset($importLines[$j])) {
625 - break;
626 - }
627 -
628 - $importLines[$i] .= "\n".$importLines[$j];
629 - $importLines[$i] = rtrim($importLines[$i], $this->separator);
630 - unset($importLines[$j]);
631 - $j++;
632 - } else {
633 - // Found the entire value, add it to data and move the position to the next separator
634 -
635 - // If the quote is at the end of the line and the line is completed...
636 - if (strlen($importLines[$i]) - 1 == $nextQuotePosition) {
637 - $data[] = substr($importLines[$i], $position + 1);
638 - break;
639 - }
640 - // ,"toto",value...
641 - // 3456789
642 - // Start in 3+1 so 4: the first quote
643 - // Length = 9+1-(3+1) = 6, the length of "toto".
644 - $data[] = substr($importLines[$i], $position + 1, $nextQuotePosition + 1 - ($position + 1));
645 - $position = $nextQuotePosition + 1;
646 - }
647 - } else {
648 - // If not encapsulated by quotes, search the next separator
649 - $nextSeparatorPosition = strpos($importLines[$i], $this->separator, $position + 1);
650 - // If not found, the line is completed
651 - if ($nextSeparatorPosition === false) {
652 - $data[] = substr($importLines[$i], $position + 1);
653 - break;
654 - } else { // If found the next separator, add the value in $data and change the position
655 - $data[] = substr($importLines[$i], $position + 1, $nextSeparatorPosition - ($position + 1));
656 - $position = $nextSeparatorPosition;
657 - }
658 - }
659 - }
660 -
661 - // We unset some lines, don't forget to change the remaining lines keys
662 - $importLines = array_merge($importLines);
663 - } else {
664 - //We remove the separators from the end of the string as we don't need them... they will be added as empty string anyway during the import process.
665 - $data = explode($this->separator, rtrim(trim($importLines[$i]), $this->separator));
666 - }
667 -
668 - //We clean it... maybe there are other arguments at the end we should remove
669 - if (!empty($this->separatorsToRemove)) {
670 - for ($b = $numberColumns + $this->separatorsToRemove - 1; $b >= $numberColumns; $b--) {
671 - if (isset($data[$b]) && (strlen($data[$b]) == 0 || $data[$b] == ' ')) {
672 - unset($data[$b]);
673 - }
674 - }
675 - }
676 -
677 - $i++;
678 - //We don't handle empty lines...
679 - if (empty($importLines[$i - 1])) {
680 - continue;
681 - }
682 -
683 - $this->totalTry++;
684 - //Lets try to fix it first...
685 - if (count($data) > $numberColumns) {
686 - $copy = $data;
687 - foreach ($copy as $oneelem => $oneval) {
688 - if (
689 - !empty($oneval[0])
690 - && $oneval[0] === '"'
691 - && $oneval[strlen($oneval) - 1] !== '"'
692 - && isset($copy[$oneelem + 1])
693 - && $copy[$oneelem + 1][strlen($copy[$oneelem + 1]) - 1] == '"'
694 - ) {
695 - //We concat both with the separator
696 - $data[$oneelem] = $copy[$oneelem].$this->separator.$copy[$oneelem + 1];
697 - unset($data[$oneelem + 1]);
698 - }
699 - }
700 -
701 - $data = array_values($data);
702 - }
703 -
704 - // Not enough columns found...
705 - if (count($data) < $numberColumns) {
706 - // If not enough info compared to the header... lets add them as empty! We don't care if the user does not specify everything...
707 - for ($a = count($data); $a < $numberColumns; $a++) {
708 - $data[$a] = '';
709 - }
710 - }
711 -
712 - if (count($data) != $numberColumns) {
713 - static $errorcount = 0;
714 - if (empty($errorcount)) {
715 - acym_enqueueMessage(acym_translationSprintf('ACYM_IMPORT_ARGUMENTS', $numberColumns), 'warning');
716 - }
717 - $errorcount++;
718 -
719 - //If it's for the first line, we return so we don't check the rest and let the user fix it
720 - if ($this->totalTry == 1) {
721 - return;
722 - }
723 - if (empty($errorLines)) {
724 - $errorLines[] = 'error,'.$importLines[0];
725 - }
726 - $errorLines[] = acym_translation('ACYM_IMPORT_ERROR_WRONG_NUMBER_ARGUMENTS').','.$importLines[$i - 1];
727 - continue;
728 - }
729 -
730 - $newUser = new \stdClass();
731 - $newUser->customfields = [];
732 -
733 - // Handle email column first to be able to use it with listids and listname
734 - $emailKey = array_search('email', $this->columns);
735 - $newUser->email = trim(acym_stripTags($data[$emailKey]), '\'" ');
736 - // Remove all whitespace type
737 - $newUser->email = preg_replace("/\s+/u", '', $newUser->email);
738 - if (!empty($newUser->email)) {
739 - $newUser->email = acym_punycode($newUser->email);
740 - }
741 - $newUser->email = trim(str_replace([' ', "\t"], '', $encodingHelper->change($newUser->email, 'UTF-8', 'ISO-8859-1')));
742 -
743 -
744 - if (!acym_isValidEmail($newUser->email)) {
745 - static $errorcountfail = 0;
746 - //We limit to 10 errors otherwise it may break the Joomla messaging system in terms of memory usage
747 - if ($errorcountfail == 0) {
748 - acym_enqueueMessage(acym_translation('ACYM_ADDRESSES_INVALID'), 'warning');
749 - }
750 - $errorcountfail++;
751 - if (empty($errorLines)) {
752 - $errorLines[] = 'error,'.$importLines[0];
753 - }
754 - $errorLines[] = acym_translation('ACYM_INVALID_EMAIL_ADDRESS').','.$importLines[$i - 1];
755 - continue;
756 - }
757 -
758 - foreach ($data as $num => $value) {
759 - // Already handled the email address
760 - if ($num == $emailKey) continue;
761 -
762 - $field = $this->columns[$num];
763 -
764 - // Ignored
765 - if ($field == 1) continue;
766 -
767 - if ($field === 'listids') {
768 - //We explode the listids separated by "-" and forach of them we add the user in the importUserInLists
769 - $liststosub = explode('-', trim($value, '\'" '));
770 - foreach ($liststosub as $onelistid) {
771 - $this->importUserInLists[intval(trim($onelistid))][] = acym_escapeDB($newUser->email);
772 - }
773 - continue;
774 - }
775 -
776 - if ($field === 'listname') {
777 - $liststosub = explode('-', trim($value, '\'" '));
778 - foreach ($liststosub as $onelistName) {
779 - if (empty($onelistName)) {
780 - continue;
781 - }
782 - $onelistName = trim($onelistName);
783 - if (empty($allLists[$onelistName])) {
784 - $newList = new \stdClass();
785 - $newList->name = $onelistName;
786 - $newList->active = 1;
787 - $colors = ['#3366ff', '#7240A4', '#7A157D', '#157D69', '#ECE649'];
788 - $newList->color = $colors[acym_rand(0, count($colors) - 1)];
789 - $listid = $listClass->save($newList);
790 - $newList->id = $listid;
791 - $allLists[$onelistName] = $newList;
792 - }
793 - $this->importUserInLists[intval($allLists[$onelistName]->id)][] = acym_escapeDB($newUser->email);
794 - }
795 - continue;
796 - }
797 -
798 - if (strpos($field, 'subscription_date_') === 0 || strpos($field, 'unsubscription_date_') === 0) {
799 - $value = trim($value, '"');
800 - if (strpos($field, 'subscription_date_') === 0) {
801 - $listId = (int)str_replace('subscription_date_', '', $field);
802 - $dateType = 'subscribed_date';
803 - } else {
804 - $listId = (int)str_replace('unsubscription_date_', '', $field);
805 - $dateType = 'unsubscribed_date';
806 - }
807 -
808 - if (!isset($this->subscriptionHistory[$listId])) {
809 - $this->subscriptionHistory[$listId] = [];
810 - }
811 -
812 - $email = $newUser->email;
813 - $userFound = false;
814 -
815 - foreach ($this->subscriptionHistory[$listId] as &$entry) {
816 - if ($entry['email'] === $email) {
817 - $entry[$dateType] = $value;
818 - $userFound = true;
819 - break;
820 - }
821 - }
822 - unset($entry);
823 -
824 - if (!$userFound) {
825 - $this->subscriptionHistory[$listId][] = [
826 - 'email' => $email,
827 - $dateType => $value,
828 - ];
829 - }
830 -
831 - continue;
832 - }
833 -
834 -
835 - // If we assigned the data to an Acy custom field
836 - if (strpos($field, 'cf_') === 0) {
837 - $newUser->customfields[substr($field, 3)] = trim(acym_stripTags($value), '\'" ');
838 - continue;
839 - }
840 -
841 - if ($value === 'null') {
842 - $newUser->$field = '';
843 - } else {
844 - //We remove anything which should not be there (quotes or spaces or return char or html tags)
845 - $newUser->$field = trim(acym_stripTags($value), '\'" ');
846 - }
847 - }
848 -
849 - if (acym_isMultilingual() && empty($newUser->language)) {
850 - $newUser->language = $this->config->get('multilingual_default', '');
851 - }
852 -
853 - //Everything is Ok... we can add the line
854 - $importUsers[] = $newUser;
855 - $this->totalValid++;
856 -
857 - //Every 50 users, we handle it
858 - if ($this->totalValid % 50 == 0) {
859 - $this->insertUsers($importUsers, $timestamp);
860 - $importUsers = [];
861 - }
862 - }
863 -
864 - if (!empty($errorLines)) {
865 - $filename = strtolower(acym_getVar('cmd', 'acym_import_filename', ''));
866 - if (!empty($filename)) {
867 - $extension = '.'.acym_fileGetExt($filename);
868 - $filename = str_replace(['.', ' '], '_', substr($filename, 0, strpos($filename, $extension))).$extension;
869 - $errorFile = implode("\n", $errorLines);
870 - acym_writeFile(ACYM_MEDIA.'import'.DS.'error_'.$filename, $errorFile);
871 - acym_enqueueMessage(
872 - '<a target="_blank" href="'.acym_prepareAjaxURL((acym_isAdmin() ? '' : 'front').'users&task=downloadImport').'&filename=error_'.preg_replace(
873 - '#\.[^.]*$#',
874 - '',
875 - $filename
876 - ).'&'.acym_noTemplate().'" >'.acym_translation('ACYM_DOWNLOAD_IMPORT_ERRORS').'</a>',
877 - 'notice'
878 - );
879 - }
880 - }
881 -
882 - $this->insertUsers($importUsers, $timestamp);
883 -
884 - acym_query('UPDATE #__acym_configuration SET `value` = '.intval($timestamp).' WHERE `name` = \'last_import\'');
885 -
886 - // We could have imported empty values
887 - acym_query('DELETE FROM #__acym_user_has_field WHERE `value` = ""');
888 -
889 - $countUsersAfterImport = $userClass->getCountTotalUsers();
890 - $totalInserted = $countUsersAfterImport - $countUsersBeforeImport;
891 -
892 - $maybeUpdated = acym_translation('ACYM_NOT_UPDATED');
893 - if ($this->overwrite) {
894 - $maybeUpdated = acym_translation('ACYM_UPDATED');
895 - }
896 - $reportMsg = acym_translationSprintf(
897 - 'ACYM_IMPORT_REPORTING_UPDATED',
898 - $this->totalTry,
899 - $totalInserted,
900 - $this->totalTry - $this->totalValid,
901 - $this->totalValid - $totalInserted,
902 - $maybeUpdated
903 - );
904 - acym_enqueueMessage($reportMsg, 'info');
905 -
906 - $this->insertSubscriptionHistory();
907 -
908 - // All users have been added properly into the database... we will now subscribe the users
909 - $this->subscribeUsers();
910 - }
911 -
912 - private function insertUsers(array $users, int $timestamp): void
913 - {
914 - if (empty($users)) {
915 - return;
916 - }
917 -
918 - $importedCols = array_keys(get_object_vars($users[0]));
919 - unset($importedCols[array_search('customfields', $importedCols)]);
920 - if ($this->forceConfirm) $importedCols[] = 'confirmed';
921 -
922 - foreach ($users as $a => $oneUser) {
923 - $this->checkData($users[$a], $timestamp);
924 - }
925 -
926 - $columns = reset($users);
927 - $colNames = array_keys(get_object_vars($columns));
928 - unset($colNames[array_search('customfields', $colNames)]);
929 -
930 - if (!in_array('key', $colNames)) $colNames[] = 'key';
931 -
932 - foreach ($colNames as $oneColumn) {
933 - acym_secureDBColumn($oneColumn);
934 - }
935 -
936 - $queryInsertUsers = 'INSERT'.($this->overwrite ? '' : ' IGNORE').' INTO #__acym_user (`'.implode('`,`', $colNames).'`) VALUES (';
937 - $values = [];
938 - $customFieldsvalues = [];
939 - $allemails = [];
940 - foreach ($users as $oneUser) {
941 - $value = [];
942 - acym_trigger('onAcymBeforeUserImport', [&$oneUser]);
943 -
944 - foreach ($oneUser as $map => $oneValue) {
945 - if ($map === 'customfields') continue;
946 -
947 - $oneValue = htmlspecialchars_decode($oneValue, ENT_QUOTES);
948 -
949 - if ($map !== 'id') {
950 - $oneValue = acym_escapeDB($oneValue);
951 - if ($map === 'email') {
952 - $allemails[] = $oneValue;
953 - }
954 - } else {
955 - $oneValue = intval($oneValue);
956 - }
957 -
958 - $value[] = $oneValue;
959 - }
960 -
961 - if (!isset($oneUser->key)) $value[] = acym_escapeDB(acym_generateKey(14));
962 - $values[] = implode(',', $value);
963 -
964 - // Prepare import custom fields
965 - if (!empty($oneUser->customfields)) $customFieldsvalues[$oneUser->email] = $oneUser->customfields;
966 - }
967 - acym_trigger('onAcymUserImport', [&$users]);
968 -
969 - $queryInsertUsers .= implode('),(', $values).')';
970 -
971 - if ($this->overwrite) {
972 - $queryInsertUsers .= ' ON DUPLICATE KEY UPDATE ';
973 - foreach ($importedCols as &$oneColumn) {
974 - acym_secureDBColumn($oneColumn);
975 - if ($oneColumn == 'key') {
976 - $oneColumn = '`'.$oneColumn.'` = `'.$oneColumn.'`';
977 - } else {
978 - $oneColumn = '`'.$oneColumn.'` = VALUES(`'.$oneColumn.'`)';
979 - }
980 - }
981 - $queryInsertUsers .= implode(',', $importedCols);
982 - }
983 -
984 - acym_query($queryInsertUsers);
985 -
986 - $importedUsers = acym_loadObjectList('SELECT id, email FROM #__acym_user WHERE email IN ('.implode(',', $allemails).')', 'id');
987 -
988 - $this->importedUsersByEmail = array_combine(array_column($importedUsers, 'email'), array_column($importedUsers, 'id'));
989 -
990 - if (!empty($customFieldsvalues)) {
991 - $insertValues = [];
992 - foreach ($importedUsers as $one) {
993 - if (empty($customFieldsvalues[$one->email])) continue;
994 -
995 - foreach ($customFieldsvalues[$one->email] as $fieldId => $value) {
996 - $value = htmlspecialchars_decode($value, ENT_QUOTES);
997 - $insertValues[] = '('.intval($one->id).','.intval($fieldId).','.acym_escapeDB($value).')';
998 - }
999 - }
1000 -
1001 - if (!empty($insertValues)) {
1002 - $queryInsertCustomFields = 'INSERT'.($this->overwrite ? '' : ' IGNORE').' INTO #__acym_user_has_field (`user_id`, `field_id`, `value`) VALUES '.implode(
1003 - ',',
1004 - $insertValues
1005 - );
1006 - if ($this->overwrite) {
1007 - $queryInsertCustomFields .= ' ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)';
1008 - }
1009 - acym_query($queryInsertCustomFields);
1010 - }
1011 - }
1012 -
1013 -
1014 - $this->allUserIds = array_merge($this->allUserIds, array_keys($importedUsers));
1015 - }
1016 -
1017 - private function checkData(object &$user, int $timestamp)
1018 - {
1019 - //Created field
1020 - if (empty($user->creation_date)) {
1021 - $user->creation_date = time();
1022 - }
1023 -
1024 - if (is_numeric($user->creation_date)) {
1025 - $user->creation_date = gmdate('Y-m-d H:i:s', $user->creation_date);
1026 - }
1027 -
1028 - if (!isset($user->active) || strlen($user->active) == 0) {
1029 - $user->active = 1;
1030 - }
1031 -
1032 - if ((!isset($user->confirmed) || strlen($user->confirmed) == 0) && $this->forceConfirm) {
1033 - $user->confirmed = 1;
1034 - }
1035 -
1036 - if (empty($user->source)) {
1037 - $user->source = 'Import on '.acym_date($timestamp, 'Y-m-d H:i:s');
1038 - }
1039 -
1040 - //name field
1041 - if (empty($user->name) && $this->generateName) {
1042 - $user->name = ucwords(trim(str_replace(['.', '_', '-', 1, 2, 3, 4, 5, 6, 7, 8, 9, 0], ' ', substr($user->email, 0, strpos($user->email, '@')))));
1043 - }
1044 - }
1045 -
1046 - private function autoDetectHeader(): bool
1047 - {
1048 - $this->separator = ',';
1049 -
1050 - // Remove BOM characters if there is one
1051 - $this->header = str_replace("\xEF\xBB\xBF", '', $this->header);
1052 -
1053 - // Detect the separator
1054 - $listSeparators = ["\t", ';', ','];
1055 - foreach ($listSeparators as $sep) {
1056 - if (strpos($this->header, $sep) !== false) {
1057 - $this->separator = $sep;
1058 - break;
1059 - }
1060 - }
1061 -
1062 - $this->columns = explode($this->separator, $this->header);
1063 -
1064 - // Clean the headers
1065 - for ($i = count($this->columns) - 1; $i >= 0; $i--) {
1066 - if (strlen($this->columns[$i]) == 0) {
1067 - unset($this->columns[$i]);
1068 - $this->separatorsToRemove++;
1069 - }
1070 - }
1071 -
1072 - $columns = acym_getColumns('user');
1073 - foreach ($columns as $i => $oneColumn) {
1074 - $columns[$i] = strtolower($oneColumn);
1075 - }
1076 -
1077 - foreach ($this->columns as $i => $oneColumn) {
1078 - $this->columns[$i] = strtolower(trim($oneColumn, '\'" '));
1079 - if (in_array($this->columns[$i], ['listids', 'listname'])) continue;
1080 - if (strpos($this->columns[$i], 'cf_') === 0) continue;
1081 - if (strpos($this->columns[$i], 'subscription_date_') === 0) continue;
1082 - if (strpos($this->columns[$i], 'unsubscription_date_') === 0) continue;
1083 -
1084 - if (!in_array($this->columns[$i], $columns) && $this->columns[$i] != 1) {
1085 - acym_enqueueMessage(
1086 - acym_translationSprintf(
1087 - 'ACYM_IMPORT_ERROR_FIELD',
1088 - '<b>'.esc_html($this->columns[$i]).'</b>',
1089 - '<b>'.implode('</b> | <b>', array_diff($columns, ['id', 'cms_id'])).'</b>'
1090 - ),
1091 - 'error'
1092 - );
1093 -
1094 - return false;
1095 - }
1096 - }
1097 -
1098 - if (!in_array('email', $this->columns)) {
1099 - return false;
1100 - }
1101 -
1102 - return true;
1103 - }
1104 -
1105 - private function cleanImportFolder(): void
1106 - {
1107 - $files = acym_getFiles(ACYM_MEDIA.'import', '.', false, true, []);
1108 - foreach ($files as $oneFile) {
1109 - if (acym_fileGetExt($oneFile) != 'csv') {
1110 - continue;
1111 - }
1112 - if (filectime($oneFile) < time() - 86400) {
1113 - acym_deleteFile($oneFile);
1114 - }
1115 - }
1116 - }
1117 -
1118 - private function subscribeUsers(): void
1119 - {
1120 - //All users are known as : $this->allUserIds
1121 - if (empty($this->allUserIds)) {
1122 - return;
1123 - }
1124 -
1125 - $subdate = gmdate('Y-m-d H:i:s', time());
1126 -
1127 - $listClass = new ListClass();
1128 - $lists = $this->getImportedLists();
1129 -
1130 - if (!acym_isAdmin() && 'joomla' === ACYM_CMS) {
1131 - $listClass = new ListClass();
1132 - $listManagementId = $listClass->getfrontManagementList();
1133 - if (empty($listManagementId)) {
1134 - acym_redirect(acym_rootURI(), 'ACYM_UNABLE_TO_CREATE_MANAGEMENT_LIST', 'error');
1135 - }
1136 -
1137 - if (empty($lists)) {
1138 - $lists = [$listManagementId => 1];
1139 - } else {
1140 - $lists[$listManagementId] = 1;
1141 - }
1142 - }
1143 -
1144 - if (!empty($this->importUserInLists)) {
1145 - //We import the users based on the subscription of each of them, specified in the listids or listname columns...
1146 - foreach ($this->importUserInLists as $listid => $arrayEmails) {
1147 - if (empty($listid)) continue;
1148 -
1149 - $listid = (int)$listid;
1150 - $query = 'INSERT IGNORE INTO #__acym_user_has_list (`list_id`,`user_id`,`subscription_date`,`status`) ';
1151 - $query .= 'SELECT '.intval($listid).',`id`,'.acym_escapeDB($subdate).',1 FROM #__acym_user WHERE `email` IN (';
1152 - $query .= implode(',', $arrayEmails).')';
1153 - $nbsubscribed = acym_query($query);
1154 - $nbsubscribed = intval($nbsubscribed);
1155 -
1156 - if (isset($this->subscribedUsers[$listid])) {
1157 - $this->subscribedUsers[$listid]->nbusers += $nbsubscribed;
1158 - } else {
1159 - $myList = $listClass->getOneById($listid);
1160 - $this->subscribedUsers[$listid] = $myList;
1161 - $this->subscribedUsers[$listid]->nbusers = $nbsubscribed;
1162 - }
1163 - }
1164 - }
1165 -
1166 - if (!empty($lists)) {
1167 - //We do one query per list to avoid problem with huge queries and so in the mean time we can display info for each list
1168 - foreach ($lists as $listid => $val) {
1169 - if (empty($val)) {
1170 - continue;
1171 - }
1172 -
1173 - if ($val == -1) {
1174 - $dateColumn = 'unsubscribe_date';
1175 - $status = 0;
1176 - } else {
1177 - $dateColumn = 'subscription_date';
1178 - $status = 1;
1179 - }
1180 -
1181 - $nbsubscribed = 0;
1182 - $listid = intval($listid);
1183 - $query = 'INSERT IGNORE INTO #__acym_user_has_list (`list_id`,`user_id`,`'.$dateColumn.'`,`status`) VALUES ';
1184 - $b = 0;
1185 - $currentSubids = [];
1186 - foreach ($this->allUserIds as $subid) {
1187 - $subid = intval($subid);
1188 - $currentSubids[] = $subid;
1189 - $b++;
1190 -
1191 - if ($b > 200) {
1192 - $query = rtrim($query, ',');
1193 - if ($val == -1) {
1194 - $query .= ' ON DUPLICATE KEY UPDATE status = 0';
1195 - $nbsubscribed = -acym_loadResult(
1196 - 'SELECT COUNT(*) FROM #__acym_listsub WHERE `list_id` = '.intval($listid).' AND status != -1 AND `user_id` IN ('.implode(',', $currentSubids).')'
1197 - );
1198 - }
1199 - $affected = acym_query($query);
1200 - $nbsubscribed += intval($affected);
1201 - $b = 0;
1202 - $currentSubids = [];
1203 - $query = 'INSERT IGNORE INTO #__acym_user_has_list (`list_id`,`user_id`,`'.$dateColumn.'`,`status`) VALUES ';
1204 - }
1205 -
1206 - $query .= '('.intval($listid).','.intval($subid).','.acym_escapeDB($subdate).','.$status.'),';
1207 - }
1208 - $query = rtrim($query, ',');
1209 - if ($val == -1) {
1210 - $query .= ' ON DUPLICATE KEY UPDATE status = 0';
1211 - // It could be empty if we imported exactly 200, 400, 600... users
1212 - if (!empty($currentSubids)) {
1213 - $nbsubscribed = -acym_loadResult(
1214 - 'SELECT COUNT(*) FROM #__acym_listsub WHERE `list_id` = '.intval($listid).' AND status != -1 AND `user_id` IN ('.implode(',', $currentSubids).')'
1215 - );
1216 - }
1217 - }
1218 -
1219 - $affected = acym_query($query);
1220 - $nbsubscribed += intval($affected);
1221 -
1222 - if (isset($this->subscribedUsers[$listid])) {
1223 - $this->subscribedUsers[$listid]->nbusers += $nbsubscribed;
1224 - } else {
1225 - $myList = $listClass->getOneById($listid);
1226 - $myList->status = $val;
1227 - $this->subscribedUsers[$listid] = $myList;
1228 - $this->subscribedUsers[$listid]->nbusers = $nbsubscribed;
1229 - }
1230 - }
1231 - }
1232 - }
1233 -
1234 - public function insertSubscriptionHistory(): void
1235 - {
1236 - if (empty($this->subscriptionHistory)) {
1237 - return;
1238 - }
1239 -
1240 - $listClass = new ListClass();
1241 -
1242 - $userIds = array_values($this->importedUsersByEmail);
1243 - $listIds = array_keys($this->subscriptionHistory);
1244 -
1245 - $existingEntries = $listClass->getUserListEntries($userIds, $listIds);
1246 -
1247 - foreach ($this->subscriptionHistory as $listId => $entries) {
1248 - foreach ($entries as $entry) {
1249 - if (empty($entry['subscribed_date']) && empty($entry['unsubscribed_date'])) {
1250 - continue;
1251 - }
1252 -
1253 - $userId = $this->importedUsersByEmail[$entry['email']] ?? null;
1254 - if (empty($userId)) {
1255 - continue;
1256 - }
1257 -
1258 - $key = $userId.'_'.$listId;
1259 - $existing = $existingEntries[$key] ?? null;
1260 -
1261 - $subscriptionDate = !empty($entry['subscribed_date']) ? acym_escapeDB($entry['subscribed_date']) : 'NULL';
1262 - $unsubscribeDate = !empty($entry['unsubscribed_date']) ? acym_escapeDB($entry['unsubscribed_date']) : 'NULL';
1263 -
1264 - if (!empty($existing)) {
1265 - if ($existing->status === 0) {
1266 - continue;
1267 - }
1268 -
1269 - $fieldsToUpdate = [];
1270 -
1271 - if (empty($existing->subscription_date)) {
1272 - if ($unsubscribeDate != 'NULL' && ($subscriptionDate != 'NULL' && $unsubscribeDate > $subscriptionDate)) {
1273 - $fieldsToUpdate[] = 'status ='. 0;
1274 - $fieldsToUpdate[] = 'unsubscribe_date ='.$unsubscribeDate;
1275 - }
1276 -
1277 - $fieldsToUpdate[] = 'subscription_date ='.$subscriptionDate;
1278 - } else {
1279 - if ($unsubscribeDate != 'NULL' && ($existing->subscription_date != 'NULL' && $unsubscribeDate > $existing->subscription_date)) {
1280 - $fieldsToUpdate[] = 'status ='. 0;
1281 - $fieldsToUpdate[] = 'unsubscribe_date ='.$unsubscribeDate;
1282 - }
1283 - }
1284 -
1285 - if (!empty($fieldsToUpdate)) {
1286 - $query = 'UPDATE #__acym_user_has_list SET '.implode(', ', $fieldsToUpdate)
1287 - .' WHERE user_id = '.$userId.' AND list_id = '.$listId;
1288 - acym_query($query);
1289 - }
1290 - } else {
1291 - if ($subscriptionDate === 'NULL' && $unsubscribeDate !== 'NULL') {
1292 - $subscriptionDate = $unsubscribeDate;
1293 - }
1294 -
1295 - $status = ($unsubscribeDate !== 'NULL') ? 0 : 1;
1296 -
1297 - $insertQuery = 'INSERT INTO #__acym_user_has_list (`list_id`, `user_id`, `subscription_date`, `status`, `unsubscribe_date`) VALUES '
1298 - .'('.$listId.','.$userId.','.$subscriptionDate.','.$status.','.$unsubscribeDate.')';
1299 - acym_query($insertQuery);
1300 - }
1301 - }
1302 - }
1303 - }
1304 -}