Jump to content

Problem getting field values


MarkE
 Share

Recommended Posts

I'm probably being a bit dim, but I have been struggling a while with this:

I'm developing a club membership site and generally it's going pretty well. I'm using custom page types as per this excellent tutorial: https://processwire.com/docs/tutorials/using-custom-page-types-in-processwire/

One such page type is a Mandate, which holds direct debit mandate details (using GoCardless). A method of the Mandate class is called whenever a webhook detects a change in status of a mandate. Two other templates are Payment and Collection. Payment pages (siblings of Mandates) hold details of required payments, whereas Collection pages (children of Mandates) hold details of collections attempted via direct debit.

The relevant code of the webhook_update method of Mandate is:

if ($event->action == 'created' || 'submitted' || 'active') {
    $osGCPayments = $this->parent->find("template=Payment, paymentStatus=order_placed, paymentMethod=1154");  // 1154 is id of GoCardless type
    if ($osGCPayments) {
        $osCollections = $this->find("template=Collection, paymentStatus!=paid_out");
        $totalInCollection = 0;
        foreach($osCollections as $colln) {
            $totalInCollection += $colln->paymentAmount;
        }
        $unpaid = -$totalInCollection;
        $payIds = [];
        foreach($osGCPayments as $os) {
            foreach ($os->fields as $f){
                $this->body .= ('Field: ' . $f->name . ', Val: ' . $os->$f . '; ');
            }
            $unpaid += $os->paymentAmount;
            $payIds += [$os->id];
        }
        if ($unpaid > 0) {
            $amountInPence = $unpaid * 100;
            $this->create_payment($client, $mandateId, $amountInPence, $payIds);
        }
    }
}

The problem is that $os->paymentAmount, which has a value on the Payment page, returns no value in the above code.

The line 

$this->body .= ('Field: ' . $f->name . ', Val: ' . $os->$f . '; ');

was inserted to aid debugging and puts all the field names and values into the body of the Mandate page. The 'foreach's containing it run and inspecting the output shows that some of the fields have the correct values (including those that uniquely identify the page so that I am sure I am looking at the right one!), but that paymentAmount (float type), paymentMethod (page reference) and paymentDate (Datetime) are shown as empty. RuntimeMarkup and Text fields are shown correctly.

The odd thing is that, for the foreach to run, $osGCPayments  clearly contains the correct Payment pages, which means that the paymentMethod=1154 selector operated correctly, but paymentMethod is one of the field values that then appears to be empty in the selected pages.

BTW, there are no Collection pages yet, so the first foreach does not run.

Thanks in advance for any suggestions and apologies if I have done something stupid?

Link to comment
Share on other sites

I'm not sure about the cause of the problem but I know a good way to get closer to the solution: install Tracy Debugger and barDump the problem variables.

bd($os->paymentAmount, '$os->paymentAmount');

My golden rule is: any time something isn't working the way you expect it to, or you don't understand how something is working, or you're just plain curious, then start dumping variables/properties/objects left, right and centre. Best way to advance your knowledge IMHO.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Thanks for that. I have installed Tracy Debugger, but haven't yet fully comprehended it. I can't get barDump to give me anything - I guess because this whole thing is run from a webhook and not executed in the browser. I'll try initiating the same code from the browser and see what happens...

Link to comment
Share on other sites

Hmm. I moved the code into a new method so that I could invoke it from the browser via a save hook or externally via a webhook. If I invoke it from the browser it works OK, but if it runs from the webhook then the problem persists. And I can't see how Tracy can help in the webhook case (which is why I dumped the vars to the page body).

Link to comment
Share on other sites

... so I disabled the direct running from the webhook and left the save hook in place. The idea being that when the webhook updated the page, the save hook would then run. Which it did, but still exhibiting the same problem...

... might it be something to do with whether the method gets initiated from the front end (webhook) or back end?..

... Aha! - looks like the missing fields have additional access restrictions. The webhook, coming from the front end is treated as "guest" so the fields are not visible to it. So I think I may have found the cause - just need to find a solution now ?

Link to comment
Share on other sites

19 minutes ago, MarkE said:

... Aha! - looks like the missing fields have additional access restrictions. The webhook, coming from the front end is treated as "guest" so the fields are not visible to it. So I think I may have found the cause - just need to find a solution now ?

There is this option on the Access tab of the restricted fields:

2019-01-04_132759.png.61fd0b9f5a89322720003b4da2ced0d6.png

 

1 hour ago, MarkE said:

I can't get barDump to give me anything - I guess because this whole thing is run from a webhook and not executed in the browser.

The Dumps Recorder panel can be useful in such cases: https://adrianbj.github.io/TracyDebugger/#/debug-bar?id=dumps-recorder

  • Like 2
Link to comment
Share on other sites

8 hours ago, Robin S said:

There is this option on the Access tab of the restricted fields:

Thanks for that. Reading the explanation (i.e. that the contents are masked by output formatting), I wonder whether it is better to over-ride this for the field in general or just in the specific use case (the webhook). I tried inserting 

$os->of(false);

and the problem was fixed ? 

It seems to me that if there is only one use case to fix, this approach may be better than generally allowing the API access. However, it's nice to have the choice and this episode once again proves how well-designed PW is (even if its features are not immediately apparent to relative newbies like me!).

  • Like 1
Link to comment
Share on other sites

19 hours ago, MarkE said:

Reading the explanation (i.e. that the contents are masked by output formatting), I wonder whether it is better to over-ride this for the field in general or just in the specific use case (the webhook).

I never noticed before that field access restrictions depend on output formatting. I guess that would be a good way to turn off the access restrictions on a per page or even per field basis.

You're right that output formatting is mentioned in the "Access toggles" field notes but it's a bit subtle and not really emphasised that field access restrictions don't work when output formatting is off. Definitely something to watch out for as it's not intuitive that these things would be connected and I can imagine situations where people could be caught out by this, accidentally revealing data that they thought was restricted.

Link to comment
Share on other sites

Maybe I am missing something, but I do find it hard to get an overview of what data a given user can access, including via the API. Having fixed the problem in the OP, a different part of the same code then gave problems:

On 1/3/2019 at 8:06 PM, MarkE said:

$osCollections = $this->find("template=Collection, paymentStatus!=paid_out");

When run from the backend this works fine and finds all the relevant children. However, the webhook, coming in as guest returns an empty array. I checked and removed any access restrictions with no luck. I also changed the code to this (i.e. removed the selectors):

            if (wire()->session->webhook) echo('This mandate details - Title: ' . $this->title . ' Id: ' . $this->mandateId . ' Num of children = ' . $this->numChildren . '<br/>');
            $osCollections = $this->children; // was find("template=Collection, paymentStatus!=paid_out");
            if (wire()->session->webhook) echo('Number of collections found = ' . $osCollections->count() . '<br/>');

This resulted in the following response to the webhook:

This mandate details - Title: Mandate Id: MD0004TV8F2YP3 Num of children = 24<br/>Number of collections found = 0<br/>

So $this->numChildren is correct, but $this->children is empty

?

FWIW, here is the print_r output immediately afterwards:

(
    [hooks] => Array
        (
            [PageArray::render] => MarkupPageArray->renderPageArray() in MarkupPageArray.module
            [PaginatedArray::renderPager] => MarkupPageArray->renderPager() in MarkupPageArray.module
        )

    [count] => 0
    [total] => 0
    [start] => 0
    [limit] => 0
    [selectors] => parent_id=2661, sort=sort, status<1024
)

 

Edited by MarkE
update
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...