1: <?php
2:
3: 4: 5:
6: class Quform_Entry_Exporter
7: {
8: 9: 10:
11: protected $repository;
12:
13: 14: 15:
16: protected $factory;
17:
18: 19: 20:
21: protected $options;
22:
23: 24: 25: 26: 27:
28: public function __construct(Quform_Repository $repository, Quform_Form_Factory $factory, Quform_Options $options)
29: {
30: $this->repository = $repository;
31: $this->factory = $factory;
32: $this->options = $options;
33: }
34:
35: 36: 37:
38: public function getExportFieldList()
39: {
40: $formId = isset($_POST['form_id']) ? (int) $_POST['form_id'] : 0;
41:
42: if ($formId == 0) {
43: wp_send_json(array(
44: 'type' => 'error',
45: 'message' => __('Bad request', 'quform')
46: ));
47: }
48:
49: $config = $this->repository->getConfig($formId);
50:
51: if ($config === null) {
52: wp_send_json(array(
53: 'type' => 'error',
54: 'message' => __('Form not found', 'quform')
55: ));
56: }
57:
58: $form = $this->factory->create($config);
59:
60: $fieldList = array();
61:
62: foreach ($form->getRecursiveIterator() as $element) {
63: if ($element->config('saveToDatabase')) {
64: $fieldList[] = array(
65: 'label' => $element->getAdminLabel(),
66: 'identifier' => $element->getIdentifier(),
67: 'value' => 'element_' . $element->getId()
68: );
69:
70: if ($element instanceof Quform_Element_Name) {
71: foreach (Quform_Element_Name::$partKeys as $partKey => $partName) {
72: $part = $element->getPart($partKey);
73:
74: if ($part instanceof Quform_Element_Field) {
75: $namePartLabel = sprintf(
76:
77: __('%1$s [%2$s]', 'quform'),
78: $element->getAdminLabel(),
79: $this->getNameElementPartName($partKey)
80: );
81:
82: $fieldList[] = array(
83: 'label' => $namePartLabel,
84: 'identifier' => $element->getIdentifier(),
85: 'value' => 'element_' . $element->getId() . '.' . $part->getId()
86: );
87: }
88: }
89: }
90: }
91: }
92:
93: foreach ($this->getCoreEntryColumns() as $key => $label) {
94: $fieldList[] = array(
95: 'value' => $key,
96: 'label' => $label
97: );
98: }
99:
100: $fieldList = $this->sortFieldList($fieldList, $form->getId());
101:
102: $fieldList = apply_filters('quform_export_field_list', $fieldList, $form);
103: $fieldList = apply_filters('quform_export_field_list_' . $form->getId(), $fieldList, $form);
104:
105: wp_send_json(array(
106: 'type' => 'success',
107: 'data' => $fieldList
108: ));
109: }
110:
111: 112: 113: 114: 115: 116:
117: protected function getNameElementPartName($partKey)
118: {
119: $name = '';
120:
121: switch ($partKey) {
122: case 1:
123: $name = __('Prefix', 'quform');
124: break;
125: case 2:
126: $name = __('First', 'quform');
127: break;
128: case 3:
129: $name = __('Middle', 'quform');
130: break;
131: case 4:
132: $name = __('Last', 'quform');
133: break;
134: case 5:
135: $name = __('Suffix', 'quform');
136: break;
137: }
138:
139: return $name;
140: }
141:
142: 143: 144: 145: 146: 147: 148:
149: protected function sortFieldList(array $fieldList, $formId)
150: {
151: $map = get_user_meta(get_current_user_id(), 'quform_export_field_list_map', true);
152:
153: if ( ! is_array($map) || ! isset($map[$formId])) {
154: return $fieldList;
155: }
156:
157: $fields = array_reverse($map[$formId]);
158:
159: foreach ($fields as $field) {
160: foreach ($fieldList as $key => $fieldListItem) {
161: if (isset($fieldListItem['value']) && $field == $fieldListItem['value']) {
162: $swap = array_splice($fieldList, $key, 1);
163: array_splice($fieldList, 0, 0, $swap);
164: }
165: }
166: }
167:
168: return $fieldList;
169: }
170:
171: 172: 173:
174: public function saveExportFieldListOrder()
175: {
176: $formId = isset($_POST['form_id']) ? (int) $_POST['form_id'] : 0;
177: $fields = isset($_POST['fields']) && is_string($_POST['fields']) ? json_decode(stripslashes($_POST['fields']), true) : null;
178:
179: if ($formId == 0 || ! is_array($fields)) {
180: wp_send_json(array(
181: 'type' => 'error',
182: 'message' => __('Bad request', 'quform')
183: ));
184: }
185:
186: if ( ! current_user_can('quform_export_entries')) {
187: wp_send_json(array(
188: 'type' => 'error',
189: 'message' => __('Insufficient permissions', 'quform')
190: ));
191: }
192:
193: $map = get_user_meta(get_current_user_id(), 'quform_export_field_list_map', true);
194:
195: if ( ! is_array($map)) {
196: $map = array();
197: }
198:
199: $map[$formId] = $fields;
200:
201: update_user_meta(get_current_user_id(), 'quform_export_field_list_map', $map);
202:
203: wp_send_json(array('type' => 'success'));
204: }
205:
206: 207: 208: 209: 210:
211: protected function getCoreEntryColumns()
212: {
213: return array(
214: 'id' => __('Entry ID', 'quform'),
215: 'ip' => __('IP address', 'quform'),
216: 'form_url' => __('Form URL', 'quform'),
217: 'referring_url' => __('Referring URL', 'quform'),
218: 'post_id' => __('Page', 'quform'),
219: 'created_by' => __('User', 'quform'),
220: 'created_at' => __('Date', 'quform'),
221: 'updated_at' => __('Last modified', 'quform')
222: );
223: }
224:
225: 226: 227: 228: 229: 230: 231: 232: 233:
234: public function generateExportFile(Quform_Form $form, array $columns = array(), $format = array(), $from = '', $to = '')
235: {
236: $entries = $this->repository->exportEntries($form, $from, $to);
237:
238:
239: $coreColumns = $this->getCoreEntryColumns();
240: $cols = array();
241:
242: foreach ($columns as $col) {
243: if (array_key_exists($col, $coreColumns)) {
244:
245: $cols[$col] = $coreColumns[$col];
246: } elseif (strpos($col, 'element_') !== false) {
247:
248: $elementId = str_replace('element_', '', $col);
249: $partKey = null;
250: $heading = '';
251:
252: if (strpos($elementId, '.') !== false) {
253: list($elementId, $partKey) = explode('.', $elementId, 2);
254: }
255:
256: $element = $form->getElementById((int) $elementId);
257:
258: if ($element instanceof Quform_Element_Field) {
259: if ($element instanceof Quform_Element_Name && Quform::isNonEmptyString($partKey)) {
260: $part = $element->getPart($partKey);
261:
262: if ($part instanceof Quform_Element_Field) {
263: $heading = sprintf(
264:
265: __('%1$s [%2$s]', 'quform'),
266: $element->getAdminLabel(),
267: $this->getNameElementPartName($partKey)
268: );
269: }
270: } else {
271: $heading = $element->getAdminLabel();
272: }
273: }
274:
275: $cols[$col] = $heading;
276: }
277: }
278:
279: require_once QUFORM_LIBRARY_PATH . '/PhpSpreadsheet/vendor/autoload.php';
280:
281: PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder(new PhpOffice\PhpSpreadsheet\Cell\StringValueBinder());
282:
283: $spreadsheet = new PhpOffice\PhpSpreadsheet\Spreadsheet();
284:
285: try {
286: $sheet = $spreadsheet->getActiveSheet();
287: } catch (Exception $e) {
288: wp_die(esc_html__('An error occurred creating the export file.', 'quform'));
289: return;
290: }
291:
292: $headingColumnCount = 1;
293: foreach ($cols as $col) {
294: $sheet->setCellValueByColumnAndRow($headingColumnCount++, 1, $col);
295: }
296:
297: $rowCount = 2;
298:
299:
300: if (is_array($entries)) {
301: foreach ($entries as $entry) {
302: $row = array();
303: $columnCount = 1;
304:
305: foreach ($cols as $col => $label) {
306: if (strpos($col, 'element_') !== false) {
307: $entryKey = $col;
308: $elementId = str_replace('element_', '', $col);
309: $partKey = null;
310: $value = '';
311:
312: if (strpos($elementId, '.') !== false) {
313: list($elementId, $partKey) = explode('.', $elementId, 2);
314: $entryKey = "element_$elementId";
315: }
316:
317: if (isset($entry[$entryKey]) && Quform::isNonEmptyString($entry[$entryKey])) {
318: $element = $form->getElementById((int) $elementId);
319:
320: if ($element instanceof Quform_Element_Field) {
321: $element->setValueFromStorage($entry[$entryKey]);
322:
323: if ($element instanceof Quform_Element_Name && Quform::isNonEmptyString($partKey)) {
324: $part = $element->getPart($partKey);
325:
326: if ($part instanceof Quform_Element_Field) {
327: $value = $part->getValueText();
328: }
329: } else {
330: $value = $element->getValueText();
331: }
332: }
333: }
334:
335: $row[$col] = $value;
336: } else {
337: $row[$col] = isset($entry[$col]) ? $entry[$col] : '';
338:
339:
340: if ($col == 'created_at' || $col == 'updated_at') {
341: $row[$col] = $this->options->formatDate($row[$col]);
342: }
343: }
344:
345: $row[$col] = apply_filters('quform_entry_exporter_value', $row[$col], $sheet, $columnCount, $rowCount, $row, $col, $form);
346:
347: $sheet->setCellValueByColumnAndRow($columnCount, $rowCount, $row[$col]);
348: $columnCount++;
349: }
350:
351: $rowCount++;
352: }
353: }
354:
355: switch (Quform::get($format, 'type')) {
356: case 'csv':
357: default:
358: $contentType = 'text/csv';
359: $extension = '.csv';
360: $writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
361: $writer->setExcelCompatibility((bool) Quform::get($format, 'excelCompatibility', false));
362: $writer->setDelimiter(Quform::get($format, 'delimiter', ','));
363: $writer->setEnclosure(Quform::get($format, 'enclosure', '"'));
364: $writer->setUseBOM((bool) Quform::get($format, 'useBom', false));
365: $writer->setLineEnding(Quform::get($format, 'lineEndings', "\r\n"));
366: break;
367: case 'xls':
368: $contentType = 'application/vnd.ms-excel';
369: $extension = '.xls';
370: $writer = new PhpOffice\PhpSpreadsheet\Writer\Xls($spreadsheet);
371: break;
372: case 'xlsx':
373: $contentType = 'application/vnd.ms-excel';
374: $extension = '.xlsx';
375: $writer = new PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
376: break;
377: case 'ods':
378: $contentType = 'application/vnd.oasis.opendocument.spreadsheet';
379: $extension = '.ods';
380: $writer = new PhpOffice\PhpSpreadsheet\Writer\Ods($spreadsheet);
381: break;
382: case 'html':
383: $contentType = 'text/html';
384: $extension = '.html';
385: $writer = new PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet);
386: break;
387: }
388:
389:
390: header('Content-Type: ' . $contentType);
391: header('Content-Disposition: attachment; filename="' . sanitize_file_name($form->config('name')) . '-' . Quform::date('Y-m-d') . $extension . '"');
392: header('Cache-Control: private, must-revalidate, max-age=0');
393:
394:
395: try {
396: $writer->save('php://output');
397: } catch (Exception $e) {
398:
399: Quform::debug(sprintf('Failed to write entry export file: %s', $e->getMessage()));
400: }
401:
402: exit;
403: }
404: }
405: