Completed
Push — master ( 43b306...d002ef )
by Jordi Sala
14s queued 11s
created

ObjectManipulator::callAdder()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 8.5706
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
            /*
76
             * NEXT_MAJOR: Use BadMethodCallException instead
77
             */
78
            throw new \RuntimeException(
79
                sprintf('Method %s::%s() does not exist.', ClassUtils::getClass($object), $method)
80
            );
81
        }
82
83
        return $object->$method();
84
    }
85
86
    /**
87
     * Call $instance->setXXX($object).
88
     *
89
     * @phpstan-template T of object
90
     * @phpstan-param T $instance
91
     * @phpstan-return T
92
     */
93
    private static function callSetter(object $instance, object $object, string $mappedBy): object
94
    {
95
        $inflector = InflectorFactory::create()->build();
96
        $method = sprintf('set%s', $inflector->classify($mappedBy));
97
98
        if (!(\is_callable([$instance, $method]) && method_exists($instance, $method))) {
99
            /*
100
             * NEXT_MAJOR: Use BadMethodCallException instead
101
             */
102
            throw new \RuntimeException(
103
                sprintf('Method %s::%s() does not exist.', ClassUtils::getClass($instance), $method)
104
            );
105
        }
106
107
        $instance->$method($object);
108
109
        return $instance;
110
    }
111
112
    /**
113
     * Call $object->addXXX($instance).
114
     *
115
     * @phpstan-template T of object
116
     * @phpstan-param T $instance
117
     * @phpstan-return T
118
     */
119
    private static function callAdder(object $object, object $instance, string $fieldName): object
120
    {
121
        $inflector = InflectorFactory::create()->build();
122
        $method = sprintf('add%s', $inflector->classify($fieldName));
123
124
        if (!(\is_callable([$object, $method]) && method_exists($object, $method))) {
125
            $method = rtrim($method, 's');
126
127
            if (!(\is_callable([$object, $method]) && method_exists($object, $method))) {
128
                $method = sprintf('add%s', $inflector->classify($inflector->singularize($fieldName)));
129
130
                if (!(\is_callable([$object, $method]) && method_exists($object, $method))) {
131
                    /*
132
                     * NEXT_MAJOR: Use BadMethodCallException instead
133
                     */
134
                    throw new \RuntimeException(
135
                        sprintf('Method %s::%s() does not exist.', ClassUtils::getClass($object), $method)
136
                    );
137
                }
138
            }
139
        }
140
141
        $object->$method($instance);
142
143
        return $instance;
144
    }
145
}
146