Completed
Push — master ( 126036...3fa63d )
by Maik
07:56
created

OrmPersister   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Test Coverage

Coverage 80.41%

Importance

Changes 5
Bugs 2 Features 0
Metric Value
wmc 25
c 5
b 2
f 0
lcom 2
cbo 3
dl 0
loc 172
ccs 78
cts 97
cp 0.8041
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A setPrimaryKey() 0 15 3
C persistMappedBy() 0 66 8
C persistProperty() 0 27 11
A persistAnnotated() 0 18 3
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 The name of class of entity
22
     * @param \Nkey\Caribu\Model\AbstractModel $object The object where the primary key should be set
23
     * @param mixed $primaryKey The primary key value
24
     * @throws OrmException
25
     */
26 10
    private static function setPrimaryKey($class, $object, $primaryKey)
27
    {
28 10
        $pkCol = self::getAnnotatedPrimaryKeyProperty($class);
29 10
        if (null === $pkCol) {
30 3
            $pkCol = self::getPrimaryKeyCol($class);
31 3
        }
32 10
        $method = sprintf("set%s", ucfirst($pkCol));
33
34
        try {
35 10
            $rfMethod = new \ReflectionMethod($class, $method);
36 10
            $rfMethod->invoke($object, $primaryKey);
37 10
        } catch (\ReflectionException $exception) {
38
            throw OrmException::fromPrevious($exception);
39
        }
40 10
    }
41
42
    /**
43
     * Persist the mapped-by entities
44
     *
45
     * @param string $class The name of class of which the data has to be persisted
46
     * @param \Nkey\Caribu\Model\AbstractModel $object The entity which contain mapped-by entries to persist
47
     *
48
     * @throws OrmException
49
     */
50 11
    private static function persistMappedBy($class, \Nkey\Caribu\Model\AbstractModel $object)
51
    {
52 11
        $instance = self::getInstance();
53 11
        $escapeSign = $instance->getDbType()->getEscapeSign();
54
55
        try {
56 11
            $rf = new \ReflectionClass($class);
57
58 11
            foreach ($rf->getProperties() as $property) {
59 11
                if (null !== ($parameters = self::getAnnotatedMappedByParameters($property->getDocComment()))) {
60 2
                    $mappedBy = self::parseMappedBy($parameters);
61
62 2
                    $rfMethod = new \ReflectionMethod($class, sprintf("get%s", ucfirst($property->getName())));
63 2
                    $foreignEntity = $rfMethod->invoke($object);
64
65 2
                    if (null !== $foreignEntity) {
66 2
                        $foreignPrimaryKey = self::getPrimaryKey(get_class($foreignEntity), $foreignEntity, true);
67 2
                        $ownPrimaryKey = self::getPrimaryKey($class, $object, true);
68
69 2
                        if (is_null($foreignPrimaryKey)) {
70
                            throw new OrmException("No primary key column for foreign key found!");
71
                        }
72 2
                        if (is_null($ownPrimaryKey)) {
73
                            throw new OrmException("No primary key column found!");
74
                        }
75
76 2
                        $query = sprintf(
77 2
                            "INSERT INTO %s%s%s (%s%s%s, %s%s%s) VALUES (:%s, :%s)",
78 2
                            $escapeSign,
79 2
                            $mappedBy['table'],
80 2
                            $escapeSign,
81 2
                            $escapeSign,
82 2
                            $mappedBy['inverseColumn'],
83 2
                            $escapeSign,
84 2
                            $escapeSign,
85 2
                            $mappedBy['column'],
86 2
                            $escapeSign,
87 2
                            $mappedBy['inverseColumn'],
88 2
                            $mappedBy['column']
89 2
                        );
90
91 2
                        $statement = null;
92
                        try {
93 2
                            $statement = $instance->startTX()->prepare($query);
94 2
                            $statement->bindValue(sprintf(':%s', $mappedBy['inverseColumn']), $ownPrimaryKey);
95 2
                            $statement->bindValue(sprintf(':%s', $mappedBy['column']), $foreignPrimaryKey);
96
97 2
                            $statement->execute();
98
99 2
                            $instance->commitTX();
100 2
                        } catch (\PDOException $exception) {
101
                            throw self::handleException(
102
                                $instance,
103
                                $statement,
104
                                $exception,
105
                                "Persisting related entities failed",
106
                                -1010
107
                            );
108
                        }
109 2
                    }
110 2
                }
111 11
            }
112 11
        } catch (\ReflectionException $exception) {
113
            throw OrmException::fromPrevious($exception);
114
        }
115 11
    }
116
117
    /**
118
     * Persist inner entity
119
     *
120
     * @param \ReflectionProperty $property The property which represents the inner entity
121
     * @param string $class The result class name
122
     * @param \Nkey\Caribu\Model\AbstractModel $object The object which holds the entity
123
     * @param string $namespace The result class namespace
124
     * @param boolean $persist Whether to persist
125
     *
126
     * @throws OrmException
127
     */
128 13
    private static function persistProperty(\ReflectionProperty $property, $class, $object, $namespace, $persist)
129
    {
130
        try {
131 13
            if (null !== ($type = self::getAnnotatedType($property->getDocComment(), $namespace)) &&
132 13
                !self::isPrimitive($type)) {
133 6
                if (!$persist && self::isCascadeAnnotated($property->getDocComment())) {
134
                    $persist = true;
135
                }
136
137 6
                $rfMethod = new \ReflectionMethod($class, sprintf("get%s", ucfirst($property->getName())));
138 6
                $entity = $rfMethod->invoke($object);
139 6
                if ($entity instanceof \Nkey\Caribu\Model\AbstractModel) {
140 6
                    if (!$persist && count($pk = self::getAnnotatedPrimaryKey($type, $entity))) {
141
                        list ($pkCol) = $pk;
142
                        if (is_empty($pk[$pkCol])) {
143
                            $persist = true;
144
                        }
145
                    }
146 6
                    if ($persist) {
147 6
                        $entity->persist();
148 6
                    }
149 6
                }
150 6
            }
151 13
        } catch (\ReflectionException $exception) {
152
            throw OrmException::fromPrevious($exception);
153
        }
154 13
    }
155
156
    /**
157
     * Persist the entity and all sub entities if necessary
158
     *
159
     * @param string $class The name of class of which the data has to be persisted
160
     * @param \Nkey\Caribu\Model\AbstractModel $object The entity to persist
161
     *
162
     * @throws OrmException
163
     */
164 13
    private static function persistAnnotated($class, $object)
165
    {
166
        try {
167 13
            $rfClass = new \ReflectionClass($class);
168
169 13
            foreach ($rfClass->getProperties() as $property) {
170 13
                self::persistProperty(
171 13
                    $property,
172 13
                    $class,
173 13
                    $object,
174 13
                    $rfClass->getNamespaceName(),
175 13
                    self::isCascadeAnnotated($rfClass->getDocComment())
176 13
                );
177 13
            }
178 13
        } catch (\ReflectionException $exception) {
179
            throw OrmException::fromPrevious($exception);
180
        }
181 13
    }
182
}
183