3.x FormHelper:: Allow to specify the source of injected form field values#9127
3.x FormHelper:: Allow to specify the source of injected form field values#9127markstory merged 19 commits intocakephp:3.nextfrom
Conversation
| return []; | ||
| } | ||
|
|
||
| public function getValuesSources() |
There was a problem hiding this comment.
Missing function doc comment
Missing blank line before return statement
| return $this; | ||
| } | ||
|
|
||
| public function getSourceValue($fieldname) |
There was a problem hiding this comment.
Missing function doc comment
| } | ||
|
|
||
| /** | ||
| * T O D O |
There was a problem hiding this comment.
Whitespace found at end of line
| if ($valuesSource === 'context') { | ||
| return $this->_getContext()->val($fieldname); | ||
| } | ||
| if (isset($this->request->{$valuesSource}[$fieldname])) { |
There was a problem hiding this comment.
You need to use the methods instead of properties else you won't get values for field names like foo.bar.
There was a problem hiding this comment.
Yes I considered that. Has that feature been merged yet? (thought it was part of the dot syntax for Entity::get()).
@ADmad So how would I differentiate between a legitimate null/false and the method just not finding anything within the path?
There was a problem hiding this comment.
1176: * When reading values you will get
nullfor keys/values that do not exist.
http://api.cakephp.org/3.3/source-class-Cake.Network.Request.html#1166-1203
Due to data() being a getter and setter I cannot even patch it to take a flag to be strict and through exceptions when values are not being found.
@markstory any ideas? New methods like getData(), setData(), getQuery(), setQuery()? where the last is $options and there you could disable throwing of exceptions?
There was a problem hiding this comment.
There was a problem hiding this comment.
So how would I differentiate between a legitimate null/false and the method just not finding anything within the path?
You don't need to since post data and query string can only have string values.
There was a problem hiding this comment.
For unmodified $_POST and $_GET, yes - for $this->request->data and $this->request->query, not necessarily.
It fails for instance if you do $this->request->data = $this->Articles->get($id) and it does fill some fields with null which you then overwrite via query sourceValues e.g. <?= $this->Form->create(null, ['values' => ['data', 'query']]) ?> - not that I advertise such code.
…ing there is never null within $this->data->post[]/query[]
| 'encoding' => strtolower(Configure::read('App.encoding')), | ||
| 'templates' => null, | ||
| 'idPrefix' => null, | ||
| 'valuesSources' => [], |
There was a problem hiding this comment.
This should default to ['data', 'context'].
There was a problem hiding this comment.
Right my mind was broken when I removed it! 'Context' alone would do it. Both or just context?
There was a problem hiding this comment.
Yes, just ['context'] would be enough.
|
Please let me know if anything is missing/wrong/off. I will probably find time the next weekend to add unit tests so that this PR becomes merge-able. @michaelze let me know if this would be sufficient for your use cases because it is an alternative implementation to your original PR. Edit: I'll take a look at why tests are failing ASAP - If you have hints/pointers. Let me know. |
| * Gets a single field value from the sources available. | ||
| * | ||
| * @param string $fieldname The fieldname to fetch the value for. | ||
| * @return string Field value derived from sources. |
There was a problem hiding this comment.
Should be string|null as the bottom of the method can return a null implicitly.
|
@ionas The tests are failing because |
|
You'll need to resolve the merge conflicts. |
|
|
||
| /** | ||
| * Tests the different input rendering values based on sources values switching while supplying | ||
| * an entity (base context) and multiple sources (durch as data, query) |
6b41d1b to
cb979eb
Compare
|
I have resolved the merge conflict by adding support for |
|
Anything else? I don't want it to get out of sync with HEAD/master again ;). |
| return $this->request->{$valuesSource}($fieldname); | ||
| } | ||
| } | ||
| if ($options['default'] !== null && $options['default'] !== false) { |
There was a problem hiding this comment.
Why do you need to exclude false? Boolean fields can have a default value of false.
| } | ||
| if ($options['schemaDefault'] !== null && $options['schemaDefault'] !== false) { | ||
| return $options['schemaDefault']; | ||
| } |
There was a problem hiding this comment.
Could tests be added for this behavior?
There was a problem hiding this comment.
Done. I did also remove the false check and hardened the not null test via isset().
…added tests for that
| return $this->request->{$valuesSource}($fieldname); | ||
| } | ||
| } | ||
| return null; |
There was a problem hiding this comment.
Missing blank line before return statement
| $this->Form->setValuesSources(['query']); | ||
| $result = $this->Form->getSourceValue('title'); | ||
| $expected = ''; | ||
| $this->assertEquals($expected, $result); |
There was a problem hiding this comment.
Why don't the schema defaults apply when the source is 'query'?
There was a problem hiding this comment.
if you want to apply the schema defaults you need to do:
$this->Form->setValuesSources('context'); // The default
// or
$this->Form->setValuesSources(['query', 'context']);
// or
$this->Form->setValuesSources(['context', 'query']);Without allowing the context, you will get nothing out of it. At least that was the goal.
And yes, usually you want the context, and you can have it.
There was a problem hiding this comment.
If the context is required to get default values, why is this code here? EntityContext:val() already handles providing schema defaults.
There was a problem hiding this comment.
Because you can supply 'schemaDefaults' as an option to FormHelper::create() but not utilise the EntityContext?
You say I should remove:
if (isset($options['schemaDefault'])) {
return $options['schemaDefault'];
}
?
There was a problem hiding this comment.
Its not in the source anymore anyway - I removed it in the last commit @ above line.
So what is missing from your point of view? What do you want me to change?
There was a problem hiding this comment.
Why don't the schema defaults apply when the source is 'query'?
@markstory Because only context instance knows about the schema defaults. So just setting sources to ['query'] wouldn't would apply schema defaults but setting it to ['query', 'context'] would.
There was a problem hiding this comment.
@ADmad Ok that makes sense to me. The duplicate code I was concerned about has been removed.
|
So is this going into master or the 3.next outlined on the right sidebar? |
|
@dereuromark I'll merge it into 3.next. I'm a little gun-shy on adding potentially disruptive features into |
|
While I don't look forward to updating it again in terms of merge conflicts I am 👍 on going more with semver on non-tiny-features. Updating docs. Let me know if I need to do anything else in before 3.next merge. |
This PR implements what has been suggested here: #8093 (comment)
In case there is a general consensus that this is a good approach, then I will add:
doc blocksDone.I did test this on a simple baked Article edit form:
https://cakephp.dev/articles/edit/1?title=foo&body=barThis would take data from query and then from context. It respects order. E.g. this would also work:
Note
Initially I wanted to let
Contextshandle this. HoweverFormHelper::_addDefaultContextProviders()is being called when theFormHelperis being constructed, not whenFormHelper::create()is being called. As far as I can see Construction time would be the only place to pass down data such as$this->request->queryor$this->request->dataConcernsMaybe the option flagDone.valuesshould be namedvaluesSourcesfor theFormHelper::create()options interface, too?Extensibility
This could also be made configurable when FormHelper is being setup via
::loadHelper().In case this makes it through I can add support for this.