1 |
|
2 |
|
3 |
|
4 | 'use strict';
|
5 |
|
6 | const Base = require('../base/Base');
|
7 |
|
8 | module.exports = class ActiveLinker extends Base {
|
9 |
|
10 | async link (name, model, extraColumns) {
|
11 | const relation = this.owner.getRelation(name);
|
12 | const method = relation.isOuterLink() ? 'linkVia' : 'linkInternal';
|
13 | await this[method](relation, model, extraColumns);
|
14 | if (!relation.isMultiple()) {
|
15 | this.owner.populateRelation(name, model);
|
16 | return PromiseHelper.setImmediate();
|
17 | }
|
18 | const related = this.owner.getRelated(name);
|
19 | if (!related) {
|
20 | return PromiseHelper.setImmediate();
|
21 | }
|
22 | const index = relation.getIndex();
|
23 | if (index) {
|
24 | related[index] = model;
|
25 | } else {
|
26 | related.push(model);
|
27 | }
|
28 | return PromiseHelper.setImmediate();
|
29 | }
|
30 |
|
31 | linkInternal (relation, model) {
|
32 | return relation.isBackRef()
|
33 | ? this.bindModels(relation.refKey, relation.linkKey, model, this.owner, relation)
|
34 | : this.bindModels(relation.linkKey, relation.refKey, this.owner, model, relation);
|
35 | }
|
36 |
|
37 | linkVia (relation, model, extraColumns) {
|
38 | const via = relation.getViaTable() || relation.getViaRelation();
|
39 | const columns = {
|
40 | [via.refKey]: this.owner.get(via.linkKey),
|
41 | [relation.linkKey]: model.get(relation.refKey)
|
42 | };
|
43 | if (extraColumns) {
|
44 | Object.assign(columns, extraColumns);
|
45 | }
|
46 | if (relation.getViaTable()) {
|
47 | return this.owner.getDb().insert(via.getTable(), columns);
|
48 | }
|
49 |
|
50 | this.owner.unsetRelated(relation.getViaRelationName());
|
51 | model = this.owner.spawn(via.model.constructor);
|
52 | model.assign(columns);
|
53 | return model.insert();
|
54 | }
|
55 |
|
56 | async unlink (name, model, deletion) {
|
57 | const relation = this.owner.getRelation(name);
|
58 | const method = relation.isOuterLink() ? 'unlinkVia' : 'unlinkInternal';
|
59 | await this[method](relation, model, deletion);
|
60 | this.unsetUnlinked(name, model, relation);
|
61 | return PromiseHelper.setImmediate();
|
62 | }
|
63 |
|
64 | async unlinkInternal (relation, model) {
|
65 | const ref = model.get(relation.refKey);
|
66 | const link = this.owner.get(relation.linkKey);
|
67 | relation.isBackRef()
|
68 | ? await QueryHelper.unlinkInternal(ref, link, model, relation.refKey)
|
69 | : await QueryHelper.unlinkInternal(link, ref, this.owner, relation.linkKey);
|
70 | }
|
71 |
|
72 | unlinkVia (relation, model, deletion = true) {
|
73 | const via = relation.getViaTable() || relation.getViaRelation();
|
74 | const condition = {
|
75 | [via.refKey]: this.owner.get(via.linkKey),
|
76 | [relation.linkKey]: model.get(relation.refKey)
|
77 | };
|
78 | const nulls = {
|
79 | [via.refKey]: null,
|
80 | [relation.linkKey]: null
|
81 | };
|
82 | if (relation.getViaTable()) {
|
83 | return deletion
|
84 | ? this.owner.getDb().delete(via.getTable(), condition)
|
85 | : this.owner.getDb().update(via.getTable(), condition, nulls);
|
86 | }
|
87 | this.owner.unsetRelated(relation.getViaRelationName());
|
88 | return deletion
|
89 | ? via.model.find(condition).delete()
|
90 | : via.model.find(condition).updateAll(nulls);
|
91 | }
|
92 |
|
93 | async unlinkAll (name, deletion) {
|
94 | const relation = this.owner.getRelation(name);
|
95 | if (relation) {
|
96 | const method = relation.isOuterLink() ? 'unlinkViaAll' : 'unlinkInternalAll';
|
97 | await this[method](relation, deletion);
|
98 | this.owner.unsetRelated(name);
|
99 | }
|
100 | }
|
101 |
|
102 | async unlinkViaAll (relation, deletion = true) {
|
103 | if (relation.getViaRelation()) {
|
104 | this.owner.unsetRelated(relation.getViaRelationName());
|
105 | }
|
106 | const via = relation.getViaTable() || relation.getViaRelation();
|
107 | let condition = {[via.refKey]: this.owner.get(via.linkKey)};
|
108 | if (via.getWhere()) {
|
109 | condition = ['AND', condition, via.getWhere()];
|
110 | }
|
111 | let nulls = {[via.refKey]: null};
|
112 | if (relation.getViaTable()) {
|
113 | condition = this.owner.getDb().buildCondition(condition);
|
114 | deletion ? await this.owner.getDb().delete(via.getTable(), condition)
|
115 | : await this.owner.getDb().update(via.getTable(), condition, nulls);
|
116 | } else if (deletion) {
|
117 | for (const model of await via.model.find(condition).all()) {
|
118 | await model.delete();
|
119 | }
|
120 | } else {
|
121 | await via.model.find(condition).updateAll(nulls);
|
122 | }
|
123 | }
|
124 |
|
125 | async unlinkInternalAll (relation) {
|
126 |
|
127 | if (Array.isArray(this.owner.get(relation.linkKey))) {
|
128 | this.owner.set(relation.linkKey, []);
|
129 | return this.owner.forceSave();
|
130 | }
|
131 | let condition = {[relation.refKey]: this.owner.get(relation.linkKey)};
|
132 | if (relation.getWhere()) {
|
133 | condition = ['AND', condition, relation.getWhere()];
|
134 | }
|
135 | relation.getViaArray()
|
136 | ? await relation.model.getDb().updateAllPull(relation.model.getTable(), {}, condition)
|
137 | : await relation.model.find(condition).updateAll({[relation.refKey]: null});
|
138 | }
|
139 |
|
140 | unsetUnlinked (name, model, relation) {
|
141 | if (!relation.isMultiple()) {
|
142 | return this.owner.unsetRelated(name);
|
143 | }
|
144 | const models = this.owner.getRelated(name);
|
145 | if (Array.isArray(models)) {
|
146 | const result = models.filter(target => !CommonHelper.isEqual(model.getId(), target.getId()));
|
147 | this.owner.populateRelation(name, result);
|
148 | }
|
149 | }
|
150 |
|
151 | bindModels (foreignKey, primaryKey, foreignModel, primaryModel, relation) {
|
152 | const value = primaryModel.get(primaryKey);
|
153 | if (!value) {
|
154 | throw new Error(this.wrapMessage('Primary key is null'));
|
155 | }
|
156 | if (!relation.getViaArray()) {
|
157 | foreignModel.set(foreignKey, value);
|
158 | return foreignModel.forceSave();
|
159 | }
|
160 | if (!Array.isArray(foreignModel.get(foreignKey))) {
|
161 | foreignModel.set(foreignKey, []);
|
162 | }
|
163 | if (!ArrayHelper.includes(value, foreignModel.get(foreignKey))) {
|
164 | foreignModel.get(foreignKey).push(value);
|
165 | return foreignModel.forceSave();
|
166 | }
|
167 | }
|
168 |
|
169 | wrapMessage (message) {
|
170 | return `${this.constructor.name}: ${this.owner.wrapMessage(message)}`;
|
171 | }
|
172 | };
|
173 |
|
174 | const ArrayHelper = require('../helper/ArrayHelper');
|
175 | const CommonHelper = require('../helper/CommonHelper');
|
176 | const PromiseHelper = require('../helper/PromiseHelper');
|
177 | const QueryHelper = require('../helper/QueryHelper'); |
\ | No newline at end of file |