Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,6 @@ jobs:
- name: Translator Tests
run: php vendor/bin/simple-phpunit
working-directory: src/Translator

- name: StimulusBundle Dependencies
uses: ramsey/composer-install@v2
with:
working-directory: src/StimulusBundle
dependency-versions: lowest
- name: StimulusBundle Tests
working-directory: src/StimulusBundle
run: php vendor/bin/simple-phpunit

tests-php-high-deps:
runs-on: ubuntu-latest
steps:
Expand Down
6 changes: 3 additions & 3 deletions src/Autocomplete/src/Doctrine/EntitySearchUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ public function addSearchClause(QueryBuilder $queryBuilder, string $query, strin

// this complex condition is needed to avoid issues on PostgreSQL databases
if (
($isSmallIntegerProperty && $isSmallIntegerQuery) ||
($isIntegerProperty && $isIntegerQuery) ||
($isNumericProperty && $isNumericQuery)
($isSmallIntegerProperty && $isSmallIntegerQuery)
|| ($isIntegerProperty && $isIntegerQuery)
|| ($isNumericProperty && $isNumericQuery)
) {
$expressions[] = $queryBuilder->expr()->eq(sprintf('%s.%s', $entityName, $propertyName), ':query_for_numbers');
$queryBuilder->setParameter('query_for_numbers', $dqlParameters['numeric_query']);
Expand Down
6 changes: 3 additions & 3 deletions src/Autocomplete/src/Form/ParentEntityAutocompleteType.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ public function __construct(
public function buildForm(FormBuilderInterface $builder, array $options)
{
$formType = $builder->getType()->getInnerType();
$attribute = AsEntityAutocompleteField::getInstance(\get_class($formType));
$attribute = AsEntityAutocompleteField::getInstance($formType::class);

if (!$attribute && empty($options['autocomplete_url'])) {
throw new \LogicException(sprintf('You must either provide your own autocomplete_url, or add #[AsEntityAutocompleteField] attribute to %s.', \get_class($formType)));
throw new \LogicException(sprintf('You must either provide your own autocomplete_url, or add #[AsEntityAutocompleteField] attribute to %s.', $formType::class));
}

// Use the provided URL, or auto-generate from the provided alias
$autocompleteUrl = $options['autocomplete_url'] ?? $this->urlGenerator->generate($attribute->getRoute(), [
'alias' => $attribute->getAlias() ?: AsEntityAutocompleteField::shortName(\get_class($formType)),
'alias' => $attribute->getAlias() ?: AsEntityAutocompleteField::shortName($formType::class),
]);

$builder
Expand Down
4 changes: 2 additions & 2 deletions src/LiveComponent/src/Attribute/AsLiveComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
final class AsLiveComponent extends AsTwigComponent
{
public function __construct(
?string $name = null,
?string $template = null,
string $name = null,
string $template = null,
private ?string $defaultAction = null,
bool $exposePublicProps = true,
string $attributesVar = 'attributes',
Expand Down
8 changes: 4 additions & 4 deletions src/LiveComponent/src/Attribute/LiveProp.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ final class LiveProp
*/
public function __construct(
bool|array $writable = false,
?string $hydrateWith = null,
?string $dehydrateWith = null,
string $hydrateWith = null,
string $dehydrateWith = null,
bool $useSerializerForHydration = false,
array $serializationContext = [],
?string $fieldName = null,
?string $format = null,
string $fieldName = null,
string $format = null,
bool $updateFromParent = false
) {
$this->writable = $writable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ public function onKernelRequest(RequestEvent $event): void
}

if (
$this->container->has(CsrfTokenManagerInterface::class) &&
$metadata->get('csrf') &&
!$this->container->get(CsrfTokenManagerInterface::class)->isTokenValid(new CsrfToken(LiveControllerAttributesCreator::getCsrfTokeName($componentName), $request->headers->get('X-CSRF-TOKEN')))) {
$this->container->has(CsrfTokenManagerInterface::class)
&& $metadata->get('csrf')
&& !$this->container->get(CsrfTokenManagerInterface::class)->isTokenValid(new CsrfToken(LiveControllerAttributesCreator::getCsrfTokeName($componentName), $request->headers->get('X-CSRF-TOKEN')))) {
throw new BadRequestHttpException('Invalid CSRF token.');
}

Expand Down Expand Up @@ -161,7 +161,7 @@ public function onKernelController(ControllerEvent $event): void
}

if (!$request->attributes->get('_component_default_action', false) && !AsLiveComponent::isActionAllowed($component, $action)) {
throw new NotFoundHttpException(sprintf('The action "%s" either doesn\'t exist or is not allowed in "%s". Make sure it exist and has the LiveAction attribute above it.', $action, \get_class($component)));
throw new NotFoundHttpException(sprintf('The action "%s" either doesn\'t exist or is not allowed in "%s". Make sure it exist and has the LiveAction attribute above it.', $action, $component::class));
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function hydrate(mixed $value, string $className): ?object
public function dehydrate(object $object): mixed
{
$id = $this
->objectManagerFor($class = \get_class($object))
->objectManagerFor($class = $object::class)
->getClassMetadata($class)
->getIdentifierValues($object)
;
Expand Down
38 changes: 19 additions & 19 deletions src/LiveComponent/src/LiveComponentHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public function dehydrate(object $component, ComponentAttributes $attributes, Li
$frontendName = $propMetadata->calculateFieldName($component, $propertyName);

if (isset($takenFrontendPropertyNames[$frontendName])) {
$message = sprintf('The field name "%s" cannot be used by multiple LiveProp properties in a component. Currently, both "%s" and "%s" are trying to use it in "%s".', $frontendName, $takenFrontendPropertyNames[$frontendName], $propertyName, \get_class($component));
$message = sprintf('The field name "%s" cannot be used by multiple LiveProp properties in a component. Currently, both "%s" and "%s" are trying to use it in "%s".', $frontendName, $takenFrontendPropertyNames[$frontendName], $propertyName, $component::class);

if ($frontendName === $takenFrontendPropertyNames[$frontendName] || $frontendName === $propertyName) {
$message .= sprintf(' Try adding LiveProp(fieldName="somethingElse") for the "%s" property to avoid this.', $frontendName);
Expand All @@ -79,7 +79,7 @@ public function dehydrate(object $component, ComponentAttributes $attributes, Li
try {
$rawPropertyValue = $this->propertyAccessor->getValue($component, $propertyName);
} catch (UninitializedPropertyException $exception) {
throw new \LogicException(sprintf('The "%s" property on the "%s" component is uninitialized. Did you forget to pass this into the component?', $propertyName, \get_class($component)), 0, $exception);
throw new \LogicException(sprintf('The "%s" property on the "%s" component is uninitialized. Did you forget to pass this into the component?', $propertyName, $component::class), 0, $exception);
}

$dehydratedValue = $this->dehydrateValue($rawPropertyValue, $propMetadata, $component);
Expand All @@ -95,14 +95,14 @@ public function dehydrate(object $component, ComponentAttributes $attributes, Li
$this->adjustPropertyPathForData($rawPropertyValue, $path)
);
} catch (NoSuchPropertyException $e) {
throw new \LogicException(sprintf('The writable path "%s" does not exist on the "%s" property of the "%s" component.', $path, $propertyName, \get_class($component)), 0, $e);
throw new \LogicException(sprintf('The writable path "%s" does not exist on the "%s" property of the "%s" component.', $path, $propertyName, $component::class), 0, $e);
} catch (PropertyAccessExceptionInterface $e) {
throw new \LogicException(sprintf('The writable path "%s" on the "%s" property of the "%s" component could not be read: %s', $path, $propertyName, \get_class($component), $e->getMessage()), 0, $e);
throw new \LogicException(sprintf('The writable path "%s" on the "%s" property of the "%s" component could not be read: %s', $path, $propertyName, $component::class, $e->getMessage()), 0, $e);
}

// TODO: maybe we allow support the same types as LiveProps later
if (!$this->isValueValidDehydratedValue($pathValue)) {
throw new \LogicException(sprintf('The writable path "%s" on the "%s" property of the "%s" component must be a scalar or array of scalars.', $path, $propertyName, \get_class($component)));
throw new \LogicException(sprintf('The writable path "%s" on the "%s" property of the "%s" component must be a scalar or array of scalars.', $path, $propertyName, $component::class));
}

$dehydratedProps->addNestedProp($frontendName, $path, $pathValue);
Expand Down Expand Up @@ -161,7 +161,7 @@ public function hydrate(object $component, array $props, array $updatedProps, Li
| 2) Set ORIGINAL "writable paths" data for this LiveProp.
| (which may represent data that was updated on a previous request)
*/
$originalWritablePaths = $this->calculateWritablePaths($propMetadata, $propertyValue, $dehydratedOriginalProps, $frontendName, \get_class($component));
$originalWritablePaths = $this->calculateWritablePaths($propMetadata, $propertyValue, $dehydratedOriginalProps, $frontendName, $component::class);
$propertyValue = $this->setWritablePaths(
$originalWritablePaths,
$frontendName,
Expand All @@ -177,7 +177,7 @@ public function hydrate(object $component, array $props, array $updatedProps, Li
*/
if ($dehydratedUpdatedProps->hasPropValue($frontendName)) {
if (!$propMetadata->isIdentityWritable()) {
throw new HydrationException(sprintf('The model "%s" was sent for update, but it is not writable. Try adding "writable: true" to the $%s property in %s.', $frontendName, $propMetadata->getName(), \get_class($component)));
throw new HydrationException(sprintf('The model "%s" was sent for update, but it is not writable. Try adding "writable: true" to the $%s property in %s.', $frontendName, $propMetadata->getName(), $component::class));
}
try {
$propertyValue = $this->hydrateValue(
Expand All @@ -193,7 +193,7 @@ public function hydrate(object $component, array $props, array $updatedProps, Li
/*
| 4) Set UPDATED "writable paths" data for this LiveProp.
*/
$updatedWritablePaths = $this->calculateWritablePaths($propMetadata, $propertyValue, $dehydratedUpdatedProps, $frontendName, \get_class($component));
$updatedWritablePaths = $this->calculateWritablePaths($propMetadata, $propertyValue, $dehydratedUpdatedProps, $frontendName, $component::class);
$propertyValue = $this->setWritablePaths(
$updatedWritablePaths,
$frontendName,
Expand Down Expand Up @@ -326,7 +326,7 @@ private function dehydrateValue(mixed $value, LivePropMetadata $propMetadata, ob
{
if ($method = $propMetadata->dehydrateMethod()) {
if (!method_exists($component, $method)) {
throw new \LogicException(sprintf('The "%s" component has a dehydrateMethod of "%s" but the method does not exist.', \get_class($component), $method));
throw new \LogicException(sprintf('The "%s" component has a dehydrateMethod of "%s" but the method does not exist.', $component::class, $method));
}

return $component->$method($value);
Expand All @@ -345,35 +345,35 @@ private function dehydrateValue(mixed $value, LivePropMetadata $propMetadata, ob
$collectionClass = $propMetadata->collectionValueType()->getClassName();
foreach ($value as $key => $objectItem) {
if (!$objectItem instanceof $collectionClass) {
throw new \LogicException(sprintf('The LiveProp "%s" on component "%s" is an array. We determined the array is full of %s objects, but at least on key had a different value of %s', $propMetadata->getName(), \get_class($component), $collectionClass, get_debug_type($objectItem)));
throw new \LogicException(sprintf('The LiveProp "%s" on component "%s" is an array. We determined the array is full of %s objects, but at least on key had a different value of %s', $propMetadata->getName(), $component::class, $collectionClass, get_debug_type($objectItem)));
}

$value[$key] = $this->dehydrateObjectValue($objectItem, $collectionClass, $propMetadata->getFormat(), \get_class($component), sprintf('%s.%s', $propMetadata->getName(), $key));
$value[$key] = $this->dehydrateObjectValue($objectItem, $collectionClass, $propMetadata->getFormat(), $component::class, sprintf('%s.%s', $propMetadata->getName(), $key));
}
}

if (!$this->isValueValidDehydratedValue($value)) {
$badKeys = $this->getNonScalarKeys($value, $propMetadata->getName());
$badKeysText = implode(', ', array_map(fn ($key) => sprintf('%s: %s', $key, $badKeys[$key]), array_keys($badKeys)));

throw new \LogicException(sprintf('The LiveProp "%s" on component "%s" is an array, but it contains one or more keys that are not scalars: %s', $propMetadata->getName(), \get_class($component), $badKeysText));
throw new \LogicException(sprintf('The LiveProp "%s" on component "%s" is an array, but it contains one or more keys that are not scalars: %s', $propMetadata->getName(), $component::class, $badKeysText));
}

return $value;
}

if (!\is_object($value)) {
throw new \LogicException(sprintf('Unable to dehydrate value of type "%s" for property "%s" on component "%s". Change this to a simpler type of an object that can be dehydrated. Or set the hydrateWith/dehydrateWith options in LiveProp or set "useSerializerForHydration: true" on the LiveProp to use the serializer.', get_debug_type($value), $propMetadata->getName(), \get_class($component)));
throw new \LogicException(sprintf('Unable to dehydrate value of type "%s" for property "%s" on component "%s". Change this to a simpler type of an object that can be dehydrated. Or set the hydrateWith/dehydrateWith options in LiveProp or set "useSerializerForHydration: true" on the LiveProp to use the serializer.', get_debug_type($value), $propMetadata->getName(), $component::class));
}

if (!$propMetadata->getType() || $propMetadata->isBuiltIn()) {
throw new \LogicException(sprintf('The "%s" property on component "%s" is missing its property-type. Add the "%s" type so the object can be hydrated later.', $propMetadata->getName(), \get_class($component), \get_class($value)));
throw new \LogicException(sprintf('The "%s" property on component "%s" is missing its property-type. Add the "%s" type so the object can be hydrated later.', $propMetadata->getName(), $component::class, $value::class));
}

// at this point, we have an object and can assume $propMetadata->getType()
// is set correctly (needed for hydration later)

return $this->dehydrateObjectValue($value, $propMetadata->getType(), $propMetadata->getFormat(), \get_class($component), $propMetadata->getName());
return $this->dehydrateObjectValue($value, $propMetadata->getType(), $propMetadata->getFormat(), $component::class, $propMetadata->getName());
}

private function dehydrateObjectValue(object $value, string $classType, ?string $dateFormat, string $componentClassForError, string $propertyPathForError): mixed
Expand All @@ -392,14 +392,14 @@ private function dehydrateObjectValue(object $value, string $classType, ?string
}
}

throw new \LogicException(sprintf('Unable to dehydrate value of type "%s" for property "%s" on component "%s". Either (1) change this to a simpler value, (2) add the hydrateWith/dehydrateWith options to LiveProp or (3) set "useSerializerForHydration: true" on the LiveProp.', \get_class($value), $propertyPathForError, $componentClassForError));
throw new \LogicException(sprintf('Unable to dehydrate value of type "%s" for property "%s" on component "%s". Either (1) change this to a simpler value, (2) add the hydrateWith/dehydrateWith options to LiveProp or (3) set "useSerializerForHydration: true" on the LiveProp.', $value::class, $propertyPathForError, $componentClassForError));
}

private function hydrateValue(mixed $value, LivePropMetadata $propMetadata, object $component): mixed
{
if ($propMetadata->hydrateMethod()) {
if (!method_exists($component, $propMetadata->hydrateMethod())) {
throw new \LogicException(sprintf('The "%s" component has a hydrateMethod of "%s" but the method does not exist.', \get_class($component), $propMetadata->hydrateMethod()));
throw new \LogicException(sprintf('The "%s" component has a hydrateMethod of "%s" but the method does not exist.', $component::class, $propMetadata->hydrateMethod()));
}

return $component->{$propMetadata->hydrateMethod()}($value);
Expand All @@ -412,7 +412,7 @@ private function hydrateValue(mixed $value, LivePropMetadata $propMetadata, obje
if ($propMetadata->collectionValueType() && Type::BUILTIN_TYPE_OBJECT === $propMetadata->collectionValueType()->getBuiltinType()) {
$collectionClass = $propMetadata->collectionValueType()->getClassName();
foreach ($value as $key => $objectItem) {
$value[$key] = $this->hydrateObjectValue($objectItem, $collectionClass, true, \get_class($component), sprintf('%s.%s', $propMetadata->getName(), $key));
$value[$key] = $this->hydrateObjectValue($objectItem, $collectionClass, true, $component::class, sprintf('%s.%s', $propMetadata->getName(), $key));
}
}

Expand All @@ -434,7 +434,7 @@ private function hydrateValue(mixed $value, LivePropMetadata $propMetadata, obje
return $value;
}

return $this->hydrateObjectValue($value, $propMetadata->getType(), $propMetadata->allowsNull(), \get_class($component), $propMetadata->getName());
return $this->hydrateObjectValue($value, $propMetadata->getType(), $propMetadata->allowsNull(), $component::class, $propMetadata->getName());
}

private function hydrateObjectValue(mixed $value, string $className, bool $allowsNull, string $componentClassForError, string $propertyPathForError): ?object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private function guessTemplateInfo(): array
foreach ($backtrace as $trace) {
if (isset($trace['object']) && $trace['object'] instanceof Template) {
$currentClass = \get_class($trace['object']);
$isEmbedContainer = null === $templateClass ? false : 0 === strpos($templateClass, $currentClass);
$isEmbedContainer = null === $templateClass ? false : str_starts_with($templateClass, $currentClass);
// START CHANGE
// if statement not needed
// if (null === $this->name || ($this->name == $trace['object']->getTemplateName() && !$isEmbedContainer)) {
Expand Down
Loading