1: <?php
2:
3: 4: 5:
6: class Quform_Element_File extends Quform_Element_Field implements Quform_Attachable, Quform_Element_Editable
7: {
8: 9: 10: 11:
12: protected $value = array();
13:
14: 15: 16:
17: protected $isMultiple = true;
18:
19: 20: 21: 22: 23:
24: public function isValid()
25: {
26: $this->clearErrors();
27: $skipValidation = false;
28: $valid = true;
29:
30:
31: if ( ! $this->isRequired()) {
32: if ( ! array_key_exists($this->getName(), $_FILES)) {
33: $skipValidation = true;
34: }
35: }
36:
37:
38: if ($this->isConditionallyHidden() || ! $this->isVisible()) {
39: $skipValidation = true;
40: }
41:
42: if ( ! $skipValidation) {
43: $value = $this->getValue();
44:
45: foreach ($this->getValidators() as $validator) {
46: if ($validator->isValid($value)) {
47: continue;
48: }
49:
50: $this->addError($validator->getMessage());
51: $valid = false;
52: break;
53: }
54:
55: $valid = apply_filters('quform_element_valid', $valid, $value, $this);
56: $valid = apply_filters('quform_element_valid_' . $this->getIdentifier(), $valid, $value, $this);
57: }
58:
59: return $valid;
60: }
61:
62: 63: 64:
65: public function getFileUploadValidator()
66: {
67: return $this->getValidator('fileUpload');
68: }
69:
70: 71: 72: 73: 74:
75: public function isRequired()
76: {
77: return $this->getFileUploadValidator()->config('required');
78: }
79:
80: 81: 82:
83: public function getEmptyValue()
84: {
85: return array();
86: }
87:
88: 89: 90: 91: 92:
93: public function getValue()
94: {
95: $value = apply_filters('quform_get_value_' . $this->getIdentifier(), $this->value, $this, $this->getForm());
96:
97: return $value;
98: }
99:
100: 101: 102: 103: 104:
105: public function getValueHtml()
106: {
107: $value = '';
108:
109: if ( ! $this->isEmpty()) {
110: $ulStyle = apply_filters('quform_value_list_file_ul_style', 'margin:0;padding:0;list-style:disc inside;', $this, $this->getForm());
111: $ulStyle = apply_filters('quform_value_list_file_ul_style_' . $this->getIdentifier(), $ulStyle, $this, $this->getForm());
112:
113: $liStyle = apply_filters('quform_value_list_file_li_style', '', $this, $this->getForm());
114: $liStyle = apply_filters('quform_value_list_file_li_style_' . $this->getIdentifier(), $liStyle, $this, $this->getForm());
115:
116: $value = sprintf(
117: '<ul class="quform-value-list quform-value-list-file"%s>',
118: Quform::isNonEmptyString($ulStyle) ? ' style="' . esc_attr($ulStyle) . '"' : ''
119: );
120:
121: foreach ($this->getValue() as $file) {
122: $value .= sprintf(
123: '<li class="quform-value-list-item quform-value-list-item-file"%s>',
124: Quform::isNonEmptyString($liStyle) ? ' style="' . esc_attr($liStyle) . '"' : ''
125: );
126:
127: if (isset($file['url'])) {
128: $value .= '<a href="' . esc_url(apply_filters('quform_file_value_url', $file['url'], $file, $this)) . '">' . Quform::escape($file['name']) . '</a>';
129: } else {
130: $value .= Quform::escape($file['name']);
131: }
132:
133: $value .= '</li>';
134: }
135:
136: $value .= '</ul>';
137: }
138:
139: $value = apply_filters('quform_get_value_html_' . $this->getIdentifier(), $value, $this, $this->getForm());
140:
141: return $value;
142: }
143:
144: 145: 146: 147: 148: 149:
150: public function getValueText($separator = ', ')
151: {
152: $value = '';
153:
154: if ( ! $this->isEmpty()) {
155: $files = array();
156:
157: foreach ($this->getValue() as $file) {
158: if (isset($file['url'])) {
159: $files[] = apply_filters('quform_file_value_url', $file['url'], $file, $this);
160: } else {
161: $files[] = $file['name'];
162: }
163: }
164:
165: $value = join($separator, $files);
166: }
167:
168: $value = apply_filters('quform_get_value_text_' . $this->getIdentifier(), $value, $this, $this->getForm());
169:
170: return $value;
171: }
172:
173: 174: 175: 176: 177:
178: public function addFile($file)
179: {
180: if ($this->isValidFile($file)) {
181: $this->value[] = $file;
182: }
183: }
184:
185: 186: 187: 188:
189: protected function isValidValue($value)
190: {
191: if ( ! is_array($value)) {
192: return false;
193: }
194:
195: foreach ($value as $val) {
196: if ( ! $this->isValidFile($val)) {
197: return false;
198: }
199: }
200:
201: return true;
202: }
203:
204: 205: 206: 207: 208: 209:
210: protected function isValidFile($file)
211: {
212: if ( ! is_array($file)) {
213: return false;
214: }
215:
216: foreach ($file as $data) {
217: if ( ! is_string($data) && ! is_int($data)) {
218: return false;
219: }
220: }
221:
222: return true;
223: }
224:
225: 226: 227: 228: 229:
230: protected function getConvertedValueForStorage()
231: {
232: return serialize($this->getValue());
233: }
234:
235: 236: 237: 238: 239: 240:
241: protected function convertValueFromStorage($value)
242: {
243: return is_serialized($value) ? unserialize($value) : $this->getEmptyValue();
244: }
245:
246: 247: 248: 249: 250: 251:
252: protected function getFieldAttributes(array $context = array())
253: {
254: $attributes = array(
255: 'type' => 'file',
256: 'id' => $this->getUniqueId(),
257: 'name' => $this->getFullyQualifiedName(),
258: 'class' => Quform::sanitizeClass($this->getFieldClasses($context))
259: );
260:
261: $validator = $this->getFileUploadValidator();
262:
263: if ($validator->config('maximumNumberOfFiles') !== 1) {
264: $attributes['multiple'] = true;
265: }
266:
267: if ($this->form->config('ajax') && $this->config('enhancedUploadEnabled')) {
268: $attributes['data-config'] = wp_json_encode($this->getUploaderConfig());
269: }
270:
271: $attributes = apply_filters('quform_field_attributes', $attributes, $this, $this->form, $context);
272: $attributes = apply_filters('quform_field_attributes_' . $this->getIdentifier(), $attributes, $this, $this->form, $context);
273:
274: return $attributes;
275: }
276:
277: 278: 279: 280: 281: 282:
283: protected function getFieldClasses(array $context = array())
284: {
285: $classes = array(
286: 'quform-field',
287: 'quform-field-file',
288: sprintf('quform-field-%s', $this->getIdentifier())
289: );
290:
291: if ($this->form->config('ajax') && $this->config('enhancedUploadEnabled')) {
292: $classes[] = 'quform-field-file-enhanced';
293: }
294:
295: if (Quform::isNonEmptyString($this->config('customClass'))) {
296: $classes[] = $this->config('customClass');
297: }
298:
299: $classes = apply_filters('quform_field_classes', $classes, $this, $this->form, $context);
300: $classes = apply_filters('quform_field_classes_' . $this->getIdentifier(), $classes, $this, $this->form, $context);
301:
302: return $classes;
303: }
304:
305: 306: 307: 308: 309:
310: protected function getUploaderConfig()
311: {
312: $validator = $this->getFileUploadValidator();
313:
314: $config = array(
315: 'id' => $this->getId(),
316: 'identifier' => $this->getIdentifier(),
317: 'name' => $this->getName(),
318: 'max' => $validator->config('maximumNumberOfFiles'),
319: 'size' => $validator->config('maximumFileSize'),
320: 'allowedExtensions' => $validator->config('allowedExtensions'),
321: 'notAllowedTypeWithFilename' => $validator->createMessage(Quform_Validator_FileUpload::NOT_ALLOWED_TYPE_FILENAME),
322: 'tooBigWithFilename' => $validator->createMessage(Quform_Validator_FileUpload::TOO_BIG_FILENAME),
323: 'tooMany' => $validator->createMessage(Quform_Validator_FileUpload::TOO_MANY),
324: 'buttonType' => $this->config('enhancedUploadStyle'),
325: 'buttonText' => $this->getTranslation('browseText', _x('Browse...', 'for a file to upload', 'quform')),
326: 'buttonIcon' => $this->config('buttonIcon'),
327: 'buttonIconPosition' => $this->config('buttonIconPosition')
328: );
329:
330: return $config;
331: }
332:
333: 334: 335: 336: 337: 338:
339: protected function getFieldHtml(array $context = array())
340: {
341: return Quform::getHtmlTag('input', $this->getFieldAttributes($context));
342: }
343:
344: 345: 346: 347: 348: 349:
350: protected function getInnerClasses(array $context = array())
351: {
352: $classes = parent::getInnerClasses($context);
353:
354: if (Quform::isNonEmptyString($this->config('uploadListLayout'))) {
355: $classes[] = sprintf('quform-upload-files-%s', $this->config('uploadListLayout'));
356: }
357:
358: if (Quform::isNonEmptyString($this->config('uploadListSize'))) {
359: $classes[] = sprintf('quform-upload-files-size-%s', $this->config('uploadListSize'));
360: }
361:
362: return $classes;
363: }
364:
365: 366: 367: 368: 369: 370:
371: protected function getInputClasses(array $context = array())
372: {
373: $classes = parent::getInputClasses($context);
374:
375: if (Quform::isNonEmptyString($context['buttonStyle'])) {
376: $classes[] = sprintf('quform-button-style-%s', $context['buttonStyle']);
377: }
378:
379: if (Quform::isNonEmptyString($context['buttonSize'])) {
380: $classes[] = sprintf('quform-button-size-%s', $context['buttonSize']);
381: }
382:
383: if (Quform::isNonEmptyString($context['buttonWidth']) && $context['buttonWidth'] != 'custom') {
384: $classes[] = sprintf('quform-button-width-%s', $context['buttonWidth']);
385: }
386:
387: return $classes;
388: }
389:
390: 391: 392: 393: 394: 395:
396: protected function getInputHtml(array $context = array())
397: {
398: $output = sprintf('<div class="%s">', Quform::escape(Quform::sanitizeClass($this->getInputClasses($context))));
399: $output .= $this->getFieldHtml();
400: $output .= '</div>';
401:
402: if ( ! $this->isEmpty()) {
403: $output .= '<div class="quform-upload-files quform-cf">';
404:
405: foreach ($this->getValue() as $file) {
406: $output .= sprintf(
407: '<div class="quform-upload-file"><span class="quform-upload-file-name">%s</span></div>',
408: Quform::escape($file['name'])
409: );
410: }
411:
412: $output .= '</div>';
413: }
414:
415: return $output;
416: }
417:
418: 419: 420: 421: 422:
423: public function getEditFieldHtml()
424: {
425: $output = sprintf('<div class="qfb-edit-file-uploads%s">', count($this->getValue()) ? '' : ' qfb-hidden');
426:
427: foreach ($this->getValue() as $file) {
428: $output .= sprintf(
429: '<div class="qfb-edit-file-upload qfb-cf" data-quform-upload-uid="%s"><div class="qfb-edit-file-upload-inner">',
430: $file['quform_upload_uid']
431: );
432:
433: $output .= sprintf(
434: '<span class="qfb-edit-file-upload-name">%s</span>',
435: Quform::escape($file['name'])
436: );
437:
438: $output .= sprintf(
439: '<span class="qfb-edit-file-upload-remove" title="%s"><i class="qfb-icon qfb-icon-trash"></i></span>',
440: esc_attr__('Remove this file', 'quform')
441: );
442:
443: $output .= '</div></div>';
444: }
445:
446: $output .= '</div>';
447:
448: $output .= $this->getFieldHtml();
449:
450: return $output;
451: }
452:
453: 454: 455:
456: public function hasAttachments()
457: {
458: return count($this->getAttachments()) > 0;
459: }
460:
461: 462: 463:
464: public function getAttachments()
465: {
466: $attachments = array();
467:
468: foreach ($this->getValue() as $file) {
469: $attachments[] = $file['path'];
470: }
471:
472: return $attachments;
473: }
474:
475: 476: 477: 478: 479: 480:
481: protected function renderCss(array $context = array())
482: {
483: $css = parent::renderCss($context);
484:
485: if ($context['fieldWidth'] == 'custom' && Quform::isNonEmptyString($context['fieldWidthCustom'])) {
486: $css .= sprintf('.quform-input-file.quform-input-%1$s, .quform-enhanced-upload .quform-input-file.quform-input-%1$s .quform-upload-dropzone { width: %2$s; }', $this->getIdentifier(), Quform::addCssUnit($context['fieldWidthCustom']));
487: $css .= sprintf('.quform-inner-%s > .quform-error > .quform-error-inner { float: left; min-width: %s; }', $this->getIdentifier(), Quform::addCssUnit($context['fieldWidthCustom']));
488: }
489:
490: if ($context['buttonWidth'] == 'custom' && Quform::isNonEmptyString($context['buttonWidthCustom'])) {
491: $css .= sprintf('.quform-input-file.quform-input-%s > .quform-upload-button { width: %s; }', $this->getIdentifier(), Quform::addCssUnit($context['buttonWidthCustom']));
492: }
493:
494: return $css;
495: }
496:
497: 498: 499: 500: 501:
502: protected function getCssSelectors()
503: {
504: return parent::getCssSelectors() + array(
505: 'uploadButton' => '%s .quform-input-%s .quform-upload-button',
506: 'uploadButtonHover' => '%s .quform-input-%s .quform-upload-button:hover',
507: 'uploadButtonActive' => '%s .quform-input-%s .quform-upload-button:active',
508: 'uploadButtonText' => '%s .quform-input-%s .quform-upload-button .quform-upload-button-text',
509: 'uploadButtonTextHover' => '%s .quform-input-%s .quform-upload-button:hover .quform-upload-button-text',
510: 'uploadButtonTextActive' => '%s .quform-input-%s .quform-upload-button:active .quform-upload-button-text',
511: 'uploadButtonIcon' => '%s .quform-input-%s .quform-upload-button .quform-upload-button-icon',
512: 'uploadButtonIconHover' => '%s .quform-input-%s .quform-upload-button:hover .quform-upload-button-icon',
513: 'uploadButtonIconActive' => '%s .quform-input-%s .quform-upload-button:active .quform-upload-button-icon',
514: 'uploadDropzone' => '%s .quform-input-%s .quform-upload-dropzone',
515: 'uploadDropzoneHover' => '%s .quform-input-%s .quform-upload-dropzone:hover',
516: 'uploadDropzoneActive' => '%s .quform-input-%s .quform-upload-dropzone:active',
517: 'uploadDropzoneText' => '%s .quform-input-%s .quform-upload-dropzone .quform-upload-dropzone-text',
518: 'uploadDropzoneTextHover' => '%s .quform-input-%s .quform-upload-dropzone:hover .quform-upload-dropzone-text',
519: 'uploadDropzoneTextActive' => '%s .quform-input-%s .quform-upload-dropzone:active .quform-upload-dropzone-text',
520: 'uploadDropzoneIcon' => '%s .quform-input-%s .quform-upload-dropzone .quform-upload-dropzone-icon',
521: 'uploadDropzoneIconHover' => '%s .quform-input-%s .quform-upload-dropzone:hover .quform-upload-dropzone-icon',
522: 'uploadDropzoneIconActive' => '%s .quform-input-%s .quform-upload-dropzone:active .quform-upload-dropzone-icon'
523: );
524: }
525:
526: 527: 528: 529: 530: 531:
532: protected function prepareContext(array $context = array())
533: {
534: $context = parent::prepareContext($context);
535:
536:
537: if ( ! in_array($context['labelPosition'], array('', 'left'), true)) {
538: $context['labelPosition'] = '';
539: }
540:
541:
542: $context['tooltipType'] = 'icon';
543:
544: return $context;
545: }
546:
547: 548: 549: 550: 551: 552:
553: public static function getDefaultConfig($key = null)
554: {
555: $config = apply_filters('quform_default_config_file', array(
556:
557: 'label' => __('Upload', 'quform'),
558: 'description' => '',
559: 'descriptionAbove' => '',
560: 'required' => false,
561:
562:
563: 'labelIcon' => '',
564: 'enhancedUploadEnabled' => true,
565: 'enhancedUploadStyle' => 'button',
566: 'buttonStyle' => 'inherit',
567: 'buttonSize' => 'inherit',
568: 'buttonWidth' => 'inherit',
569: 'buttonWidthCustom' => '',
570: 'buttonIcon' => 'qicon-file_upload',
571: 'buttonIconPosition' => 'right',
572: 'uploadListLayout' => '',
573: 'uploadListSize' => '',
574: 'fieldWidth' => 'inherit',
575: 'fieldWidthCustom' => '',
576: 'customClass' => '',
577: 'customElementClass' => '',
578: 'styles' => array(),
579:
580:
581: 'subLabel' => '',
582: 'subLabelAbove' => '',
583: 'adminLabel' => '',
584: 'tooltip' => '',
585: 'tooltipType' => 'icon',
586: 'tooltipEvent' => 'inherit',
587: 'labelPosition' => 'inherit',
588: 'labelWidth' => '',
589:
590:
591: 'logicEnabled' => false,
592: 'logicAction' => true,
593: 'logicMatch' => 'all',
594: 'logicRules' => array(),
595:
596:
597: 'minimumNumberOfFiles' => '0',
598: 'maximumNumberOfFiles' => '1',
599: 'allowedExtensions' => 'jpg, jpeg, png, gif',
600: 'maximumFileSize' => '10',
601: 'saveToServer' => true,
602: 'savePath' => 'quform/{form_id}-{upload_security_token}/{year}/{month}/',
603: 'addToMediaLibrary' => false,
604: 'showInEmail' => true,
605: 'saveToDatabase' => true,
606:
607:
608: 'visibility' => '',
609:
610:
611: 'browseText' => '',
612: 'messageFileUploadRequired' => '',
613: 'messageFileNumRequired' => '',
614: 'messageFileTooMany' => '',
615: 'messageFileTooBigFilename' => '',
616: 'messageFileTooBig' => '',
617: 'messageNotAllowedTypeFilename' => '',
618: 'messageNotAllowedType' => ''
619: ));
620:
621: $config['type'] = 'file';
622:
623: if (Quform::isNonEmptyString($key)) {
624: return Quform::get($config, $key);
625: }
626:
627: return $config;
628: }
629: }
630: