diff --git a/app/Http/Controllers/SkinlibController.php b/app/Http/Controllers/SkinlibController.php
index 2399c17e..1a35de9e 100644
--- a/app/Http/Controllers/SkinlibController.php
+++ b/app/Http/Controllers/SkinlibController.php
@@ -295,6 +295,35 @@ class SkinlibController extends Controller
}
} // @codeCoverageIgnore
+ public function model(Request $request) {
+ $user = Auth::user();
+ $data = $this->validate($request, [
+ 'tid' => 'required|integer',
+ 'model' => 'required|in:steve,alex,cape'
+ ]);
+
+ $t = Texture::find($request->input('tid'));
+
+ if (! $t)
+ return json(trans('skinlib.non-existent'), 1);
+
+ if ($t->uploader != $user->uid && !$user->isAdmin())
+ return json(trans('skinlib.no-permission'), 1);
+
+ $duplicate = Texture::where('hash', $t->hash)
+ ->where('type', $request->input('model'))
+ ->where('tid', '<>', $t->tid)
+ ->first();
+ if ($duplicate && $duplicate->public) {
+ return json(trans('skinlib.model.duplicate', ['name' => $duplicate->name]), 1);
+ }
+
+ $t->type = $request->input('model');
+ $t->save();
+
+ return json(trans('skinlib.model.success', ['model' => $data['model']]), 0);
+ }
+
/**
* Check Uploaded Files
*
diff --git a/resources/assets/src/components/skinlib/Show.vue b/resources/assets/src/components/skinlib/Show.vue
index d64fa028..f18d8418 100644
--- a/resources/assets/src/components/skinlib/Show.vue
+++ b/resources/assets/src/components/skinlib/Show.vue
@@ -55,7 +55,7 @@
|
{{ name }}
-
+
|
@@ -64,6 +64,9 @@
{{ $t('general.cape') }}
{{ type }}
+
+
+
|
@@ -253,6 +256,34 @@ export default {
toastr.warning(msg);
}
},
+ async changeModel() {
+ const { dismiss, value } = await swal({
+ text: this.$t('skinlib.setNewTextureModel'),
+ input: 'select',
+ inputValue: this.type,
+ inputOptions: {
+ steve: 'Steve',
+ alex: 'Alex',
+ cape: this.$t('general.cape')
+ },
+ showCancelButton: true,
+ inputClass: 'form-control'
+ });
+ if (dismiss) {
+ return;
+ }
+
+ const { errno, msg } = await this.$http.post(
+ '/skinlib/model',
+ { tid: this.tid, model: value }
+ );
+ if (errno === 0) {
+ this.type = value;
+ toastr.success(msg);
+ } else {
+ toastr.warning(msg);
+ }
+ },
async togglePrivacy() {
const { dismiss } = await swal({
text: this.public
diff --git a/resources/assets/tests/components/skinlib/Show.test.js b/resources/assets/tests/components/skinlib/Show.test.js
index 6b327c49..ef9a5038 100644
--- a/resources/assets/tests/components/skinlib/Show.test.js
+++ b/resources/assets/tests/components/skinlib/Show.test.js
@@ -249,6 +249,38 @@ test('change texture name', async () => {
expect(wrapper.vm.name).toBe('new-name');
});
+test('change texture model', async () => {
+ Vue.prototype.$http.get.mockResolvedValue({ type: 'steve' });
+ Vue.prototype.$http.post
+ .mockResolvedValueOnce({ errno: 1, msg: '1' })
+ .mockResolvedValue({ errno: 0, msg: '0' });
+ jest.spyOn(toastr, 'warning');
+ swal.mockResolvedValueOnce({ dismiss: 1 })
+ .mockResolvedValue({ value: 'alex' });
+ const wrapper = mount(Show, {
+ mocks: {
+ $route: ['/skinlib/show/1', '1']
+ },
+ stubs: { previewer }
+ });
+ const button = wrapper.findAll('small').at(1).find('a');
+
+ button.trigger('click');
+ expect(Vue.prototype.$http.post).not.toBeCalled();
+
+ button.trigger('click');
+ await flushPromises();
+ expect(Vue.prototype.$http.post).toBeCalledWith(
+ '/skinlib/model',
+ { tid: 1, model: 'alex' }
+ );
+ expect(toastr.warning).toBeCalledWith('1');
+
+ button.trigger('click');
+ await flushPromises();
+ expect(wrapper.vm.type).toBe('alex');
+});
+
test('toggle privacy', async () => {
Vue.prototype.$http.get.mockResolvedValue({ public: true });
Vue.prototype.$http.post
diff --git a/resources/lang/en/front-end.yml b/resources/lang/en/front-end.yml
index e5a8bbef..cf6ff145 100644
--- a/resources/lang/en/front-end.yml
+++ b/resources/lang/en/front-end.yml
@@ -70,6 +70,7 @@ skinlib:
setPublicNotice: Sure to set this as public texture?
setPrivateNotice: Sure to set this as private texture?
deleteNotice: Are you sure to delete this texture?
+ setNewTextureModel: "Please select a new texture model:"
upload:
texture-name: Texture Name
texture-type: Texture Type
@@ -85,7 +86,7 @@ skinlib:
likes: People who like this
detail: Details
name: Texture Name
- edit-name: Edit Name
+ edit: Edit
model: Applicable Model
download-raw: Click to download raw texture
size: File Size
diff --git a/resources/lang/en/skinlib.yml b/resources/lang/en/skinlib.yml
index deb945e2..123a8f8f 100644
--- a/resources/lang/en/skinlib.yml
+++ b/resources/lang/en/skinlib.yml
@@ -85,10 +85,14 @@ privacy:
change-privacy: Change Privacy
set-as-private: Set as Private
set-as-public: Set as Public
- success: The texture was setted to :privacy successfully.
+ success: The texture was set to :privacy successfully.
rename:
success: The texture was renamed to :name successfully.
+model:
+ success: The texture's model was changed to :model successfully.
+ duplicate: "The same texture available for the chosen model already exists in skinlib (Name: :tid). You can add it to your closet directly."
+
no-permission: You aren't the uploader of this texture.
non-existent: Non-existent texture.
diff --git a/resources/lang/zh_CN/front-end.yml b/resources/lang/zh_CN/front-end.yml
index d7d6ee22..206abcd8 100644
--- a/resources/lang/zh_CN/front-end.yml
+++ b/resources/lang/zh_CN/front-end.yml
@@ -72,6 +72,7 @@ skinlib:
setPublicNotice: 要将此材质设置为公开吗?
setPrivateNotice: 要将此材质设置为私有吗?
deleteNotice: 真的要删除此材质吗?
+ setNewTextureModel: 请选择新的材质适用模型:
upload:
texture-name: 材质名称
texture-type: 材质类型
@@ -87,7 +88,7 @@ skinlib:
likes: 收藏人数
detail: 详细信息
name: 名称
- edit-name: 修改名称
+ edit: 修改
model: 适用模型
download-raw: 右键另存为即可下载原始皮肤文件
size: 文件大小
diff --git a/resources/lang/zh_CN/skinlib.yml b/resources/lang/zh_CN/skinlib.yml
index a2fe8919..e569cbde 100644
--- a/resources/lang/zh_CN/skinlib.yml
+++ b/resources/lang/zh_CN/skinlib.yml
@@ -89,5 +89,9 @@ privacy:
rename:
success: 材质名称已被成功设置为 :name
+model:
+ success: 材质的适用模型已被修改为 :model
+ duplicate: 已经有人上传过适用于该模型的相同材质了,直接去皮肤库收藏使用吧(名称::tid)
+
no-permission: 你不是这个材质的上传者哦
non-existent: 材质不存在
diff --git a/routes/web.php b/routes/web.php
index e5c10b6f..410b8ee1 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -86,7 +86,7 @@ Route::group(['prefix' => 'skinlib'], function ()
{
Route::get ('/upload', 'SkinlibController@upload');
Route::post('/upload', 'SkinlibController@handleUpload');
-
+ Route::post('/model', 'SkinlibController@model');
Route::post('/rename', 'SkinlibController@rename');
Route::post('/privacy', 'SkinlibController@privacy');
Route::post('/delete', 'SkinlibController@delete');
diff --git a/tests/SkinlibControllerTest.php b/tests/SkinlibControllerTest.php
index afbcc065..b160b1b2 100644
--- a/tests/SkinlibControllerTest.php
+++ b/tests/SkinlibControllerTest.php
@@ -895,4 +895,86 @@ class SkinlibControllerTest extends TestCase
]);
$this->assertEquals('new_name', Texture::find($texture->tid)->name);
}
+
+ public function testModel()
+ {
+ $uploader = factory(User::class)->create();
+ $other = factory(User::class)->create();
+ $texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
+
+ // Non-existed texture
+ $this->actAs($uploader)
+ ->postJson('/skinlib/model', [
+ 'tid' => -1,
+ 'model' => 'alex'
+ ])
+ ->assertJson([
+ 'errno' => 1,
+ 'msg' => trans('skinlib.non-existent')
+ ]);
+
+ // Other user should not be able to change model
+ $this->actAs($other)
+ ->postJson('/skinlib/model', [
+ 'tid' => $texture->tid,
+ 'model' => 'alex'
+ ])
+ ->assertJson([
+ 'errno' => 1,
+ 'msg' => trans('skinlib.no-permission')
+ ]);
+
+ // Administrators should be able to change model
+ $this->actAs('admin')
+ ->postJson('/skinlib/model', [
+ 'tid' => $texture->tid,
+ 'model' => 'alex'
+ ])
+ ->assertJson([
+ 'errno' => 0,
+ 'msg' => trans('skinlib.model.success', ['model' => 'alex'])
+ ]);
+ $this->assertEquals('alex', Texture::find($texture->tid)->type);
+
+ // Uploader should be able to change model
+ $this->actAs($uploader)
+ ->postJson('/skinlib/model', [
+ 'tid' => $texture->tid,
+ 'model' => 'steve'
+ ])
+ ->assertJson([
+ 'errno' => 0,
+ 'msg' => trans('skinlib.model.success', ['model' => 'steve'])
+ ]);
+ $this->assertEquals('steve', Texture::find($texture->tid)->type);
+
+ $duplicate = factory(Texture::class, 'alex')->create([
+ 'uploader' => $other->uid,
+ 'hash' => $texture->hash
+ ]);
+
+ // Should fail if there is already a texture with same hash and chosen model
+ $this->actAs($uploader)
+ ->postJson('/skinlib/model', [
+ 'tid' => $texture->tid,
+ 'model' => 'alex'
+ ])
+ ->assertJson([
+ 'errno' => 1,
+ 'msg' => trans('skinlib.model.duplicate', ['name' => $duplicate->name])
+ ]);
+
+ // Allow private texture
+ $duplicate->public = false;
+ $duplicate->save();
+ $this->actAs($uploader)
+ ->postJson('/skinlib/model', [
+ 'tid' => $texture->tid,
+ 'model' => 'alex'
+ ])
+ ->assertJson([
+ 'errno' => 0,
+ 'msg' => trans('skinlib.model.success', ['model' => 'alex'])
+ ]);
+ }
}