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