Completed
Pull Request — master (#6210)
by Jordi Sala
37:29
created

ObjectManipulator::callAdder()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

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