Completed
Push — master ( 348a0e...d82154 )
by Maik
06:35
created

OrmPersister::setPrimaryKey()   A

Complexity

Conditions 3
Paths 6

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.072

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 8
cts 10
cp 0.8
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 10
nc 6
nop 3
crap 3.072
1
<?php
2
namespace Nkey\Caribu\Orm;
3
4
/**
5
 * Persisting provider for Caribu Orm
6
 *
7
 * This class is part of Caribu package
8
 *
9
 * @author Maik Greubel <[email protected]>
10
 */
11
trait OrmPersister
12
{
13
    /**
14
     * Include statement related functionality
15
     */
16
    use OrmStatement;
17
18
    /**
19
     * Set the primary key value after persist
20
     *
21
     * @param string $class
22
     *            The name of class of entity
23
     * @param \Nkey\Caribu\Model\AbstractModel $object
24
     *            The object where the primary key should be set
25
     * @param mixed $primaryKey
26
     *            The primary key value
27
     * @throws OrmException
28
     */
29 10
    private static function setPrimaryKey($class, $object, $primaryKey)
30
    {
31 10
        $pkCol = self::getAnnotatedPrimaryKeyProperty($class);
32 10
        if ("" === $pkCol) {
33 3
            $pkCol = self::getPrimaryKeyCol($class);
34
        }
35 10
        $method = sprintf("set%s", ucfirst($pkCol));
36
        
37
        try {
38 10
            $rfMethod = new \ReflectionMethod($class, $method);
39 10
            $rfMethod->invoke($object, $primaryKey);
40
        } catch (\ReflectionException $exception) {
41
            throw OrmException::fromPrevious($exception);
42
        }
43 10
    }
44
45
    /**
46
     * Persist the mapped-by entities
47
     *
48
     * @param string $class
49
     *            The name of class of which the data has to be persisted
50
     * @param \Nkey\Caribu\Model\AbstractModel $object
51
     *            The entity which contain mapped-by entries to persist
52
     *            
53
     * @throws OrmException
54
     */
55 11
    private static function persistMappedBy(string $class, \Nkey\Caribu\Model\AbstractModel $object)
56
    {
57 11
        $instance = self::getInstance();
58 11
        $escapeSign = $instance->getDbType()->getEscapeSign();
59
        
60
        try {
61 11
            $rf = new \ReflectionClass($class);
62
            
63 11
            foreach ($rf->getProperties() as $property) {
64 11
                if ("" !== ($parameters = self::getAnnotatedMappedByParameters($property->getDocComment()))) {
65 2
                    $mappedBy = self::parseMappedBy($parameters);
66
                    
67 2
                    $rfMethod = new \ReflectionMethod($class, sprintf("get%s", ucfirst($property->getName())));
68 2
                    $foreignEntity = $rfMethod->invoke($object);
69
                    
70 2
                    if (null !== $foreignEntity) {
71 2
                        $foreignPrimaryKey = self::getPrimaryKey(get_class($foreignEntity), $foreignEntity, true);
72 2
                        $ownPrimaryKey = self::getPrimaryKey($class, $object, true);
73
                        
74 2
                        if (is_null($foreignPrimaryKey)) {
75
                            throw new OrmException("No primary key column for foreign key found!");
76
                        }
77 2
                        if (is_null($ownPrimaryKey)) {
78
                            throw new OrmException("No primary key column found!");
79
                        }
80
                        
81 2
                        $query = sprintf("INSERT INTO %s%s%s (%s%s%s, %s%s%s) VALUES (:%s, :%s)", $escapeSign, $mappedBy['table'], $escapeSign, $escapeSign, $mappedBy['inverseColumn'], $escapeSign, $escapeSign, $mappedBy['column'], $escapeSign, $mappedBy['inverseColumn'], $mappedBy['column']);
82
                        
83 2
                        $statement = null;
84
                        try {
85 2
                            $statement = $instance->startTX()->prepare($query);
86 2
                            $statement->bindValue(sprintf(':%s', $mappedBy['inverseColumn']), $ownPrimaryKey);
87 2
                            $statement->bindValue(sprintf(':%s', $mappedBy['column']), $foreignPrimaryKey);
88
                            
89 2
                            $statement->execute();
90
                            
91 2
                            $instance->commitTX();
92
                        } catch (\PDOException $exception) {
93 11
                            throw self::handleException($instance, $statement, $exception, "Persisting related entities failed", - 1010);
94
                        }
95
                    }
96
                }
97
            }
98
        } catch (\ReflectionException $exception) {
99
            throw OrmException::fromPrevious($exception);
100
        }
101 11
    }
102
103
    /**
104
     * Persist inner entity
105
     *
106
     * @param \ReflectionProperty $property
107
     *            The property which represents the inner entity
108
     * @param string $class
109
     *            The result class name
110
     * @param \Nkey\Caribu\Model\AbstractModel $object
111
     *            The object which holds the entity
112
     * @param string $namespace
113
     *            The result class namespace
114
     * @param bool $persist
115
     *            Whether to persist
116
     *            
117
     * @throws OrmException
118
     */
119 13
    private static function persistProperty(\ReflectionProperty $property, string $class, \Nkey\Caribu\Model\AbstractModel $object, string $namespace, bool $persist)
120
    {
121
        try {
122 13
            if ("" !== ($type = self::getAnnotatedType($property->getDocComment(), $namespace)) && ! self::isPrimitive($type)) {
123 6
                if (! $persist && self::isCascadeAnnotated($property->getDocComment())) {
124
                    $persist = true;
125
                }
126
                
127 6
                $rfMethod = new \ReflectionMethod($class, sprintf("get%s", ucfirst($property->getName())));
128 6
                $entity = $rfMethod->invoke($object);
129 6
                if ($entity instanceof \Nkey\Caribu\Model\AbstractModel) {
130 6
                    if (! $persist && count($pk = self::getAnnotatedPrimaryKey($type, $entity, false))) {
131
                        list ($pkCol) = $pk;
132
                        if (is_empty($pk[$pkCol])) {
133
                            $persist = true;
134
                        }
135
                    }
136 6
                    if ($persist) {
137 6
                        $entity->persist();
138
                    }
139
                }
140
            }
141
        } catch (\ReflectionException $exception) {
142
            throw OrmException::fromPrevious($exception);
143
        }
144 13
    }
145
146
    /**
147
     * Persist the entity and all sub entities if necessary
148
     *
149
     * @param string $class
150
     *            The name of class of which the data has to be persisted
151
     * @param \Nkey\Caribu\Model\AbstractModel $object
152
     *            The entity to persist
153
     *            
154
     * @throws OrmException
155
     */
156 13
    private static function persistAnnotated(string $class, \Nkey\Caribu\Model\AbstractModel $object)
157
    {
158
        try {
159 13
            $rfClass = new \ReflectionClass($class);
160
            
161 13
            foreach ($rfClass->getProperties() as $property) {
162 13
                self::persistProperty($property, $class, $object, $rfClass->getNamespaceName(), self::isCascadeAnnotated($rfClass->getDocComment()));
163
            }
164
        } catch (\ReflectionException $exception) {
165
            throw OrmException::fromPrevious($exception);
166
        }
167 13
    }
168
}
169