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/ExportHelper.php +0 -553 10.0.1 → 11.1.1 View file →
@@ -1,553 +1,0 @@
1 -<?php
2 -
3 -namespace AcyMailing\Helpers;
4 -
5 -use AcyMailing\Classes\ListClass;
6 -use AcyMailing\Classes\MailClass;
7 -use AcyMailing\Core\AcymObject;
8 -
9 -class ExportHelper extends AcymObject
10 -{
11 - var $eol = "\r\n";
12 - var $before = '"';
13 - var $after = '"';
14 -
15 - public function setDownloadHeaders($filename = 'export', $extension = 'csv')
16 - {
17 - acym_header('Pragma: public');
18 - acym_header('Expires: 0');
19 - acym_header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
20 -
21 - acym_header('Content-Type: application/force-download');
22 - acym_header('Content-Type: application/octet-stream');
23 - acym_header('Content-Type: application/download');
24 -
25 - acym_header('Content-Disposition: attachment; filename='.$filename.'.'.$extension);
26 - acym_header('Content-Transfer-Encoding: binary');
27 - }
28 -
29 - public function exportTemplate($template)
30 - {
31 - $name = preg_replace('#[^a-z0-9]#Uis', '_', $template->name);
32 - $name = preg_replace('#_+#s', '_', $name);
33 - $exportFolder = ACYM_ROOT.ACYM_MEDIA_FOLDER.'tmp'.DS.$name;
34 - acym_createFolder($exportFolder);
35 -
36 - $template->body = acym_absoluteURL($template->body);
37 - $images = [];
38 - preg_match_all('#<img[^>]* src="([^"]+)"#Uis', $template->body, $images);
39 -
40 - if (!empty($images[1])) {
41 - $imagesFolder = $exportFolder.DS.'images';
42 - acym_createFolder($imagesFolder);
43 -
44 - $replace = [];
45 - foreach ($images[1] as $oneImage) {
46 - if (isset($replace[$oneImage])) continue;
47 -
48 - $location = str_replace(
49 - [ACYM_LIVE, '/'],
50 - [ACYM_ROOT, DS],
51 - $oneImage
52 - );
53 - if (strpos($location, 'http') === 0) continue;
54 -
55 - if (!file_exists($location)) continue;
56 -
57 - $filename = basename($location);
58 - while (file_exists($imagesFolder.DS.$filename)) {
59 - $filename = rand(0, 99).$filename;
60 - }
61 -
62 - acym_copyFile($location, $imagesFolder.DS.$filename);
63 - $replace[$oneImage] = 'images/'.$filename;
64 - }
65 -
66 - $template->body = str_replace(array_keys($replace), $replace, $template->body);
67 - }
68 -
69 - $structure = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
70 -<html xmlns="http://www.w3.org/1999/xhtml">
71 -<head>
72 -<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
73 -
74 - $dataToCopy = [
75 - 'fromname',
76 - 'fromemail',
77 - 'replyname',
78 - 'replyemail',
79 - 'subject',
80 - 'settings',
81 - ];
82 - foreach ($dataToCopy as $oneData) {
83 - if (empty($template->$oneData)) continue;
84 - $structure .= "\n".'<meta name="'.$oneData.'" content="'.acym_escape($template->$oneData).'" />';
85 - }
86 -
87 - $structure .= "\n".'<title>'.$template->name.'</title>
88 -</head>
89 -<body>
90 -'.$template->body.'
91 -</body>
92 -</html>';
93 -
94 - acym_writeFile($exportFolder.DS.'template.html', $structure);
95 -
96 - $thumbnail = acym_getMailThumbnail($template->thumbnail);
97 - $thumbnail = str_replace(ACYM_LIVE, ACYM_ROOT, $thumbnail);
98 - acym_copyFile($thumbnail, $exportFolder.DS.'thumbnail.png');
99 -
100 - if (!empty($template->stylesheet)) {
101 - acym_createFolder($exportFolder.DS.'css');
102 - acym_writeFile($exportFolder.DS.'css'.DS.'custom.css', $template->stylesheet);
103 - }
104 -
105 - $zipFiles = [];
106 - $folders = acym_getFolders($exportFolder, '.', true, true);
107 - array_push($folders, $exportFolder);
108 - foreach ($folders as $folder) {
109 - $files = acym_getFiles($folder, '.', false, true);
110 - foreach ($files as $file) {
111 - $posSlash = strrpos($file, '/');
112 - $posASlash = strrpos($file, '\\');
113 - $pos = ($posSlash < $posASlash) ? $posASlash : $posSlash;
114 - if (!empty($pos)) $file = substr_replace($file, DS, $pos, 1);
115 -
116 - $data = acym_fileGetContent($file);
117 - $zipFiles[] = [
118 - 'name' => str_replace(
119 - $exportFolder.DS,
120 - '',
121 - $file
122 - ),
123 - 'data' => $data,
124 - ];
125 - }
126 - }
127 -
128 - acym_createArchive($exportFolder, $zipFiles);
129 -
130 - acym_deleteFolder($exportFolder);
131 -
132 - $this->setDownloadHeaders($name, 'zip');
133 - echo acym_fileGetContent($exportFolder.'.zip');
134 - acym_deleteFile($exportFolder.'.zip');
135 -
136 - exit;
137 - }
138 -
139 - public function exportStatsFormattedCSV($mailName, $globalDonutsData, $globaline, $timeLinechart)
140 - {
141 - $nbExport = $this->getExportLimit();
142 - acym_displayErrors();
143 -
144 - if ($timeLinechart == 'month') {
145 - $timeLinechart = acym_translation('ACYM_MONTHLY_STATS');
146 - } elseif ($timeLinechart == 'week') {
147 - $timeLinechart = acym_translation('ACYM_WEEKLY_STATS');
148 - } else {
149 - $timeLinechart = acym_translation('ACYM_DAILY_STATS');
150 - }
151 -
152 - $separator = '","';
153 -
154 - $csvLines = [];
155 - $csvLines[] = $this->before.$mailName.$this->after;
156 -
157 - $csvLines[] = $this->eol;
158 -
159 - $globalDonutsTitle = [
160 - acym_translation('ACYM_SUCCESSFULLY_SENT'),
161 - acym_translation('ACYM_OPEN_RATE'),
162 - acym_translation('ACYM_CLICK_RATE'),
163 - acym_translation('ACYM_BOUNCE_RATE'),
164 - acym_translation('ACYM_UNSUBSCRIBE_RATE'),
165 - ];
166 -
167 - $csvLines[] = $this->before.implode($separator, $globalDonutsTitle).$this->after;
168 - $csvLines[] = $this->before.implode($separator, $globalDonutsData).$this->after;
169 -
170 - $csvLines[] = $this->eol;
171 -
172 - $csvLines[] = $this->before.$timeLinechart.$separator.acym_translation('ACYM_OPEN').$separator.acym_translation('ACYM_CLICK').$this->after;
173 -
174 - $i = 0;
175 - foreach ($globaline as $date => $value) {
176 - if ($i > $nbExport) break;
177 - $csvLines[] = $this->before.$date.$separator.$value['open'].$separator.$value['click'].$this->after;
178 - $i++;
179 - }
180 -
181 - $this->finishStatsExport($csvLines);
182 - }
183 -
184 - public function exportStatsFullCSV($query, $columns, $type = 'global')
185 - {
186 - $mailsStats = acym_loadObjectList($query);
187 - $mailClass = new MailClass();
188 - $mailClass->exceptKeysDecode = ['name'];
189 - $mailsStats = $mailClass->decode($mailsStats);
190 - $nbExport = $this->getExportLimit();
191 - acym_displayErrors();
192 -
193 - $separator = '","';
194 - $csvLines = [];
195 -
196 - $csvLines[] = $this->before.implode($separator, $columns).$this->after;
197 -
198 - $valueNeedNumber = ['click'];
199 -
200 - $i = 0;
201 - foreach ($mailsStats as $mailStat) {
202 - if ($i > $nbExport) break;
203 - $oneLine = [];
204 - foreach ($columns as $key => $trad) {
205 - $key = strpos($key, '.') !== false ? explode('.', $key) : $key;
206 - if (is_array($key)) $key = $key[1];
207 - $line = in_array($key, $valueNeedNumber) && empty($mailStat->{$key}) ? 0 : $mailStat->{$key};
208 - if (is_null($line)) {
209 - $line = '';
210 - }
211 - if ($key === 'bounce_details' && !empty($line)) {
212 - $line = @unserialize($line);
213 - if ($line !== false) {
214 - $formattedLine = '';
215 - foreach ($line as $detailKey => $detailValue) {
216 - $formattedLine .= $detailKey.': '.$detailValue.'; ';
217 - }
218 - $line = rtrim($formattedLine, '; ');
219 - }
220 - }
221 - $oneLine[] = htmlspecialchars($line, ENT_QUOTES, 'UTF-8');
222 - }
223 - $csvLines[] = $this->before.implode($separator, $oneLine).$this->after;
224 - $i++;
225 - }
226 -
227 - $this->finishStatsExport($csvLines, $type);
228 - }
229 -
230 - private function finishStatsExport($csvLines, $type = 'global')
231 - {
232 - $final = implode($this->eol, $csvLines);
233 -
234 - if (ACYM_CMS === 'wordpress') @ob_get_clean();
235 - $filename = 'export_stats_'.$type.'_'.date('Y-m-d');
236 - $this->setDownloadHeaders($filename);
237 - echo $final;
238 -
239 - return '';
240 - }
241 -
242 - private function getLists(): array
243 - {
244 - static $lists = null;
245 - if (empty($lists)) {
246 - $listClass = new ListClass();
247 - $lists = $listClass->getAllWithIdName();
248 - }
249 -
250 - return $lists;
251 - }
252 -
253 - public function exportCSV($query, $fieldsToExport, $customFieldsToExport, $specialFieldsToExport, $separator = ',', $charset = 'UTF-8', $exportFile = null, $flagToRemove = 0)
254 - {
255 - $nbExport = $this->getExportLimit();
256 - acym_displayErrors();
257 - $encodingClass = new EncodingHelper();
258 - $excelSecure = $this->config->get('export_excelsecurity', 0);
259 -
260 - if (!in_array($separator, [',', ';'])) $separator = ',';
261 - $separator = '"'.$separator.'"';
262 -
263 - $allFieldsToExport = array_merge($fieldsToExport, $customFieldsToExport);
264 -
265 - foreach ($allFieldsToExport as $key => $field) {
266 - $allFieldsToExport[$key] = $encodingClass->change($field, 'UTF-8', $charset);
267 - }
268 -
269 - if (in_array('subscribe_date', $specialFieldsToExport)) {
270 - $lists = $this->getLists();
271 - foreach ($lists as $oneList) {
272 - $allFieldsToExport[] = acym_translation('ACYM_SUBSCRIPTION_DATE').' '.acym_translation($oneList);
273 - }
274 - }
275 -
276 - if (in_array('unsubscribe_date', $specialFieldsToExport)) {
277 - $lists = $this->getLists();
278 - foreach ($lists as $oneList) {
279 - $allFieldsToExport[] = acym_translation('ACYM_UNSUBSCRIPTION_DATE').' '.acym_translation($oneList);
280 - }
281 - }
282 -
283 - $firstLine = $this->before.implode($separator, $allFieldsToExport).$this->after.$this->eol;
284 -
285 - if (empty($exportFile)) {
286 - @ob_get_clean();
287 - $filename = 'export_'.date('Y-m-d');
288 - $this->setDownloadHeaders($filename);
289 - echo $firstLine;
290 - } else {
291 - preg_match('#^(.+/)[^/]+$#', $exportFile, $folder);
292 - if (!empty($folder[1]) && !file_exists($folder[1])) acym_createDir($folder[1]);
293 -
294 - $fp = fopen($exportFile, 'w');
295 - if (false === $fp) {
296 - if ($flagToRemove !== 0) {
297 - $automationHelper = new AutomationHelper();
298 - $automationHelper->removeFlag($flagToRemove);
299 - }
300 -
301 - return acym_translationSprintf('ACYM_FAIL_SAVE_FILE', $exportFile);
302 - }
303 -
304 - $error = fwrite($fp, $firstLine);
305 - if (false === $error) {
306 - if ($flagToRemove !== 0) {
307 - $automationHelper = new AutomationHelper();
308 - $automationHelper->removeFlag($flagToRemove);
309 - }
310 -
311 - return acym_translationSprintf('ACYM_UNWRITABLE_FILE', $exportFile);
312 - }
313 - }
314 -
315 - $start = 0;
316 - do {
317 - try {
318 - $users = acym_loadObjectList($query.' LIMIT '.intval($start).', '.intval($nbExport), 'id');
319 - } catch (\Exception $e) {
320 - $users = false;
321 - }
322 - $start += $nbExport;
323 -
324 - if ($users === false) {
325 - $errorLine = $this->eol.$this->eol.'Error: '.(isset($e) ? $e->getMessage() : acym_getDBError());
326 -
327 - if (empty($exportFile)) {
328 - echo $errorLine;
329 - } else {
330 - $error = fwrite($fp, $errorLine);
331 - if (false === $error) {
332 - if ($flagToRemove !== 0) {
333 - $automationHelper = new AutomationHelper();
334 - $automationHelper->removeFlag($flagToRemove);
335 - }
336 -
337 - return acym_translationSprintf('ACYM_UNWRITABLE_FILE', $exportFile);
338 - }
339 - }
340 - }
341 -
342 - if (empty($users)) break;
343 -
344 - foreach ($users as $userID => $oneUser) {
345 - unset($oneUser->id);
346 -
347 - $data = get_object_vars($oneUser);
348 -
349 - if (!empty($customFieldsToExport)) {
350 - $fieldIDs = array_keys($customFieldsToExport);
351 - acym_arrayToInteger($fieldIDs);
352 -
353 - $userCustomFields = acym_loadObjectList(
354 - 'SELECT `field_id`, `value`
355 - FROM #__acym_user_has_field
356 - WHERE user_id = '.intval($userID).' AND field_id IN ('.implode(',', $fieldIDs).')',
357 - 'field_id'
358 - );
359 -
360 - foreach ($customFieldsToExport as $fieldID => $fieldName) {
361 - if (empty($userCustomFields[$fieldID])) {
362 - $data[] = '';
363 - } else {
364 - $data[] = acym_triggerCmsHook(
365 - 'onUserExportFieldData',
366 - [$userCustomFields[$fieldID]->value, $fieldID, $fieldName],
367 - false
368 - );
369 - }
370 - }
371 - unset($userCustomFields);
372 - }
373 -
374 - if (isset($lists)) {
375 - $userSubscriptions = acym_loadObjectList(
376 - 'SELECT `list_id`, `subscription_date`, `unsubscribe_date`
377 - FROM #__acym_user_has_list
378 - WHERE user_id = '.intval($userID),
379 - 'list_id'
380 - );
381 -
382 - if (in_array('subscribe_date', $specialFieldsToExport)) {
383 - foreach ($lists as $listId => $oneList) {
384 - $data[] = $userSubscriptions[$listId]->subscription_date ?? '';
385 - }
386 - }
387 -
388 - if (in_array('unsubscribe_date', $specialFieldsToExport)) {
389 - foreach ($lists as $listId => $oneList) {
390 - $data[] = $userSubscriptions[$listId]->unsubscribe_date ?? '';
391 - }
392 - }
393 -
394 - unset($userSubscriptions);
395 - }
396 -
397 - foreach ($data as &$oneData) {
398 - if (is_null($oneData)) {
399 - continue;
400 - }
401 -
402 - if ($excelSecure == 1) {
403 - $firstCharacter = substr($oneData, 0, 1);
404 - if (in_array($firstCharacter, ['=', '+', '-', '@'])) {
405 - $oneData = ' '.$oneData;
406 - }
407 - }
408 -
409 - $oneData = htmlspecialchars($oneData);
410 - }
411 -
412 - $dataexport = implode($separator, $data);
413 - unset($data);
414 -
415 - $oneLine = $this->before.$encodingClass->change($dataexport, 'UTF-8', $charset).$this->after.$this->eol;
416 - if (empty($exportFile)) {
417 - echo $oneLine;
418 - } else {
419 - $error = fwrite($fp, $oneLine);
420 - if (false === $error) {
421 - if ($flagToRemove !== 0) {
422 - $automationHelper = new AutomationHelper();
423 - $automationHelper->removeFlag($flagToRemove);
424 - }
425 -
426 - return acym_translationSprintf('ACYM_UNWRITABLE_FILE', $exportFile);
427 - }
428 - }
429 - }
430 -
431 - unset($users);
432 - } while (true);
433 -
434 - if ($flagToRemove !== 0) {
435 - $automationHelper = new AutomationHelper();
436 - $automationHelper->removeFlag($flagToRemove);
437 - }
438 -
439 - if (!empty($exportFile)) fclose($fp);
440 -
441 - return '';
442 - }
443 -
444 - private function getExportLimit()
445 - {
446 - $serverLimit = acym_bytes(ini_get('memory_limit'));
447 - if ($serverLimit > 150000000) {
448 - return 50000;
449 - } elseif ($serverLimit > 80000000) {
450 - return 15000;
451 - } else {
452 - return 5000;
453 - }
454 - }
455 -
456 - public function getExportChangesFileName($year, $month, $extension = true)
457 - {
458 - $filename = 'export_changes_'.$year.'_'.$month;
459 -
460 - if ($extension) $filename .= '.csv';
461 -
462 - return $filename;
463 - }
464 -
465 - public function getExportChangesFilePath()
466 - {
467 - $filename = $this->getExportChangesFileName(acym_date('now', 'Y'), acym_date('now', 'm'));
468 -
469 - return acym_getLogPath($filename);
470 - }
471 -
472 - public function generateExportChangesFilePathConfigChanges()
473 - {
474 - $filename = $this->getExportChangesFileName(acym_date('now', 'Y'), acym_date('now', 'm'), false);
475 -
476 - $i = 1;
477 -
478 - $newFilename = $filename.'_'.$i.'.csv';
479 -
480 - while (file_exists(acym_getLogPath($newFilename))) {
481 - $i++;
482 - $newFilename = $filename.'_'.$i.'.csv';
483 - }
484 -
485 - return acym_getLogPath($newFilename);
486 - }
487 -
488 - public function exportChanges($user, $fieldsToExport, $fieldName, $newValue, $oldValue)
489 - {
490 - if (empty($user) || empty($fieldName)) return;
491 -
492 - $exportFullPath = $this->getExportChangesFilePath();
493 -
494 - $separator = '","';
495 - $content = '';
496 -
497 - if (!file_exists($exportFullPath)) {
498 - $columnsHeader = [];
499 - foreach ($fieldsToExport as $field) {
500 - $columnsHeader[] = $field;
501 - }
502 - $columnsHeader = array_merge(
503 - $columnsHeader,
504 - [
505 - acym_translation('ACYM_FIELD_MODIFIED'),
506 - acym_translation('ACYM_NEW_VALUE'),
507 - acym_translation('ACYM_OLD_VALUE'),
508 - acym_translation('ACYM_DATE'),
509 - ]
510 - );
511 - $content .= $this->before.implode($separator, $columnsHeader).$this->after;
512 - }
513 -
514 -
515 - $columns = [];
516 -
517 - foreach ($fieldsToExport as $field) {
518 - $columns[] = empty($user[$field]) ? '' : $user[$field];
519 - }
520 -
521 - $columns = array_merge(
522 - $columns,
523 - [
524 - $fieldName,
525 - $newValue,
526 - $oldValue,
527 - acym_date(),
528 - ]
529 - );
530 -
531 - $content .= $this->eol;
532 - $content .= $this->before.implode($separator, $columns).$this->after;
533 -
534 - file_put_contents(
535 - $exportFullPath,
536 - $content,
537 - FILE_APPEND
538 - );
539 - }
540 -
541 - public function cleanExportChangesFile()
542 - {
543 - $exportFolder = acym_getLogPath('');
544 - $files = scandir($exportFolder);
545 - if (empty($files)) return;
546 -
547 - $filenameToSearch = $this->getExportChangesFileName(acym_date('2 month ago', 'Y'), acym_date('2 month ago', 'm'), false);
548 - foreach ($files as $file) {
549 - if (strpos($file, $filenameToSearch) === false) continue;
550 - @unlink(acym_getLogPath($file));
551 - }
552 - }
553 -}