Support changing texture model from skinlib

This commit is contained in:
printempw 2018-07-24 16:13:51 +08:00
parent bcf8710019
commit e0c7292d35
11 changed files with 230 additions and 10 deletions

View File

@ -295,6 +295,35 @@ class SkinlibController extends Controller
}
} // @codeCoverageIgnore
public function model(Request $request) {
$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 != $this->user->uid && !$this->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', ['tid' => $duplicate->tid]), 1);
}
$t->type = $request->input('model');
$t->save();
return json(trans('skinlib.model.success', ['model' => request('model')]), 0);
}
/**
* Check Uploaded Files
*

View File

@ -506,3 +506,15 @@ if (! function_exists('report')) {
app(Illuminate\Contracts\Debug\ExceptionHandler::class)->report($exception);
}
}
if (! function_exists('can_moderate_texture')) {
function can_moderate_texture($user, $texture) {
if (! $user) {
return false;
}
// Only uploader and admins can moderate textures
return ($texture->uploader == $user->uid || $user->isAdmin());
}
}

View File

@ -503,6 +503,57 @@ describe('tests for "operations" module', () => {
expect(showAjaxError).toBeCalled();
});
it('change texture model', async () => {
const fetch = jest.fn()
.mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
.mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
.mockReturnValueOnce(Promise.reject());
window.fetch = fetch;
const url = jest.fn(path => path);
window.url = url;
const trans = jest.fn(key => key);
window.trans = trans;
const swal = jest.fn()
.mockImplementationOnce(() => Promise.reject())
.mockImplementationOnce(() => Promise.resolve('alex'));
window.swal = swal;
const modal = jest.fn();
const toastr = {
success: jest.fn(),
warning: jest.fn()
};
window.toastr = toastr;
const showAjaxError = jest.fn();
window.showAjaxError = showAjaxError;
document.body.innerHTML = '<div id="model"></div>';
const changeTextureModel = require(modulePath).changeTextureModel;
await changeTextureModel(1, 'steve');
expect(fetch).not.toBeCalled();
await changeTextureModel(1, 'steve');
expect(swal).toBeCalledWith(expect.objectContaining({
text: trans('skinlib.setNewTextureModel'),
input: 'select',
inputValue: 'steve',
}));
expect(fetch).toBeCalledWith({
type: 'POST',
url: 'skinlib/model',
dataType: 'json',
data: { tid: 1, model: 'alex' }
});
expect($('div').text()).toBe('alex');
expect(toastr.success).toBeCalledWith('success');
await changeTextureModel(1, 'steve');
expect(toastr.warning).toBeCalledWith('warning');
await changeTextureModel(1, 'steve');
expect(showAjaxError).toBeCalled();
});
it('update texture status', () => {
window.trans = jest.fn(key => key);
document.body.innerHTML = `

View File

@ -130,6 +130,47 @@ async function changeTextureName(tid, oldName) {
}
}
async function changeTextureModel(tid, oldModel) {
const models = {
steve: 'steve',
alex: 'alex',
cape: trans('general.cape')
};
let newTextureModel = '';
try {
newTextureModel = await swal({
text: trans('skinlib.setNewTextureModel'),
input: 'select',
inputValue: oldModel,
inputOptions: models,
showCancelButton: true,
inputClass: 'form-control'
});
} catch (error) {
return;
}
try {
const { errno, msg } = await fetch({
type: 'POST',
url: url('skinlib/model'),
dataType: 'json',
data: { tid: tid, model: newTextureModel }
});
if (errno === 0) {
$('#model').text(models[newTextureModel]);
toastr.success(msg);
} else {
toastr.warning(msg);
}
} catch (error) {
showAjaxError(error);
}
}
/**
* Update button action & likes of texture.
*
@ -231,6 +272,7 @@ if (process.env.NODE_ENV === 'test') {
ajaxAddToCloset,
removeFromCloset,
changeTextureName,
changeTextureModel,
updateTextureStatus,
};
}

View File

@ -47,6 +47,9 @@
setNewTextureName: 'Please enter the new texture name:',
emptyNewTextureName: 'Empty new texture name.',
// Change Model
setNewTextureModel: 'Please select a new texture model:',
// Skinlib
filter: {
skin: '(Any Model)',

View File

@ -36,7 +36,7 @@ show:
detail: Details
name: Texture Name
edit-name: Edit Name
edit: Edit
model: Applicable Model
download-raw: Click to download raw texture
size: File Size
@ -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 (TID: :tid). You can add it to your closet directly."
no-permission: You aren't the uploader of this texture.
non-existent: Non-existent texture.

View File

@ -67,6 +67,9 @@
setNewTextureName: '请输入新的材质名称:',
emptyNewTextureName: '你还没有输入新名称啊',
// Change Model
setNewTextureModel: '请选择新的材质适用模型:',
// Upload
emptyTextureName: '给你的材质起个名字吧',
emptyTextureType: '请选择材质的类型',

View File

@ -36,7 +36,7 @@ show:
detail: 详细信息
name: 名称
edit-name: 修改名称
edit: 修改
model: 适用模型
download-raw: 右键另存为即可下载原始皮肤文件
size: 文件大小
@ -89,5 +89,9 @@ privacy:
rename:
success: 材质名称已被成功设置为 :name
model:
success: 材质的适用模型已被修改为 :model
duplicate: 已经有人上传过适用于该模型的相同材质了直接去皮肤库收藏使用吧TID:tid
no-permission: 你不是这个材质的上传者哦
non-existent: 材质不存在

View File

@ -48,10 +48,11 @@
<tbody>
<tr>
<td>{{ trans('skinlib.show.name') }}</td>
<td id="name">{{ $texture->name }}
@if (!is_null($user) && ($texture->uploader == $user->uid || $user->isAdmin()))
<td>
<span id="name">{{ $texture->name }}</span>
@if (can_moderate_texture($user, $texture))
<small>
<a style="cursor: pointer" onclick="changeTextureName({{ $texture->tid }}, '{{ $texture->name }}');">{{ trans('skinlib.show.edit-name') }}</a>
<a style="cursor: pointer" onclick="changeTextureName({{ $texture->tid }}, '{{ $texture->name }}');">{{ trans('skinlib.show.edit') }}</a>
</small>
@endif
</td>
@ -59,10 +60,11 @@
<tr>
<td>{{ trans('skinlib.show.model') }}</td>
<td>
@if ($texture->type == 'cape')
{{ trans('general.cape') }}
@else
{{ $texture->type }}
<span id="model">{{ $texture->type == 'cape' ? trans('general.cape') : $texture->type }}</span>
@if (can_moderate_texture($user, $texture))
<small>
<a style="cursor: pointer" onclick="changeTextureModel({{ $texture->tid }}, '{{ $texture->type }}');">{{ trans('skinlib.show.edit') }}</a>
</small>
@endif
</td>
</tr>

View File

@ -86,6 +86,7 @@ Route::group(['prefix' => 'skinlib'], function ()
Route::post('/upload', 'SkinlibController@handleUpload');
Route::post('/rename', 'SkinlibController@rename');
Route::post('/model', 'SkinlibController@model');
Route::post('/privacy', 'SkinlibController@privacy');
Route::post('/delete', 'SkinlibController@delete');
});

View File

@ -933,4 +933,73 @@ class SkinlibControllerTest extends TestCase
]);
$this->assertEquals('new_name', Texture::find($texture->tid)->name);
}
public function testChangeModel()
{
$uploader = factory(User::class)->create();
$other = factory(User::class)->create();
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
// Non-existed texture
$this->actAs($uploader)
->post('/skinlib/model', [
'tid' => -1,
'model' => 'alex'
])
->seeJson([
'errno' => 1,
'msg' => trans('skinlib.non-existent')
]);
// Other user should not be able to change model
$this->actAs($other)
->post('/skinlib/model', [
'tid' => $texture->tid,
'model' => 'alex'
])
->seeJson([
'errno' => 1,
'msg' => trans('skinlib.no-permission')
]);
// Administrators should be able to change model
$this->actAs('admin')
->post('/skinlib/model', [
'tid' => $texture->tid,
'model' => 'alex'
])
->seeJson([
'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)
->post('/skinlib/model', [
'tid' => $texture->tid,
'model' => 'steve'
])
->seeJson([
'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)
->post('/skinlib/model', [
'tid' => $texture->tid,
'model' => 'alex'
])
->seeJson([
'errno' => 1,
'msg' => trans('skinlib.model.duplicate', ['tid' => $duplicate->tid])
]);
}
}