4
4
5
5
use Doctrine \ORM \EntityManager ;
6
6
use Doctrine \ORM \EntityRepository ;
7
+ use Doctrine \ORM \Mapping \MappingException ;
8
+ use Symfony \Component \PropertyAccess \PropertyAccessorInterface ;
9
+ use Trikoder \JsonApiBundle \Contracts \RelationshipDoesNotExistException ;
10
+ use Trikoder \JsonApiBundle \Contracts \RelationshipRepositoryInterface ;
7
11
use Trikoder \JsonApiBundle \Contracts \RepositoryInterface ;
12
+ use Trikoder \JsonApiBundle \Contracts \ResourceDoesNotExistException ;
8
13
9
14
/**
10
15
* Class DoctrineRepository
11
16
*/
12
- class DoctrineRepository implements RepositoryInterface
17
+ class DoctrineRepository implements RepositoryInterface, RelationshipRepositoryInterface
13
18
{
14
19
/**
15
20
* @var EntityRepository
@@ -20,13 +25,22 @@ class DoctrineRepository implements RepositoryInterface
20
25
*/
21
26
protected $ entityManager ;
22
27
28
+ /**
29
+ * @var PropertyAccessorInterface
30
+ */
31
+ protected $ propertyAccessor ;
32
+
23
33
/**
24
34
* DoctrineRepository constructor.
25
35
*/
26
- public function __construct (EntityRepository $ entityRepository , EntityManager $ entityManager )
27
- {
36
+ public function __construct (
37
+ EntityRepository $ entityRepository ,
38
+ EntityManager $ entityManager ,
39
+ PropertyAccessorInterface $ propertyAccessor
40
+ ) {
28
41
$ this ->entityRepository = $ entityRepository ;
29
42
$ this ->entityManager = $ entityManager ;
43
+ $ this ->propertyAccessor = $ propertyAccessor ;
30
44
}
31
45
32
46
/**
@@ -75,4 +89,82 @@ public function remove($model)
75
89
$ this ->entityManager ->remove ($ model );
76
90
$ this ->entityManager ->flush ();
77
91
}
92
+
93
+ /**
94
+ * {@inheritdoc}
95
+ */
96
+ public function addToRelationship ($ model , string $ relationshipName , array $ relationshipData )
97
+ {
98
+ $ modelMeta = $ this ->entityManager ->getClassMetadata ($ this ->entityRepository ->getClassName ());
99
+
100
+ try {
101
+ $ relationshipModelClassName = $ modelMeta ->getAssociationMapping ($ relationshipName )['targetEntity ' ];
102
+ } catch (MappingException $ e ) {
103
+ throw new RelationshipDoesNotExistException ($ relationshipName );
104
+ }
105
+
106
+ $ relationshipModelMeta = $ this ->entityManager ->getClassMetadata ($ relationshipModelClassName );
107
+ $ relationshipIdentifier = $ relationshipModelMeta ->getSingleIdentifierFieldName ();
108
+
109
+ $ repository = $ this ->entityManager ->getRepository ($ relationshipModelClassName );
110
+ $ currentRelationshipModels = $ this ->propertyAccessor ->getValue ($ model , $ relationshipName );
111
+
112
+ $ relationshipModels = [];
113
+
114
+ //add current relationship resources to array
115
+ foreach ($ currentRelationshipModels as $ data ) {
116
+ $ relationshipModels [$ this ->propertyAccessor ->getValue ($ data , $ relationshipIdentifier )] = $ data ;
117
+ }
118
+
119
+ $ newRelationshipModels = $ repository ->findBy ([$ relationshipIdentifier => array_column ($ relationshipData , 'id ' )]);
120
+
121
+ /*
122
+ * @see https://gitlab.trikoder.net/trikoder/jsonapibundle/merge_requests/102#note_251076
123
+ */
124
+ if (\count ($ newRelationshipModels ) !== \count ($ relationshipData )) {
125
+ throw new ResourceDoesNotExistException ();
126
+ }
127
+
128
+ //add new relationship resources to array
129
+ foreach ($ newRelationshipModels as $ data ) {
130
+ $ relationshipModels [$ this ->propertyAccessor ->getValue ($ data , $ relationshipIdentifier )] = $ data ;
131
+ }
132
+
133
+ $ this ->propertyAccessor ->setValue ($ model , $ relationshipName , $ relationshipModels );
134
+
135
+ return $ this ->save ($ model );
136
+ }
137
+
138
+ /**
139
+ * {@inheritdoc}
140
+ */
141
+ public function removeFromRelationship ($ model , string $ relationshipName , array $ relationshipData )
142
+ {
143
+ $ modelMeta = $ this ->entityManager ->getClassMetadata ($ this ->entityRepository ->getClassName ());
144
+
145
+ try {
146
+ $ relationshipModelClassName = $ modelMeta ->getAssociationMapping ($ relationshipName )['targetEntity ' ];
147
+ } catch (MappingException $ e ) {
148
+ throw new RelationshipDoesNotExistException ($ relationshipName );
149
+ }
150
+
151
+ $ relationshipModelMeta = $ this ->entityManager ->getClassMetadata ($ relationshipModelClassName );
152
+ $ relationshipIdentifier = $ relationshipModelMeta ->getSingleIdentifierFieldName ();
153
+
154
+ $ relationshipModels = $ this ->propertyAccessor ->getValue ($ model , $ relationshipName );
155
+ $ relationshipIds = array_column ($ relationshipData , 'id ' );
156
+
157
+ $ this ->propertyAccessor ->setValue (
158
+ $ model ,
159
+ $ relationshipName ,
160
+ array_filter (
161
+ iterator_to_array ($ relationshipModels ),
162
+ function ($ data ) use ($ relationshipIdentifier , $ relationshipIds ) {
163
+ return !\in_array ($ this ->propertyAccessor ->getValue ($ data , $ relationshipIdentifier ), $ relationshipIds );
164
+ }
165
+ )
166
+ );
167
+
168
+ return $ this ->save ($ model );
169
+ }
78
170
}
0 commit comments