1: <?php
  2: 
  3:   4:   5: 
  6: class Quform_Element_Name extends Quform_Element_Field implements Quform_Element_Editable
  7: {
  8:       9:  10: 
 11:     static $partKeys = array(
 12:         1 => 'prefix',
 13:         2 => 'first',
 14:         3 => 'middle',
 15:         4 => 'last',
 16:         5 => 'suffix'
 17:     );
 18: 
 19:      20:  21: 
 22:     protected $parts = array();
 23: 
 24:      25:  26: 
 27:     protected $value = array();
 28: 
 29:      30:  31:  32:  33: 
 34:     public function setValue($value)
 35:     {
 36:         parent::setValue($value);
 37: 
 38:         $value = $this->getValue();
 39: 
 40:         foreach (self::$partKeys as $key => $slug) {
 41:             if (array_key_exists($key, $this->parts) && array_key_exists($key, $value)) {
 42:                 $this->parts[$key]->setValue($value[$key]);
 43:             }
 44:         }
 45:     }
 46: 
 47:      48:  49:  50:  51: 
 52:     public function getValue()
 53:     {
 54:         $value = $this->value;
 55: 
 56:         $this->filterValueRecursive($value);
 57: 
 58:         $value = apply_filters('quform_get_value_' . $this->getIdentifier(), $value, $this, $this->getForm());
 59: 
 60:         return $value;
 61:     }
 62: 
 63:      64:  65:  66:  67: 
 68:     public function getValueHtml()
 69:     {
 70:         $value = Quform::escape($this->getValueText());
 71: 
 72:         $value = apply_filters('quform_get_value_html_' . $this->getIdentifier(), $value, $this, $this->getForm());
 73: 
 74:         return $value;
 75:     }
 76: 
 77:      78:  79:  80:  81:  82: 
 83:     public function getValueText($separator = ', ')
 84:     {
 85:         $nonEmptyParts = array();
 86: 
 87:         foreach ($this->getValue() as $value) {
 88:             if (Quform::isNonEmptyString($value)) {
 89:                 $nonEmptyParts[] = $value;
 90:             }
 91:         }
 92: 
 93:         $value = join(' ', $nonEmptyParts);
 94: 
 95:         $value = apply_filters('quform_get_value_text_' . $this->getIdentifier(), $value, $this, $this->getForm());
 96: 
 97:         return $value;
 98:     }
 99: 
100:     101: 102: 103: 104: 105: 
106:     protected function isValidValue($value)
107:     {
108:         if ( ! is_array($value)) {
109:             return false;
110:         }
111: 
112:         foreach ($value as $key => $val) {
113:             if ( ! array_key_exists($key, self::$partKeys) || ! parent::isValidValue($val)) {
114:                 return false;
115:             }
116:         }
117: 
118:         return true;
119:     }
120: 
121:     122: 123: 124: 125: 126: 
127:     public function hasValue($value)
128:     {
129:         return $this->getValueText() === $value;
130:     }
131: 
132:     133: 134: 
135:     public function getEmptyValue()
136:     {
137:         return array();
138:     }
139: 
140:     141: 142: 143: 144: 
145:     protected function getConvertedValueForStorage()
146:     {
147:         return serialize($this->getValue());
148:     }
149: 
150:     151: 152: 153: 154: 155: 
156:     protected function convertValueFromStorage($value)
157:     {
158:         return is_serialized($value) ? unserialize($value) : $this->getEmptyValue();
159:     }
160: 
161:     162: 163: 
164:     public function isRequired()
165:     {
166:         $required = false;
167: 
168:         foreach ($this->parts as $part) {
169:             if ($part->isRequired()) {
170:                 $required = true;
171:             }
172:         }
173: 
174:         return $required;
175:     }
176: 
177:     178: 179: 180: 181: 
182:     public function isEmpty()
183:     {
184:         return $this->hasValue('');
185:     }
186: 
187:     188: 189: 190: 191: 192: 
193:     public function setPart($name, Quform_Element_Field $element)
194:     {
195:         $this->parts[$name] = $element;
196:     }
197: 
198:     199: 200: 201: 202: 203: 
204:     public function getPart($name)
205:     {
206:         return isset($this->parts[$name]) ? $this->parts[$name] : null;
207:     }
208: 
209:     210: 211: 212: 213: 
214:     public function isValid()
215:     {
216:         $this->clearErrors();
217:         $skipValidation = false;
218:         $valid = true;
219: 
220:         
221:         if ($this->isConditionallyHidden() || ! $this->isVisible()) {
222:             $skipValidation = true;
223:         }
224: 
225:         if ( ! $skipValidation) {
226:             $value = $this->getValue();
227: 
228:             foreach ($this->parts as $part) {
229:                 if ( ! $part->isValid()) {
230:                     $valid = false;
231:                 }
232:             }
233: 
234:             foreach ($this->getValidators() as $validator) {
235:                 if ($validator->isValid($value)) {
236:                     continue;
237:                 }
238: 
239:                 $this->addError($validator->getMessage());
240:                 $valid = false;
241:                 break;
242:             }
243: 
244:             $valid = apply_filters('quform_element_valid', $valid, $value, $this);
245:             $valid = apply_filters('quform_element_valid_' . $this->getIdentifier(), $valid, $value, $this);
246:         }
247: 
248:         return $valid;
249:     }
250: 
251:     252: 253: 
254:     public function hasError()
255:     {
256:         $hasError = false;
257: 
258:         if (parent::hasError()) {
259:             $hasError = true;
260:         }
261: 
262:         foreach ($this->parts as $part) {
263:             if ($part->hasError()) {
264:                 $hasError = true;
265:             }
266:         }
267: 
268:         return $hasError;
269:     }
270: 
271:     272: 273: 
274:     public function getErrorArray()
275:     {
276:         $errors = array();
277: 
278:         if (parent::hasError()) {
279:             $errors[$this->getIdentifier()] = $this->getError();
280:         }
281: 
282:         foreach ($this->parts as $part) {
283:             if ($part->hasError()) {
284:                 $errors[$part->getIdentifier()] = $part->getError();
285:             }
286:         }
287: 
288:         return $errors;
289:     }
290: 
291:     292: 293: 294: 295: 296: 297: 298: 
299:     protected function getLabelHtml(array $context = array(), $forAttribute = true, $id = false)
300:     {
301:         return parent::getLabelHtml($context, false, true);
302:     }
303: 
304:     305: 306: 307: 308: 309: 
310:     protected function getInputHtml(array $context = array())
311:     {
312:         $output = sprintf('<div class="%s">', Quform::escape(Quform::sanitizeClass($this->getInputClasses($context))));
313: 
314:         $rowClasses = array(
315:             'quform-element-row',
316:             sprintf('quform-%d-columns', count($this->parts)),
317:             Quform::isNonEmptyString($context['fieldWidth']) ? 'quform-element-row-size-float' : 'quform-element-row-size-fixed', 
318:         );
319: 
320:         if (Quform::isNonEmptyString($context['responsiveColumns']) && $context['responsiveColumns'] != 'custom') {
321:             $rowClasses[] = sprintf('quform-responsive-columns-%s', $context['responsiveColumns']);
322:         }
323: 
324:         $output .= sprintf('<div class="%s">', Quform::escape(Quform::sanitizeClass($rowClasses)));
325: 
326:         $output .= $this->getFieldHtml($context);
327: 
328:         $output .= '</div>';
329: 
330:         $output .= '</div>';
331: 
332:         return $output;
333:     }
334: 
335:     336: 337: 338: 339: 340: 
341:     protected function getFieldHtml(array $context = array())
342:     {
343:         $output = '';
344: 
345:         foreach (self::$partKeys as $key => $slug) {
346:             if ($this->config($slug . 'Enabled') && ($part = $this->getPart($key)) instanceof Quform_Element) {
347:                 $ariaLabelledby = array();
348: 
349:                 if (Quform::isNonEmptyString($this->getLabel($context))) {
350:                     $ariaLabelledby[] = $this->getUniqueId() . '_label';
351:                 }
352: 
353:                 if (Quform::isNonEmptyString($part->config('subLabelAbove'))) {
354:                     $ariaLabelledby[] = $part->getUniqueId() . '_sub_label_above';
355:                 }
356: 
357:                 if (Quform::isNonEmptyString($part->config('subLabel'))) {
358:                     $ariaLabelledby[] = $part->getUniqueId() . '_sub_label_below';
359:                 }
360: 
361:                 if (count($ariaLabelledby)) {
362:                     $part->setConfig('aria-labelledby', join(' ', $ariaLabelledby));
363:                 }
364: 
365:                 $output .= sprintf('<div class="quform-element-column">%s</div>', $part->render($context));
366:             }
367:         }
368: 
369:         return $output;
370:     }
371: 
372:     373: 374: 375: 376: 
377:     public function getEditFieldHtml()
378:     {
379:         $output = sprintf('<div class="qfb-edit-name-row qfb-edit-name-row-%d">', count($this->parts));
380: 
381:         foreach (self::$partKeys as $key => $slug) {
382:             if ($this->config($slug . 'Enabled') && $this->getPart($key) instanceof Quform_Element_Editable) {
383:                 $part = $this->getPart($key);
384: 
385:                 $output .= sprintf(
386:                     '<div class="qfb-edit-name-column"><div class="qfb-edit-element qfb-edit-element-%1$s"><div class="qfb-edit-input qfb-edit-input-%1$s">%2$s</div></div></div>',
387:                     $part->getIdentifier(),
388:                     $part->getEditFieldHtml()
389:                 );
390:             }
391:         }
392: 
393:         $output .= '</div>';
394: 
395:         return $output;
396:     }
397: 
398:     399: 400: 401: 402: 403: 
404:     protected function renderCss(array $context = array())
405:     {
406:         $css = parent::renderCss($context);
407: 
408:         if ($context['fieldWidth'] == 'custom' && Quform::isNonEmptyString($context['fieldWidthCustom'])) {
409:             $css .= sprintf('.quform-input-name.quform-input-%s { width: %s; }', $this->getIdentifier(), Quform::addCssUnit($context['fieldWidthCustom']));
410:             $css .= sprintf('.quform-input-name.quform-input-%s .quform-inner > .quform-input { width: 100%% !important; }', $this->getIdentifier(), Quform::addCssUnit($context['fieldWidthCustom']));
411:             $css .= sprintf('.quform-inner-%s > .quform-error > .quform-error-inner { float: left; min-width: %s; }', $this->getIdentifier(), Quform::addCssUnit($context['fieldWidthCustom']));
412:         }
413: 
414:         if ($context['responsiveColumns'] == 'custom' && Quform::isNonEmptyString($context['responsiveColumnsCustom'])) {
415:             $css .= sprintf(
416:                 '@media (max-width: %s) { .quform-input-%s > .quform-element-row > .quform-element-column { float: none; width: 100%% !important; } }',
417:                 Quform::addCssUnit($context['responsiveColumnsCustom']),
418:                 $this->getIdentifier()
419:             );
420:         }
421: 
422:         foreach ($this->parts as $part) {
423:             $css .= $part->getCss($context);
424:         }
425: 
426:         return $css;
427:     }
428: 
429:     430: 431: 432: 433: 434: 
435:     protected function prepareContext(array $context = array())
436:     {
437:         $context = parent::prepareContext($context);
438: 
439:         
440:         if ( ! in_array($context['labelPosition'], array('', 'left'), true)) {
441:             $context['labelPosition'] = '';
442:         }
443: 
444:         
445:         $context['tooltipType'] = 'icon';
446: 
447:         if (is_string($this->config('responsiveColumns'))) {
448:             if ($this->config('responsiveColumns') != 'inherit') {
449:                 $context['responsiveColumns'] = $this->config('responsiveColumns');
450: 
451:                 if ($this->config('responsiveColumns') == 'custom' && Quform::isNonEmptyString($this->config('responsiveColumnsCustom'))) {
452:                     $context['responsiveColumnsCustom'] = $this->config('responsiveColumnsCustom');
453:                 }
454:             }
455:         }
456: 
457:         return $context;
458:     }
459: 
460:     461: 462: 463: 464: 465: 
466:     public static function getDefaultConfig($key = null)
467:     {
468:         $config = apply_filters('quform_default_config_name', array(
469:             
470:             'label' => __('Name', 'quform'),
471:             'description' => '',
472:             'descriptionAbove' => '',
473:             'prefixEnabled' => false,
474:             'prefixRequired' => false,
475:             'prefixOptions' => array(
476:                 array('id' => 1, 'label' => __('Mr', 'quform'), 'value' => __('Mr', 'quform')),
477:                 array('id' => 2, 'label' => __('Mrs', 'quform'), 'value' => __('Mrs', 'quform')),
478:                 array('id' => 3, 'label' => __('Ms', 'quform'), 'value' => __('Ms', 'quform')),
479:                 array('id' => 4, 'label' => __('Miss', 'quform'), 'value' => __('Miss', 'quform')),
480:                 array('id' => 5, 'label' => __('Dr', 'quform'), 'value' => __('Dr', 'quform')),
481:             ),
482:             'prefixNextOptionId' => 6,
483:             'prefixDefaultValue' => '',
484:             'prefixCustomiseValues' => false,
485:             'prefixNoneOption' => true,
486:             'prefixSubLabel' => __('Prefix', 'quform'),
487:             'prefixSubLabelAbove' => '',
488:             'prefixCustomClass' => '',
489:             'prefixCustomElementClass' => '',
490:             'firstEnabled' => true,
491:             'firstRequired' => false,
492:             'firstPlaceholder' => '',
493:             'firstSubLabel' => __('First', 'quform'),
494:             'firstSubLabelAbove' => '',
495:             'firstDefaultValue' => '',
496:             'firstCustomClass' => '',
497:             'firstCustomElementClass' => '',
498:             'firstAutocomplete' => '',
499:             'middleEnabled' => false,
500:             'middleRequired' => false,
501:             'middlePlaceholder' => '',
502:             'middleSubLabel' => __('Middle', 'quform'),
503:             'middleSubLabelAbove' => '',
504:             'middleDefaultValue' => '',
505:             'middleCustomClass' => '',
506:             'middleCustomElementClass' => '',
507:             'middleAutocomplete' => '',
508:             'lastEnabled' => true,
509:             'lastRequired' => false,
510:             'lastPlaceholder' => '',
511:             'lastSubLabel' => __('Last', 'quform'),
512:             'lastSubLabelAbove' => '',
513:             'lastDefaultValue' => '',
514:             'lastCustomClass' => '',
515:             'lastCustomElementClass' => '',
516:             'lastAutocomplete' => '',
517:             'suffixEnabled' => false,
518:             'suffixRequired' => false,
519:             'suffixPlaceholder' => '',
520:             'suffixSubLabel' => __('Suffix', 'quform'),
521:             'suffixSubLabelAbove' => '',
522:             'suffixDefaultValue' => '',
523:             'suffixCustomClass' => '',
524:             'suffixCustomElementClass' => '',
525: 
526:             
527:             'labelIcon' => '',
528:             'fieldSize' => 'inherit',
529:             'fieldWidth' => 'inherit',
530:             'fieldWidthCustom' => '',
531:             'responsiveColumns' => 'inherit',
532:             'responsiveColumnsCustom' => '',
533:             'customClass' => '',
534:             'customElementClass' => '',
535:             'styles' => array(),
536: 
537:             
538:             'subLabel' => '',
539:             'subLabelAbove' => '',
540:             'adminLabel' => '',
541:             'tooltip' => '',
542:             'tooltipType' => 'icon',
543:             'tooltipEvent' => 'inherit',
544:             'labelPosition' => 'inherit',
545:             'labelWidth' => '',
546: 
547:             
548:             'logicEnabled' => false,
549:             'logicAction' => true,
550:             'logicMatch' => 'all',
551:             'logicRules' => array(),
552: 
553:             
554:             'dynamicDefaultValue' => false,
555:             'dynamicKey' => '',
556:             'showInEmail' => true,
557:             'saveToDatabase' => true,
558: 
559:             
560:             'visibility' => '',
561:             'validators' => array(),
562: 
563:             
564:             'prefixNoneOptionText' => '',
565:             'messageRequired' => ''
566:         ));
567: 
568:         $config['type'] = 'name';
569: 
570:         if (Quform::isNonEmptyString($key)) {
571:             return Quform::get($config, $key);
572:         }
573: 
574:         return $config;
575:     }
576: }
577: