44
55use Doctrine \ORM \EntityManager ;
66use 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 ;
711use Trikoder \JsonApiBundle \Contracts \RepositoryInterface ;
12+ use Trikoder \JsonApiBundle \Contracts \ResourceDoesNotExistException ;
813
914/**
1015 * Class DoctrineRepository
1116 */
12- class DoctrineRepository implements RepositoryInterface
17+ class DoctrineRepository implements RepositoryInterface, RelationshipRepositoryInterface
1318{
1419 /**
1520 * @var EntityRepository
@@ -20,13 +25,22 @@ class DoctrineRepository implements RepositoryInterface
2025 */
2126 protected $ entityManager ;
2227
28+ /**
29+ * @var PropertyAccessorInterface
30+ */
31+ protected $ propertyAccessor ;
32+
2333 /**
2434 * DoctrineRepository constructor.
2535 */
26- public function __construct (EntityRepository $ entityRepository , EntityManager $ entityManager )
27- {
36+ public function __construct (
37+ EntityRepository $ entityRepository ,
38+ EntityManager $ entityManager ,
39+ PropertyAccessorInterface $ propertyAccessor
40+ ) {
2841 $ this ->entityRepository = $ entityRepository ;
2942 $ this ->entityManager = $ entityManager ;
43+ $ this ->propertyAccessor = $ propertyAccessor ;
3044 }
3145
3246 /**
@@ -75,4 +89,82 @@ public function remove($model)
7589 $ this ->entityManager ->remove ($ model );
7690 $ this ->entityManager ->flush ();
7791 }
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+ }
78170}
0 commit comments