Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
100.00% |
1 / 1 |
|
100.00% |
0 / 0 |
CRAP | |
100.00% |
0 / 0 |
| BrowseController | |
100.00% |
1 / 1 |
|
100.00% |
4 / 4 |
21 | |
100.00% |
0 / 0 |
| index | |
100.00% |
1 / 1 |
11 | |
100.00% |
0 / 0 |
|||
| anonymous function | |
100.00% |
1 / 1 |
1 | |
100.00% |
0 / 0 |
|||
| convertQuery | |
100.00% |
1 / 1 |
3 | |
100.00% |
0 / 0 |
|||
| generateUrl | |
100.00% |
1 / 1 |
6 | |
100.00% |
0 / 0 |
|||
| <?php | |
| namespace Mtc\Shop\Http\Controllers; | |
| use App\Http\Controllers\Controller; | |
| use Illuminate\Http\Request; | |
| use Mtc\Core\Admin\Node; | |
| use Mtc\Core\Taxonomy; | |
| use Mtc\Shop\Contracts\ProductRepositoryContract; | |
| use Mtc\Shop\Product; | |
| class BrowseController extends Controller | |
| { | |
| public $sort_options = [ | |
| [ | |
| 'key' => 'new-additions', | |
| 'label' => 'New Additions' | |
| ], | |
| [ | |
| 'key' => 'price-asc', | |
| 'label' => 'Price (Low-High)' | |
| ], | |
| [ | |
| 'key' => 'price-desc', | |
| 'label' => 'Price (High-Low)' | |
| ], | |
| ]; | |
| public function index(Request $request, ProductRepositoryContract $repository, $query = '') | |
| { | |
| if (false === $request->wantsJson()) { | |
| return view('shop::public.browse')->with($this->convertQuery($query)); | |
| } | |
| $products = $repository->filter($request); | |
| if (true == $request->input('full', true)) { | |
| // @todo: Limit to all product nodes and the taxonomies ancestors. | |
| // @todo: Functionalty to go through taxonomy levels. | |
| $options = \Cache::remember( | |
| 'taxonomy_roots_with_children', | |
| 30, | |
| function() { | |
| return Taxonomy::roots()->with('children')->get(); | |
| } | |
| ); | |
| $selected = Taxonomy::whereIn( | |
| 'id', | |
| collect( | |
| $request->input('selected', []) | |
| )->pluck('id') | |
| )->get() | |
| ->map( | |
| function($item) use ($options) { | |
| // As we are using nested sets, we can determine the | |
| // root by finding which ids are within the root's | |
| // lft/rgt attributes. | |
| foreach ($options as $root) { | |
| if ( | |
| $item->id > $root->lft && | |
| $item->id < $root->rgt | |
| ) { | |
| $item->root = $root; | |
| return $item; | |
| } | |
| } | |
| return $item; | |
| } | |
| ); | |
| $options = $options->map( | |
| function($option) use ($selected, $request) { | |
| $children = $selected->where('root.id', $option->id) | |
| ->sortByDesc('id'); | |
| $option = $option->toArray(); | |
| if ($children->isEmpty() === false) { | |
| $taxonomy = $children->first(); | |
| if ($taxonomy->children->isEmpty() === false) { | |
| $option['children'] = $taxonomy->children; | |
| } elseif ($taxonomy->isLeaf()) { | |
| $option['children'] = $taxonomy->siblingsAndSelf()->get(); | |
| }; | |
| // Generate a URL for each option | |
| foreach ($option['children'] as &$child) { | |
| $items = collect($request->input('selected', [])); | |
| // If selected, remove the item from the URL. | |
| if ($items->where('id', $child->id)->isEmpty()) { | |
| $items = $items->push(['id' => $child->id]); | |
| // If not selected, add the item in. | |
| } else { | |
| $items = $items->reject( | |
| function($item) use ($child) { | |
| return $item['id'] == $child->id; | |
| } | |
| ); | |
| } | |
| $child['url'] = $this->generateUrl($request, $items); | |
| } | |
| } | |
| return (object)$option; | |
| } | |
| ); | |
| } | |
| $url = $this->generateUrl($request); | |
| $sort_options = $this->sort_options; | |
| return compact('products', 'options', 'url', 'sort_options'); | |
| } | |
| /** | |
| * Take the incoming URL and parse this into the selected variables, sort, | |
| * and pagination. | |
| * | |
| * @param string $query Incoming query string | |
| * @return array | |
| */ | |
| protected function convertQuery($query) | |
| { | |
| // Set any defaults | |
| $data = [ | |
| 'selected' => collect([]), | |
| 'sort' => '', | |
| 'page' => 1, | |
| ]; | |
| // Get the sort/page information | |
| preg_match_all("/\/?(sort|page)-([-_\w]+)?/", $query, $matches); | |
| collect($matches)->transpose()->each( | |
| function($item) use (&$data) { | |
| $data[$item[1]] = $item[2]; | |
| } | |
| ); | |
| // + will be used to separate items within the same taxonomy | |
| $query = str_replace('+', '/', $query); | |
| // / will be used to seperate different terms | |
| $slugs = collect(explode('/', $query)) | |
| ->reject( | |
| function($item) { | |
| // Remove sort/pagination (just in case) | |
| return empty($item) || preg_match('/(?:sort|page)-.*/', $item) > 0; | |
| } | |
| ); | |
| // If we have potential nodes, get information about them. | |
| if ($slugs->isEmpty() === false) { | |
| $data['selected'] = Node::select(['nodeable_id as id', 'title']) | |
| ->whereIn('slug', $slugs) | |
| ->get(); | |
| } | |
| return $data; | |
| } | |
| /** | |
| * Generate the current URL or a URL containing additional options. | |
| * | |
| * @param Request $request | |
| * @param array $selected Optionally include an array to override | |
| * $request->input('selected') | |
| * @return array | |
| */ | |
| public function generateUrl(Request $request, $selected = []) | |
| { | |
| // Get a list of all IDs selected. | |
| $selected = empty($selected) ? $request->input('selected', []) : $selected; | |
| $ids = collect($selected)->pluck('id'); | |
| $ids = Taxonomy::whereIn('id', $ids)->get(); | |
| // Now find the root notes for each. | |
| $root_nodes = $ids->map( | |
| function($child) { | |
| return $child->getRoot(); | |
| } | |
| )->unique()->sortBy('id'); | |
| // Determine sort of page options | |
| $additional = []; | |
| if ($request->input('sort_by')) { | |
| $additional[] = 'sort-' . $request->input('sort_by'); | |
| } | |
| if ($request->input('page') && $request->input('page') > 1) { | |
| $additional[] = 'page-' . $request->input('page'); | |
| } | |
| // Generate the URL | |
| return route('shop.browse') . '/' . $root_nodes->map( | |
| function($root) use (&$ids) { | |
| return $ids->map( | |
| function($child, $child_index) use ($root, &$ids) { | |
| if ($child->isDescendantOf($root)) { | |
| $ids->forget($child_index); | |
| return $child->node->slug; | |
| } | |
| return null; | |
| } | |
| )->reject( | |
| function($child) { | |
| return is_null($child); | |
| } | |
| )->implode('+'); | |
| } | |
| )->push($additional)->flatten()->implode('/'); | |
| return $root_nodes->toArray(); | |
| } | |
| } |