diff --git a/packages/Webkul/Admin/src/Config/system.php b/packages/Webkul/Admin/src/Config/system.php index cade2e2a0..efad8bd08 100644 --- a/packages/Webkul/Admin/src/Config/system.php +++ b/packages/Webkul/Admin/src/Config/system.php @@ -206,10 +206,68 @@ return [ 'channel_based' => true, ], ], + ], [ + 'key' => 'catalog.rich_snippets', + 'name' => 'admin::app.admin.system.rich-snippets', + 'sort' => 3, + ], [ + 'key' => 'catalog.rich_snippets.products', + 'name' => 'admin::app.admin.system.products', + 'sort' => 1, + 'fields' => [ + [ + 'name' => 'enable', + 'title' => 'admin::app.admin.system.enable', + 'type' => 'boolean', + ], [ + 'name' => 'show_sku', + 'title' => 'admin::app.admin.system.show-sku', + 'type' => 'boolean', + ], [ + 'name' => 'show_weight', + 'title' => 'admin::app.admin.system.show-weight', + 'type' => 'boolean', + ], [ + 'name' => 'show_categories', + 'title' => 'admin::app.admin.system.show-categories', + 'type' => 'boolean', + ], [ + 'name' => 'show_images', + 'title' => 'admin::app.admin.system.show-images', + 'type' => 'boolean', + ], [ + 'name' => 'show_reviews', + 'title' => 'admin::app.admin.system.show-reviews', + 'type' => 'boolean', + ], [ + 'name' => 'show_ratings', + 'title' => 'admin::app.admin.system.show-ratings', + 'type' => 'boolean', + ], [ + 'name' => 'show_offers', + 'title' => 'admin::app.admin.system.show-offers', + 'type' => 'boolean', + ], + ], + ], [ + 'key' => 'catalog.rich_snippets.categories', + 'name' => 'admin::app.admin.system.categories', + 'sort' => 1, + 'fields' => [ + [ + 'name' => 'enable', + 'title' => 'admin::app.admin.system.enable', + 'type' => 'boolean', + ], [ + 'name' => 'show_search_input_field', + 'title' => 'admin::app.admin.system.show-search-input-field', + 'type' => 'boolean', + ] + ] ], [ 'key' => 'customer', 'name' => 'admin::app.admin.system.customer', - 'sort' => 3, + 'sort' => 4, ], [ 'key' => 'customer.settings', 'name' => 'admin::app.admin.system.settings', @@ -252,7 +310,7 @@ return [ ], [ 'key' => 'emails', 'name' => 'admin::app.admin.emails.email', - 'sort' => 1, + 'sort' => 5, ], [ 'key' => 'emails.general', 'name' => 'admin::app.admin.emails.notification_label', diff --git a/packages/Webkul/Admin/src/Resources/lang/en/app.php b/packages/Webkul/Admin/src/Resources/lang/en/app.php index dfb8ac0d9..b13b2ec4e 100755 --- a/packages/Webkul/Admin/src/Resources/lang/en/app.php +++ b/packages/Webkul/Admin/src/Resources/lang/en/app.php @@ -1331,7 +1331,21 @@ return [ 'cheapest-first' => 'Cheapest First', 'expensive-first' => 'Expensive First', 'comma-seperated' => 'Comma Seperated', - 'favicon' => 'Favicon' + 'favicon' => 'Favicon', + 'seo' => 'SEO', + 'rich-snippets' => 'Rich Snippets', + 'products' => 'Products', + 'enable' => 'Enable', + 'show-weight' => 'Show Weight', + 'show-categories' => 'Show Categories', + 'show-images' => 'Show Images', + 'show-reviews' => 'Show Reviews', + 'show-ratings' => 'Show Ratings', + 'show-offers' => 'Show Offers', + 'show-sku' => 'Show SKU', + 'categories' => 'Categories', + 'show-sku' => 'Show SKU', + 'show-search-input-field' => 'Show Search Input Field' ] ] ]; diff --git a/packages/Webkul/Category/src/Repositories/CategoryRepository.php b/packages/Webkul/Category/src/Repositories/CategoryRepository.php index 3785b1c41..b42dbe2d3 100755 --- a/packages/Webkul/Category/src/Repositories/CategoryRepository.php +++ b/packages/Webkul/Category/src/Repositories/CategoryRepository.php @@ -103,7 +103,7 @@ class CategoryRepository extends Repository { static $categories = []; - if(array_key_exists($id, $categories)) { + if (array_key_exists($id, $categories)) { return $categories[$id]; } diff --git a/packages/Webkul/Product/src/Helpers/ProductImage.php b/packages/Webkul/Product/src/Helpers/ProductImage.php index 451eec453..8556f14bd 100755 --- a/packages/Webkul/Product/src/Helpers/ProductImage.php +++ b/packages/Webkul/Product/src/Helpers/ProductImage.php @@ -21,8 +21,9 @@ class ProductImage extends AbstractProduct $images = []; foreach ($product->images as $image) { - if (! Storage::has($image->path)) + if (! Storage::has($image->path)) { continue; + } $images[] = [ 'small_image_url' => url('cache/small/' . $image->path), diff --git a/packages/Webkul/Product/src/Helpers/Review.php b/packages/Webkul/Product/src/Helpers/Review.php index 4312f4e09..993e90b14 100755 --- a/packages/Webkul/Product/src/Helpers/Review.php +++ b/packages/Webkul/Product/src/Helpers/Review.php @@ -71,7 +71,7 @@ class Review extends AbstractProduct return $totalRating[$product->id]; } - return $totalRating[$product->id] = $product->reviews()->where('status','approved')->sum('rating'); + return $totalRating[$product->id] = $product->reviews()->where('status', 'approved')->sum('rating'); } /** @@ -85,7 +85,7 @@ class Review extends AbstractProduct $reviews = $product->reviews()->where('status', 'approved') ->select('rating', DB::raw('count(*) as total')) ->groupBy('rating') - ->orderBy('rating','desc') + ->orderBy('rating', 'desc') ->get(); $totalReviews = $this->getTotalReviews($product); diff --git a/packages/Webkul/Product/src/Helpers/SEO.php b/packages/Webkul/Product/src/Helpers/SEO.php new file mode 100644 index 000000000..8a7e44a3d --- /dev/null +++ b/packages/Webkul/Product/src/Helpers/SEO.php @@ -0,0 +1,185 @@ + 'https://schema.org/', + '@type' => 'Product', + 'name' => $product->name, + 'description' => $product->description, + 'url' => route('shop.productOrCategory.index', $product->url_key), + ]; + + if (core()->getConfigData('catalog.rich_snippets.products.show_sku')) { + $data['sku'] = $product->sku; + } + + if (core()->getConfigData('catalog.rich_snippets.products.show_weight')) { + $data['image'] = $product->weight; + } + + if (core()->getConfigData('catalog.rich_snippets.products.show_categories')) { + $data['categories'] = $this->getProductCategories($product); + } + + if (core()->getConfigData('catalog.rich_snippets.products.show_images')) { + $data['image'] = $this->getProductImages($product); + } + + if (core()->getConfigData('catalog.rich_snippets.products.show_reviews')) { + $data['review'] = $this->getProductReviews($product); + } + + if (core()->getConfigData('catalog.rich_snippets.products.show_ratings')) { + $data['aggregateRating'] = $this->getProductAggregateRating($product); + } + + if (core()->getConfigData('catalog.rich_snippets.products.show_offers')) { + $data['offers'] = $this->getProductOffers($product); + } + + return json_encode($data); + } + + /** + * Returns product categories + * + * @param \Webkul\Product\Contracts\Product|\Webkul\Product\Contracts\ProductFlat $product + * @return string + */ + public function getProductCategories($product) + { + if ($product instanceof \Webkul\Product\Models\ProductFlat) { + $categories = $product->product->categories; + } else { + $categories = $product->categories; + } + + $names = []; + + foreach ($categories as $key => $category) { + $names[] = $category->name; + } + + return implode(', ', $names); + } + + /** + * Returns product images + * + * @param \Webkul\Product\Contracts\Product|\Webkul\Product\Contracts\ProductFlat $product + * @return array + */ + public function getProductImages($product) + { + $images = []; + + foreach ($product->images as $image) { + if (! Storage::has($image->path)) { + continue; + } + + $images[] = $image->url; + } + + return $images; + } + + /** + * Returns product reviews + * + * @param \Webkul\Product\Contracts\Product|\Webkul\Product\Contracts\ProductFlat $product + * @return array + */ + public function getProductReviews($product) + { + $reviews = []; + + foreach ($product->reviews()->where('status', 'approved')->get() as $review) { + $reviews[] = [ + '@type' => 'Review', + 'reviewRating' => [ + '@type' => 'Rating', + 'ratingValue' => $review->rating, + 'bestRating' => '5', + ], + 'author' => [ + '@type' => 'Person', + 'name' => $review->name, + ], + ]; + } + + return $reviews; + } + + /** + * Returns product average ratings + * + * @param \Webkul\Product\Contracts\Product|\Webkul\Product\Contracts\ProductFlat $product + * @return array + */ + public function getProductAggregateRating($product) + { + $reviewHelper = app('Webkul\Product\Helpers\Review'); + + return [ + '@type' => 'AggregateRating', + 'ratingValue' => $reviewHelper->getAverageRating($product), + 'reviewCount' => $reviewHelper->getTotalReviews($product), + ]; + } + + /** + * Returns product average ratings + * + * @param \Webkul\Product\Contracts\Product|\Webkul\Product\Contracts\ProductFlat $product + * @return array + */ + public function getProductOffers($product) + { + return [ + '@type' => 'Offer', + 'priceCurrency' => core()->getCurrentCurrencyCode(), + 'price' => $product->getTypeInstance()->getMinimalPrice(), + 'availability' => 'https://schema.org/InStock', + ]; + } + + /** + * Returns product json ld data for category + * + * @param \Webkul\Category\Contracts\Category $category + * @return array + */ + public function getCategoryJsonLd($category) + { + $data = [ + '@type' => 'WebSite', + '@context' => 'http://schema.org', + 'url' => config('app.url'), + ]; + + if (core()->getConfigData('catalog.rich_snippets.categories.show_search_input_field')) { + $data['potentialAction'] = [ + '@type' => 'SearchAction', + 'target' => config('app.url') . '/search/?term={search_term_string}', + 'query-input' => 'required name=search_term_string', + ]; + } + + return json_encode($data); + } +} \ No newline at end of file diff --git a/packages/Webkul/Shop/src/Resources/views/products/index.blade.php b/packages/Webkul/Shop/src/Resources/views/products/index.blade.php index 7575e86a9..6a4df8163 100755 --- a/packages/Webkul/Shop/src/Resources/views/products/index.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/products/index.blade.php @@ -6,7 +6,14 @@ @section('seo') meta_description : \Illuminate\Support\Str::limit(strip_tags($category->description), 120, '') }}"/> + + + @if (core()->getConfigData('catalog.rich_snippets.categories.enable')) + + @endif @stop @section('content-wrapper') diff --git a/packages/Webkul/Shop/src/Resources/views/products/view.blade.php b/packages/Webkul/Shop/src/Resources/views/products/view.blade.php index 0dfd7eda6..b42af9de1 100755 --- a/packages/Webkul/Shop/src/Resources/views/products/view.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/products/view.blade.php @@ -6,7 +6,14 @@ @section('seo') meta_description : \Illuminate\Support\Str::limit(strip_tags($product->description), 120, '') }}"/> + + + @if (core()->getConfigData('catalog.rich_snippets.products.enable')) + + @endif @stop @section('content-wrapper')