Refactor Closet model

This commit is contained in:
Pig Fang 2017-11-05 16:54:01 +08:00
parent 8d1adc7e4d
commit 739bc17c3a
3 changed files with 94 additions and 125 deletions

View File

@ -36,27 +36,23 @@ class ClosetController extends Controller
$page = abs($request->input('page', 1)); $page = abs($request->input('page', 1));
$q = $request->input('q', null); $q = $request->input('q', null);
$items = []; $items = collect();
if ($q) { if ($q) {
// do search // do search
foreach ($this->closet->getItems($category) as $item) { $items = $this->closet->getItems($category)->filter(function ($item) use ($q) {
if (stristr($item->name, $q)) { return stristr($item['name'], $q);
$items[] = $item; });
}
}
} else { } else {
$items = $this->closet->getItems($category); $items = $this->closet->getItems($category);
} }
// pagination // pagination
$total_pages = ceil(count($items) / 6); $total_pages = ceil($items->count() / 6);
$items = array_slice($items, ($page - 1) * 6, 6);
return response()->json([ return response()->json([
'category' => $category, 'category' => $category,
'items' => $items, 'items' => $items->forPage($page, 6)->values(),
'total_pages' => $total_pages 'total_pages' => $total_pages
]); ]);
} }

View File

@ -3,6 +3,7 @@
namespace App\Models; namespace App\Models;
use DB; use DB;
use Illuminate\Support\Collection;
class Closet class Closet
{ {
@ -18,30 +19,16 @@ class Closet
/** /**
* Textures array generated from json. * Textures array generated from json.
* *
* @var Array * @var Collection
*/ */
private $textures = []; private $textures;
/** /**
* Array of App\Models\Texture instances. * Indicates if closet has been modified
* *
* @var array * @var array
*/ */
private $textures_skin = []; private $closet_modified = false;
/**
* Array of App\Models\Texture instances.
*
* @var array
*/
private $textures_cape = [];
/**
* Items that are modified.
*
* @var array
*/
private $items_modified = [];
/** /**
* Construct Closet object with owner's uid. * Construct Closet object with owner's uid.
@ -57,42 +44,22 @@ class Closet
if (!$this->db->where('uid', $uid)->get()) { if (!$this->db->where('uid', $uid)->get()) {
$this->db->insert([ $this->db->insert([
'uid' => $uid, 'uid' => $uid,
'textures' => '' 'textures' => '[]'
]); ]);
} }
// load items from json string // load items from json string
$this->textures = json_decode($this->db->where('uid', $uid)->get()[0]->textures, true); $this->textures = collect(json_decode(
$this->textures = is_array($this->textures) ? $this->textures : []; $this->db->where('uid', $uid)->first()->textures,
true
$textures_invalid = []; ));
// traverse items in the closet // traverse items in the closet
foreach ($this->textures as $texture) { $this->textures->filter(function ($texture) {
$result = Texture::find($texture['tid']); return is_null(Texture::find($texture['tid']));
})->each(function ($tid) {
if ($result) {
// set user custom texture name
$result->name = $texture['name'];
// push instances of App\Models\Texture to the bag
if ($result->type == "cape") {
$this->textures_cape[] = $result;
} else {
$this->textures_skin[] = $result;
}
} else {
$textures_invalid[] = $texture['tid'];
continue;
}
}
// remove invalid textures from closet
foreach ($textures_invalid as $tid) {
$this->remove($tid); $this->remove($tid);
} });
unset($textures_invalid);
} }
/** /**
@ -103,15 +70,31 @@ class Closet
*/ */
public function getItems($category = "all") public function getItems($category = "all")
{ {
$textures = Texture::whereIn('tid', $this->textures->pluck('tid')->all())
->get()
->map(function ($texture) {
$in_closet = $this->textures
->where('tid', $texture->tid)
->first();
return [
'tid' => $texture->tid,
'name' => $in_closet['name'],
'type' => $texture->type,
'add_at' => $in_closet['add_at']
];
})
->sortByDesc('add_at');
if ($category == "all") { if ($category == "all") {
$items = array_merge($this->textures_skin, $this->textures_cape); return $textures->values()->all();
} elseif ($category == 'cape') {
return $textures->filter(function ($texture) {
return $texture['type'] == 'cape';
})->values();
} else { } else {
$property = "textures_$category"; return $textures->reject(function ($texture) {
$items = $this->$property; return $texture['type'] == 'cape';
})->values();
} }
// reverse the array to sort desc by add_at
return array_reverse($items);
} }
/** /**
@ -123,18 +106,17 @@ class Closet
*/ */
public function add($tid, $name) public function add($tid, $name)
{ {
foreach ($this->textures as $item) { if ($this->has($tid)) {
if ($item['tid'] == $tid) return false;
return false;
} }
$this->textures[] = array( $this->textures->push([
'tid' => $tid, 'tid' => $tid,
'name' => $name, 'name' => $name,
'add_at' => time() 'add_at' => time()
); ]);
$this->items_modified[] = $tid; $this->closet_modified = true;
return true; return true;
} }
@ -147,10 +129,18 @@ class Closet
*/ */
public function has($tid) public function has($tid)
{ {
foreach ($this->textures as $item) { return $this->textures->contains('tid', $tid);
if ($item['tid'] == $tid) return true; }
}
return false; /**
* Get one texture info
*
* @param $tid Texture ID
* @return array|null Result
*/
public function get($tid)
{
return $this->textures->where('tid', $tid)->first();
} }
/** /**
@ -166,15 +156,14 @@ class Closet
return false; return false;
} }
$offset = 0; $this->textures->transform(function ($texture) use ($tid, $new_name) {
foreach ($this->textures as $item) { if ($texture['tid'] == $tid) {
if ($item['tid'] == $tid) { $texture['name'] = $new_name;
$this->textures[$offset]['name'] = $new_name;
} }
$offset++; return $texture;
} });
$this->items_modified[] = $tid; $this->closet_modified = true;
return true; return true;
} }
@ -186,40 +175,26 @@ class Closet
*/ */
public function remove($tid) public function remove($tid)
{ {
$offset = 0; if (!$this->has($tid)) {
return false;
// traverse items
foreach ($this->textures as $item) {
if ($item['tid'] == $tid) {
$this->items_modified[] = $tid;
// remove element from array
return array_splice($this->textures, $offset, 1);
}
$offset++;
} }
$this->textures = $this->textures->reject(function ($texture) use ($tid) {
return $texture['tid'] == $tid;
});
return false; $this->closet_modified = true;
} return true;
/**
* Check if given tid is valid.
*
* @param int $tid
* @return bool
*/
private function checkTextureExist($tid)
{
return ! Texture::where('tid', $tid)->isEmpty();
} }
/** /**
* Set textures string manually. * Set textures string manually.
* *
* @param string $textures * @param string $textures
* @return int
*/ */
public function setTextures($textures) public function setTextures($textures)
{ {
return $this->db->where('uid', $this->uid)->update(['textures' => $textures]);; return $this->db->where('uid', $this->uid)->update(['textures' => $textures]);
} }
/** /**
@ -229,9 +204,9 @@ class Closet
*/ */
public function save() public function save()
{ {
if (empty($this->items_modified)) return; if (!$this->closet_modified) return false;
return $this->setTextures(json_encode($this->textures)); return $this->setTextures($this->textures->toJson());
} }
/** /**

View File

@ -39,29 +39,26 @@ class ClosetControllerTest extends TestCase
// Use default query parameters // Use default query parameters
$this->get('/user/closet-data') $this->get('/user/closet-data')
->seeJson([ ->seeJsonStructure([
'category' => 'skin', 'category',
'total_pages' => 1, 'total_pages',
'items' => $textures->map(function ($item) { 'items' => [['tid', 'name', 'type', 'add_at']]
$item->upload_at = $item->upload_at->format('Y-m-d H:i:s');
$item->public = $item->public ? 1 : 0;
return $item;
})->take(6)->toArray()
]); ]);
// Get capes // Get capes
$cape = factory(Texture::class, 'cape')->create(); $cape = factory(Texture::class, 'cape')->create();
$closet->add($cape->tid, $cape->name); $closet->add($cape->tid, 'custom_name');
$closet->save(); $closet->save();
$this->get('/user/closet-data?category=cape') $this->get('/user/closet-data?category=cape')
->seeJson([ ->seeJson([
'category' => 'cape', 'category' => 'cape',
'total_pages' => 1, 'total_pages' => 1,
'items' => collect([$cape])->map(function ($item) { 'items' => [[
$item->upload_at = $item->upload_at->format('Y-m-d H:i:s'); 'tid' => $cape->tid,
$item->public = $item->public ? 1 : 0; 'name' => 'custom_name',
return $item; 'type' => 'cape',
})->take(6)->toArray() 'add_at' => $closet->get($cape->tid)['add_at']
]]
]); ]);
// Search by keyword // Search by keyword
@ -70,7 +67,12 @@ class ClosetControllerTest extends TestCase
->seeJson([ ->seeJson([
'category' => 'skin', 'category' => 'skin',
'total_pages' => 1, 'total_pages' => 1,
'items' => collect([$random])->take(6)->toArray() 'items' => [[
'tid' => $random->tid,
'name' => $random->name,
'type' => $random->type,
'add_at' => $closet->get($random->tid)['add_at']
]]
]); ]);
} }
@ -226,11 +228,7 @@ class ClosetControllerTest extends TestCase
]); ]);
$closet->save(); $closet->save();
$closet = new Closet($this->user->uid); $closet = new Closet($this->user->uid);
$this->assertTrue( $this->assertFalse(collect($closet->getItems())->where('name', 'new')->isEmpty());
in_array($name, array_map(function ($item) {
return $item->name;
}, $closet->getItems()))
);
} }
public function testRemove() public function testRemove()