Forms API

Posted in: Developer Documentation

In WPAdverts forms are essential part of the plugin, they allow post and search Ads among other things, this is why WPAdverts has advanced Adverts_Form class for manging all forms via actions and filters without chnaging original files.

If you would like to take a look at the Adverts_Form class source code you will find it in wpadverts/includes/class-adverts-form.php file.

Actions and Filters

Adverts_Form class has to main hooks (one action and one filter) which you can use to customize form structure or behavior.

adverts_form_load filter

this filter allows you to customize form scheme before it’s loaded, this means that at this point field values are unknown aside of default values.

Each of WPAdverts forms is using this filter, so you when you are using it you need to check which form is being proccessed so you will modify only the form you wish to change.

By default WPAdverts has following forms registerd:

  • advert – this is form used in [adverts_add] shortcode and in wp-admin / Classifieds panel when editing an Ad.
  • search – this is the top search form in [adverts_list] shortcode.
  • adverts-bank-transfer – if you are accepting payments for Ads using Bank Transfer payment method this form will be generated in [adverts_add] shortcode in third step.
  • adverts-paypal-standard – as above, but for PayPal Payments Standard payment method.
  • payments_history – this form is being used in wp-admin / Classifieds / Payments History panel when viewing payment details.

How do i check which form i am currently proccessing? This is pretty simple to do lets assume we want to add an additional field to Bank Transfer and PayPal payment methods. Following code would do that

add_filter( "adverts_form_load", "forms_api_example_load" );

function forms_api_example_load( $form ) {
    $allowed = array("adverts-bank-transfer", "adverts-paypal-standard");
    if( ! in_array( $form['name'], $allowed ) ) {
        return $form;
    }
    // add new field here
    return $form;
}

You are probably wandering, ok but what is inside the $form variable? This variable is an array which stores complete form structure, when “printed” it will look somewhat like this:

array(
    "name"  => "form-name",
    "action" => "", // one of "get", "post" or ""
    "field"    => array() // array of form fields
);

The “name” and “action” keys are pretty simple they are just string, “field” is more complex, but do not worry about it right now, we will describe how to customize this below.

adverts_form_bind action

This action is executed after “adverts_form_load”, it allows to bind / set values for fields in the form, it’s handy when the default value is unique for each user (for example when default value is current user login).

add_filter( "adverts_form_bind", "forms_api_example_bind_defaults", 10, 2);

/**
 * Sets default values for Bank Transfer form
 * 
 * @param Adverts_Form $form Instance of form.
 * @param array $data User submitted form values ( key => value )
 * @return Adverts_Form Modified instance of form.
 */
function forms_api_example_bind_defaults( Adverts_Form $form, $data ) {
    
    $scheme = $form->get_scheme();
    
    if( $scheme["name"] != "adverts-bank-transfer" ) {
        return $form;
    }
    
    if( empty( $data ) ) {
        $login = wp_get_current_user()->user_login;
        $form->set_value( "login", $login );
    }

    return $form;
}

In the example above we are setting default value for field “login” in “adverts-bank-transfer” form. Note that the form is already loaded so unlike in adverts_form_load it is now being represented by Adverts_Form class. Form array scheme we can get using $form->get_scheme() function.

Note, we do not want to override “login” value submitted by user, hence the if( empty( $data ) ) { ... } condition.

Field Structure

Each Adverts_Form field is an associative array which describes a field, this array includes information like filed label, name, CSS class, order in the form and so on, some of the field options are common to each field to make the document clear i will list the common options below:

  • name (string) – field name, should contain only lowercase a-z, 0-9 and _ characters. This usually will also be a $_REQUEST key when submitting a form. For example if the field name is “my_custom_field” then after form submission you can access submitted value using $_REQUEST[‘my_custom_field’].
  • type (string) – one of registered field type. Field types can be registered using adverts_form_add_field() function. You can find out how to use it in wpadverts/includes/defaults.php file. Types available by default are listed below in “Field Types” section.
  • order (int) – field position in the form, the lower the value the higher the field will be.
  • label (string) – field description usually visible next to the field
  • is_required (int) – if set to 1 it will display a red asterisk next to label.
  • validator (array) – list of field validators, that is functions which check if provided value is correct, for example to check if the field is an email or URL.
  • filter (array) – list of field filters, that is function which format submitted value before validation, for example to make sure that submitted value is integer.
  • attr (array) – list of attributes that will be appended to the field
  • meta (array) – some arbitrary data for your own use

Validators and Filters will probably require some longer explenation so lets stop here to lear what they are and how to use them.

Validators

By default WPAdverts has following validators:

  • is_required – checks if value was submitted and if it’s not empty.
  • is_email – checks if submitted value is valid email address.
  • is_email_registered – checks if submitted email is already in wp_users DB. This validator is mainly for use with [adverts_add] shortcode and “Create Account” field, you shoudn’t use it in your custom code
  • is_integer – checks if submitted value is an integer
  • string_length – checks if submitted string has correct length.

Creating your own validator is pretty simple, just remember that the validation function needs to return “true” if submitted value is ok, or error code if it’s not. Let’s quickly create a simple validation function which will check if value is a number greater than “min” and smaller than “max”, the “min” and “max” will be provided as params so it will be easy to reuse the function later.

/**
 * Is Between VALIDATOR
 * 
 * @param mixed $data Value entered in form
 * @param array $params Validation parameters (min and max values)
 * @return string|boolean
 */
function in_between( $data, $params = null ) {

    if( isset( $params["min"] ) && $data < $params["min"] ) {
        return "to_small";
    } 
    
    if( isset( $params["max"] ) && $data > $params["max"] ) {
        return "to_big";
    } 
    
    return true;
}

Writing a function was quite easy, now we need to register new validator using adverts_form_add_validator function in order to be able to use it.

adverts_form_add_validator("in_between", array(
    "callback" => "in_between",
    "label" => "In Between",
    "default_error" => __( "Incorrect value.", "adverts" ),
    "message" => array(
        "to_small" => "Value has to be greater than %min%.",
        "to_big" => "Value has to be smaller than %max%."
    ),
    "validate_empty" => false
));

The first argument is validator name, you can now apply this validator to fields, second argument is more interesting, it has following options

  • callback – name of a function which does the validation.
  • label – human readable validator name (mainly for future use)
  • default_error – error message which will be displayed when in_between() function will return an error code not available inside “message” array
  • message – list of specific error messages, for example when in_between() will return “to_small” error code, then error message “to_small” will be displayed.
  • validate_empty – should the validation be run if provided value is empty, most of the time you will want to use no, as usually we do not want to validate empty optional fields.

Now applying this validator to a field is a simple as changing it’s validator to

"validator" => array(
    array(
        "name" => "in_between",
        "min" => 10,
        "max" => 100,
    )
    // more validators here
);

Filters

Filters are functions which are run on submitted value before validation it allows to “correct” the value on the fly if user entered incorrect value by mistake, by there is only one filter registered

  • money – removes all currency formatting and returns a float value

Creating your own filter function is pretty simple, for example the filter below will make sure thatsubmitted number does not start with zero.

/**
 * No leading zero FILTER
 * 
 * Rmoves leading zero from submitted value
 * 
 * @param string $data
 * @return string
 */
function no_leading_zero( $data ) {
    return ltrim( $data, "0" );
}

Now we need to register this function as filter

adverts_form_add_filter("no_leading_zero", array(
    "callback" => "no_leading_zero"
));

And use it in the field structure

"filter" => array(
    array( "name" => "money" ),
    // more filters here ...
)

Field Types

In “Field Structure” chapter we discussed common params for each field type, but every field type has usually its own specific params

Header ‘adverts_field_header’

This technically is not a field, it’s just seperates group fields from each other and does not have any specific parameters.

 

Hidden ‘adverts_field_hidden’ <input type="hidden" />

Displays hidden input does not have any specific parameters as well.

 

Text ‘adverts_field_text’ <input type="text" />

  • class (string) – allows to enter CSS class for the field
  • placeholder (string) – allows to enter text which will be visible when field value is empty.

 

Textarea ‘adverts_field_textarea’ <textarea></textarea>

  • mode (string) – one of: plain-text, tinymce-mini, tinymce-full. The tinymce-* options enable tinyMCE editor for the input.
  • placeholder (string) – allows to enter text which will be visible when field value is empty, applicable only if mode = plain-text

 

Select ‘adverts_field_select’ <select></select>

  • max_choices (int) – maximum number of items user can select, note that setting this field to value greater than 1 will automatically enable multiselect for category field.
  • empty_option (int) – if 1 then at the beginning of the list an empty option (that is option with value=””) will be added.
  • empty_option_text (string) – label for empty option
  • options_callback (mixed) – callback / function which returns options for this field (useful if options are dynamic and often updated)
  • options (array) – list of select options, note that if options_callback is set then this option even if set will be ignored.

The options array should be multi-dimensional array formatted similarly to this

array(
    array( "value" => 1, "text" => "One", "depth" => 1 ),
    array( "value" => 5, "text" => "Five", "depth" => 1 ),
    // more options here ...
);

If you are using options_callback then your callback function should also return array formatted like the one above.

The “value” and “text” keys are self explanatory i think, as for “depth” it allows indent option, the higer the depth value the bigger indention, this is being used mainly for building options trees for hierarchical data like categories.

 

Radio ‘adverts_field_radio’ <input type="radio" />

  • options (array) – see ‘adverts_field_select’ above.

 

Checkbox ‘adverts_field_checkbox’ <input type="checkbox" />

  • options (array) – see ‘adverts_field_select’ above.

 

Putting it all togheter

This whole article mainly explains all the available possibilities in WPAdverts API, but it is hard to make use of it without any practical application, so below you will find a couple of examples where we take advantage of the Forms API.