| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 | <?phpnamespace App\Http\Controllers\Admin\Products;use App\Shop\Attributes\Repositories\AttributeRepositoryInterface;use App\Shop\AttributeValues\Repositories\AttributeValueRepositoryInterface;use App\Shop\Brands\Repositories\BrandRepositoryInterface;use App\Shop\Categories\Repositories\Interfaces\CategoryRepositoryInterface;use App\Shop\ProductAttributes\ProductAttribute;use App\Shop\Products\Exceptions\ProductInvalidArgumentException;use App\Shop\Products\Exceptions\ProductNotFoundException;use App\Shop\Products\Product;use App\Shop\Products\Repositories\Interfaces\ProductRepositoryInterface;use App\Shop\Products\Repositories\ProductRepository;use App\Shop\Products\Requests\CreateProductRequest;use App\Shop\Products\Requests\UpdateProductRequest;use App\Http\Controllers\Controller;use App\Shop\Products\Transformations\ProductTransformable;use App\Shop\Tools\UploadableTrait;use Illuminate\Http\Request;use Illuminate\Http\UploadedFile;use Illuminate\Support\Facades\DB;use Illuminate\Support\Facades\Log;use Illuminate\Support\Facades\Validator;class ProductController extends Controller{    use ProductTransformable, UploadableTrait;    /**     * @var ProductRepositoryInterface     */    private $productRepo;    /**     * @var CategoryRepositoryInterface     */    private $categoryRepo;    /**     * @var AttributeRepositoryInterface     */    private $attributeRepo;    /**     * @var AttributeValueRepositoryInterface     */    private $attributeValueRepository;    /**     * @var ProductAttribute     */    private $productAttribute;    /**     * @var BrandRepositoryInterface     */    private $brandRepo;    /**     * ProductController constructor.     *     * @param ProductRepositoryInterface $productRepository     * @param CategoryRepositoryInterface $categoryRepository     * @param AttributeRepositoryInterface $attributeRepository     * @param AttributeValueRepositoryInterface $attributeValueRepository     * @param ProductAttribute $productAttribute     * @param BrandRepositoryInterface $brandRepository     */    public function __construct(        ProductRepositoryInterface $productRepository,        CategoryRepositoryInterface $categoryRepository,        AttributeRepositoryInterface $attributeRepository,        AttributeValueRepositoryInterface $attributeValueRepository,        ProductAttribute $productAttribute,        BrandRepositoryInterface $brandRepository    ) {        $this->productRepo = $productRepository;        $this->categoryRepo = $categoryRepository;        $this->attributeRepo = $attributeRepository;        $this->attributeValueRepository = $attributeValueRepository;        $this->productAttribute = $productAttribute;        $this->brandRepo = $brandRepository;        $this->middleware(['permission:create-product, guard:employee'], ['only' => ['create', 'store']]);        $this->middleware(['permission:update-product, guard:employee'], ['only' => ['edit', 'update']]);        $this->middleware(['permission:delete-product, guard:employee'], ['only' => ['destroy']]);        $this->middleware(['permission:view-product, guard:employee'], ['only' => ['index', 'show']]);    }    /**     * Display a listing of the resource.     *     * @return \Illuminate\Http\Response     */    public function index()    {        $list = $this->productRepo->listProducts('id');        if (request()->has('q') && request()->input('q') != '') {            $list = $this->productRepo->searchProduct(request()->input('q'));        }        $products = $list->map(function (Product $item) {            return $this->transformProduct($item);        })->all();        return view('admin.products.list', [            'products' => $this->productRepo->paginateArrayResults($products, 25)        ]);    }    /**     * Show the form for creating a new resource.     *     * @return \Illuminate\Http\Response     */    public function create()    {        $categories = $this->categoryRepo->listCategories('name', 'asc');        return view('admin.products.create', [            'categories' => $categories,            'brands' => $this->brandRepo->listBrands(['*'], 'name', 'asc'),            'default_weight' => env('SHOP_WEIGHT'),            'weight_units' => Product::MASS_UNIT,            'product' => new Product        ]);    }    /**     * Store a newly created resource in storage.     *     * @param  CreateProductRequest $request     *     * @return \Illuminate\Http\Response     */    public function store(CreateProductRequest $request)    {        $data = $request->except('_token', '_method');        $data['slug'] = str_slug($request->input('name'));        if ($request->hasFile('cover') && $request->file('cover') instanceof UploadedFile) {            $data['cover'] = $this->productRepo->saveCoverImage($request->file('cover'));        }        $product = $this->productRepo->createProduct($data);        $productRepo = new ProductRepository($product);        if ($request->hasFile('image')) {            $productRepo->saveProductImages(collect($request->file('image')));        }        if ($request->has('categories')) {            $productRepo->syncCategories($request->input('categories'));        } else {            $productRepo->detachCategories();        }        return redirect()->route('admin.products.edit', $product->id)->with('message', 'Create successful');    }    /**     * Display the specified resource.     *     * @param  int $id     *     * @return \Illuminate\Http\Response     */    public function show(int $id)    {        $product = $this->productRepo->findProductById($id);        return view('admin.products.show', compact('product'));    }    /**     * Show the form for editing the specified resource.     *     * @param  int $id     *     * @return \Illuminate\Http\Response     */    public function edit(int $id)    {        $product = $this->productRepo->findProductById($id);        $productAttributes = $product->attributes()->get();        $qty = $productAttributes->map(function ($item) {            return $item->quantity;        })->sum();        if (request()->has('delete') && request()->has('pa')) {            $pa = $productAttributes->where('id', request()->input('pa'))->first();            $pa->attributesValues()->detach();            $pa->delete();            request()->session()->flash('message', 'Delete successful');            return redirect()->route('admin.products.edit', [$product->id, 'combination' => 1]);        }        $categories = $this->categoryRepo->listCategories('name', 'asc')->toTree();	        return view('admin.products.edit', [            'product' => $product,            'images' => $product->images()->get(['src']),            'categories' => $categories,            'selectedIds' => $product->categories()->pluck('category_id')->all(),            'attributes' => $this->attributeRepo->listAttributes(),            'productAttributes' => $productAttributes,            'qty' => $qty,            'brands' => $this->brandRepo->listBrands(['*'], 'name', 'asc'),            'weight' => $product->weight,            'default_weight' => $product->mass_unit,            'weight_units' => Product::MASS_UNIT        ]);    }    /**     * Update the specified resource in storage.     *     * @param  UpdateProductRequest $request     * @param  int $id     *     * @return \Illuminate\Http\Response     * @throws \App\Shop\Products\Exceptions\ProductUpdateErrorException     */    public function update(UpdateProductRequest $request, int $id)    {        $product = $this->productRepo->findProductById($id);        $productRepo = new ProductRepository($product);        if ($request->has('attributeValue')) {            $this->saveProductCombinations($request, $product);            return redirect()->route('admin.products.edit', [$id, 'combination' => 1])                ->with('message', 'Attribute combination created successful');        }        $data = $request->except(            'categories',            '_token',            '_method',            'default',            'image',            'productAttributeQuantity',            'productAttributePrice',            'attributeValue',            'combination'        );        $data['slug'] = str_slug($request->input('name'));        if ($request->hasFile('cover')) {            $data['cover'] = $productRepo->saveCoverImage($request->file('cover'));        }        if ($request->hasFile('image')) {            $productRepo->saveProductImages(collect($request->file('image')));        }        if ($request->has('categories')) {            $productRepo->syncCategories($request->input('categories'));        } else {            $productRepo->detachCategories();        }        $productRepo->updateProduct($data);        return redirect()->route('admin.products.edit', $id)            ->with('message', 'Update successful');    }    /**     * Remove the specified resource from storage.     *     * @param  int $id     *     * @return \Illuminate\Http\Response     * @throws \Exception     */    public function destroy($id)    {        $product = $this->productRepo->findProductById($id);        $product->categories()->sync([]);        $productAttr = $product->attributes();        $productAttr->each(function ($pa) {            DB::table('attribute_value_product_attribute')->where('product_attribute_id', $pa->id)->delete();        });        $productAttr->where('product_id', $product->id)->delete();        $productRepo = new ProductRepository($product);        $productRepo->removeProduct();        return redirect()->route('admin.products.index')->with('message', 'Delete successful');    }    /**     * @param Request $request     *     * @return \Illuminate\Http\RedirectResponse     */    public function removeImage(Request $request)    {        $this->productRepo->deleteFile($request->only('product', 'image'), 'uploads');        return redirect()->back()->with('message', 'Image delete successful');    }    /**     * @param Request $request     *     * @return \Illuminate\Http\RedirectResponse     */    public function removeThumbnail(Request $request)    {        $this->productRepo->deleteThumb($request->input('src'));        return redirect()->back()->with('message', 'Image delete successful');    }    /**     * @param Request $request     * @param Product $product     * @return boolean     */    private function saveProductCombinations(Request $request, Product $product): bool    {        $fields = $request->only(            'productAttributeQuantity',            'productAttributePrice',            'sale_price',            'default'        );        if ($errors = $this->validateFields($fields)) {            return redirect()->route('admin.products.edit', [$product->id, 'combination' => 1])                ->withErrors($errors);        }        $quantity = $fields['productAttributeQuantity'];        $price = $fields['productAttributePrice'];        $sale_price = null;        if (isset($fields['sale_price'])) {            $sale_price = $fields['sale_price'];        }        $attributeValues = $request->input('attributeValue');        $productRepo = new ProductRepository($product);        $hasDefault = $productRepo->listProductAttributes()->where('default', 1)->count();        $default = 0;        if ($request->has('default')) {            $default = $fields['default'];        }        if ($default == 1 && $hasDefault > 0) {            $default = 0;        }        $productAttribute = $productRepo->saveProductAttributes(            new ProductAttribute(compact('quantity', 'price', 'sale_price', 'default'))        );        // save the combinations        return collect($attributeValues)->each(function ($attributeValueId) use ($productRepo, $productAttribute) {            $attribute = $this->attributeValueRepository->find($attributeValueId);            return $productRepo->saveCombination($productAttribute, $attribute);        })->count();    }    /**     * @param array $data     *     * @return     */    private function validateFields(array $data)    {        $validator = Validator::make($data, [            'productAttributeQuantity' => 'required'        ]);        if ($validator->fails()) {            return $validator;        }    }}
 |