Merge pull request #3088 from jitendra-webkul/1.0
Rich snippet feature added for products and category
This commit is contained in:
commit
84aede5cef
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -1323,7 +1323,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'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1329,7 +1329,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'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1333,8 +1333,21 @@ return [
|
|||
'cheapest-first' => 'I più convenienti prima',
|
||||
'expensive-first' => 'I più cari prima',
|
||||
'comma-seperated' => 'Separato da virgola',
|
||||
'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'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1328,7 +1328,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'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1002,7 +1002,7 @@ return [
|
|||
'specific-coupon' => 'Konkretny kupon',
|
||||
'auto-generate-coupon' => 'Automatyczniegeneruj kupon',
|
||||
'no' => 'Nie',
|
||||
'yes' => 'Tak,
|
||||
'yes' => 'Tak',
|
||||
'coupon-code' => 'Kod kuponu',
|
||||
'uses-per-coupon' => 'Wartość wykorzystania na kupon',
|
||||
'uses-per-customer' => 'Wartość wykorzystania na klienta',
|
||||
|
|
@ -1318,7 +1318,21 @@ return [
|
|||
'all-customer-groups' => 'Wszystkie grupy klientów',
|
||||
'invoice-slip-design' => 'Wzór wydruku faktury',
|
||||
'logo' => 'Logo',
|
||||
'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'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
@ -1332,7 +1332,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'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,185 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Helpers;
|
||||
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class SEO
|
||||
{
|
||||
/**
|
||||
* Returns product json ld data for product
|
||||
*
|
||||
* @param \Webkul\Product\Contracts\Product|\Webkul\Product\Contracts\ProductFlat $product
|
||||
* @return array
|
||||
*/
|
||||
public function getProductJsonLd($product)
|
||||
{
|
||||
$data = [
|
||||
'@context' => '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);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,14 @@
|
|||
|
||||
@section('seo')
|
||||
<meta name="description" content="{{ trim($category->meta_description) != "" ? $category->meta_description : \Illuminate\Support\Str::limit(strip_tags($category->description), 120, '') }}"/>
|
||||
|
||||
<meta name="keywords" content="{{ $category->meta_keywords }}"/>
|
||||
|
||||
@if (core()->getConfigData('catalog.rich_snippets.categories.enable'))
|
||||
<script type="application/ld+json">
|
||||
{!! app('Webkul\Product\Helpers\SEO')->getCategoryJsonLd($category) !!}
|
||||
</script>
|
||||
@endif
|
||||
@stop
|
||||
|
||||
@section('content-wrapper')
|
||||
|
|
|
|||
|
|
@ -6,7 +6,14 @@
|
|||
|
||||
@section('seo')
|
||||
<meta name="description" content="{{ trim($product->meta_description) != "" ? $product->meta_description : \Illuminate\Support\Str::limit(strip_tags($product->description), 120, '') }}"/>
|
||||
|
||||
<meta name="keywords" content="{{ $product->meta_keywords }}"/>
|
||||
|
||||
@if (core()->getConfigData('catalog.rich_snippets.products.enable'))
|
||||
<script type="application/ld+json">
|
||||
{!! app('Webkul\Product\Helpers\SEO')->getProductJsonLd($product) !!}
|
||||
</script>
|
||||
@endif
|
||||
@stop
|
||||
|
||||
@section('content-wrapper')
|
||||
|
|
|
|||
Loading…
Reference in New Issue