|  | 
| 2 | 2 | 
 | 
| 3 | 3 | namespace Coduo\PHPMatcher\Matcher; | 
| 4 | 4 | 
 | 
|  | 5 | +use Coduo\PHPMatcher\Exception\Exception; | 
| 5 | 6 | use Coduo\PHPMatcher\Parser; | 
| 6 | 7 | use Coduo\ToString\StringConverter; | 
| 7 | 8 | use Symfony\Component\PropertyAccess\PropertyAccess; | 
| @@ -144,19 +145,56 @@ private function iterateMatch(array $values, array $patterns, $parentPath = "") | 
| 144 | 145 |     private function isPatternValid(array $pattern, array $values, $parentPath) | 
| 145 | 146 |     { | 
| 146 | 147 |         if (is_array($pattern)) { | 
| 147 |  | -            $notExistingKeys = array_diff_key($pattern, $values); | 
|  | 148 | +            $skipPattern = static::UNBOUNDED_PATTERN; | 
|  | 149 | + | 
|  | 150 | +            $pattern = array_filter( | 
|  | 151 | +                $pattern, | 
|  | 152 | +                function ($item) use ($skipPattern) { | 
|  | 153 | +                    return $item !== $skipPattern; | 
|  | 154 | +                } | 
|  | 155 | +            ); | 
|  | 156 | + | 
|  | 157 | +            $notExistingKeys = $this->findNotExistingKeys($pattern, $values); | 
| 148 | 158 | 
 | 
| 149 | 159 |             if (count($notExistingKeys) > 0) { | 
| 150 | 160 |                 $keyNames = array_keys($notExistingKeys); | 
| 151 | 161 |                 $path = $this->formatFullPath($parentPath, $this->formatAccessPath($keyNames[0])); | 
| 152 | 162 |                 $this->setMissingElementInError('value', $path); | 
|  | 163 | + | 
| 153 | 164 |                 return false; | 
| 154 | 165 |             } | 
| 155 | 166 |         } | 
| 156 | 167 | 
 | 
| 157 | 168 |         return true; | 
| 158 | 169 |     } | 
| 159 | 170 | 
 | 
|  | 171 | +    /** | 
|  | 172 | +     * Finds not existing keys | 
|  | 173 | +     * Excludes keys with pattern which includes Optional Expander | 
|  | 174 | +     * | 
|  | 175 | +     * @param $pattern | 
|  | 176 | +     * @param $values | 
|  | 177 | +     * @return array | 
|  | 178 | +     */ | 
|  | 179 | +    private function findNotExistingKeys($pattern, $values) | 
|  | 180 | +    { | 
|  | 181 | +        $notExistingKeys = array_diff_key($pattern, $values); | 
|  | 182 | + | 
|  | 183 | +        return array_filter($notExistingKeys, function ($pattern) use ($values) { | 
|  | 184 | +            if (is_array($pattern)) { | 
|  | 185 | +                return !$this->match($values, $pattern); | 
|  | 186 | +            } | 
|  | 187 | + | 
|  | 188 | +            try { | 
|  | 189 | +                $typePattern = $this->parser->parse($pattern); | 
|  | 190 | +            } catch (Exception $e) { | 
|  | 191 | +                return true; | 
|  | 192 | +            } | 
|  | 193 | + | 
|  | 194 | +            return !$typePattern->hasExpander('optional'); | 
|  | 195 | +        }); | 
|  | 196 | +    } | 
|  | 197 | + | 
| 160 | 198 |     /** | 
| 161 | 199 |      * @param $value | 
| 162 | 200 |      * @param $pattern | 
|  | 
0 commit comments