Skip to content

Commit df84398

Browse files
authored
Merge branch '3.x' into fix/error-handler
2 parents 6d5c1ba + 9b421e8 commit df84398

File tree

6 files changed

+81
-17
lines changed

6 files changed

+81
-17
lines changed

src/Models/Behaviors/HasFiles.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public function files()
1818
File::class,
1919
'fileable',
2020
config('twill.fileables_table', 'twill_fileables')
21-
)->withPivot(['role', 'locale'])
21+
)->withPivot(['id', 'role', 'locale'])
2222
->withTimestamps()->orderBy(config('twill.fileables_table', 'twill_fileables') . '.id', 'asc');
2323
}
2424

src/Models/Behaviors/HasMedias.php

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function medias()
4545
'mediable',
4646
config('twill.mediables_table', 'twill_mediables')
4747
)->withPivot([
48+
'id',
4849
'crop',
4950
'role',
5051
'crop_w',

src/Repositories/Behaviors/HandleFiles.php

+13-8
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
namespace A17\Twill\Repositories\Behaviors;
44

5+
use A17\Twill\Facades\TwillUtil;
6+
use A17\Twill\Models\Behaviors\HasFiles;
57
use A17\Twill\Models\Contracts\TwillModelContract;
68
use A17\Twill\Models\File;
7-
use Illuminate\Support\Arr;
89
use Illuminate\Support\Str;
910
use Illuminate\Support\Collection;
1011

@@ -37,7 +38,7 @@ public function hydrateHandleFiles($object, $fields)
3738
}
3839

3940
/**
40-
* @param \A17\Twill\Models\Model $object
41+
* @param \A17\Twill\Models\Model|HasFiles $object
4142
* @param array $fields
4243
* @return void
4344
*/
@@ -47,7 +48,7 @@ public function afterSaveHandleFiles($object, $fields)
4748
return;
4849
}
4950

50-
$object->files()->sync($this->getFiles($fields));
51+
TwillUtil::syncUsingPrimaryKey($object->files(), $this->getFiles($fields));
5152
}
5253

5354
/**
@@ -73,11 +74,11 @@ private function getFiles($fields)
7374
|| in_array($role, config('twill.block_editor.files', []))
7475
) {
7576
Collection::make($filesForRole)->each(function ($file) use (&$files, $role, $locale) {
76-
$files->push([
77+
$files[$file['pivot_id'] ?? uniqid('file')] = [
7778
'file_id' => $file['id'],
7879
'role' => $role,
7980
'locale' => $locale,
80-
]);
81+
];
8182
});
8283
}
8384
}
@@ -97,8 +98,8 @@ public function getFormFieldsHandleFiles($object, $fields)
9798
if ($object->has('files')) {
9899
foreach ($object->files->groupBy('pivot.role') as $role => $filesByRole) {
99100
foreach ($filesByRole->groupBy('pivot.locale') as $locale => $filesByLocale) {
100-
$fields['files'][$locale][$role] = $filesByLocale->map(function ($file) {
101-
return $file->toCmsArray();
101+
$fields['files'][$locale][$role] = $filesByLocale->map(function (File $file) {
102+
return $file->toCmsArray() + ['pivot_id' => $file->pivot->id];
102103
});
103104
}
104105
}
@@ -107,9 +108,13 @@ public function getFormFieldsHandleFiles($object, $fields)
107108
return $fields;
108109
}
109110

111+
/**
112+
* @param HasFiles|TwillModelContract $object
113+
* @param HasFiles|TwillModelContract $newObject
114+
*/
110115
public function afterDuplicateHandleFiles(TwillModelContract $object, TwillModelContract $newObject): void
111116
{
112-
$newObject->files()->sync(
117+
$newObject->files()->attach(
113118
$object->files->mapWithKeys(function ($file) use ($object) {
114119
return [
115120
$file->id => Collection::make($object->files()->getPivotColumns())->mapWithKeys(

src/Repositories/Behaviors/HandleMedias.php

+10-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace A17\Twill\Repositories\Behaviors;
44

55
use A17\Twill\Facades\TwillBlocks;
6+
use A17\Twill\Facades\TwillUtil;
7+
use A17\Twill\Models\Behaviors\HasMedias;
68
use A17\Twill\Models\Contracts\TwillModelContract;
79
use A17\Twill\Models\Media;
810
use Illuminate\Support\Arr;
@@ -43,7 +45,7 @@ public function hydrateHandleMedias($object, $fields)
4345
}
4446

4547
/**
46-
* @param \A17\Twill\Models\Model $object
48+
* @param \A17\Twill\Models\Model|HasMedias $object
4749
* @param array $fields
4850
* @return void
4951
*/
@@ -53,7 +55,7 @@ public function afterSaveHandleMedias($object, $fields)
5355
return;
5456
}
5557

56-
$object->medias()->sync($this->getMedias($fields));
58+
TwillUtil::syncUsingPrimaryKey($object->medias(), $this->getMedias($fields));
5759
}
5860

5961
/**
@@ -80,7 +82,7 @@ private function getMedias($fields)
8082
$customMetadatas = $media['metadatas']['custom'] ?? [];
8183
if (isset($media['crops']) && !empty($media['crops'])) {
8284
foreach ($media['crops'] as $cropName => $cropData) {
83-
$medias->push([
85+
$medias[$cropData['pivot_id'] ?? uniqid('media')] = [
8486
'media_id' => $media['id'],
8587
'crop' => $cropName,
8688
'role' => $role,
@@ -91,11 +93,11 @@ private function getMedias($fields)
9193
'crop_x' => $cropData['x'],
9294
'crop_y' => $cropData['y'],
9395
'metadatas' => json_encode($customMetadatas),
94-
]);
96+
];
9597
}
9698
} else {
9799
foreach ($this->getCrops($role) as $cropName => $cropDefinitions) {
98-
$medias->push([
100+
$medias[$media['pivot_id'] ?? uniqid('media')] = [
99101
'media_id' => $media['id'],
100102
'crop' => $cropName,
101103
'role' => $role,
@@ -106,7 +108,7 @@ private function getMedias($fields)
106108
'crop_x' => null,
107109
'crop_y' => null,
108110
'metadatas' => json_encode($customMetadatas),
109-
]);
111+
];
110112
}
111113
}
112114
});
@@ -157,12 +159,14 @@ private function getMediaFormItems($medias)
157159
$item = $mediasById->first();
158160

159161
$itemForForm = $item->toCmsArray();
162+
$itemForForm['pivot_id'] = $item->pivot->id;
160163

161164
$itemForForm['metadatas']['custom'] = json_decode($item->pivot->metadatas, true);
162165

163166
foreach ($mediasById->groupBy('pivot.crop') as $crop => $mediaByCrop) {
164167
$media = $mediaByCrop->first();
165168
$itemForForm['crops'][$crop] = [
169+
'pivot_id' => $media->pivot->id,
166170
'name' => $media->pivot->ratio,
167171
'width' => $media->pivot->crop_w,
168172
'height' => $media->pivot->crop_h,

src/Repositories/BlockRepository.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace A17\Twill\Repositories;
44

55
use A17\Twill\Facades\TwillBlocks;
6+
use A17\Twill\Models\Block;
67
use A17\Twill\Models\Contracts\TwillModelContract;
78
use A17\Twill\Repositories\Behaviors\HandleFiles;
89
use A17\Twill\Repositories\Behaviors\HandleMedias;
@@ -75,10 +76,11 @@ public function afterSave(TwillModelContract $model, array $fields): void
7576
parent::afterSave($model, $fields);
7677
}
7778

79+
/** @param Block $object */
7880
public function afterDelete(TwillModelContract $object): void
7981
{
80-
$object->medias()->sync([]);
81-
$object->files()->sync([]);
82+
$object->medias()->detach();
83+
$object->files()->detach();
8284

8385
if (Schema::hasTable(config('twill.related_table', 'twill_related'))) {
8486
$object->clearAllRelated();

src/TwillUtil.php

+52
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace A17\Twill;
44

55
use A17\Twill\Models\Contracts\TwillLinkableModel;
6+
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
67
use Illuminate\Database\Eloquent\Relations\Relation;
78
use Illuminate\Support\Facades\Session;
89

@@ -103,4 +104,55 @@ private function pushToTempStore(string $key, int $frontendId, int $dbId): void
103104

104105
Session::put(self::SESSION_FIELD, $sessionData);
105106
}
107+
108+
public function syncUsingPrimaryKey(BelongsToMany $relation, $ids, $detaching = true): array
109+
{
110+
return (function ($ids, $detaching = true) {
111+
$changes = [
112+
'attached' => [], 'detached' => [], 'updated' => [],
113+
];
114+
115+
// First we need to attach any of the associated models that are not currently
116+
// in this joining table. We'll spin through the given IDs, checking to see
117+
// if they exist in the array of current ones, and if not we will insert.
118+
$current = $this->getCurrentlyAttachedPivots()
119+
->pluck('id')->all();
120+
121+
$records = $this->formatRecordsList($this->parseIds($ids));
122+
123+
// Next, we will take the differences of the currents and given IDs and detach
124+
// all of the entities that exist in the "current" array but are not in the
125+
// array of the new IDs given to the method which will complete the sync.
126+
if ($detaching) {
127+
$detach = array_diff($current, array_keys($records));
128+
129+
if (count($detach) > 0) {
130+
$this->newPivotQuery()->whereIn('id', $detach)->delete();
131+
132+
$changes['detached'] = $this->castKeys($detach);
133+
}
134+
}
135+
136+
// Now we are finally ready to attach the new records. Note that we'll disable
137+
// touching until after the entire operation is complete so we don't fire a
138+
// ton of touch operations until we are totally done syncing the records.
139+
$changes = array_merge(
140+
$changes,
141+
$this->attachNew($records, $current, false)
142+
);
143+
144+
// Once we have finished attaching or detaching the records, we will see if we
145+
// have done any attaching or detaching, and if we have we will touch these
146+
// relationships if they are configured to touch on any database updates.
147+
if (
148+
count($changes['attached']) ||
149+
count($changes['updated']) ||
150+
count($changes['detached'])
151+
) {
152+
$this->touchIfTouching();
153+
}
154+
155+
return $changes;
156+
})->call($relation, $ids, $detaching);
157+
}
106158
}

0 commit comments

Comments
 (0)