Skip to content
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

Add tests to ModelManager and DateFilter #368

Merged
merged 2 commits into from
Jul 26, 2020

Conversation

franmomu
Copy link
Member

@franmomu franmomu commented Jun 20, 2020

Subject

This is a part of #360, there are some comments there about these changes.

I am targeting this branch, because this is BCish.

Changelog

### Deprecated
- Deprecated `AbstractDateFilter::typeRequiresValue`.
- Deprecated `ModelManager::camelize`.
- Deprecated constructing `ModelManager` without passing an instance of `PropertyAccessorInterface` as second argument.

@franmomu franmomu added the minor label Jun 20, 2020
src/Filter/DateFilter.php Outdated Show resolved Hide resolved
@greg0ire
Copy link
Contributor

Coverage increased (+10.6%) to 35.962%

Holy shit! Nice! (and also, the current coverage is so, so low…)

greg0ire
greg0ire previously approved these changes Jun 20, 2020
src/Filter/AbstractDateFilter.php Outdated Show resolved Hide resolved
src/Filter/AbstractDateFilter.php Outdated Show resolved Hide resolved
tests/Model/ModelManagerTest.php Outdated Show resolved Hide resolved
tests/Model/ModelManagerTest.php Outdated Show resolved Hide resolved
tests/Model/ModelManagerTest.php Outdated Show resolved Hide resolved
tests/Model/ModelManagerTest.php Outdated Show resolved Hide resolved
@@ -119,26 +124,41 @@ public function getRenderSettings()
]];
}

abstract protected function applyTypeIsLessEqual(ProxyQueryInterface $queryBuilder, string $field, array $data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK this is a BC break, because you introduce new API methods without that MUST be implemented.

Copy link
Member

@VincentLanglet VincentLanglet Jun 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


public function getExamples(): array
{
return [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add at least one case using \DateTimeImmutable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should change that for the next major.

core23
core23 previously approved these changes Jul 2, 2020
src/Filter/AbstractDateFilter.php Outdated Show resolved Hide resolved
src/Model/ModelManager.php Outdated Show resolved Hide resolved
@SonataCI
Copy link
Collaborator

Could you please rebase your PR and fix merge conflicts?

@@ -458,7 +472,7 @@ public function modelReverseTransform($class, array $array = [])
$instance->$property = $value;
} elseif ($reflClass->hasProperty($property)) {
if (!$reflClass->getProperty($property)->isPublic()) {
throw new PropertyAccessDeniedException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "set%s()"?', $property, $reflClass->getName(), ucfirst($property)));
throw new \BadMethodCallException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "set%s()"?', $property, $reflClass->getName(), ucfirst($property)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the checked element here is a property, I think \BadMethodCallException is not the proper exception.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that you point this out, rethinking about this, maybe we can just use PropertyAccessor class instead of all this code.

-        $reflClass = $metadata->reflClass;
+        $propertyAccesor = PropertyAccess::createPropertyAccessorBuilder()
+            ->enableMagicCall()
+            ->getPropertyAccessor();
+
         foreach ($array as $name => $value) {
-            $reflection_property = false;
             // property or association ?
             if (\array_key_exists($name, $metadata->fieldMappings)) {
                 $property = $metadata->fieldMappings[$name]['fieldName'];
-                $reflection_property = $metadata->reflFields[$name];
             } elseif (\array_key_exists($name, $metadata->associationMappings)) {
                 $property = $metadata->associationMappings[$name]['fieldName'];
             } else {
                 $property = $name;
             }

-            $setter = 'set'.$this->camelize($name);
-
-            if ($reflClass->hasMethod($setter)) {
-                if (!$reflClass->getMethod($setter)->isPublic()) {
-                    throw new \BadMethodCallException(sprintf('Method "%s()" is not public in class "%s"', $setter, $reflClass->getName()));
-                }
-
-                $instance->$setter($value);
-            } elseif ($reflClass->hasMethod('__set')) {
-                // needed to support magic method __set
-                $instance->$property = $value;
-            } elseif ($reflClass->hasProperty($property)) {
-                if (!$reflClass->getProperty($property)->isPublic()) {
-                    throw new \BadMethodCallException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "set%s()"?', $property, $reflClass->getName(), ucfirst($property)));
-                }
-
-                $instance->$property = $value;
-            } elseif ($reflection_property) {
-                $reflection_property->setValue($instance, $value);
-            }
+            $propertyAccesor->setValue($instance, $property, $value);
         }

The problem I see is that I don't know how to reach this case:

$reflection_property->setValue($instance, $value);

Or change the exception, any suggestion? I've looking for one, but haven't found one that I like.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if there is any chance to identify the mentioned case through the PropertyAccessor class. Did you find another approach?

Copy link
Member Author

@franmomu franmomu Jul 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think we could replace this with the PropertyAccess class, because what I understand is...

it checks first if there is a public setter:

$setter = 'set'.$this->camelize($name);

if ($reflClass->hasMethod($setter)) {
    if (!$reflClass->getMethod($setter)->isPublic()) {
        throw new \BadMethodCallException(sprintf('Method "%s()" is not public in class "%s"', $setter, $reflClass->getName()));
    }

    $instance->$setter($value);

then checks the __set method:

} elseif ($reflClass->hasMethod('__set')) {
    // needed to support magic method __set
    $instance->$property = $value;

and then a public property:

} elseif ($reflClass->hasProperty($property)) {
    if (!$reflClass->getProperty($property)->isPublic()) {
        throw new \BadMethodCallException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "set%s()"?', $property, $reflClass->getName(), ucfirst($property)));
    }

    $instance->$property = $value;

and finally this:

} elseif ($reflection_property) {
    $reflection_property->setValue($instance, $value);
}

I think that $reflection_property->setValue($instance, $value); is covered by the previous cases and it would fail if the property is not accesible. So basically I think it could be all replaced by PropertyAccess and the current exceptions wouldn't be a problem since the classes don't exist anymore.

*/
private $propertyAccessor;

public function __construct(ManagerRegistry $registry, ?PropertyAccessorInterface $propertyAccessor = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And what about requiring the param in the next major ? (And add a deprecation in 3.x if it's not provided)

@franmomu franmomu force-pushed the add_test branch 4 times, most recently from b070cfe to 3911eeb Compare July 25, 2020 18:14
VincentLanglet
VincentLanglet previously approved these changes Jul 25, 2020
Comment on lines 53 to 58
if (null === $propertyAccessor) {
@trigger_error(sprintf(
'Constructing "%s" without passing an instance of "%s" as second argument is deprecated since'
.' sonata-project/doctrine-mongodb-admin-bundle 3.x and will be mandatory in 4.0',
static::class,
PropertyAccessorInterface::class
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (null === $propertyAccessor) {
@trigger_error(sprintf(
'Constructing "%s" without passing an instance of "%s" as second argument is deprecated since'
.' sonata-project/doctrine-mongodb-admin-bundle 3.x and will be mandatory in 4.0',
static::class,
PropertyAccessorInterface::class
if (!$propertyAccessor instanceof PropertyAccessorInterface) {
@trigger_error(sprintf(
'Not passing an object implementing "%s" as argument 2 for "%s()" is deprecated since'
.' sonata-project/doctrine-mongodb-admin-bundle 3.x and will throw a %s error in 4.0.',
PropertyAccessorInterface::class,
__METHOD__,
\TypeError::class

jordisala1991
jordisala1991 previously approved these changes Jul 25, 2020
@franmomu franmomu requested a review from phansys July 25, 2020 23:00
@jordisala1991 jordisala1991 merged commit b382c81 into sonata-project:3.x Jul 26, 2020
@jordisala1991
Copy link
Member

Thank you @franmomu

@franmomu franmomu deleted the add_test branch July 26, 2020 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants