Do you have some feature in mind that you'd love to see in Couch? Let us know.
5 posts Page 1 of 1
@KK,

I could say that 99% of examples in the forum with db_persist tag involve condition on k_success / k_error variables.
If a third-party code sets a custom error on 'page_saved' event, it can be surprising that k_error would not have anything set in it.

Code: Select all
(excerpt from data-bound-form.php)


// Save..
$errors = $pg->save( $node->name );

..

if( $errors ){
..
    $str_err = '';
..
    $CTX->set( 'k_success', '' );
    $CTX->set( 'k_error', $str_err );
    $CTX->set( 'k_error_count', $errors );
    $CTX->set( 'k_persist_error', $str_err );
    $CTX->set( 'k_persist_error_count', $errors );

    // HOOK: db_xxx_savefailed
..
}


My experience today -

Screenshot_2020-07-04 Screenshot.png
Screenshot_2020-07-04 Screenshot.png (4.59 KiB) Viewed 871 times


I did not see any constraint on what we can set as $errors. I passed a string 'Readonly!', but could be anything, right? I am sure we can improve the situation. Stuffing 'k_error' with something should allow to trigger error handling in commonly-written code. By 'commonly-written' I mean code that does not use k_error_count or k_persist_error_count at all.
The $errors value is indeed a count of errors and is returned by $pg->save().

It is passed on through a couple of events for custom code to add their own validations and the expectation is that the custom code will act the way native validation works -
that is to check the field(s) it is interested in and if any fails custom validation, set that field's 'err_msg' and increase the $errors count e.g.
Code: Select all
$f->err_msg = 'This cannot be done this way!';
$errors++;

If this convention is followed, things will work as expected (e.g. the 'k_error' variable will contain the error message set above).

Now perhaps your next question would be as to why we don't enforce that convention.
Well, when the core allows custom code to jump into the workflow, a tacit understanding is that the called code is trusted and knows what it is doing (as opposed to the code used on the frontend that needs a lot more hand-holding).

Hope this answers your query.
@KK,

One more thing, please.

KK wrote: ..to check the field(s) it is interested in and if any fails custom validation, set that field's 'err_msg' and increase the $errors count.
My understanding is that either a field can fail custom validation, or a page can fail a custom validation as illustrated by this excerpt of couch/page.php -

Code: Select all

// Validate all fields before persisting changes
$errors = 0;
for( $x=0; $x<count($this->fields); $x++ ){
    ..
    // HOOK: validate_field
    ..
    if( !$f->validate() ) $errors++;
}

// HOOK: page_validate
// can add some custom page-level validation here if required.
$FUNCS->dispatch_event( 'page_validate', array(&$this->fields, &$errors, &$this) );

if( $errors ){ $DB->rollback(); return $errors; }

On top of that, subsequent events tied to saving individual field etc can generate errors as well.
In other words, you say that attaching an error to a field guarantees that 'k_error' will be set.

Finally, the 'page_saved' event provides the last opportunity to influence the workflow -
Code: Select all
// HOOK: page_saved
$FUNCS->dispatch_event( 'page_saved', array(&$this, &$errors) );
if( $errors ){ $DB->rollback(); return $errors; }


What would you recommend to do if the final decision is not tied to any field of that page? Should we just pick any arbitrary field (knowing that it is irrelevant to decision) - for instance a system field 'publish_date' - and attach '<h2>Shoo off!!</h2>' to it ?
My understanding is that either a field can fail custom validation, or a page can fail a custom validation as illustrated by this excerpt of couch/page.php -
I am sorry if that comment is ambiguous; The hook here supplies the fields and the current error count to custom code which then is supposed to work using these two values.

As for raising an error that is not tied to any field, there is no such provision so the code needs to piggy-back on any existing field.
KK wrote: As for raising an error that is not tied to any field, there is no such provision so the code needs to piggy-back on any existing field.

My routine is meant for both backend / frontend. I attached an error to a system field, because it is always present.

I like that saving a page in the front-end is not broken anymore and client-side code based on 'k_error' will react to a problem.

Screenshot_2020-07-05 Screenshot.png
Screenshot_2020-07-05 Screenshot.png (6.7 KiB) Viewed 859 times
A side effect is, of course, a message in Admin Panel with error description.

Screenshot_2020-07-05 Admin Panel.png
Screenshot_2020-07-05 Admin Panel.png (3.63 KiB) Viewed 859 times
I prefer to not display any messages in Admin Panel and keep them only to frontend scripts. In search of the solution, I explored KWebpage object and found a candybar that you left via function resolve_active_fallback. Finally, I used that and set up error
Code: Select all
if( $obj instanceof KWebpage ){
    // fallback for pages saved without using a form
    if( isset($obj->__args) && $obj->__args[0]=='db_persist' ){
        $obj->_fields['k_publish_date']->err_msg = 'Can not save at this moment!';
    }
}


Thank you for your interim help! :) I am still keeping my hopes for extending error messaging beyond a field!
5 posts Page 1 of 1