1+ <?php
2+
3+ namespace Wetzel \Datamapper \Versioning ;
4+
5+ use Illuminate \Database \Eloquent \Builder as BaseBuilder ;
6+ use Illuminate \Database \Query \Builder as QueryBuilder ;
7+
8+ class Builder extends BaseBuilder {
9+
10+ /**
11+ * Insert a new record into the database.
12+ *
13+ * @param array $values
14+ * @return bool
15+ */
16+ public function insert (array $ values )
17+ {
18+ // get version values & values
19+ $ versionValues = $ this ->getVersionValues ($ values );
20+ $ values = $ this ->getValues ($ values );
21+
22+ // set version and latest_version
23+ $ values [$ this ->model ->getLatestVersionColumn ()] = 1 ;
24+ $ versionValues [$ this ->model ->getVersionColumn ()] = 1 ;
25+
26+ // insert main table record
27+ if (! $ this ->query ->insert ($ values )) {
28+ return false ;
29+ }
30+
31+ // insert version table record
32+ $ db = $ this ->model ->getConnection ();
33+ return $ db ->table ($ this ->model ->getVersionTable ())->insert ($ versionValues );
34+ }
35+
36+ /**
37+ * Update a record in the database.
38+ *
39+ * @param array $values
40+ * @return int
41+ */
42+ public function update (array $ values )
43+ {
44+ // update timestamps
45+ $ values = $ this ->addUpdatedAtColumn ($ values );
46+
47+ // get version values & values
48+ $ versionValues = $ this ->getVersionValues ($ values );
49+ $ values = $ this ->getValues ($ values );
50+
51+ // get records
52+ $ affectedRecords = $ this ->getAffectedRecordsWithVersion ();
53+
54+ // update main table records
55+ if (! $ this ->query ->increment ($ this ->model ->getLatestVersionColumn (), 1 , $ values )) {
56+ return false ;
57+ }
58+
59+ // update version table records
60+ $ db = $ this ->model ->getConnection ();
61+ foreach ($ affectedRecords as $ id => $ version ) {
62+ $ affectedRecordVersionValues = array_merge ([
63+ $ this ->model ->getVersionKeyName () => $ id ,
64+ $ this ->model ->getVersionColumn () => $ version +1
65+ ], $ versionValues );
66+
67+ if (! $ db ->table ($ this ->model ->getVersionTable ())->insert ($ affectedRecordVersionValues )) {
68+ return false ;
69+ }
70+ }
71+
72+ return true ;
73+ }
74+
75+ /**
76+ * Delete a record from the database.
77+ *
78+ * @return mixed
79+ */
80+ public function delete ()
81+ {
82+ if (isset ($ this ->onDelete )) {
83+ return call_user_func ($ this ->onDelete , $ this );
84+ }
85+
86+ $ this ->forceDelete ();
87+ }
88+
89+ /**
90+ * Run the default delete function on the builder.
91+ *
92+ * @return mixed
93+ */
94+ public function forceDelete ()
95+ {
96+ // get version values & values
97+ $ versionValues = $ this ->getVersionValues ($ values );
98+ $ values = $ this ->getValues ($ values );
99+
100+ // get records
101+ $ affectedRecords = $ this ->getAffectedRecordsWithVersion ();
102+
103+ // delete main table records
104+ if (! $ this ->query ->delete ()) {
105+ return false ;
106+ }
107+
108+ // delete version table records
109+ $ db = $ this ->model ->getConnection ();
110+ return $ db ->table ($ this ->model ->getVersionTable ())
111+ ->whereIn ($ this ->model ->getVersionKeyName (), array_flip ($ affectedRecords ))
112+ ->delete ();
113+ }
114+
115+ /**
116+ * Get affected records.
117+ *
118+ * @return array
119+ */
120+ protected function getAffectedRecordsWithUpdatedVersion ()
121+ {
122+ // model only
123+ if ($ this ->model ->getKey ()) {
124+ $ records = [
125+ $ this ->model ->getKey () => $ this ->model ->{$ this ->model ->getLatestVersionColumn ()}
126+ ];
127+ }
128+
129+ // mass assignment
130+ else {
131+ $ records = [];
132+ foreach ($ this ->query ->get () as $ record ) {
133+ $ records [$ record ->{$ this ->model ->getKeyName ()}] = $ record ->{$ this ->model ->getLatestVersionColumn ()};
134+ }
135+ }
136+
137+ return $ records ;
138+ }
139+
140+ /**
141+ * Get affected ids.
142+ *
143+ * @param array $values
144+ * @return array
145+ */
146+ protected function getValues (array $ values )
147+ {
148+ $ versionedKeys = $ this ->model ->getVersionedAttributeNames ();
149+
150+ $ array = array_diff_key ($ values , array_flip ($ versionedKeys ));
151+
152+ return $ array ;
153+ }
154+
155+ /**
156+ * Get affected ids.
157+ *
158+ * @param array $values
159+ * @return array
160+ */
161+ protected function getVersionValues (array $ values )
162+ {
163+ $ versionedKeys = $ this ->model ->getVersionedAttributeNames ();
164+
165+ $ array = array_intersect_key ($ values , array_flip ($ versionedKeys ));
166+ $ array [$ this ->model ->getVersionKeyName ()] = $ this ->model ->getKey ();
167+
168+ return $ array ;
169+ }
170+
171+ /**
172+ * Add the "updated at" column to an array of values.
173+ *
174+ * @param array $values
175+ * @return array
176+ */
177+ protected function addUpdatedAtColumn (array $ values )
178+ {
179+ if (! $ this ->model ->usesTimestamps () && ! $ this ->model ->usesVersionTimestamps ()) return $ values ;
180+
181+ if ($ this ->model ->usesTimestamps ()) {
182+ $ column = $ this ->model ->getUpdatedAtColumn ();
183+ }
184+
185+ if ($ this ->model ->usesVersionTimestamps ()) {
186+ $ column = $ this ->model ->getUpdatedAtColumn ();
187+ }
188+
189+ return array_add ($ values , $ column , $ this ->model ->freshTimestampString ());
190+ }
191+
192+ /**
193+ * Get updatedAt timestamp.
194+ *
195+ * @return array
196+ */
197+ protected function getUpdatedAtTimestamp ()
198+ {
199+ if ( ! $ model ->usesTimestamps ()) return $ values ;
200+
201+ return [$ this ->model ->getUpdatedAtColumn () => $ this ->model ->freshTimestampString ()];
202+ }
203+
204+ /**
205+ * Get deletedAt timestamp.
206+ *
207+ * @return array
208+ */
209+ protected function getDeletedAtTimestamp ()
210+ {
211+ return [$ this ->model ->getQualifiedDeletedAtColumn () => $ this ->model ->freshTimestampString ()];
212+ }
213+
214+ }
0 commit comments