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: