/** * @param string $term * @return string */ public function autocompleteAction($term) { $searchProperty = $this->widgetConfiguration['searchProperty']; /** @var $queryResult QueryResultInterface */ $queryResult = $this->widgetConfiguration['objects']; $query = clone $queryResult->getQuery(); $constraint = $query->getConstraint(); if ($constraint !== null) { $query->matching($query->logicalAnd($constraint, $query->like($searchProperty, '%' . $term . '%', false))); } else { $query->matching($query->like($searchProperty, '%' . $term . '%', false)); } if (isset($this->configuration['limit'])) { $query->setLimit((int) $this->configuration['limit']); } $results = $query->execute(); $output = array(); $values = array(); foreach ($results as $singleResult) { $val = ObjectAccess::getPropertyPath($singleResult, $searchProperty); if (isset($values[$val])) { continue; } $values[$val] = true; $output[] = array('id' => $val, 'label' => $val, 'value' => $val); } return json_encode($output); }
/** * The input is assumed to be an array or Collection of objects. Groups this input by the $groupingKey property of each element. * * @param array|Collection $set * @param string $groupingKey * @return array */ public function groupBy($set, $groupingKey) { $result = array(); foreach ($set as $element) { $result[ObjectAccess::getPropertyPath($element, $groupingKey)][] = $element; } return $result; }
/** * @return void */ public function up() { $this->processConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, function (array &$configuration) { $presetsConfiguration = ObjectAccess::getPropertyPath($configuration, 'Neos.Form.presets'); if (!is_array($presetsConfiguration)) { return; } $presetsConfiguration = $this->renameTranslationPackage($presetsConfiguration); $configuration['TYPO3']['Form']['presets'] = $presetsConfiguration; }, true); }
/** * Renders the view * * @return string The rendered view * @api */ public function render() { $source = $this->getOption('templateSource'); $templatePathAndFilename = $this->getOption('templatePathAndFilename'); if ($templatePathAndFilename !== null) { $source = file_get_contents($templatePathAndFilename); } return preg_replace_callback('/\\{([a-zA-Z0-9\\-_.]+)\\}/', function ($matches) { return ObjectAccess::getPropertyPath($this->variables, $matches[1]); }, $source); }
/** * Updates the password credential from the POST vars, if the POST parameters * are available. Sets the authentication status to AUTHENTICATION_NEEDED, if credentials have been sent. * * Note: You need to send the password in this POST parameter: * __authentication[TYPO3][Flow][Security][Authentication][Token][PasswordToken][password] * * @param ActionRequest $actionRequest The current action request * @return void */ public function updateCredentials(ActionRequest $actionRequest) { if ($actionRequest->getHttpRequest()->getMethod() !== 'POST') { return; } $postArguments = $actionRequest->getInternalArguments(); $password = ObjectAccess::getPropertyPath($postArguments, '__authentication.TYPO3.Flow.Security.Authentication.Token.PasswordToken.password'); if (!empty($password)) { $this->credentials['password'] = $password; $this->setAuthenticationStatus(self::AUTHENTICATION_NEEDED); } }
/** * Returns contents of Composer manifest - or part there of. * * @param string $manifestPath * @param string $configurationPath Optional. Only return the part of the manifest indexed by configurationPath * @return array|mixed */ public static function getComposerManifest($manifestPath, $configurationPath = null) { $composerManifest = static::readComposerManifest($manifestPath); if ($composerManifest === null) { return null; } if ($configurationPath !== null) { return ObjectAccess::getPropertyPath($composerManifest, $configurationPath); } else { return $composerManifest; } }
/** * {@inheritdoc} * * @param FlowQuery $flowQuery the FlowQuery object * @param array $arguments the property path to use (in index 0) * @return mixed */ public function evaluate(FlowQuery $flowQuery, array $arguments) { if (!isset($arguments[0]) || empty($arguments[0])) { throw new FlowQueryException('property() must be given an attribute name when used on objects, fetching all attributes is not supported.', 1332492263); } else { $context = $flowQuery->getContext(); if (!isset($context[0])) { return null; } $element = $context[0]; $propertyPath = $arguments[0]; return ObjectAccess::getPropertyPath($element, $propertyPath); } }
/** * @test * @dataProvider attributeExamples */ public function evaluateTests($properties, $expectedOutput) { $path = 'attributes/test'; $this->mockTsRuntime->expects($this->any())->method('evaluate')->will($this->returnCallback(function ($evaluatePath, $that) use($path, $properties) { $relativePath = str_replace($path . '/', '', $evaluatePath); return ObjectAccess::getPropertyPath($properties, str_replace('/', '.', $relativePath)); })); $typoScriptObjectName = 'Neos.Fusion:Attributes'; $renderer = new AttributesImplementation($this->mockTsRuntime, $path, $typoScriptObjectName); if ($properties !== null) { foreach ($properties as $name => $value) { ObjectAccess::setProperty($renderer, $name, $value); } } $result = $renderer->evaluate(); $this->assertEquals($expectedOutput, $result); }
/** * {@inheritdoc} * * @param FlowQuery $flowQuery the FlowQuery object * @param array $arguments the arguments for this operation * @return mixed */ public function evaluate(FlowQuery $flowQuery, array $arguments) { if (!isset($arguments[0]) || empty($arguments[0])) { throw new FlowQueryException('property() does not support returning all attributes yet', 1332492263); } else { $context = $flowQuery->getContext(); $propertyPath = $arguments[0]; if (!isset($context[0])) { return null; } $element = $context[0]; if ($propertyPath[0] === '_') { return ObjectAccess::getPropertyPath($element, substr($propertyPath, 1)); } else { return $element->getProperty($propertyPath); } } }
/** * {@inheritdoc} * * First argument is the node property to sort by. Works with internal arguments (_xyz) as well. * Second argument is the sort direction (ASC or DESC). * * @param FlowQuery $flowQuery the FlowQuery object * @param array $arguments the arguments for this operation. * @return mixed */ public function evaluate(FlowQuery $flowQuery, array $arguments) { $nodes = $flowQuery->getContext(); // Check sort property if (isset($arguments[0]) && !empty($arguments[0])) { $sortProperty = $arguments[0]; } else { throw new \Neos\Eel\FlowQuery\FlowQueryException('Please provide a node property to sort by.', 1467881104); } // Check sort direction if (isset($arguments[1]) && !empty($arguments[1]) && in_array(strtoupper($arguments[1]), ['ASC', 'DESC'])) { $sortOrder = strtoupper($arguments[1]); } else { throw new \Neos\Eel\FlowQuery\FlowQueryException('Please provide a valid sort direction (ASC or DESC)', 1467881105); } $sortedNodes = []; $sortSequence = []; $nodesByIdentifier = []; // Determine the property value to sort by /** @var Node $node */ foreach ($nodes as $node) { if ($sortProperty[0] === '_') { $propertyValue = \Neos\Utility\ObjectAccess::getPropertyPath($node, substr($sortProperty, 1)); } else { $propertyValue = $node->getProperty($sortProperty); } if ($propertyValue instanceof \DateTime) { $propertyValue = $propertyValue->getTimestamp(); } $sortSequence[$node->getIdentifier()] = $propertyValue; $nodesByIdentifier[$node->getIdentifier()] = $node; } // Create the sort sequence if ($sortOrder === 'DESC') { arsort($sortSequence); } elseif ($sortOrder === 'ASC') { asort($sortSequence); } // Build the sorted context that is returned foreach ($sortSequence as $nodeIdentifier => $value) { $sortedNodes[] = $nodesByIdentifier[$nodeIdentifier]; } $flowQuery->setContext($sortedNodes); }
/** * @param array $commandOptions * @param array $adjustmentOptions * @param string $commandOptionPath * @param string $adjustmentOptionName * @return void */ protected function transferOptionFromCommandToAdjustment(array $commandOptions, array &$adjustmentOptions, $commandOptionPath, $adjustmentOptionName) { $commandOptionValue = ObjectAccess::getPropertyPath($commandOptions, $commandOptionPath); if ($commandOptionValue !== null) { ObjectAccess::setProperty($adjustmentOptions, $adjustmentOptionName, $commandOptionValue); } }
/** * Redirects directly to \Neos\Utility\ObjectAccess::getPropertyPath($result, $propertyPath) * This is only needed for unit tests! * * @param mixed $object The object to fetch the property from * @param string $path The path to the property to be fetched * @return mixed The property value */ public function getObjectValueByPath($object, $path) { return ObjectAccess::getPropertyPath($object, $path); }
/** * Read the option called $optionName from $this->options, and parse {...} * as object accessors. * * if $optionName was not found, the corresponding default option is returned (from $this->defaultOptions) * * @param string $optionName * @return mixed * @api */ protected function parseOption($optionName) { if (!isset($this->options[$optionName]) || $this->options[$optionName] === '') { if (isset($this->defaultOptions[$optionName])) { $option = $this->defaultOptions[$optionName]; } else { return null; } } else { $option = $this->options[$optionName]; } if (!is_string($option)) { return $option; } $formRuntime = $this->finisherContext->getFormRuntime(); return preg_replace_callback('/{([^}]+)}/', function ($match) use($formRuntime) { return \Neos\Utility\ObjectAccess::getPropertyPath($formRuntime, $match[1]); }, $option); }
/** * Returns the route value of the current route part. * This method can be overridden by custom RoutePartHandlers to implement custom resolving mechanisms. * * @param array $routeValues An array with key/value pairs to be resolved by Dynamic Route Parts. * @return string|array value to resolve. * @api */ protected function findValueToResolve(array $routeValues) { return ObjectAccess::getPropertyPath($routeValues, $this->name); }
/** * @param string $path * @return mixed */ public function getOptionByPath($path) { return ObjectAccess::getPropertyPath($this->options, $path); }
/** * {@inheritdoc} * * @param object $element * @param string $propertyPath * @return mixed */ protected function getPropertyPath($element, $propertyPath) { if ($propertyPath[0] === '_') { return ObjectAccess::getPropertyPath($element, substr($propertyPath, 1)); } else { return $element->getProperty($propertyPath); } }
/** * Evaluate a property path. This is outsourced to a single method * to make overriding this functionality easy. * * @param object $element * @param string $propertyPath * @return mixed */ protected function getPropertyPath($element, $propertyPath) { return ObjectAccess::getPropertyPath($element, $propertyPath); }
/** * returns the default value of the specified form element * or NULL if no default value was set * * @param string $elementIdentifier identifier of the form element. This supports property paths! * @return mixed The elements default value * @internal */ public function getElementDefaultValueByIdentifier($elementIdentifier) { return \Neos\Utility\ObjectAccess::getPropertyPath($this->elementDefaultValues, $elementIdentifier); }
/** * @test */ public function getPropertyPathReturnsNullIfSubjectOnPathIsNoObject() { $object = new \stdClass(); $object->foo = 'Hello World'; $this->assertNull(ObjectAccess::getPropertyPath($object, 'foo.bar')); }
/** * Iterates through all segments in $this->uriPattern and creates * appropriate RoutePart instances. * * @return void * @throws InvalidRoutePartHandlerException * @throws InvalidUriPatternException */ public function parse() { if ($this->isParsed || $this->uriPattern === null || $this->uriPattern === '') { return; } $this->routeParts = []; $currentRoutePartIsOptional = false; if (substr($this->uriPattern, -1) === '/') { throw new InvalidUriPatternException('The URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" ends with a slash, which is not allowed. You can put the trailing slash in brackets to make it optional.', 1234782997); } if ($this->uriPattern[0] === '/') { throw new InvalidUriPatternException('The URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" starts with a slash, which is not allowed.', 1234782983); } $matches = []; preg_match_all(self::PATTERN_EXTRACTROUTEPARTS, $this->uriPattern, $matches, PREG_SET_ORDER); /** @var $lastRoutePart RoutePartInterface */ $lastRoutePart = null; foreach ($matches as $match) { $routePartType = empty($match['dynamic']) ? self::ROUTEPART_TYPE_STATIC : self::ROUTEPART_TYPE_DYNAMIC; $routePartName = $match['content']; if (!empty($match['optionalStart'])) { if ($lastRoutePart !== null && $lastRoutePart->isOptional()) { throw new InvalidUriPatternException('the URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" contains successive optional Route sections, which is not allowed.', 1234562050); } $currentRoutePartIsOptional = true; } $routePart = null; switch ($routePartType) { case self::ROUTEPART_TYPE_DYNAMIC: if ($lastRoutePart instanceof DynamicRoutePartInterface) { throw new InvalidUriPatternException('the URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" contains successive Dynamic Route Parts, which is not allowed.', 1218446975); } if (isset($this->routePartsConfiguration[$routePartName]['handler'])) { $routePart = $this->objectManager->get($this->routePartsConfiguration[$routePartName]['handler']); if (!$routePart instanceof DynamicRoutePartInterface) { throw new InvalidRoutePartHandlerException(sprintf('routePart handlers must implement "%s" in route "%s"', DynamicRoutePartInterface::class, $this->getName()), 1218480972); } } elseif (isset($this->routePartsConfiguration[$routePartName]['objectType'])) { $routePart = new IdentityRoutePart(); $routePart->setObjectType($this->routePartsConfiguration[$routePartName]['objectType']); if (isset($this->routePartsConfiguration[$routePartName]['uriPattern'])) { $routePart->setUriPattern($this->routePartsConfiguration[$routePartName]['uriPattern']); } } else { $routePart = new DynamicRoutePart(); } $routePartDefaultValue = ObjectAccess::getPropertyPath($this->defaults, $routePartName); if ($routePartDefaultValue !== null) { $routePart->setDefaultValue($routePartDefaultValue); } break; case self::ROUTEPART_TYPE_STATIC: $routePart = new StaticRoutePart(); if ($lastRoutePart !== null && $lastRoutePart instanceof DynamicRoutePartInterface) { /** @var DynamicRoutePartInterface $lastRoutePart */ $lastRoutePart->setSplitString($routePartName); } } $routePart->setName($routePartName); if ($currentRoutePartIsOptional) { $routePart->setOptional(true); if ($routePart instanceof DynamicRoutePartInterface && !$routePart->hasDefaultValue()) { throw new InvalidRouteSetupException(sprintf('There is no default value specified for the optional route part "{%s}" of route "%s", but all dynamic optional route parts need a default.', $routePartName, $this->getName()), 1477140679); } } $routePart->setLowerCase($this->lowerCase); if (isset($this->routePartsConfiguration[$routePartName]['options'])) { $routePart->setOptions($this->routePartsConfiguration[$routePartName]['options']); } if (isset($this->routePartsConfiguration[$routePartName]['toLowerCase'])) { $routePart->setLowerCase($this->routePartsConfiguration[$routePartName]['toLowerCase']); } $this->routeParts[] = $routePart; if (!empty($match['optionalEnd'])) { if (!$currentRoutePartIsOptional) { throw new InvalidUriPatternException('The URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" contains an unopened optional section.', 1234564495); } $currentRoutePartIsOptional = false; } $lastRoutePart = $routePart; } if ($currentRoutePartIsOptional) { throw new InvalidUriPatternException('The URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" contains an unterminated optional section.', 1234563922); } $this->isParsed = true; }
/** * Evaluate the property name filter by traversing to the child object. We only support * nested objects right now * * @param FlowQuery $query * @param string $propertyNameFilter * @return void */ protected function evaluatePropertyNameFilter(FlowQuery $query, $propertyNameFilter) { $resultObjects = []; $resultObjectHashes = []; foreach ($query->getContext() as $element) { $subProperty = ObjectAccess::getPropertyPath($element, $propertyNameFilter); if (is_object($subProperty) || is_array($subProperty)) { if (is_array($subProperty) || $subProperty instanceof \Traversable) { foreach ($subProperty as $childElement) { if (!isset($resultObjectHashes[spl_object_hash($childElement)])) { $resultObjectHashes[spl_object_hash($childElement)] = true; $resultObjects[] = $childElement; } } } elseif (!isset($resultObjectHashes[spl_object_hash($subProperty)])) { $resultObjectHashes[spl_object_hash($subProperty)] = true; $resultObjects[] = $subProperty; } } } $query->setContext($resultObjects); }
/** * @return array */ protected function getRequireJsPathMapping() { $pathMappings = array(); $validatorSettings = ObjectAccess::getPropertyPath($this->settings, 'userInterface.validators'); if (is_array($validatorSettings)) { foreach ($validatorSettings as $validatorName => $validatorConfiguration) { if (isset($validatorConfiguration['path'])) { $pathMappings[$validatorName] = $this->getStaticResourceWebBaseUri($validatorConfiguration['path']); } } } $editorSettings = ObjectAccess::getPropertyPath($this->settings, 'userInterface.inspector.editors'); if (is_array($editorSettings)) { foreach ($editorSettings as $editorName => $editorConfiguration) { if (isset($editorConfiguration['path'])) { $pathMappings[$editorName] = $this->getStaticResourceWebBaseUri($editorConfiguration['path']); } } } $requireJsPathMappingSettings = ObjectAccess::getPropertyPath($this->settings, 'userInterface.requireJsPathMapping'); if (is_array($requireJsPathMappingSettings)) { foreach ($requireJsPathMappingSettings as $namespace => $path) { $pathMappings[$namespace] = $this->getStaticResourceWebBaseUri($path); } } return $pathMappings; }
/** * Creates a URI representation (path segment) for the given object matching $this->uriPattern. * * @param mixed $object object of type $this->objectType * @return string URI representation (path segment) of the given object * @throws InvalidUriPatternException */ protected function createPathSegmentForObject($object) { $matches = []; preg_match_all('/(?P<dynamic>{?)(?P<content>[^}{]+)}?/', $this->getUriPattern(), $matches, PREG_SET_ORDER); $pathSegment = ''; foreach ($matches as $match) { if (empty($match['dynamic'])) { $pathSegment .= $match['content']; } else { $dynamicPathSegmentParts = explode(':', $match['content']); $propertyPath = $dynamicPathSegmentParts[0]; $dynamicPathSegment = ObjectAccess::getPropertyPath($object, $propertyPath); if (is_object($dynamicPathSegment)) { if ($dynamicPathSegment instanceof \DateTimeInterface) { $dateFormat = isset($dynamicPathSegmentParts[1]) ? trim($dynamicPathSegmentParts[1]) : 'Y-m-d'; $pathSegment .= $this->rewriteForUri($dynamicPathSegment->format($dateFormat)); } else { throw new InvalidUriPatternException(sprintf('Invalid uriPattern "%s" for route part "%s". Property "%s" must be of type string or \\DateTime. "%s" given.', $this->getUriPattern(), $this->getName(), $propertyPath, is_object($dynamicPathSegment) ? get_class($dynamicPathSegment) : gettype($dynamicPathSegment)), 1316442409); } } else { $pathSegment .= $this->rewriteForUri($dynamicPathSegment); } } } return $pathSegment; }
/** * Get the current property of the object bound to this form. * * @return mixed Value */ protected function getPropertyValue() { if (!$this->viewHelperVariableContainer->exists(\Neos\FluidAdaptor\ViewHelpers\FormViewHelper::class, 'formObject')) { return null; } $formObject = $this->viewHelperVariableContainer->get(\Neos\FluidAdaptor\ViewHelpers\FormViewHelper::class, 'formObject'); $propertyNameOrPath = $this->arguments['property']; return ObjectAccess::getPropertyPath($formObject, $propertyNameOrPath); }
/** * Get the option value for an object * * @param mixed $valueElement * @return string */ protected function getOptionValueScalar($valueElement) { if (is_object($valueElement)) { if ($this->hasArgument('optionValueField')) { return ObjectAccess::getPropertyPath($valueElement, $this->arguments['optionValueField']); } elseif ($this->persistenceManager->getIdentifierByObject($valueElement) !== null) { return $this->persistenceManager->getIdentifierByObject($valueElement); } else { return (string) $valueElement; } } else { return $valueElement; } }
/** * Checks if the given $nodeType is allowed as a childNode of the given $childNodeName * (which must be auto-created in $this NodeType). * * Only allowed to be called if $childNodeName is auto-created. * * @param string $childNodeName The name of a configured childNode of this NodeType * @param NodeType $nodeType The NodeType to check constraints for. * @return boolean TRUE if the $nodeType is allowed as grandchild node, FALSE otherwise. * @throws \InvalidArgumentException If the given $childNodeName is not configured to be auto-created in $this. */ public function allowsGrandchildNodeType($childNodeName, NodeType $nodeType) { $autoCreatedChildNodes = $this->getAutoCreatedChildNodes(); if (!isset($autoCreatedChildNodes[$childNodeName])) { throw new \InvalidArgumentException('The method "allowsGrandchildNodeType" can only be used on auto-created childNodes, given $childNodeName "' . $childNodeName . '" is not auto-created.', 1403858395); } $constraints = $autoCreatedChildNodes[$childNodeName]->getConfiguration('constraints.nodeTypes') ?: array(); $childNodeConfiguration = []; foreach ($this->getConfiguration('childNodes') as $name => $configuration) { $childNodeConfiguration[Utility::renderValidNodeName($name)] = $configuration; } $childNodeConstraintConfiguration = ObjectAccess::getPropertyPath($childNodeConfiguration, $childNodeName . '.constraints.nodeTypes') ?: array(); $constraints = Arrays::arrayMergeRecursiveOverrule($constraints, $childNodeConstraintConfiguration); return $this->isNodeTypeAllowedByConstraints($nodeType, $constraints); }
/** * Collect the array keys inside $this->subject with each position meta-argument. * If there is no position but the array is numerically ordered, we use the array index as position. * * @return array an associative array where each key of $subject has a position string assigned */ protected function collectArrayKeysAndPositions() { $arrayKeysWithPosition = []; foreach ($this->subject as $key => $value) { // if the value was set to NULL it was unset and should not be used if ($value === null) { continue; } $position = ObjectAccess::getPropertyPath($value, $this->positionPropertyPath); if ($position !== null) { $arrayKeysWithPosition[$key] = $position; } elseif (is_numeric($key)) { $arrayKeysWithPosition[$key] = $key; } else { $arrayKeysWithPosition[$key] = 0; } } return $arrayKeysWithPosition; }