init_defaults(); } private function init_defaults() { $this->field_dir = '/wpforo/users/fields/'; $this->default = [ 'label' => '', 'title' => '', 'name' => '', 'value' => '', 'values' => '', 'type' => 'text', 'placeholder' => '', 'description' => '', 'id' => '', 'class' => '', 'attributes' => '', 'isDefault' => 0, 'isWrapItem' => '', 'isLabelFirst' => '', 'isDisabled' => 0, 'isEditable' => 1, 'isRequired' => 0, 'isMultiChoice' => 0, 'isAllowedCustomValues' => 0, 'UGroupIdsFrontAddNewDefaultValues' => [], 'isOnlyForGuests' => 0, 'isRemovable' => 1, 'isSearchable' => 0, 'allowedGroupIds' => [], 'fileExtensions' => '', 'fileSize' => 1, 'minLength' => 0, 'maxLength' => 0, 'faIcon' => '', 'html' => '', 'varname' => '', 'template' => '', 'cantBeInactive' => [], 'canEdit' => [ 1 ], 'canView' => [ 1, 2, 3, 5 ], 'can' => '', 'isDisplayDefaultValues' => 0, ]; } public function fix_field( $field ) { return wpforo_array_args_cast_and_merge( (array) $field, $this->default ); } /** * Form builder * for form layout and field building * * @param array $fields associative multi-level array * * @return string form HTML */ public function build( $fields ) { if( empty( $fields ) ) return ''; $html = ''; foreach( $fields as $row_key => $row ) { $row_class = "row-$row_key " . apply_filters( 'wpforo_row_classes', '', $row_key ); $html .= '
'; foreach( $row as $col_key => $col ) { $col_class_field = ''; foreach( $col as $field ) { $col_class_field .= ' wpf-row-' . wpfval( $field, 'name' ); } reset( $col ); $col_class = "row_$row_key-col_$col_key " . $col_class_field . ' ' . apply_filters( 'wpforo_col_classes', '', $row_key, $col_key ); $html .= '
'; foreach( $col as $field ) { if( ! empty( $field ) ) $html .= $this->build_field( $field ); } $html .= '
'; } $html .= '
'; } return $html; } /** * Builds field with input HTML and wrapper divs * * @param array $args field arguments * * @return string field HTML */ public function build_field( $args ) { if( is_string( $args ) ) $args = WPF()->member->get_field( $args ); $html = ''; if( ! is_array( $args ) || empty( $args ) ) return ''; $f = wpforo_parse_args( $args, $this->default ); $f = $this->prepare_args( $f ); //Get field input tag $field_html = $this->field( $f ); //Wrapping field input if( $f['template'] === 'register' ) { if( $this->can_add( $f ) ) { $html = $this->field_wrap_register( $field_html, $f ); } } elseif( $f['template'] === 'account' ) { if( $this->can_edit( $f ) ) { $html = $this->field_wrap_account( $field_html, $f ); } } elseif( $f['template'] === 'profile' ) { if( $this->can_view( $f ) && $this->can_show_value( $f ) ) { $f = $this->esc_field( $f ); $html = $this->field_wrap_profile( $field_html, $f ); } } elseif( $f['template'] === 'members' ) { if( $this->can_show_value( $f ) ) $html = $this->field_wrap_members( $field_html, $f ); } else { $html = $this->field_wrap_default( $field_html, $f ); } return $html; } /** * Field input HTML builder * * @param array $f field arguments * * @return string field input HTML */ public function field( $f ) { $f = $this->prepare_field_args( $f ); $f = apply_filters( 'wpforo_form_field', $f ); switch( $f['type'] ) { case 'url': $field_html = $this->field_url( $f ); break; case 'file': $field_html = $this->field_file( $f ); break; case 'html': $field_html = $this->field_html( $f ); break; case 'radio': $field_html = $this->field_radio( $f ); break; case 'select': $field_html = $this->field_select( $f ); break; case 'avatar': $field_html = $this->field_avatar( $f ); break; case 'textarea': $field_html = $this->field_textarea( $f ); break; case 'tinymce': $field_html = $this->field_tinymce( $f ); break; case 'password': $field_html = $this->field_password( $f ); break; case 'checkbox': $field_html = $this->field_checkbox( $f ); break; case 'usergroup': $field_html = $this->field_usergroup( $f ); break; case 'secondary_groups': $field_html = $this->field_secondary_groups( $f ); break; case 'user_nicename': $field_html = $this->field_nicename( $f ); break; case 'tel': $field_html = $this->field_tel( $f ); break; case 'autocomplete': $field_html = $this->field_autocomplete( $f ); break; default: $field_html = $this->field_text( $f ); } return apply_filters( 'wpforo_form_field_html', $field_html, $f ); } /** * Wraps input HTML for Registration form * * @param string $field_html input HTML * @param array $f field arguments * * @return string wrapped field input HTML */ public function field_wrap_register( $field_html, $f ) { $html = '
'; if( $f['type'] !== 'html' ) { if( $f['label'] || $f['description'] ) { $html .= '
'; if( $f['label'] ) { $html .= '

' . $f['label'] . $f['required_indicator'] . '

'; } if( $f['description'] ) { $html .= '
' . $f['description'] . '
'; } $html .= '
'; } $html .= '
'; if( $f['faIcon'] ) { $html .= ''; } $html .= $field_html; $html .= '
'; } else { $html .= $field_html; } $html .= '
'; return $html; } /** * Wraps input HTML for Account form * * @param string $field_html input HTML * @param array $f field arguments * * @return string wrapped field input HTML */ public function field_wrap_account( $field_html, $f ) { $html = '
'; if( $f['type'] === 'html' ) { $html .= $field_html; } elseif( $f['name'] === 'user_login' ) { $html .= '
'; $html .= '

' . stripslashes( (string) $f['label'] ) . '

'; $html .= '
'; $html .= '
'; $html .= '' . $f['value'] . ''; $html .= '
'; } elseif( $f['type'] !== 'password' && ! $f['isEditable'] && ! $this->can_moderate( $f ) && WPF()->current_user_groupid !== 1 ) { $f = $this->esc_field( $f ); $html .= '
'; $html .= '

' . stripslashes( (string) $f['label'] ) . '

'; $html .= '
'; $html .= '
'; $html .= ' ' . $f['value'] . ''; $html .= '
'; } else { if( $f['label'] || $f['description'] ) { $html .= '
'; if( $f['label'] ) { $html .= '

' . stripslashes( (string) $f['label'] ) . $f['required_indicator'] . '

'; } if( $f['description'] ) { $html .= '
' . $f['description'] . '
'; } $html .= '
'; } $html .= '
'; if( $f['faIcon'] ) { $html .= ''; } $html .= $field_html; $html .= '
'; } $html .= '
'; return $html; } /** * Wraps input HTML for Profile page * * @param string $field_html input HTML * @param array $f field arguments * * @return string wrapped field input HTML */ public function field_wrap_profile( $field_html, $f ) { if( ! in_array( $f['type'], [ 'html', 'avatar' ] ) && ! ( $f['isRequired'] && $f['isDisplayDefaultValues'] ) && ( ! isset( $f['value'] ) || ( ! is_numeric( $f['value'] ) && empty( $f['value'] ) ) ) ) { return false; } $html = '
'; if( $f['type'] !== 'html' ) { if( ! $f['faIcon'] ) { $f['faIcon'] = 'fas fa-address-card'; } if( $f['label'] ) { $html .= '

' . $f['label'] . '

'; } if( $f['type'] === 'avatar' || ( isset( $f['value'] ) && ! empty( $f['value'] ) ) ) { if( is_array( $f['value'] ) ) { $html .= esc_html( implode( ', ', $f['value'] ) ); } else { $f = $this->prepare_values( $f, WPF()->current_object['userid'] ); $html .= '
'; $html .= $f['value']; $html .= '
'; } } else { if( $default_values = wpforo_preg_grep_recursive( '#^\[.+?]$#isu', $f['values'] ) ) { $_html = ''; foreach( $default_values as $default_key => $default_value ) { if( ! is_array( $default_value ) ) { $item = $this->build_item_value_lable( $default_value ); $_html .= $item['label'] . ', '; } else { $csv = ''; foreach( $default_value as $_default_value ) { if( ! is_array( $_default_value ) ) { $item = $this->build_item_value_lable( $_default_value ); $csv .= $item['label'] . ', '; } } $_html .= trim( (string) $default_key ) . '( ' . trim( (string) $csv, ', ' ) . ' ), '; } } $html .= sprintf( '
%1$s
', trim( (string) $_html, ', ' ) ); } else { return false; } } } else { $html .= $field_html; } $html .= '
'; return $html; } /** * Wraps input HTML for Members Search form * * @param string $field_html input HTML * @param array $f field arguments * * @return string wrapped field input HTML */ public function field_wrap_members( $field_html, $f ) { $html = '
'; if( $f['type'] === 'html' ) { $html .= $field_html; } else { if( $f['label'] || $f['description'] ) { $html .= '
'; if( $f['label'] ) { $html .= '

' . stripslashes( (string) $f['label'] ) . $f['required_indicator'] . '

'; } if( $f['description'] ) { $html .= '
' . $f['description'] . '
'; } $html .= '
'; } $html .= '
'; if( $f['faIcon'] ) { $html .= ''; } $html .= $field_html; $html .= '
'; } $html .= '
'; return $html; } /** * Default wrapper of input HTML * * @param string $field_html input HTML * @param array $f field arguments * * @return string wrapped field input HTML */ public function field_wrap_default( $field_html, $f ) { $html = '
'; if( $f['type'] === 'html' ) { $html .= $field_html; } else { if( $f['label'] || $f['description'] ) { $html .= '
'; if( $f['faIcon'] ) $html .= ''; if( $f['label'] ) { $html .= '

' . stripslashes( (string) $f['label'] ) . $f['required_indicator'] . '

'; } if( wpfval( $f, 'type' ) === 'file' && ( $file_size = wpfval( $f, 'fileSize' ) ) ) { $html .= ' (' . wpforo_phrase( 'max allowed file size', false, 'lower' ) . ' ' . $file_size . 'MB)'; } if( $f['description'] ) { $html .= '
' . $f['description'] . '
'; } $html .= '
'; } else { if( $f['faIcon'] ) $html .= ''; } $html .= '
'; $html .= $field_html; $html .= '
'; } $html .= '
'; return $html; } /** * File - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_file( $f ) { $field_html = ''; $extensions = ''; if( $f['fileExtensions'] ) { foreach( $f['fileExtensions'] as $key => $ext ) { if( strpos( (string) $ext, '.' ) === false ) { $f['fileExtensions'][ $key ] = '.' . $ext; } } $f['fileExtensions'] = implode( ', ', $f['fileExtensions'] ); if( $f['fileExtensions'] ) $extensions = ' accept="' . esc_attr( $f['fileExtensions'] ) . '" '; } if( $f['value'] ) { $f['isRequired'] = ''; if( is_array( $f['value'] ) ) { $file_name = (string) wpfval( $f['value'], 'filename' ); $f['value'] = (string) wpfval( $f['value'], 'fileurl' ); } else { $file_name = basename( (string) $f['value'] ); } $extension = pathinfo( $f['value'], PATHINFO_EXTENSION ); $f['value'] = wpforo_fix_upload_url( $f['value'] ); if( wpfval( WPF()->current_object['user'], 'userid' ) ) { $delete = '?wpfaction=ucf_file_delete&foro_f=' . $f['name'] . '&foro_u=' . WPF()->current_object['user']['userid']; $delete_url = wp_nonce_url( $delete, 'wpforo_delete_profile_field', 'foro_n' ); $delete_html = '  |  '; } else { $delete_html = '  |  '; } if( $extension && wpforo_is_image( $extension ) ) { $field_html .= '
' . esc_attr( $file_name ) . '
' . esc_attr( $file_name ) . '' . $delete_html . '
'; } else { $field_html .= '
' . esc_attr( $file_name ) . '' . $delete_html . '
'; } } $field_html .= ''; return $field_html; } private function form_extra( $f ) { $form_type = wpfval( $f, 'form_type' ); switch( $form_type ) { case 'topic': if( $forum = wpfval( $f, 'meta', 'forum' ) ) { wpforo_topic_form_extra( (int) wpfval( $forum, 'forumid' ), (array) wpfval( $f, 'meta', 'values' ) ); } break; case 'post': if( $topic = wpfval( $f, 'meta', 'topic' ) ) { wpforo_reply_form_extra( $topic, (array) wpfval( $f, 'meta', 'values' ) ); } break; } } /** * Textarea - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_textarea( $f ) { $field_html = ''; if( $f['fieldKey'] === 'body' ) { ob_start(); $this->form_extra( $f ); $field_html .= ob_get_clean(); } return $field_html; } /** * Textarea - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_tinymce( $f ) { WPF()->current_object['load_tinymce'] = true; $f['isRequired'] = ''; $f['attributes'] .= ' data-wpforoeditor="tinymce" '; if( empty( $f['wp_editor_settings'] ) ) $f['wp_editor_settings'] = WPF()->tpl->editor_buttons(); $f['wp_editor_settings'] = apply_filters( 'wpforo_form_field_tinymce_editor_settings', $f['wp_editor_settings'], $f ); wp_localize_script( 'wpforo-frontend-js', 'wpforo_editor_settings_' . esc_attr( $f['fieldId'] ), $f['wp_editor_settings'] ); return $this->field_textarea( $f ); } /** * Password - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_password( $f ) { $field_html = ''; if( $f['template'] === 'account' ) { $f['isRequired'] = 0; $f['label'] = wpforo_phrase( 'Old password', false ); $f['description'] = ''; $field_html .= ' '; } $p1 = '1'; $p2 = '2'; if( ! empty( $f['varname'] ) ) { $f['fieldName'] = $f['varname'] . '[' . $f['name'] . $p1 . ']'; } else { $f['fieldName'] = $f['name'] . $p1; } if( $f['template'] === 'account' ) { $f['label'] = wpforo_phrase( 'New', false ) . ' ' . wpforo_phrase( $f['label'], false, 'lower' ); $f['placeholder'] = wpforo_phrase( 'New', false ) . ' ' . wpforo_phrase( $f['placeholder'], false, 'lower' ); } if( in_array( $f['template'], [ 'account', 'register' ], true ) ) { if( $f['template'] === 'account' ) $field_html .= '
'; $field_html .= ''; if( $f['template'] === 'register' ) { $field_html .= ''; } if( $f['template'] === 'account' ) { $field_html .= '
'; } $f['label'] = wpforo_phrase( 'Confirm Password', false ); $f['placeholder'] = wpforo_phrase( 'Confirm Password', false ); $f['description'] = ''; $f['fieldName'] = ( ! empty( $f['varname'] ) ? $f['varname'] . '[' . $f['name'] . $p2 . ']' : $f['name'] . $p2 ); $field_html .= '
'; $field_html .= ''; $field_html .= '
'; } return $field_html; } /** * Checkbox - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_checkbox( $f ) { $i = 0; $field_html = ''; $f['value'] = $this->build_array_value( $f['value'], "\n" ); $f['values'] = $this->build_array_using_string_rows( $f['values'] ); if( ! empty( $f['values'] ) ) { $item_field_name = $f['fieldName'] . '[]'; $use_default_selected = ( trim( (string) $f['isRequired'] ) && ! $f['value'] ); $f['isRequired'] = ( count( $f['values'] ) == 1 ) ? $f['isRequired'] : ''; $field_html .= ''; foreach( $f['values'] as $row ) { $item = $this->build_item_value_lable( $row ); $id = $f['fieldId'] . '_' . ++ $i; $field_html .= '
'; $item_html = 'check( $item['value'], $f['value'] ) ) . ' name="' . esc_attr( $item_field_name ) . '" value="' . esc_attr( $item['value'] ) . '" id="' . esc_attr( $id ) . '" class="wpf-input-checkbox ' . esc_attr( $f['class'] ) . '" ' . $f['isDisabled'] . ' ' . $f['isRequired'] . ' ' . $f['attributes'] . '>'; $field_html .= $this->build_label( $item['label'], $item_html, $f, $id ); $field_html .= '
'; } } return $field_html; } /** * Radio - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_radio( $f ) { $i = 0; $field_html = ''; $f['value'] = $this->build_array_value( $f['value'], "\n" ); $f['values'] = $this->build_array_using_string_rows( $f['values'] ); $use_default_selected = ( trim( (string) $f['isRequired'] ) && ! $f['value'] ); if( ! empty( $f['values'] ) ) { foreach( $f['values'] as $row ) { $item = $this->build_item_value_lable( $row ); $id = $f['fieldId'] . '_' . ++ $i; $field_html .= '
'; $item_html = 'check( $item['value'], $f['value'] ) ) . ' name="' . esc_attr( $f['fieldName'] ) . '" value="' . esc_attr( $item['value'] ) . '" id="' . esc_attr( $id ) . '" class="wpf-input-radio ' . esc_attr( $f['class'] ) . '" ' . $f['isDisabled'] . ' ' . $f['isRequired'] . ' ' . $f['attributes'] . ' />'; $field_html .= $this->build_label( $item['label'], $item_html, $f, $id ); $field_html .= '
'; } } return $field_html; } /** * Radio - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_select( $f ) { $field_html = ''; $f['value'] = $this->build_array_value( $f['value'], "\n" ); $f['values'] = $this->build_array_using_string_rows( $f['values'] ); $use_default_selected = ( trim( (string) $f['isRequired'] ) && ! $f['value'] ); if( ! empty( $f['values'] ) ) { $field_html .= ''; } return $field_html; } public function generate_multi_item( $val, $dvalues = [], $save_button = false ) { return sprintf( '
%2$s%3$s
', (int) in_array( $val, $dvalues, true ), $val, ( $save_button ? sprintf( '', wpforo_phrase( 'Add to pre-defined values', false ) ) : '' ), wpforo_phrase( 'remove', false ) ); } /** * Radio - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_autocomplete( $f ) { $f['value'] = $this->build_array_value( $f['value'], "\n" ); $f['values'] = $this->build_array_using_string_rows( $f['values'] ); $save_button = (int) wpfval( $f, 'formid' ) > 0 && array_intersect( WPF()->current_user_groupids, (array) wpfval( $f, 'UGroupIdsFrontAddNewDefaultValues' ) ); return sprintf( '<%1$s data-dbvariants="%16$s" data-formid="%2$d" data-fieldkey="%3$s">%4$s%13$s%14$s%15$s', ( $f['isMultiChoice'] ? 'wpf-multi-input' : 'wpf-autocomplete-input' ), (int) wpfval( $f, 'formid' ), $f['fieldKey'], ( $f['isMultiChoice'] ? sprintf( '', $this->generate_multi_item( '', [], $save_button ) ) . implode( '', array_map( function( $val ) use ( $f, $save_button ) { return $this->generate_multi_item( $val, $f['values'], $save_button ); }, array_filter( $f['value'] ) ) ) : '' ), esc_attr( $f['fieldName'] ), esc_attr( $f['fieldId'] ), esc_attr( $f['class'] ), ( ! $f['isMultiChoice'] ? current( $f['value'] ) : '' ), $f['isDisabled'], $f['isRequired'], $f['attributes'], ( (int) $f['isAllowedCustomValues'] || $save_button ? 'allow-custom-values' : '' ), wpforo_phrase( 'This Field is Required', false ), wpforo_phrase( 'Wrong Value (This Field Allows Only Predefined Values)', false ), ( ( $values = (array) wpfval( $f, 'values' ) ) ? sprintf( '%2$s', esc_attr( $f['fieldId'] ), implode( '', array_map( function( $value ) { return sprintf( '', esc_attr( $value ) ); }, array_diff( $values, $f['value'] ) ) ) ) : '' ), esc_attr( wp_json_encode( $f['values'] ) ) ); } /** * Usergroup - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_usergroup( $f ) { $field_html = ''; if( ! empty( $f['allowedGroupIds'] ) ) { $field_html .= ''; } return $field_html; } public function field_secondary_groups( $f ) { $field_html = ''; if( $groups = WPF()->usergroup->get_secondary_groups() ) { $allowed_groupids = (array) wpfval( $f, 'allowedGroupIds' ); $i = 0; $field_html .= ''; foreach( $groups as $group ) { if( in_array( $group['groupid'], [ 1, 2, 4 ] ) || ( $allowed_groupids && ! in_array( $group['groupid'], $allowed_groupids ) ) ) continue; $id = $f['fieldId'] . '_' . ++ $i; $field_html .= '
'; $item_html = 'check( $group['groupid'], $f['value'] ) . ' name="' . esc_attr( $f['fieldName'] . '[]' ) . '" value="' . esc_attr( $group['groupid'] ) . '" id="' . esc_attr( $id ) . '" class="wpf-input-checkbox ' . esc_attr( $f['class'] ) . '" ' . $f['isDisabled'] . ' ' . $f['attributes'] . '>'; $field_html .= $this->build_label( $group['name'], $item_html, $f, $id ); $field_html .= '
'; } } return $field_html; } /** * Avatar - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_avatar( $f ) { $protocol = is_ssl() ? 'https://' : 'http://'; $remote_url = ( $f['value'] && strpos( (string) $f['value'], 'wpforo/avatars' ) === false ) ? $f['value'] : ''; $field_html = ' '; return $field_html; } /** * HTML - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_html( $f ) { return stripslashes( do_shortcode( wpforo_apply_ucf_shortcode( (string) $f['html'] ) ) ); } /** * URL - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_url( $f ) { return ''; } /** * Nickname - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_nicename( $f ) { return ''; } /** * Text - Field builder * * @param array $f field arguments * * @return string field HTML */ public function field_text( $f ) { return ''; } public function field_tel( $f ) { return ''; } /** * Prepares displayed values for Profile fields * * @param array $f field arguments * @param int $userid * * @return array prepared values */ public function prepare_values( $f, $userid = 0 ) { switch( $f['type'] ) { case 'textarea': $f['value'] = wpforo_kses( wpforo_decode( $f['value'] ) ); break; case 'date': // $f['value'] = wpforo_date($f['value'], 'date', false); break; case 'datetime': $f['value'] = wpforo_date( $f['value'], 'datetime', false ); break; case 'url': $f['value'] = sprintf( '%2$s', esc_url( $f['value'] ), esc_html( $f['value'] ) ); break; case 'email': $f['value'] = sprintf( '%2$s', esc_attr( $f['value'] ), esc_html( $f['value'] ) ); break; case 'tel': $f['value'] = sprintf( '%2$s', esc_attr( $f['value'] ), esc_html( $f['value'] ) ); break; case 'file': if( ! empty( $f['value'] ) ) { if( is_array( $f['value'] ) ) { $file_name = (string) wpfval( $f['value'], 'filename' ); $f['value'] = (string) wpfval( $f['value'], 'fileurl' ); } else { $file_name = basename( (string) $f['value'] ); } $f['value'] = wpforo_fix_upload_url( $f['value'] ); $file_url = esc_url_raw( $f['value'] ); $file_name = esc_attr( $file_name ); $extension = pathinfo( $f['value'], PATHINFO_EXTENSION ); if( wpforo_is_image( $extension ) ) { $f['value'] = sprintf( '%2$s', esc_url( $file_url ), esc_attr( $file_name ) ); } elseif( wpforo_is_audio( $extension ) ) { $f['value'] = sprintf( '', esc_url( $file_url ), esc_attr( $file_name ) ); } elseif( wpforo_is_video( $extension ) ) { $f['value'] = sprintf( '', esc_url( $file_url ), esc_attr( $file_name ) ); } else { $f['value'] = sprintf( '%s', esc_url( $file_url ), esc_html( $file_name ) ); } } break; case 'avatar': $f['value'] = ( WPF()->usergroup->can( 'va' ) && wpforo_setting( 'profiles', 'avatars' ) ) ? WPF()->member->get_avatar_html( $f['value'], $userid ) : ''; break; case 'color': if( $f['value'] ) { $f['value'] = ''; } break; } switch( $f['name'] ) { case 'skype': $f['value'] = sprintf( '%s', esc_attr( $f['value'] ), esc_html( $f['value'] ) ); break; case 'location': $f['value'] = sprintf( '%s', esc_attr( $f['value'] ), esc_html( $f['value'] ) ); break; case 'signature': $f['value'] = wpforo_signature( $f['value'], [ 'echo' => 0 ] ); break; case 'about': $f['value'] = wpforo_nofollow_tag( $f['value'] ); break; } return apply_filters( 'wpforo_form_prepare_values', $f ); } /** * Prepares arguments * * @param array $f field arguments * * @return array prepared values */ public function prepare_args( $f ) { $is_owner = $this->owner(); //field_class $f['field_class'] = sanitize_text_field( $f['name'] ); //varname $f['varname'] = $f['isDefault'] ? (string) wpfval( $this->current, 'varname' ) : 'data'; //template $f['template'] = ( isset( $this->current['template'] ) ) ? $this->current['template'] : WPF()->current_object['template']; //value $f['value'] = ( isset( $this->current['value'][ $f['name'] ] ) ) ? $this->current['value'][ $f['name'] ] : $f['value']; if( ! $f['isDefault'] && $f['varname'] ) { $f['value'] = ( isset( $this->current['value'][ $f['varname'] ][ $f['name'] ] ) ) ? $this->current['value'][ $f['varname'] ][ $f['name'] ] : $f['value']; } $f['value'] = wpforo_unslashe( $f['value'] ); $f['value'] = wpforo_decode( $f['value'] ); if( $f['name'] === 'user_nicename' ) { $f['value'] = urldecode( (string) $f['value'] ); } //allowedGroupIds $groups = []; if( ! empty( $f['allowedGroupIds'] ) ) $groups = $this->build_array_value( $f['allowedGroupIds'] ); if( $f['type'] === 'usergroup' ) { if( ! $is_owner && wpforo_current_user_is( 'admin' ) ) { $groups = WPF()->usergroup->get_usergroups( 'groupid' ); } elseif( $is_owner && ! in_array( WPF()->current_user_groupid, $f['allowedGroupIds'] ) ) { $groups = []; } } $f['allowedGroupIds'] = array_filter( $groups ); //isRequired if( $f['isRequired'] ) { $f['required_class'] = ' wpf-field-required '; $f['required_indicator'] = ' *'; } else { $f['required_class'] = ''; $f['required_indicator'] = ''; } return $f; } /** * @param array $f field arguments * * @return array prepared values */ public function prepare_field_args( $f ) { //faIcon $f['faIcon'] = trim( (string) $f['faIcon'] ); if( strpos( $f['faIcon'], ' ' ) === false ) $f['faIcon'] = 'fas ' . $f['faIcon']; //isRequired $f['isRequired'] = ( $f['isRequired'] ) ? ' required="required" ' : ''; //isDisabled $f['isDisabled'] = ( $f['isDisabled'] ) ? ' disabled="disabled" ' : ''; //fieldName | new key in args $f['fieldName'] = ( ! empty( $f['varname'] ) ? $f['varname'] . '[' . $f['name'] . ']' : $f['name'] ); //isMultiChoice if( $f['isMultiChoice'] ) { $f['fieldName'] .= '[]'; $f['isMultiChoice'] = ' multiple="multiple" '; } else { $f['isMultiChoice'] = ''; } //fieldId | new key in args $f['fieldId'] = ( $f['varname'] ? $f['varname'] . '_' : '' ) . ( $f['id'] ?: $f['name'] ); $f['fieldId'] = uniqid( $f['fieldId'] . '_' ); //minLength & maxLength $f['minLength'] = ( $f['minLength'] ) ? intval( $f['minLength'] ) : ''; $f['maxLength'] = ( $f['maxLength'] ) ? intval( $f['maxLength'] ) : ''; if( $f['minLength'] ) { $minLength_attr = ( $f['type'] === 'date' || $f['type'] === 'number' || $f['type'] === 'range' ) ? ' min="' . $f['minLength'] . '" ' : ' minlength="' . $f['minLength'] . '" '; } if( $f['maxLength'] ) { $maxLength_attr = ( $f['type'] === 'date' || $f['type'] === 'number' || $f['type'] === 'range' ) ? ' max="' . $f['maxLength'] . '" ' : ' maxlength="' . $f['maxLength'] . '" '; } $f['minmax'] = isset( $minLength_attr ) ? $minLength_attr : ''; $f['minmax'] .= isset( $maxLength_attr ) ? ' ' . $maxLength_attr : ''; //attributes $f['attributes'] .= ' autocomplete="off"'; if( wpfkey( $f, 'fileExtensions' ) ) { if( is_scalar( $f['fileExtensions'] ) ) $f['fileExtensions'] = explode( ',', $f['fileExtensions'] ); $f['fileExtensions'] = array_filter( $f['fileExtensions'] ); } return $f; } /** * @param array $file_data * @param int $userid * * @return array */ public function prepare_file_args( $file_data, $userid = 1 ) { $file = [ 'files' => [], 'fields' => [] ]; $userid = $userid ?: WPF()->current_userid; if( ! empty( $file_data ) ) { foreach( $file_data as $file_field_name => $file_name ) { $field_name_folder = substr( (string) $file_field_name, 6 ); $file_upload_dir = wpforo_fix_dir_sep( WPF()->folders['wp_upload']['dir'] . $this->field_dir . $userid . DIRECTORY_SEPARATOR . $field_name_folder ) . DIRECTORY_SEPARATOR; $file_path = $file_upload_dir . $file_name; $file['files'][ $file_field_name ] = $file_path; $file['fields'][ $file_field_name ] = $this->field_dir . $userid . '/' . $field_name_folder . '/' . $file_name; wp_mkdir_p( $file_upload_dir ); } } return $file; } public function check( $needle, $haystack ) { if( is_scalar( $haystack ) ) $haystack = explode( ',', $haystack ); return in_array( $needle, (array) $haystack ) ? 'checked' : ''; } public function select( $needle, $haystack ) { return in_array( $needle, (array) $haystack ) ? 'selected' : ''; } public function build_label( $item_label, $item_html, $f, $for = '' ) { $label = ''; $field_html = $f['isLabelFirst'] ? $label . ' ' . $item_html : $item_html . ' ' . $label; if( $f['isWrapItem'] ) $field_html = ''; return $field_html; } public function build_item_value_lable( $string, $sep = '=>' ) { $string = trim( (string) $string ); $count = 0; $string = preg_replace( '#^\[(.+?)]$#isu', '$1', (string) $string, 1, $count ); $default_selected = (bool) $count; $data = explode( $sep, $string ); $value = wpfkey( $data, 0 ) ? trim( (string) $data[0] ) : 'no_value'; $label = wpfkey( $data, 1 ) ? trim( (string) $data[1] ) : $value; return compact( 'value', 'label', 'default_selected' ); } public function build_array_value( $var, $sep = ',' ) { if( is_scalar( $var ) ) { $var = trim( (string) $var ); if( ! strlen( (string) $var ) ) return []; } if( is_serialized( $var ) ) { $var = unserialize( $var ); } elseif( is_scalar( $var ) && strpos( (string) $var, $sep ) !== false ) { $var = explode( $sep, $var ); } return array_map( 'trim', (array) $var ); } public function build_array_using_string_rows( $string, $regexp = '' ) { if( is_scalar( $string ) ) { if( ! $regexp ) $regexp = '#' . preg_quote( PHP_EOL ) . '#isu'; return array_filter( preg_split( $regexp, $string ) ); } return $string; } public function sanitize( $data, $fields ) { $types = $this->field_types( $fields ); if( ! empty( $data ) && ! empty( $types ) ) { foreach( $data as $name => $value ) { if( wpfval( $types, $name ) ) { $data[ $name ] = $this->sanitize_field( $value, $types[ $name ], $name ); } } } return $data; } public function sanitize_field( $value, $type = 'text', $name = '' ) { if( ! is_null( $value ) ) { if( $type === 'text' ) { $value = sanitize_text_field( $value ); if( $name === 'user_nicename' ) { $value = sanitize_title( sanitize_user( $value, true ) ); } } elseif( $type === 'url' ) { $value = esc_url_raw( $value ); } elseif( $type === 'date' ) { $value = sanitize_text_field( $value ); } elseif( $type === 'textarea' ) { $value = stripslashes( wpforo_kses( trim( (string) $value ), 'user_description' ) ); } elseif( $type === 'email' ) { $value = sanitize_email( $value ); } elseif( $type === 'password' ) { $value = trim( (string) $value ); } elseif( $type === 'usergroup' ) { $value = intval( $value ); } elseif( $type === 'radio' ) { $value = sanitize_text_field( $value ); } elseif( $type === 'checkbox' ) { if( $name === 'secondary_groupids' ) { $value = wpforo_sanitize_int( $value ); } else { $value = wpforo_sanitize_text( $value ); } } elseif( $type === 'select' ) { $value = sanitize_text_field( $value ); } elseif( $type === 'color' ) { $value = sanitize_text_field( $value ); } elseif( $type === 'number' ) { $value = intval( $value ); } elseif( $type === 'tel' ) { $value = sanitize_text_field( $value ); } elseif( $type === 'html' ) { $value = preg_replace( '#(.*?)#is', '', (string) $value ); } if( is_string( $value ) ) { $value = stripslashes( (string) $value ); } } return $value; } public function esc_field( $f ) { if( wpfkey( $f, 'value' ) ) { $f['value'] = wpforo_trim( $f['value'] ); if( in_array( wpfval( $f, 'type' ), [ 'textarea', 'tinymce' ], true ) ) { $f['value'] = wpautop( wpforo_kses( stripslashes( (string) $f['value'] ) ) ); } elseif( wpfval( $f, 'type' ) === 'file' ) { $f['value'] = wpfval( $f['value'], 'fileurl' ) ?: $f['value']; } elseif( $f['name'] === 'timezone' ) { $f['value'] = str_replace( '_', ' ', $f['value'] ); } elseif( $f['fieldKey'] === 'secondary_groupids' ) { $f['value'] = WPF()->usergroup->get_secondary_group_names( $f['value'] ); $f['value'] = implode( ', ', $f['value'] ); } elseif( $f['type'] === 'usergroup' && $f['fieldKey'] === 'groupid' && ( $f['value'] = intval( $f['value'] ) ) ) { if( $group = WPF()->usergroup->get_usergroup( $f['value'] ) ) $f['value'] = wpfval( $group, 'name' ); } elseif( is_array( $f['value'] ) ) { $f['value'] = array_filter( $f['value'] ); $f['value'] = implode( ', ', $f['value'] ); } } $f['value'] = apply_filters( 'wpforo_display_field_value', $f['value'], $f ); return $f; } public function validate( &$data, &$fields ) { $type = ''; $label = ''; $userid = ''; $error = []; $return = []; $is_owner = $this->owner(); $template = ( isset( $this->current['template'] ) ) ? $this->current['template'] : WPF()->current_object['template']; if( empty( $data ) ) $error[] = 'No data submitted'; if( empty( $fields ) ) $error[] = 'User profile fields not found'; if( empty( $error ) ) { foreach( $fields as $r_key => $rows ) { foreach( $rows as $c_key => $cols ) { foreach( $cols as $key => $field ) { if( wpfval( $field, 'name' ) ) { $name = $field['name']; if( ! $template && wpfval( $field, 'template' ) ) $template = $field['template']; if( wpfval( $field, 'label' ) ) $label = esc_html( $field['label'] ); if( wpfval( $field, 'type' ) ) $type = $field['type']; if( wpfval( $data, 'userid' ) ) $userid = $data['userid']; if( $template && $template !== 'register' ) { if( $template === 'account' && $field['type'] === 'password' ) $field['isRequired'] = 0; if( ! $this->can_edit( $field ) ) { unset( $cols[ $key ] ); unset( $data[ $name ] ); unset( $fields[ $r_key ][ $c_key ][ $key ] ); } } if( wpfkey( $cols, $key ) && wpfkey( $data, $name ) ) { $value = $data[ $name ]; if( is_string( $value ) ) { $value = trim( $value ); $value = htmlspecialchars_decode( $value ); } if( wpfval( $field, 'isRequired' ) && ! $value ) { $error[] = $label . ' ' . wpforo_phrase( 'field is required', false, false ); } if( $value ) { if( $type === 'number' ) { if( wpfval( $field, 'minLength' ) ) { if( (int) $value < $field['minLength'] ) { $error[] = $label . ' ' . sprintf( wpforo_phrase( 'field value must be at least %d', false, false ), intval( $field['minLength'] ) ); } } if( wpfval( $field, 'maxLength' ) ) { if( (int) $value > $field['maxLength'] ) { $error[] = $label . ' ' . sprintf( wpforo_phrase( 'field value cannot be greater than %d', false, false ), intval( $field['maxLength'] ) ); } } } else { if( wpfval( $field, 'minLength' ) ) { if( wpforo_strlen( $value ) < $field['minLength'] ) { $error[] = $label . ' ' . sprintf( wpforo_phrase( 'field length must be at least %d characters', false, false ), intval( $field['minLength'] ) ); } } if( wpfval( $field, 'maxLength' ) ) { if( wpforo_strlen( $value ) > $field['maxLength'] ) { $error[] = $label . ' ' . sprintf( wpforo_phrase( 'field length cannot be greater than %d characters', false, false ), intval( $field['maxLength'] ) ); } } } if( $type === 'url' && filter_var( $value, FILTER_VALIDATE_URL ) === false ) { $error[] = $label . ' ' . wpforo_phrase( 'field value is not a valid URL', false, false ); } if( $type === 'email' ) { if( ! is_email( $value ) ) { $error[] = $label . ' ' . wpforo_phrase( 'Invalid Email address', false, false ); } if( $name === 'user_email' ) { $email_owner = email_exists( $value ); if( $email_owner && $email_owner != $userid ) { $error[] = $label . ' ' . wpforo_phrase( 'This email address is already registered. Please insert another', false, false ); } } } if( $type === 'file' ) { $extension = pathinfo( $value, PATHINFO_EXTENSION ); $extension = ( function_exists( 'mb_strtolower' ) ) ? mb_strtolower( (string) $extension ) : strtolower( (string) $extension ); if( wpfval( $field, 'fileExtensions' ) ) { if( $extension ) { if( ! in_array( $extension, $field['fileExtensions'] ) ) { $error[] = $label . ' ' . wpforo_phrase( 'file type is not allowed', false, false ); $error[] = sprintf( 'Allowed file types: %s', implode( ', ', $field['fileExtensions'] ) ); } } else { $error[] = $label . ' ' . wpforo_phrase( 'file type is not detected', false, false ); } } else { $mime_types = get_allowed_mime_types(); $mime_types = array_flip( $mime_types ); if( ! empty( $mime_types ) ) { $implode_types = implode( '|', $mime_types ); $explode_types = explode( '|', $implode_types ); if( ! in_array( $extension, $explode_types ) ) { $error[] = $label . ' ' . sprintf( wpforo_phrase( 'file type %s is not allowed', false, false ), $extension ); } if( ! WPF()->perm->can_attach_file_type( $extension ) ) { $error[] = 'You are not allowed to attach this file type'; } } } if( wpfval( $field, 'fileSize' ) ) { if( wpfval( $_FILES, 'data', 'size', $name ) && $_FILES['data']['size'][ $name ] > ( $field['fileSize'] * 1024 * 1024 ) ) { $error[] = $label . ' ' . wpforo_phrase( 'file is too large', false, false ); $error[] = sprintf( 'Maximum allowed file size is %s MB', $field['fileSize'] ); } } } if( $name === 'user_nicename' ) { $value = sanitize_text_field( $value ); $user_nicename = sanitize_title( sanitize_user( $value, true ) ); if( ! $user_nicename ) { $error[] = 'Nickname validation failed'; } $sql = "SELECT `ID` FROM `" . WPF()->db->users . "` WHERE `ID` != " . intval( $userid ) . " AND `user_nicename` LIKE '" . esc_sql( $user_nicename ) . "'"; if( WPF()->db->get_var( $sql ) ) { $error[] = 'This nickname is already in use. Please insert another.'; } } if( $name === 'groupid' ) { if( $template !== 'register' ) { if( $is_owner || ! wpforo_current_user_is( 'admin' ) ) { $error[] = 'You have no permission to edit Usergroup field'; } } else { if( in_array( $value, [ 1, 2, 4 ] ) ) { $error[] = 'Admin and Moderator Usergroups are not permitted'; } else { if( wpfval( $field, 'allowedGroupIds' ) ) { $allowedGroupIds = wpforo_parse_args( $field['allowedGroupIds'] ); if( ! in_array( $value, $allowedGroupIds ) ) { $error[] = 'The selected Usergroup cannot be set'; } } else { $error[] = 'The selected Usergroup is not found in allowed list'; } } } } if( $name === 'secondary_groupids' ) { if( $template === 'register' || ( $is_owner && $field['isEditable'] ) || ( ! $is_owner && in_array( WPF()->current_user_groupid, (array) $field['canEdit'] ) ) || wpforo_current_user_is( 'admin' ) ) { if( ! empty( $value ) && is_array( $value ) ) { $secondary_groupids = WPF()->usergroup->get_secondary_groupids(); foreach( $value as $secondary_groupid ) { if( in_array( $secondary_groupid, [ 1, 2, 4 ] ) ) { $error[] = 'Admin and Moderator Usergroups are not permitted'; } if( $secondary_groupid && ! in_array( $secondary_groupid, $secondary_groupids ) ) { $error[] = 'One of the selected Usergroups cannot be set as Secondary'; } } } } else { $error[] = 'You have no permission to edit Usergroup field'; } } } } } } } } } if( ! empty( $error ) ) { $return['error'] = $error; return $return; } else { return true; } } public function validate_password( $data ) { $error = []; $return = [ 'error' => false ]; if( wpfval( $data, 'old_pass' ) && wpfval( $data, 'user_pass1' ) && wpfval( $data, 'user_pass2' ) ) { if( $data['user_pass1'] !== $data['user_pass2'] ) { $error[] = 'New Passwords do not match'; } else { return true; } } if( ! empty( $error ) ) { $return['error'] = $error; return $return; } return false; } public function field_types( $fields ) { $name_type_fields = []; if( ! empty( $fields ) ) { foreach( $fields as $rows ) { foreach( $rows as $cols ) { foreach( $cols as $field ) { if( wpfval( $field, 'name' ) && wpfval( $field, 'type' ) ) { $name_type_fields[ $field['name'] ] = $field['type']; } } } } } return $name_type_fields; } public function owner( $object_userid = false ): bool { if( ! $object_userid ) { if( wpfval( WPF()->current_object, 'user', 'userid' ) ) { return wpforo_is_owner( WPF()->current_object['user']['userid'] ); } else { return false; } } else { return wpforo_is_owner( $object_userid ); } } /** * @param array $f * * @return bool */ public function can_add( $f ) { if( wpfval( $f, 'name' ) ) { if( $f['name'] === 'signature' && ! wpforo_setting( 'profiles', 'signature' ) ) { return false; } if( $f['name'] === 'avatar' && ( ! wpforo_setting( 'profiles', 'custom_avatars' ) || ! wpforo_setting( 'profiles', 'avatars' ) ) ) { return false; } } return true; } /** * @param array $f * * @return bool */ public function can_view( $f ) { return wpforo_current_user_is( 'admin' ) || ! ( ! $this->owner() && ! in_array( WPF()->current_user_groupid, (array) $f['canView'] ) ); } /** * @param array $f * * @return bool */ public function can_edit( $f ) { if( wpfval( WPF()->current_object, 'user', 'userid' ) ) { $is_owner = $this->owner(); $value = wpfkey( $f, 'value' ) ? $f['value'] : false; $can_edit = wpfkey( $f, 'isEditable' ) ? $f['isEditable'] : false; $can_moderate = $this->can_moderate( $f ); if( ! $is_owner && ! $can_moderate && WPF()->current_user_groupid !== 1 ) { return false; } if( ! $can_edit && ! $can_moderate && WPF()->current_user_groupid !== 1 && ! $value ) { return false; } if( wpfkey( $f, 'name' ) ) { if( $f['name'] === 'signature' && ( ! WPF()->usergroup->can( 'ups' ) || ! wpforo_setting( 'profiles', 'signature' ) ) ) { return false; } if( $f['name'] === 'avatar' && ( ! wpforo_setting( 'profiles', 'custom_avatars' ) || ! wpforo_setting( 'profiles', 'avatars' ) ) ) { return false; } if( $f['name'] === 'groupid' && ( WPF()->current_user_groupid != 1 || $is_owner || ! current_user_can( 'administrator' ) ) ) { return false; } } return true; } else { return false; } } /** * @param array $f * * @return bool */ public function can_moderate( $f ) { if( empty( $f ) ) return false; $usergroups_who_can_edit = ! empty( $f['canEdit'] ) ? (array) $f['canEdit'] : [ 1 ]; return in_array( WPF()->current_user_groupid, $usergroups_who_can_edit ); } public function can_show_value( $f ) { $return = true; if( is_string( $f ) ) $f = WPF()->member->get_field( $f ); $f = wpforo_parse_args( $f, $this->default ); if( $f['type'] === 'password' ) $return = false; return apply_filters( 'wpforo_form_can_show_value', $return, $f ); } }