michaeluno / admin-page-framework

Facilitates WordPress plugin and theme development.
http://admin-page-framework.michaeluno.jp/
Other
340 stars 71 forks source link

Problem: validation in meta boxes #90

Closed patrickf0 closed 10 years ago

patrickf0 commented 10 years ago

I´ve got a problem when validating field data in meta boxes on post.php

public function validation_Event_Location_MetaBox( $inputArray , $oldInputArray ) {

    if ( !empty( $inputArray['event_location_new']['event_location_name'] ) ) {

            $this->setFieldErrors( $inputArray['event_location_new']['event_location_name'] );
            $this->setSettingNotice( 'There was an error in your input.' );
            return $oldInputArray;

        } else {
           // Do something else cause data is valid
        }

}

Everything is fine but it sets no setting notice at all. From what I can tell it still saves the post data whether there is an error or not...?

michaeluno commented 10 years ago

Currently meta box fields do not support validation errors and preventing saving submitted data.

I'll add this to the todo list.

michaeluno commented 10 years ago

It has been added in the 3.0.4b branch,

3.0.4b: https://github.com/michaeluno/admin-page-framework/tree/3.0.4b download: https://github.com/michaeluno/admin-page-framework/archive/3.0.4b.zip

patrickf0 commented 10 years ago

Works nice ;)

Maybe you can get the setFieldErrors method running as well?

patrickf0 commented 10 years ago

The Post is still published or updated even when a field value is not valid, is there a way to avoid this?

michaeluno commented 10 years ago

Maybe you can get the setFieldErrors method running as well?

The setFieldErrors() method is already available.

The Post is still published or updated even when a field value is not valid, is there a way to avoid this?

Currently if the framework sees the transient set via the setFieldErrors() method, it marks the post as draft. So set a value that yields true in setFieldErrors() in the validation callback method. The example is included in the APF_MetaBox_BuiltinFieldTypes class.

    public function validation_APF_MetaBox_BuiltinFieldTypes( $aInput, $aOldInput ) {   // validation_{instantiated class name}

        $_fIsValid = true;
        $_aErrors = array();

        // You can check the passed values and correct the data by modifying them.
        // $this->oDebug->logArray( $aInput );      

        // Validate the submitted data.
        if ( strlen( trim( $aInput['metabox_text_field'] ) ) < 3 ) {

            $_aErrors['metabox_text_field'] = __( 'The entered text is too short! Type more than 2 characters.', 'admin-page-framework-demo' ) . ': ' . $aInput['metabox_text_field'];
            $_fIsValid = false;         

        }

        if ( ! $_fIsValid ) {

            $this->setFieldErrors( $_aErrors );
            $this->setSettingNotice( 'There was an error in your input.' ); 
            return $aOldInput;

        }

        return $aInput;

    }
patrickf0 commented 10 years ago

Okay got it.

It seems work very well but when you put a field inside a section there is no error label on the field. So the setFieldErrors does not do it´s job within a field within a section.

Otherwise it works.

michaeluno commented 10 years ago

Really? Try adding the section dimension to the field error array.

patrickf0 commented 10 years ago

I already did but no effect.

if ( empty( $inputArray['event_location_new']['event_street'] ) ) {

        $_aErrors['event_location_new']['event_street'] = __( 'The entered text is too short! Type more than 2 characters.', 'admin-page-framework-demo' ) . ': ' . $inputArray['event_location_new']['event_street'];
        $_fIsValid = false;         

    }
michaeluno commented 10 years ago

I uploaded the 3.0.4b branch that includes an example of setting a field error for the field that belongs to a section.

    public function validation_APF_MetaBox_BuiltinFieldTypes( $aInput, $aOldInput ) {   // validation_{instantiated class name}

        $_fIsValid = true;
        $_aErrors = array();

        // You can check the passed values and correct the data by modifying them.
        // $this->oDebug->logArray( $aInput );      

        // Validate the submitted data.
        if ( strlen( trim( $aInput['metabox_text_field'] ) ) < 3 ) {

            $_aErrors['metabox_text_field'] = __( 'The entered text is too short! Type more than 2 characters.', 'admin-page-framework-demo' ) . ': ' . $aInput['metabox_text_field'];
            $_fIsValid = false;         

        }
        if ( empty( $aInput['misc']['metabox_password'] ) ) {

            $_aErrors['misc']['metabox_password'] = __( 'The password cannot be empty.', 'admin-page-framework-demo' );
            $_fIsValid = false;

        }

        if ( ! $_fIsValid ) {

            $this->setFieldErrors( $_aErrors );
            $this->setSettingNotice( __( 'There was an error in your input.', 'admin-page-framework-demo' ) );  
            return $aOldInput;

        }

        return $aInput;

    }

Download: https://github.com/michaeluno/admin-page-framework/archive/3.0.4b.zip

In this update, the ability to set an error message to the whole section was added.

            $_aErrors['misc'] = __( 'There is an error in your input in the misc section.', 'admin-page-framework-demo' );
patrickf0 commented 10 years ago

I still do not get the error message :/

My SectionSetting

$this->addSettingSections(
        array( 
            'section_id'    => 'event_location_old',
            'description'   => 'Sie k&ouml;nnen entweder einen bereits gespeicherten Ort suchen oder einen neuen Ort anlegen.',
        ),
        array(
            'section_id'    => 'event_location_new',
            'description'   => 'Legen Sie hier einen neuen Ort an. Er wird automatisch abgespeichert, sobald Sie die Veranstaltung spiechern.',
        )
    );

My fields

 $this->addSettingFields(
        array(
            'section_id'    =>  'event_location_old',
            'type'          =>  'autocomplete',     
            'field_id'      =>  'event_location',
            'title'         =>  'Ort ausw&auml;hlen',
            'settings'      =>  $event_locations,
            'settings2'     =>  array(  // equivalent to the second parameter of the tokenInput() method
                'tokenLimit'        =>  1,
                'hintText'          =>  'Geben Sie einen Kurznamen, die Strasse oder den Ort ein'
            ),
        ),
        array(
            'field_id'      =>  'event_location_add',
            'section_id'    =>  'event_location_old',
            'type'          =>  'submit',
            'value'         =>  'Neuen Ort eingeben',
            'attributes'    =>  array(
                'class'     =>  'button button-secondary'
            )
        ),
        array(
            'field_id'      =>  'event_street',
            'section_id'    =>  'event_location_new',
            'title'         =>  'Stra&szlige und Hausnummer',
            'type'          =>  'text',
            'attributes'    =>  array(
                'size'  => 30
            )
        ),
        array(
            'field_id'      =>  'event_zip',
            'section_id'    =>  'event_location_new',
            'title'         =>  'PLZ',
            'type'          =>  'text',
            'attributes'    =>  array(
                'size'  => 30
            )
        ),
        array(
            'field_id'      =>  'event_town',
            'section_id'    =>  'event_location_new',
            'title'         =>  'Ort',
            'type'          =>  'text',
            'attributes'    =>  array(
                'size'  => 30
            )
        ),
        array(
            'field_id'      =>  'event_location_name',
            'section_id'    =>  'event_location_new',
            'title'         =>  'Kurzname des Ortes',
            'type'          =>  'text',
            'attributes'    =>  array(
                'size'  => 30
            ),
            'description'   =>  'Bitte beachten Sie, dass Sie einen eindeutigen Kurznamen angeben<br/>
                                (Unter diesem Kurznamen wird der Ort abgespeichert)!'
        )
    );

My validation:

public function validation_Event_Location_MetaBox( $inputArray , $oldInputArray ) {

    $_fIsValid = true;
    $_aErrors = array();

    // You can check the passed values and correct the data by modifying them.
    // $this->oDebug->logArray( $aInput );      

    // Validate the submitted data.
    if ( empty( $inputArray['event_location_new']['event_street'] ) ) {

        $_aErrors['event_location_new'] = __( 'The entered text is too short! Type more than 2 characters.', 'admin-page-framework-demo' );
        $_fIsValid = false;         

    }

    if ( ! $_fIsValid ) {

        $this->setFieldErrors( $_aErrors );
        $this->setSettingNotice( 'There was an error in your input.' ); 
        return $$oldInputArray;

    }

    return $inputArray;

}
michaeluno commented 10 years ago

That's strange. Is the example of the demo plugin working?

By the way, I just updated the 3.0.4b branch which fixes a fatal error that occurred in some pages so please make sure that you have the latest version 3.0.4b04.

[edit] You have a typo here return $$oldInputArray; but I'm not sure if that helps.

patrickf0 commented 10 years ago

The Demo does the job... maybe I´ve got an error somewhere. I corrected the typo but doesn´t make a difference.

michaeluno commented 10 years ago

It is recommended to set these constants in your wp-config.php.

    define('WP_DEBUG', true);
    define('WP_DEBUG_LOG', true);

And try inserting the following debug function calls in your start_{class name}() method and creating a new post with field values which deliberately fail the validation. A framework log file should be created in the wp-content folder. And let me know if the field errors are recorded.

    public function start_Event_Location_MetaBox() {        // start_{instantiated class name}

        // check the field error transient
        $this->oDebug->logArray( array( 'AdminPageFramework_FieldErrors' => get_transient( 'AdminPageFramework_FieldErrors' ) ) );
        $this->oDebug->logArray( array( '_getFieldErrors()' => $this->_getFieldErrors() ) );

    }
michaeluno commented 10 years ago

The request has been implemented so I'm going to close this topic. If there is a problem with this new functionality, post a new issue.