Completed
Pull Request — 3.x (#6171)
by Vincent
05:16
created

ObjectManipulator::setObject()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
cc 2
nc 2
nop 3
1
<?php
2
3
namespace Sonata\AdminBundle\Manipulator;
4
5
use Doctrine\Common\Util\ClassUtils;
6
use Doctrine\Inflector\InflectorFactory;
7
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
8
9
class ObjectManipulator
10
{
11
    /**
12
     * Add the instance to the object provided.
13
     *
14
     * @phpstan-template T of object
15
     * @phpstan-param T $instance
16
     * @phpstan-return T
17
     */
18
    public static function addInstance(
19
        object $object,
20
        object $instance,
21
        FieldDescriptionInterface $parentFieldDescription
22
    ): object {
23
        $associationMapping = $parentFieldDescription->getAssociationMapping();
24
        $parentAssociationMappings = $parentFieldDescription->getParentAssociationMappings();
25
26
        foreach ($parentAssociationMappings as $parentAssociationMapping) {
27
            $object = self::callGetter($object, $parentAssociationMapping['fieldName']);
28
        }
29
30
        return self::callAdder($object, $instance, $associationMapping['fieldName']);
31
    }
32
33
    /**
34
     * Set the object to the instance provided.
35
     *
36
     * @phpstan-template T of object
37
     * @phpstan-param T $instance
38
     * @phpstan-return T
39
     */
40
    public static function setObject(
41
        object $instance,
42
        object $object,
43
        FieldDescriptionInterface $parentFieldDescription
44
    ): object {
45
        $associationMapping = $parentFieldDescription->getAssociationMapping();
46
        $parentAssociationMappings = $parentFieldDescription->getParentAssociationMappings();
47
48
        foreach ($parentAssociationMappings as $parentAssociationMapping) {
49
            $object = self::callGetter($object, $parentAssociationMapping['fieldName']);
50
        }
51
52
        return self::callSetter($instance, $object, $associationMapping['mappedBy']);
53
    }
54
55
    /**
56
     * Call $object->getXXX()
57
     */
58
    private static function callGetter(object $object, string $fieldName): object
59
    {
60
        $inflector = InflectorFactory::create()->build();
61
        $method = sprintf('get%s', $inflector->classify($fieldName));
62
63
        if (!(\is_callable([$object, $method]) && method_exists($object, $method))) {
64
            /*
65
             * NEXT_MAJOR: Use BadMethodCallException instead
66
             */
67
            throw new \RuntimeException(
68
                sprintf('Method %s::%s() does not exist.', ClassUtils::getClass($object), $method)
69
            );
70
        }
71
72
        return $object->$method();
73
    }
74
75
    /**
76
     * Call $instance->setXXX($object)
77
     *
78
     * @phpstan-template T of object
79
     * @phpstan-param T $instance
80
     * @phpstan-return T
81
     */
82
    private static function callSetter(object $instance, object $object, string $mappedBy): object
83
    {
84
        $inflector = InflectorFactory::create()->build();
85
        $method = sprintf('set%s', $inflector->classify($mappedBy));
86
87
        if (!(\is_callable([$instance, $method]) && method_exists($instance, $method))) {
88
            /*
89
             * NEXT_MAJOR: Use BadMethodCallException instead
90
             */
91
            throw new \RuntimeException(
92
                sprintf('Method %s::%s() does not exist.', ClassUtils::getClass($instance), $method)
93
            );
94
        }
95
96
        $instance->$method($object);
97
98
        return $instance;
99
    }
100
101
    /**
102
     * Call $object->addXXX($instance)
103
     *
104
     * @phpstan-template T of object
105
     * @phpstan-param T $instance
106
     * @phpstan-return T
107
     */
108
    private static function callAdder(object $object, object $instance, string $fieldName): object
109
    {
110
        $inflector = InflectorFactory::create()->build();
111
        $method = sprintf('add%s', $inflector->classify($fieldName));
112
113
        if (!(\is_callable([$object, $method]) && method_exists($object, $method))) {
114
            $method = rtrim($method, 's');
115
116
            if (!(\is_callable([$object, $method]) && method_exists($object, $method))) {
117
                $method = sprintf('add%s', $inflector->classify($inflector->singularize($fieldName)));
118
119
                if (!(\is_callable([$object, $method]) && method_exists($object, $method))) {
120
                    /*
121
                     * NEXT_MAJOR: Use BadMethodCallException instead
122
                     */
123
                    throw new \RuntimeException(
124
                        sprintf('Method %s::%s() does not exist.', ClassUtils::getClass($object), $method)
125
                    );
126
                }
127
            }
128
        }
129
130
        $object->$method($instance);
131
132
        return $instance;
133
    }
134
}
135