public function DataFetcher::autocompletePropertyPath in Typed Data API enhancements 8
Provides autocomplete suggestions for an incomplete property path.
Parameters
\Drupal\Core\TypedData\DataDefinitionInterface[] $data_definitions: A map of available data definitions that should be seareched. The array keys are the first part of the property path.
string $partial_property_path: The partial property path, example: "node.uid.ent".
Return value
array[] A list of autocomplete suggestions - valid property paths for one of the provided data definitions. Each entry is an array with the following keys:
- value: the data selector property path.
- label: the human readable label suggestion.
Overrides DataFetcherInterface::autocompletePropertyPath
File
- src/
DataFetcher.php, line 166
Class
- DataFetcher
- Implementation of the data fetcher service.
Namespace
Drupal\typed_dataCode
public function autocompletePropertyPath(array $data_definitions, $partial_property_path) {
// For the empty string we suggest the names of the data definitions.
if ($partial_property_path == '') {
return array_keys($data_definitions);
}
$results = [];
// Suggest top level variables where the partial path matches the start of
// the top level variable name.
foreach ($data_definitions as $variable_name => $data_definition) {
if (stripos($variable_name, $partial_property_path) === 0) {
$results = array_merge($results, $this
->getAutocompleteSuggestion($data_definition, $variable_name));
}
}
if (!empty($results)) {
return $results;
}
// Partial path now contains more than just a top level variable. In order
// to separate the variable parts we have to account for the syntax of
// global context variables versus local context variables.
// Global context variables begin with '@' and have a colon separating the
// global context from the variable.
$colon = strpos($partial_property_path, ':');
if ($colon === FALSE) {
// This is NOT a global context variable, so we only have to worry about
// the '.' separators.
$parts = explode('.', $partial_property_path);
$first_part = array_shift($parts);
}
else {
// This IS a global context variable, so the entire string up to and
// including the ':' needs to be removed before we split the remainder
// at the '.' separators.
$parts = explode('.', substr($partial_property_path, $colon + 1));
$first_part = substr($partial_property_path, 0, $colon + 1) . array_shift($parts);
}
if (!isset($data_definitions[$first_part])) {
return [];
}
$last_part = array_pop($parts);
$middle_path = implode('.', $parts);
if ($middle_path === '') {
$variable_definition = $data_definitions[$first_part];
}
else {
try {
$variable_definition = $this
->fetchDefinitionByPropertyPath($data_definitions[$first_part], $middle_path);
} catch (InvalidArgumentException $e) {
// Invalid property path, so no suggestions available.
return [];
}
}
// If the current data is just a reference then directly dereference the
// target.
if ($variable_definition instanceof DataReferenceDefinitionInterface) {
$variable_definition = $variable_definition
->getTargetDefinition();
}
if ($variable_definition instanceof ListDataDefinitionInterface) {
// Suggest a couple of example indices of a list if there is nothing
// selected on it yet. Special case for fields: only make the suggestion
// if this is a multi-valued field.
if ($last_part === '' && !($variable_definition instanceof FieldDefinitionInterface && $variable_definition
->getFieldStorageDefinition()
->getCardinality() === 1)) {
if ($middle_path === '') {
$property_path = $first_part;
}
else {
$property_path = "{$first_part}.{$middle_path}";
}
$item_definition = $variable_definition
->getItemDefinition();
for ($i = 0; $i < 3; $i++) {
$results = array_merge($results, $this
->getAutocompleteSuggestion($item_definition, "{$property_path}.{$i}"));
}
}
// If this is a list but the selector is not an integer, we forward the
// selection to the first element in the list.
if (!ctype_digit($last_part)) {
$variable_definition = $variable_definition
->getItemDefinition();
}
}
if ($variable_definition instanceof ComplexDataDefinitionInterface) {
foreach ($variable_definition
->getPropertyDefinitions() as $property_name => $property_definition) {
// If the property starts with the part then we have a suggestion. If
// the part after the dot is the empty string we include all properties.
if (stripos($property_name, $last_part) === 0 || $last_part === '') {
if ($middle_path === '') {
$property_path = "{$first_part}.{$property_name}";
}
else {
$property_path = "{$first_part}.{$middle_path}.{$property_name}";
}
$results = array_merge($results, $this
->getAutocompleteSuggestion($property_definition, $property_path));
}
}
}
usort($results, function ($a, $b) {
return strnatcasecmp($a['value'], $b['value']);
});
return $results;
}