New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
!!! FEATURE: Arrays::getValueByPath with escaped dot #1903
base: 8.2
Are you sure you want to change the base?
Conversation
e48558a
to
7e024b5
Compare
Technically that's a feature, so should go into next release. But then again, escaping a dot might be an expected enough thing that we could relabel it as "BUGFIX"... Anyway, one thing I'm unsure about: $foo = ['bar\\' => ['baz' => 'value']]; I know, looks weird, but assume the key comes from a path traversal and stores directory names on a windows machine... (whole lot of edgy cases). |
@albe I have adapted the regular expression so that your example can be escaped. This makes it a breaking change, I think. |
7e024b5
to
7795c5f
Compare
Why would it be expected? I don't even know why it should be possible in the first place? This is an application specific syntax expression (aka path syntax) why does it need escaping support? |
With this change it is possible to use the command 'configuration:show' also for e.g. NodeTypes.
|
should do fine? |
Note: No it doesn't, got it now! |
It would also be nice to do something like this:
|
Shouldn't we then rather think about a nice syntax extension for the scope? Eg. Obviously we need to select the separate well! The brackets look nice but might collide with something ofc. |
Was just fiddling around with the regex myself and was now stuck at Edit: For reference, here's my fiddle with the ugly-ass "generic" solution: https://3v4l.org/pFoER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two small optimizations
} else { | ||
$path = preg_split('#((?<!\\\\)\\.|(?<=\\\\\\\\)\\.)#', $path); | ||
$path = array_map( | ||
function ($value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Micro-Optimization: this can be a static function ($value)
$path = preg_split('#((?<!\\\\)\\.|(?<=\\\\\\\\)\\.)#', $path); | ||
$path = array_map( | ||
function ($value) { | ||
return str_replace('\\.', '.', str_replace('\\\\', '\\', $value)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be reduced to str_replace(['\\\\', '\\.'], ['\\', '.'], $value)
As alternative here the version with the brackets: |
7795c5f
to
ca00646
Compare
The biggest gripe I have with both variants right now is that it turns a super simple and fast function that is used all over the place into something substantially more complex. And while the increase in processing time might be minimal the amount it gets used will probably make it tangible. |
The path given to utility can already be an array (probably should be split into two functions but separate problem) but I guess I woudl rather like to see the command doing the work and we accept a new argument "pathSegments" or something that is then an array of keys |
Yes, performance is an argument. I would have, under certain circumstances, the functionality not only in the command. What do you think about a second method "getValueByPathString" or something in the Arrays utility? |
Yep, that's also why I even slightly prefer the "imperfect" solution without the array_reduce. Guess that's something we can't easily debate or refactor away. Moving the splitting outside the function will strip it of it's core functionality, plus you have to handle all those places where the function is used. I agree though, that the method should be split into two - one that takes a So it comes down to a general decision/trade-off of "allowing dots in array keys" vs. code complexity+performance |
IDK, for me the nodetypes are a bit special, do we have any other place where we need this functionality? |
Then it shouldn't be in a general arrays utility, should it? I use it often with other arrays as well. |
I mean, it fullfills a specific task and that it does fast, but yeah we should certainly talk about that. |
So, how do we proceed? @kitsunet |
Not quite sure what happened to this PR, but it somehow got rebased (?) and a whole lot of other commits pulled in :/ Would like to go over this again tomorrow and see if we can make it mergeable then @kitsunet or rather postpone to 6.3 |
b949ec1
to
d527bc0
Compare
@albe I only see one commit, is there anything I can do to help? |
D'oh - has this resolved itself? :D Thanks! This bot is running rouge... |
See I tend to overlook that part :D I guess having 50k calls to strpos should be fine...? |
even though we have the |
just tested it, the regex, that i suggested takes less steps and is bullet proof too.
vs: |
As i see it its not important where we implement it: may it be directly in Sure it would be nice if this function can handle it as feature in the future but much more important - at least as i find - is that we have a way to use For now you can add the above into the
- $configuration = Arrays::getValueByPath($configuration, $path);
+ $configuration = Arrays::getValueByPath(
+ $configuration,
+ array_map('stripslashes', preg_split('#(?:\\\.)(*SKIP)(*FAIL)|\\.#', $path))
+ ); use it like:
(ps. dont miss the qoutes around the path, otherwise you need to escape the backslash) |
I think, that's a great compromise for an otherwise rather profound change! |
I will prepare a bugfix-pr for that |
Did the bugfix ever happen, as it's not referenced in here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By now I am less sceptical about this, so if we still want, lets do it.
Haha caught, no I never did that xD … yet … |
@kitsunet there was lately a discussion in slack about something similar and a lot of pain involved with escaping things. Since escaping multiple context is always hard to grasp (like when using ddev -> shell -> flow or worse when building up escaped commands in yaml) … I just want to make sure we make the right choice! After thinking about it i think i like your idea better: #1903 (comment) |
i think this is so much better
than
(note due to ddev we need another escaping layer in between, and its common to have to double escape stuff and hard to wrap the head around.) Btw its a breaking change ... technically ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aaand target 8.3
<?php
function parseInputString(string $input): array
{
$result = [];
$current = '';
$len = \strlen($input);
for ($i = 0; $i < $len; $i++) {
$char = $input[$i];
switch ($char) {
case "[":
if ($current !== "") {
$result[] = $current;
$current = "";
}
for ($i++; $i < $len; $i++) {
$char = $input[$i];
switch ($char) {
case "[":
throw new \Exception(sprintf('Unexpected char "%s" at position "%s" in "%s"', $char, $i, $input));
case "]":
if ($current !== "") {
$result[] = $current;
$current = "";
}
$nextChar = $input[$i + 1] ?? "";
if ($nextChar !== "" && $nextChar !== ".") {
throw new Exception('Missing dot after closing');
}
break 2;
default:
$current .= $char;
}
}
break;
case "]":
throw new \Exception(sprintf('Unexpected char "%s" at position "%s" in "%s"', $char, $i, $input));
case ".":
if ($current !== "") {
$result[] = $current;
$current = "";
}
break;
default:
$current .= $char;
}
}
if ($current !== "") {
$result[] = $current;
}
return $result;
}
$input = 'fooo.bar[dots.are.are.lowed].something.else';
$output = parseInputString($input);
print_r($output); i will implement this in the config:show command as bugfix ;)
|
grüße aus dreden |
it was discussed on the dd sprint 23 #2973 (comment) that we want to use json for complex cli arguments (including dot escaping) and use Array.getValueByPath on php site better with actual arrays instead of paths |
It is now possible to escape the dot in the path of Arrays::getValueByPath.
With this you get array keys, which have a dot.
Example:
What I did
It is now possible to escape the dot in the path of Arrays::getValueByPath.
How I did it
I have adapted the method Arrays::getValueByPath
How to verify it
I wrote a test for it.
Checklist