Merge branch 'master' of https://github.com/bagisto/bagisto into development

This commit is contained in:
rahulshukla-home 2020-09-04 13:15:45 +05:30
commit d7edcdb8bc
73 changed files with 2082 additions and 352 deletions

View File

@ -1,6 +1,6 @@
APP_NAME=Bagisto APP_NAME=Bagisto
APP_ENV=local APP_ENV=local
APP_VERSION=1.2.0-BETA1 APP_VERSION=1.2.0
APP_KEY= APP_KEY=
APP_DEBUG=true APP_DEBUG=true
APP_URL=http://localhost APP_URL=http://localhost

View File

@ -1,6 +1,6 @@
APP_NAME=Laravel APP_NAME=Laravel
APP_ENV=local APP_ENV=local
APP_VERSION=1.2.0-BETA1 APP_VERSION=1.2.0
APP_KEY=base64:G4KY3tUsTaY9ONo1n/QyJvVLQZdJDgbIkSJswFK01HE= APP_KEY=base64:G4KY3tUsTaY9ONo1n/QyJvVLQZdJDgbIkSJswFK01HE=
APP_DEBUG=true APP_DEBUG=true
APP_URL=http://localhost APP_URL=http://localhost

2
.gitignore vendored
View File

@ -25,4 +25,4 @@ yarn.lock
storage/*.key storage/*.key
/docker-compose-collection/ /docker-compose-collection/
/resources/themes/velocity/* /resources/themes/velocity/*
/resources/lang /resources/lang/vendor/webkul/admin/*

View File

@ -2,6 +2,56 @@
#### This changelog consists the bug & security fixes and new features being included in the releases listed below. #### This changelog consists the bug & security fixes and new features being included in the releases listed below.
## **v1.2.0 (7th of September 2020)** - *Release*
* #1257 [fixed] - Getting issue in install of v0.1.6
* #3643 [fixed] - Invoices should contain the company/store data
* #3772 [fixed] - Unable to add more than 4 products in related products
* #3781 [fixed] - Getting exception on frontend after installation.
* #3782 [fixed] - Getting error on running php artisan migrate if db_prefix contains decimal value
* #3783 [fixed] - Correct the product name alignment in compare list of default theme.
* #3784 [fixed] - Responsive issue on iPad
* #3786 [fixed] - Default advertisement images should display in images section.
* #3789 [fixed] - Filter conditions need to be change according to Boolean in newsletter subscription grid for subscribed column
* #3791 [fixed] - validation message showing for wrong field while editing user from admin end
* #3792 [fixed] - Recently viewed product is not working for Locales other than default.
* #3799 [fixed] - Featured Products and New Products should not display on front end if admin has set 0 in velocity meta data
* #3800 [fixed] - Header Content Count field should convert the value into 0 if given anything apart from valid data(numeric value)
* #3802 [fixed] - Layout issue while adding linked products
* #3804 [fixed] - uploading image on search is not resulting in any keywords
* #3811 [fixed] - Velocity cms page url should be added by default
* #3819 [fixed] - Export Function not working in Firefox/Linux
* #3822 [fixed] - Publish translations from Webkul\Admin
* #3828 [fixed] - success alert is not visible while removing product from wishlist as guest
* #3831 [fixed] - social icons are not visible in footer
* #3852 [fixed] - Product copy functionality is not working properly for configurable products
* #3854 [fixed] - Fix reset password alert message
* #3861 [fixed] - Payment Instruction is not implemented for velocity theme
## **v1.2.0-BETA1 (18th of August 2020)** - *Release* ## **v1.2.0-BETA1 (18th of August 2020)** - *Release*
* [feature] - Customer group price for products implemented * [feature] - Customer group price for products implemented

832
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -88,6 +88,25 @@ return [
'channel_based' => true, 'channel_based' => true,
], ],
], ],
], [
'key' => 'general.content.custom_scripts',
'name' => 'admin::app.admin.system.custom-scripts',
'sort' => 1,
'fields' => [
[
'name' => 'custom_css',
'title' => 'admin::app.admin.system.custom-css',
'type' => 'textarea',
'channel_based' => true,
'locale_based' => false,
], [
'name' => 'custom_javascript',
'title' => 'admin::app.admin.system.custom-javascript',
'type' => 'textarea',
'channel_based' => true,
'locale_based' => false,
]
],
], [ ], [
'key' => 'general.design', 'key' => 'general.design',
'name' => 'admin::app.admin.system.design', 'name' => 'admin::app.admin.system.design',

View File

@ -151,7 +151,7 @@ class CartRuleDataGrid extends DataGrid
'title' => trans('admin::app.datagrid.copy'), 'title' => trans('admin::app.datagrid.copy'),
'method' => 'GET', 'method' => 'GET',
'route' => 'admin.cart-rules.copy', 'route' => 'admin.cart-rules.copy',
'icon' => 'icon note-icon', 'icon' => 'icon copy-icon',
]); ]);
$this->addAction([ $this->addAction([

View File

@ -74,7 +74,7 @@ class ProductDataGrid extends DataGrid
DB::raw('SUM(DISTINCT ' . DB::getTablePrefix() . 'product_inventories.qty) as quantity') DB::raw('SUM(DISTINCT ' . DB::getTablePrefix() . 'product_inventories.qty) as quantity')
); );
$queryBuilder->groupBy('product_flat.product_id', 'product_flat.locale', 'product_flat.channel'); $queryBuilder->groupBy('product_flat.product_id', 'product_flat.channel');
$queryBuilder->whereIn('product_flat.locale', $whereInLocales); $queryBuilder->whereIn('product_flat.locale', $whereInLocales);
$queryBuilder->whereIn('product_flat.channel', $whereInChannels); $queryBuilder->whereIn('product_flat.channel', $whereInChannels);
@ -206,7 +206,7 @@ class ProductDataGrid extends DataGrid
'title' => trans('admin::app.datagrid.copy'), 'title' => trans('admin::app.datagrid.copy'),
'method' => 'GET', 'method' => 'GET',
'route' => 'admin.catalog.products.copy', 'route' => 'admin.catalog.products.copy',
'icon' => 'icon note-icon', 'icon' => 'icon copy-icon',
]); ]);
$this->addMassAction([ $this->addMassAction([

View File

@ -1351,7 +1351,10 @@ return [
'contact-number' => 'رقم الاتصال', 'contact-number' => 'رقم الاتصال',
'bank-details' => 'التفاصيل المصرفية', 'bank-details' => 'التفاصيل المصرفية',
'mailing-address' => 'Send Check to', 'mailing-address' => 'Send Check to',
'instructions' => 'Instructions' 'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript'
] ]
] ]
]; ];

View File

@ -1334,7 +1334,10 @@ return [
'contact-number' => 'Kontakt Nummer', 'contact-number' => 'Kontakt Nummer',
'bank-details' => 'Bankdaten', 'bank-details' => 'Bankdaten',
'mailing-address' => 'Send Check to', 'mailing-address' => 'Send Check to',
'instructions' => 'Instructions' 'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript'
], ],
], ],
]; ];

View File

@ -1356,7 +1356,10 @@ return [
'contact-number' => 'Contact Number', 'contact-number' => 'Contact Number',
'bank-details' => 'Bank Details', 'bank-details' => 'Bank Details',
'mailing-address' => 'Send Check to', 'mailing-address' => 'Send Check to',
'instructions' => 'Instructions' 'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript'
] ]
] ]
]; ];

View File

@ -1316,7 +1316,10 @@ return [
'contact-number' => 'Número de contacto', 'contact-number' => 'Número de contacto',
'bank-details' => 'Detalles del banco', 'bank-details' => 'Detalles del banco',
'mailing-address' => 'Send Check to', 'mailing-address' => 'Send Check to',
'instructions' => 'Instructions' 'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript'
] ]
] ]
]; ];

View File

@ -1352,7 +1352,10 @@ return [
'contact-number' => 'شماره تماس', 'contact-number' => 'شماره تماس',
'bank-details' => 'اطلاعات دقیق بانکی', 'bank-details' => 'اطلاعات دقیق بانکی',
'mailing-address' => 'Send Check to', 'mailing-address' => 'Send Check to',
'instructions' => 'Instructions' 'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript'
] ]
] ]
]; ];

View File

@ -1357,7 +1357,10 @@ return [
'contact-number' => 'Numero di contatto', 'contact-number' => 'Numero di contatto',
'bank-details' => 'Coordinate bancarie', 'bank-details' => 'Coordinate bancarie',
'mailing-address' => 'Send Check to', 'mailing-address' => 'Send Check to',
'instructions' => 'Instructions' 'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript'
] ]
] ]
]; ];

View File

@ -1352,7 +1352,10 @@ return [
'contact-number' => 'Contact nummer', 'contact-number' => 'Contact nummer',
'bank-details' => 'Bankgegevens', 'bank-details' => 'Bankgegevens',
'mailing-address' => 'Send Check to', 'mailing-address' => 'Send Check to',
'instructions' => 'Instructions' 'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript'
] ]
] ]
]; ];

View File

@ -1341,7 +1341,10 @@ return [
'contact-number' => 'Numer kontaktowy', 'contact-number' => 'Numer kontaktowy',
'bank-details' => 'Dane bankowe', 'bank-details' => 'Dane bankowe',
'mailing-address' => 'Send Check to', 'mailing-address' => 'Send Check to',
'instructions' => 'Instructions' 'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript'
] ]
] ]
]; ];

View File

@ -1355,7 +1355,10 @@ return [
'contact-number' => 'Número de contato', 'contact-number' => 'Número de contato',
'bank-details' => 'Detalhes bancários', 'bank-details' => 'Detalhes bancários',
'mailing-address' => 'Send Check to', 'mailing-address' => 'Send Check to',
'instructions' => 'Instructions' 'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript'
] ]
] ]
]; ];

View File

@ -1338,7 +1338,10 @@ return [
'contact-number' => 'İletişim numarası', 'contact-number' => 'İletişim numarası',
'bank-details' => 'Banka detayları', 'bank-details' => 'Banka detayları',
'mailing-address' => 'Send Check to', 'mailing-address' => 'Send Check to',
'instructions' => 'Instructions' 'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript'
] ]
] ]
]; ];

View File

@ -200,6 +200,7 @@ class Booking extends Virtual
continue; continue;
} }
$data['quantity'] = $qty;
$data['booking']['ticket_id'] = $ticketId; $data['booking']['ticket_id'] = $ticketId;
$cartProducts = parent::prepareForCart($data); $cartProducts = parent::prepareForCart($data);
@ -232,17 +233,16 @@ class Booking extends Virtual
*/ */
public function compareOptions($options1, $options2) public function compareOptions($options1, $options2)
{ {
if ($this->product->id != $options2['product_id']) { if ($this->product->id !== (int) $options2['product_id']) {
return false; return false;
} }
if (isset($options1['booking']) && isset($options2['booking'])) { if (isset($options1['booking'], $options2['booking'])
return $options1['booking'] == $options2['booking']; && $options1['booking']['ticket_id'] === $options2['booking']['ticket_id']) {
} elseif (! isset($options1['booking'])) { return true;
return false;
} elseif (! isset($options2['booking'])) {
return false;
} }
return false;
} }
/** /**

View File

@ -293,7 +293,6 @@ class Cart
public function getItemByProduct($data) public function getItemByProduct($data)
{ {
$items = $this->getCart()->all_items; $items = $this->getCart()->all_items;
foreach ($items as $item) { foreach ($items as $item) {
if ($item->product->getTypeInstance()->compareOptions($item->additional, $data['additional'])) { if ($item->product->getTypeInstance()->compareOptions($item->additional, $data['additional'])) {
if (isset($data['additional']['parent_id'])) { if (isset($data['additional']['parent_id'])) {

View File

@ -53,7 +53,7 @@ class ForgotPasswordController extends Controller
); );
if ($response == Password::RESET_LINK_SENT) { if ($response == Password::RESET_LINK_SENT) {
session()->flash('success', trans($response)); session()->flash('success', trans('customer::app.forget_password.reset_link_sent'));
return back(); return back();
} }
@ -61,7 +61,7 @@ class ForgotPasswordController extends Controller
return back() return back()
->withInput(request(['email'])) ->withInput(request(['email']))
->withErrors([ ->withErrors([
'email' => trans($response), 'email' => trans('customer::app.forget_password.email_not_exist'),
]); ]);
} catch (\Swift_RfcComplianceException $e) { } catch (\Swift_RfcComplianceException $e) {
session()->flash('success', trans('customer::app.forget_password.reset_link_sent')); session()->flash('success', trans('customer::app.forget_password.reset_link_sent'));

View File

@ -15,6 +15,7 @@ return [
'empty' => 'You have not reviewed any of product yet' 'empty' => 'You have not reviewed any of product yet'
], ],
'forget_password' => [ 'forget_password' => [
'reset_link_sent' => 'We have e-mailed your reset password link.' 'reset_link_sent' => 'We have e-mailed your reset password link.',
'email_not_exist' => "We can't find a user with that e-mail address"
] ]
]; ];

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{ {
"/js/shop.js": "/js/shop.js?id=d64fdfe9e3fe3e4b9ee4", "/js/shop.js": "/js/shop.js?id=d64fdfe9e3fe3e4b9ee4",
"/css/shop.css": "/css/shop.css?id=4cb765ae858499c72bc3" "/css/shop.css": "/css/shop.css?id=dbbe4951362b3f0ea3e2"
} }

View File

@ -4118,6 +4118,11 @@ section.review {
margin-left: 0px; margin-left: 0px;
margin-right: 15px; margin-right: 15px;
} }
.downloadable-container .link-list ul li a {
float: left;
margin-top: 3px;
}
} }
} }

View File

@ -12,7 +12,7 @@
<div class="account-layout"> <div class="account-layout">
<div class="account-head mb-15"> <div class="account-head mb-15">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i class="icon icon-menu-back"></i></a></span> <span class="back-icon"><a href="{{ route('customer.address.index') }}"><i class="icon icon-menu-back"></i></a></span>
<span class="account-heading">{{ __('shop::app.customer.account.address.create.title') }}</span> <span class="account-heading">{{ __('shop::app.customer.account.address.create.title') }}</span>
<span></span> <span></span>
</div> </div>

View File

@ -12,7 +12,7 @@
<div class="account-layout"> <div class="account-layout">
<div class="account-head mb-15"> <div class="account-head mb-15">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i class="icon icon-menu-back"></i></a></span> <span class="back-icon"><a href="{{ route('customer.address.index') }}"><i class="icon icon-menu-back"></i></a></span>
<span class="account-heading">{{ __('shop::app.customer.account.address.edit.title') }}</span> <span class="account-heading">{{ __('shop::app.customer.account.address.edit.title') }}</span>
<span></span> <span></span>
</div> </div>

View File

@ -13,8 +13,7 @@
<div class="account-layout"> <div class="account-layout">
<div class="account-head"> <div class="account-head">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i <span class="back-icon"><a href="{{ route('customer.profile.index') }}"><i class="icon icon-menu-back"></i></a></span>
class="icon icon-menu-back"></i></a></span>
<span <span
class="account-heading">{{ __('shop::app.customer.account.address.index.title') }}</span> class="account-heading">{{ __('shop::app.customer.account.address.index.title') }}</span>

View File

@ -12,7 +12,7 @@
<div class="account-layout"> <div class="account-layout">
<div class="account-head mb-10"> <div class="account-head mb-10">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i class="icon icon-menu-back"></i></a></span> <span class="back-icon"><a href="{{ route('customer.profile.index') }}"><i class="icon icon-menu-back"></i></a></span>
<span class="account-heading"> <span class="account-heading">
{{ __('shop::app.customer.account.downloadable_products.title') }} {{ __('shop::app.customer.account.downloadable_products.title') }}
</span> </span>
@ -26,7 +26,7 @@
<div class="account-table-content"> <div class="account-table-content">
{!! app('Webkul\Shop\DataGrids\DownloadableProductDataGrid')->render() !!} {!! app('Webkul\Shop\DataGrids\DownloadableProductDataGrid')->render() !!}
</div> </div>
</div> </div>

View File

@ -12,7 +12,7 @@
<div class="account-layout"> <div class="account-layout">
<div class="account-head mb-10"> <div class="account-head mb-10">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i class="icon icon-menu-back"></i></a></span> <span class="back-icon"><a href="{{ route('customer.profile.index') }}"><i class="icon icon-menu-back"></i></a></span>
<span class="account-heading"> <span class="account-heading">
{{ __('shop::app.customer.account.order.index.title') }} {{ __('shop::app.customer.account.order.index.title') }}
</span> </span>
@ -26,7 +26,7 @@
<div class="account-table-content"> <div class="account-table-content">
{!! app('Webkul\Shop\DataGrids\OrderDataGrid')->render() !!} {!! app('Webkul\Shop\DataGrids\OrderDataGrid')->render() !!}
</div> </div>
</div> </div>

View File

@ -12,7 +12,7 @@
<div class="account-layout"> <div class="account-layout">
<div class="account-head"> <div class="account-head">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i class="icon icon-menu-back"></i></a></span> <span class="back-icon"><a href="{{ route('customer.orders.index') }}"><i class="icon icon-menu-back"></i></a></span>
<span class="account-heading"> <span class="account-heading">
{{ __('shop::app.customer.account.order.view.page-tile', ['order_id' => $order->increment_id]) }} {{ __('shop::app.customer.account.order.view.page-tile', ['order_id' => $order->increment_id]) }}

View File

@ -12,7 +12,7 @@
<div class="account-layout"> <div class="account-layout">
<div class="account-head mb-10"> <div class="account-head mb-10">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i class="icon icon-menu-back"></i></a></span> <span class="back-icon"><a href="{{ route('customer.profile.index') }}"><i class="icon icon-menu-back"></i></a></span>
<span class="account-heading">{{ __('shop::app.customer.account.profile.edit-profile.title') }}</span> <span class="account-heading">{{ __('shop::app.customer.account.profile.edit-profile.title') }}</span>

View File

@ -14,7 +14,7 @@
<div class="account-head"> <div class="account-head">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i class="icon icon-menu-back"></i></a></span> <span class="back-icon"><a href="{{ route('customer.profile.index') }}"><i class="icon icon-menu-back"></i></a></span>
<span class="account-heading">{{ __('shop::app.customer.account.profile.index.title') }}</span> <span class="account-heading">{{ __('shop::app.customer.account.profile.index.title') }}</span>

View File

@ -13,7 +13,7 @@
<div class="account-layout"> <div class="account-layout">
<div class="account-head"> <div class="account-head">
<span class="back-icon"><a href="{{ route('customer.account.index') }}"><i class="icon icon-menu-back"></i></a></span> <span class="back-icon"><a href="{{ route('customer.profile.index') }}"><i class="icon icon-menu-back"></i></a></span>
<span class="account-heading">{{ __('shop::app.customer.account.review.index.title') }}</span> <span class="account-heading">{{ __('shop::app.customer.account.review.index.title') }}</span>

View File

@ -107,11 +107,11 @@
{{ __('shop::app.mail.order.contact') }} : {{ $order->billing_address->phone }} {{ __('shop::app.mail.order.contact') }} : {{ $order->billing_address->phone }}
</div> </div>
<div style="font-weight: bold;font-size: 16px; color: #242424;"> <div style="font-weight: bold; font-size: 16px; color: #242424;">
{{ __('shop::app.mail.order.payment') }} {{ __('shop::app.mail.order.payment') }}
</div> </div>
<div style="font-size: 16px; color: #242424;"> <div style="font-weight: bold; font-size: 16px; color: #242424;">
{{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }} {{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }}
</div> </div>
</div> </div>

View File

@ -104,11 +104,11 @@
{{ __('shop::app.mail.order.contact') }} : {{ $order->billing_address->phone }} {{ __('shop::app.mail.order.contact') }} : {{ $order->billing_address->phone }}
</div> </div>
<div style="font-weight: bold;font-size: 16px; color: #242424;"> <div style="font-weight: bold; font-size: 16px; color: #242424;">
{{ __('shop::app.mail.order.payment') }} {{ __('shop::app.mail.order.payment') }}
</div> </div>
<div style="font-weight: bold;font-size: 16px; color: #242424;"> <div style="font-weight: bold; font-size: 16px; color: #242424;">
{{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }} {{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }}
</div> </div>
</div> </div>
@ -171,4 +171,4 @@
</p> </p>
</div> </div>
</div> </div>
@endcomponent @endcomponent

View File

@ -32,6 +32,10 @@
{!! view_render_event('bagisto.shop.layout.head') !!} {!! view_render_event('bagisto.shop.layout.head') !!}
<style>
{!! core()->getConfigData('general.content.custom_scripts.custom_css') !!}
</style>
</head> </head>
@ -117,6 +121,10 @@
<div class="modal-overlay"></div> <div class="modal-overlay"></div>
<script>
{!! core()->getConfigData('general.content.custom_scripts.custom_javascript') !!}
</script>
</body> </body>
</html> </html>

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

View File

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19 19L19 3L8 3" stroke="#979797" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 21L5 6L16 6L16 21L5 21Z" stroke="#979797" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 372 B

View File

@ -1,4 +1,4 @@
{ {
"/js/ui.js": "/js/ui.js?id=706b63016a08ec91d32b", "/js/ui.js": "/js/ui.js?id=706b63016a08ec91d32b",
"/css/ui.css": "/css/ui.css?id=54e0814214c81d98a101" "/css/ui.css": "/css/ui.css?id=5673703005b2ac3d0889"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

View File

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19 19L19 3L8 3" stroke="#979797" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 21L5 6L16 6L16 21L5 21Z" stroke="#979797" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 372 B

View File

@ -248,6 +248,12 @@
height: 24px; height: 24px;
} }
.copy-icon {
background-image: url("../images/copy-icon.png");
width: 24px;
height: 24px;
}
.active { .active {
.dashboard-icon { .dashboard-icon {
background-image: url("../images/Icon-Dashboard-Active.svg"); background-image: url("../images/Icon-Dashboard-Active.svg");

View File

@ -65,7 +65,7 @@ class ForgetPasswordController extends Controller
); );
if ($response == Password::RESET_LINK_SENT) { if ($response == Password::RESET_LINK_SENT) {
session()->flash('success', trans($response)); session()->flash('success', trans('customer::app.forget_password.reset_link_sent'));
return back(); return back();
} }
@ -73,7 +73,7 @@ class ForgetPasswordController extends Controller
return back() return back()
->withInput(request(['email'])) ->withInput(request(['email']))
->withErrors([ ->withErrors([
'email' => trans($response), 'email' => trans('customer::app.forget_password.email_not_exist'),
]); ]);
} catch(\Exception $e) { } catch(\Exception $e) {
session()->flash('error', trans($e->getMessage())); session()->flash('error', trans($e->getMessage()));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
{ {
"/js/velocity.js": "/js/velocity.js?id=ba5f055c5d095149e9ad", "/js/velocity.js": "/js/velocity.js?id=ba5f055c5d095149e9ad",
"/css/velocity-admin.css": "/css/velocity-admin.css?id=612d35e452446366eef7", "/css/velocity-admin.css": "/css/velocity-admin.css?id=612d35e452446366eef7",
"/css/velocity.css": "/css/velocity.css?id=6fdfc5106a6165fc591e" "/css/velocity.css": "/css/velocity.css?id=79ef3d43d1d30d35cd2c"
} }

View File

@ -95,6 +95,7 @@
}, },
mounted: function () { mounted: function () {
$('.cd-quick-view').fadeIn(500);
$('.compare-icon').click(this.closeQuickView); $('.compare-icon').click(this.closeQuickView);
$('.wishlist-icon').click(this.closeQuickView); $('.wishlist-icon').click(this.closeQuickView);
$('.add-to-cart-btn').click(() => setTimeout(this.closeQuickView, 0)); $('.add-to-cart-btn').click(() => setTimeout(this.closeQuickView, 0));

View File

@ -1527,6 +1527,23 @@
> .row { > .row {
margin-bottom: 20px; margin-bottom: 20px;
} }
.instructions {
margin-top: 5px;
margin-left: -13px;
label {
font-weight: 600;
font-size: 14px;
}
p {
margin: 0;
font-size: 14px;
color: #777777;
font-style: italic;
}
}
} }
.address-summary { .address-summary {

View File

@ -594,7 +594,7 @@ body::after {
width: 700px; width: 700px;
z-index: 101; z-index: 101;
padding: 40px; padding: 40px;
display: block; display: none;
position: absolute; position: absolute;
margin-bottom: 50px; margin-bottom: 50px;
left: calc(50% - 350px); left: calc(50% - 350px);

View File

@ -11,6 +11,12 @@ body {
header { header {
#search-form { #search-form {
#header-search-icon {
float: right;
border-radius: 2px 0px 0px 2px;
}
.btn-group { .btn-group {
select { select {
border-left: 0; border-left: 0;
@ -44,12 +50,14 @@ body {
.mini-cart-container { .mini-cart-container {
~ .compare-btn, ~ .compare-btn,
~ .wishlist-btn { ~ .wishlist-btn {
float: left;
.badge-container { .badge-container {
.badge { .badge {
top: -28px; top: -28px;
left: -2px; left: -2px;
} }
} }
} }
~ .wishlist-btn , ~ .compare-btn { ~ .wishlist-btn , ~ .compare-btn {
@ -327,7 +335,7 @@ body {
.modal-footer>:not(:last-child) { .modal-footer>:not(:last-child) {
margin-left: .25rem; margin-left: .25rem;
} }
.compare-products { .compare-products {
.wishlist-icon { .wishlist-icon {
left: 60px; left: 60px;
@ -366,7 +374,7 @@ body {
left: 40px; left: 40px;
right: unset; right: unset;
} }
} }
} }
} }
@ -424,6 +432,11 @@ body {
} }
} }
.downloadable-container .link-list ul li a {
float: left;
margin-top: 3px;
}
// Shared // Shared
.text-right { .text-right {
text-align: left !important; text-align: left !important;
@ -469,6 +482,39 @@ body {
} }
} }
@media only screen and (max-width: 1192px) {
body {
&.rtl {
#search-form {
#header-search-icon {
float: right;
border-radius: 2px 0px 0px 2px;
}
.btn-group {
.selectdiv {
width: 190px;
}
}
.selectdiv {
+ div {
input {
width: 220px;
}
}
}
}
.image-search-container {
left: 70px;
}
}
}
}
@media only screen and (max-width: 992px) { @media only screen and (max-width: 992px) {
body { body {
&.rtl { &.rtl {
@ -483,7 +529,7 @@ body {
} }
} }
} }
.wrapper { .wrapper {
.vc-customer-options { .vc-customer-options {
li { li {

View File

@ -42,6 +42,15 @@
<div class="row"> <div class="row">
<span class="method-summary">{{ __($payment['description']) }}</span> <span class="method-summary">{{ __($payment['description']) }}</span>
</div> </div>
<?php $additionalDetails = \Webkul\Payment\Payment::getAdditionalDetails($payment['method']); ?>
@if (! empty($additionalDetails))
<div class="instructions" v-show="payment.method == '{{$payment['method']}}'">
<label>{{ $additionalDetails['title'] }}</label>
<p>{{ $additionalDetails['value'] }}</p>
</div>
@endif
</div> </div>
</div> </div>

View File

@ -11,10 +11,7 @@
<shimmer-component v-if="isLoading && !isMobileView"></shimmer-component> <shimmer-component v-if="isLoading && !isMobileView"></shimmer-component>
<template v-else-if="newProducts.length > 0"> <template v-else-if="newProducts.length > 0">
<card-list-header <card-list-header heading="{{ __('shop::app.home.new-products') }}">
row-class="pl-26"
heading="{{ __('shop::app.home.new-products') }}"
>
</card-list-header> </card-list-header>
{!! view_render_event('bagisto.shop.new-products.before') !!} {!! view_render_event('bagisto.shop.new-products.before') !!}
@ -123,9 +120,8 @@
{!! view_render_event('bagisto.shop.new-products.after') !!} {!! view_render_event('bagisto.shop.new-products.after') !!}
</template> </template>
@if($count==0) @if ($count==0)
<template> <template>
@if ($showRecentlyViewed) @if ($showRecentlyViewed)
@push('css') @push('css')
<style> <style>
@ -142,7 +138,7 @@
'quantity' => 3, 'quantity' => 3,
'addClass' => 'col-lg-3 col-md-12', 'addClass' => 'col-lg-3 col-md-12',
]) ])
</div> </div>
@endif @endif
</template> </template>
@endif @endif

View File

@ -57,6 +57,10 @@
{!! view_render_event('bagisto.shop.layout.head') !!} {!! view_render_event('bagisto.shop.layout.head') !!}
<style>
{!! core()->getConfigData('general.content.custom_scripts.custom_css') !!}
</style>
</head> </head>
<body @if (core()->getCurrentLocale()->direction == 'rtl') class="rtl" @endif> <body @if (core()->getCurrentLocale()->direction == 'rtl') class="rtl" @endif>
@ -206,5 +210,9 @@
</script> </script>
@stack('scripts') @stack('scripts')
<script>
{!! core()->getConfigData('general.content.custom_scripts.custom_javascript') !!}
</script>
</body> </body>
</html> </html>

View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'Diese Zugangsdaten stimmen nicht mit unseren Aufzeichnungen überein.',
'throttle' => 'Zu viele Anmeldeversuche. Bitte versuchen Sie es in :seconds erneut.',
];

View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Vorherige',
'next' => 'Nächste &raquo;',
];

View File

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Die Passwörter müssen aus mindestens sechs Zeichen bestehen und mit der Bestätigung übereinstimmen.',
'reset' => 'Ihr Passwort wurde zurückgesetzt!',
'sent' => 'Wir haben Ihnen einen Link zum Zurücksetzen des Passworts per E-Mail geschickt!',
'token' => 'Dieses Token zum Zurücksetzen des Passworts ist ungültig.',
'user' => 'Wir können keinen Benutzer mit dieser E-Mail-Adresse finden.',
];

View File

@ -0,0 +1,146 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'Das Attribut :attribute muss akzeptiert werden.',
'active_url' => 'Das :attribute ist keine gültige URL.',
'after' => 'Das Attribut :attribute muss ein Datum nach :date sein.',
'after_or_equal' => 'Das Attribut :attribute muss ein Datum nach oder gleich :date sein.',
'alpha' => 'Das Attribut :attribute darf nur Buchstaben enthalten.',
'alpha_dash' => 'Das Attribut :darf nur Buchstaben, Zahlen, Striche und Unterstriche enthalten.',
'alpha_num' => 'Das Attribut :attribute darf nur Buchstaben und Zahlen enthalten.',
'array' => 'Das :attribute muss ein Array sein.',
'before' => 'Das Attribut :attribute muss ein Datum vor :date sein.',
'before_or_equal' => 'Das Attribut :attribute muss ein Datum vor oder gleich :date sein.',
'between' => [
'numeric' => 'Das Attribut :attribute muss zwischen :min und :max liegen.',
'file' => 'Das Attribut :attribute muss zwischen :min und :max Kilobyte liegen.',
'string' => 'Das Attribut :attribute muss zwischen :min und :max Zeichen liegen.',
'array' => 'Das Attribut :attribute muss zwischen :min und :max Elemente haben.',
],
'boolean' => 'Das Feld :attribute muss wahr oder falsch sein.',
'confirmed' => 'Die Bestätigung des :attribute stimmt nicht überein.',
'date' => 'Das Attribut :attribute ist kein gültiges Datum.',
'date_format' => 'Das Attribut :attribute entspricht nicht dem Format :format.',
'different' => 'Das Attribut :attribute und :other müssen unterschiedlich sein.',
'digits' => 'Das Attribut :attribute muss aus Ziffern bestehen.',
'digits_between' => 'Das Attribut :attribute muss zwischen :min und :max Ziffern liegen.',
'dimensions' => 'Das Attribut :attribute hat ungültige Bildabmessungen.',
'distinct' => 'Das Feld :attribute hat einen doppelten Wert.',
'email' => 'Das Attribut :attribute muss eine gültige E-Mail-Adresse sein.',
'exists' => 'Das ausgewählte :attribute ist ungültig.',
'file' => 'Das Attribut :attribute muss eine Datei sein.',
'filled' => 'Das Feld :attribute muss einen Wert haben.',
'gt' => [
'numeric' => 'Das Attribut :attribute muss größer als :value sein.',
'file' => 'Das Attribut :attribute muss größer als der Wert :value kilobytes sein.',
'string' => 'Das Attribut :attribute muss größer als :value Zeichen sein.',
'array' => 'Das Attribut :attribute muss mehr als :value items haben.',
],
'gte' => [
'numeric' => 'Das Attribut :attribute muss größer oder gleich :value sein.',
'file' => 'Das Attribut :attribute muss größer oder gleich :value kilobytes sein.',
'string' => 'Das Attribut :attribute muss größer oder gleich :value Zeichen sein.',
'array' => 'Das Attribut :attribute muss :value items oder mehr haben.',
],
'image' => 'Das Attribut :attribute muss ein Bild sein.',
'in' => 'Das ausgewählte :attribute ist ungültig.',
'in_array' => 'Das Feld :attribute existiert nicht in :other.',
'integer' => 'Das Attribut :attribute muss eine ganze Zahl sein.',
'ip' => 'Das Attribut :attribute muss eine gültige IP-Adresse sein.',
'ipv4' => 'Das :attribute muss eine gültige IPv4-Adresse sein.',
'ipv6' => 'Das :attribute muss eine gültige IPv6-Adresse sein.',
'json' => 'Das :attribute muss ein gültiger JSON-String sein.',
'lt' => [
'numeric' => 'Das Attribut :attribute muss kleiner als :value sein.',
'file' => 'Das Attribut :attribute muss kleiner als der Wert :value kilobytes sein.',
'string' => 'Das Attribut :attribute muss kleiner als :value Zeichen sein.',
'array' => 'Das Attribut :attribute muss kleiner als :value items sein.',
],
'lte' => [
'numeric' => 'Das Attribut :attribute muss kleiner oder gleich :value sein.',
'file' => 'Das Attribut :attribute muss kleiner oder gleich :value kilobytes sein.',
'string' => 'Das Attribut :attribute muss kleiner oder gleich :value Zeichen sein.',
'array' => 'Das Attribut :attribute darf nicht mehr als :value items haben.',
],
'max' => [
'numeric' => 'Das Attribut :attribute darf nicht größer als :max sein.',
'file' => 'Das Attribut :attribute darf nicht größer als :max Kilobytes sein.',
'string' => 'Das Attribut :attribute darf nicht größer als :max Zeichen sein.',
'array' => 'Das Attribut :attribute darf nicht mehr als :max Elemente enthalten.',
],
'mimes' => 'Das Attribut :attribute muss eine Datei vom Typ: :values sein.',
'mimetypes' => 'Das Attribut :attribute muss eine Datei vom Typ: :values sein.',
'min' => [
'numeric' => 'Das Attribut :attribute muss mindestens :min. sein.',
'file' => 'Das Attribut :attribute muss mindestens :min Kilobytes betragen.',
'string' => 'Das Attribut :attribute muss aus mindestens :min Zeichen bestehen.',
'array' => 'Das Attribut :attribute muss mindestens :min Elemente enthalten.',
],
'not_in' => 'Das ausgewählte :attribute ist ungültig.',
'not_regex' => 'Das Format des :attribute ist ungültig.',
'numeric' => 'Das Attribut :attribute muss eine Zahl sein.',
'present' => 'Das Feld :attribute muss vorhanden sein.',
'regex' => 'Das Format des :attribute ist ungültig.',
'required' => 'Das Feld :attribute ist erforderlich.',
'required_if' => 'Das Feld :attribute wird benötigt, wenn :other der Wert :value ist.',
'required_unless' => 'Das Feld :attribute ist erforderlich, es sei denn, :other steht in :values.',
'required_with' => 'Das Feld :attribute ist erforderlich, wenn :values vorhanden ist.',
'required_with_all' => 'Das Feld :attribute ist erforderlich, wenn :values vorhanden ist.',
'required_without' => 'Das Attributfeld :attribute ist erforderlich, wenn :values nicht vorhanden ist.',
'required_without_all' => 'Das Attributfeld :attribute wird benötigt, wenn keiner der :values vorhanden ist.',
'same' => 'Das Attribut :attribute und :other müssen übereinstimmen.',
'size' => [
'numeric' => 'Das Attribut :attribute muss :size sein.',
'file' => 'Das Attribut :attribute muss :size kilobytes sein.',
'string' => 'Das Attribut :attribute muss :size Zeichen sein.',
'array' => 'Das Attribut :attribute muss :size Elemente enthalten.',
],
'string' => 'Das :attribute muss eine Zeichenkette sein.',
'timezone' => 'Das Attribut :attribute muss eine gültige Zone sein.',
'unique' => 'Das Attribut :attribute wurde bereits vergeben.',
'uploaded' => 'Das :attribute konnte nicht hochgeladen werden.',
'url' => 'Das Format des :attribute ist ungültig.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'kundenspezifische Nachricht',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [],
];

19
resources/lang/en/auth.php Executable file
View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'These credentials do not match our records.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
];

View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Previous',
'next' => 'Next &raquo;',
];

22
resources/lang/en/passwords.php Executable file
View File

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Passwords must be at least six characters and match the confirmation.',
'reset' => 'Your password has been reset!',
'sent' => 'We have e-mailed your password reset link!',
'token' => 'This password reset token is invalid.',
'user' => "We can't find a user with that e-mail address.",
];

146
resources/lang/en/validation.php Executable file
View File

@ -0,0 +1,146 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'The :attribute must be accepted.',
'active_url' => 'The :attribute is not a valid URL.',
'after' => 'The :attribute must be a date after :date.',
'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
'alpha' => 'The :attribute may only contain letters.',
'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.',
'alpha_num' => 'The :attribute may only contain letters and numbers.',
'array' => 'The :attribute must be an array.',
'before' => 'The :attribute must be a date before :date.',
'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'string' => 'The :attribute must be between :min and :max characters.',
'array' => 'The :attribute must have between :min and :max items.',
],
'boolean' => 'The :attribute field must be true or false.',
'confirmed' => 'The :attribute confirmation does not match.',
'date' => 'The :attribute is not a valid date.',
'date_format' => 'The :attribute does not match the format :format.',
'different' => 'The :attribute and :other must be different.',
'digits' => 'The :attribute must be :digits digits.',
'digits_between' => 'The :attribute must be between :min and :max digits.',
'dimensions' => 'The :attribute has invalid image dimensions.',
'distinct' => 'The :attribute field has a duplicate value.',
'email' => 'The :attribute must be a valid email address.',
'exists' => 'The selected :attribute is invalid.',
'file' => 'The :attribute must be a file.',
'filled' => 'The :attribute field must have a value.',
'gt' => [
'numeric' => 'The :attribute must be greater than :value.',
'file' => 'The :attribute must be greater than :value kilobytes.',
'string' => 'The :attribute must be greater than :value characters.',
'array' => 'The :attribute must have more than :value items.',
],
'gte' => [
'numeric' => 'The :attribute must be greater than or equal :value.',
'file' => 'The :attribute must be greater than or equal :value kilobytes.',
'string' => 'The :attribute must be greater than or equal :value characters.',
'array' => 'The :attribute must have :value items or more.',
],
'image' => 'The :attribute must be an image.',
'in' => 'The selected :attribute is invalid.',
'in_array' => 'The :attribute field does not exist in :other.',
'integer' => 'The :attribute must be an integer.',
'ip' => 'The :attribute must be a valid IP address.',
'ipv4' => 'The :attribute must be a valid IPv4 address.',
'ipv6' => 'The :attribute must be a valid IPv6 address.',
'json' => 'The :attribute must be a valid JSON string.',
'lt' => [
'numeric' => 'The :attribute must be less than :value.',
'file' => 'The :attribute must be less than :value kilobytes.',
'string' => 'The :attribute must be less than :value characters.',
'array' => 'The :attribute must have less than :value items.',
],
'lte' => [
'numeric' => 'The :attribute must be less than or equal :value.',
'file' => 'The :attribute must be less than or equal :value kilobytes.',
'string' => 'The :attribute must be less than or equal :value characters.',
'array' => 'The :attribute must not have more than :value items.',
],
'max' => [
'numeric' => 'The :attribute may not be greater than :max.',
'file' => 'The :attribute may not be greater than :max kilobytes.',
'string' => 'The :attribute may not be greater than :max characters.',
'array' => 'The :attribute may not have more than :max items.',
],
'mimes' => 'The :attribute must be a file of type: :values.',
'mimetypes' => 'The :attribute must be a file of type: :values.',
'min' => [
'numeric' => 'The :attribute must be at least :min.',
'file' => 'The :attribute must be at least :min kilobytes.',
'string' => 'The :attribute must be at least :min characters.',
'array' => 'The :attribute must have at least :min items.',
],
'not_in' => 'The selected :attribute is invalid.',
'not_regex' => 'The :attribute format is invalid.',
'numeric' => 'The :attribute must be a number.',
'present' => 'The :attribute field must be present.',
'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values is present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute and :other must match.',
'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'array' => 'The :attribute must contain :size items.',
],
'string' => 'The :attribute must be a string.',
'timezone' => 'The :attribute must be a valid zone.',
'unique' => 'The :attribute has already been taken.',
'uploaded' => 'The :attribute failed to upload.',
'url' => 'The :attribute format is invalid.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [],
];

View File

@ -0,0 +1,18 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'Deze combinatie van e-mailadres en wachtwoord is niet geldig.',
'throttle' => 'Te veel mislukte loginpogingen. Probeer het over :seconds seconden nogmaals.',
];

View File

@ -0,0 +1,18 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Vorige',
'next' => 'Volgende &raquo;',
];

View File

@ -0,0 +1,21 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reminder Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Wachtwoord moet minimaal zes tekens lang zijn en de wachtwoorden moeten overeenkomen.',
'reset' => 'Het wachtwoord van uw account is gewijzigd.',
'sent' => 'We hebben een e-mail verstuurd met instructies om een nieuw wachtwoord in te stellen.',
'token' => 'Dit wachtwoordhersteltoken is ongeldig of verlopen.',
'user' => 'Geen gebruiker bekend met het e-mailadres.',
];

View File

@ -0,0 +1,179 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages.
|
*/
'accepted' => ':attribute moet geaccepteerd zijn.',
'active_url' => ':attribute is geen geldige URL.',
'after' => ':attribute moet een datum na :date zijn.',
'after_or_equal' => ':attribute moet een datum na of gelijk aan :date zijn.',
'alpha' => ':attribute mag alleen letters bevatten.',
'alpha_dash' => ':attribute mag alleen letters, nummers, underscores (_) en streepjes (-) bevatten.',
'alpha_num' => ':attribute mag alleen letters en nummers bevatten.',
'array' => ':attribute moet geselecteerde elementen bevatten.',
'before' => ':attribute moet een datum voor :date zijn.',
'before_or_equal' => ':attribute moet een datum voor of gelijk aan :date zijn.',
'between' => [
'numeric' => ':attribute moet tussen :min en :max zijn.',
'file' => ':attribute moet tussen :min en :max kilobytes zijn.',
'string' => ':attribute moet tussen :min en :max karakters zijn.',
'array' => ':attribute moet tussen :min en :max items bevatten.',
],
'boolean' => ':attribute moet ja of nee zijn.',
'confirmed' => ':attribute bevestiging komt niet overeen.',
'date' => ':attribute moet een datum bevatten.',
'date_format' => ':attribute moet een geldig datum formaat bevatten.',
'different' => ':attribute en :other moeten verschillend zijn.',
'digits' => ':attribute moet bestaan uit :digits cijfers.',
'digits_between' => ':attribute moet bestaan uit minimaal :min en maximaal :max cijfers.',
'dimensions' => ':attribute heeft geen geldige afmetingen voor afbeeldingen.',
'distinct' => ':attribute heeft een dubbele waarde.',
'email' => ':attribute is geen geldig e-mailadres.',
'exists' => ':attribute bestaat niet.',
'file' => ':attribute moet een bestand zijn.',
'filled' => ':attribute is verplicht.',
'gt' => [
'numeric' => 'De :attribute moet groter zijn dan :value.',
'file' => 'De :attribute moet groter zijn dan :value kilobytes.',
'string' => 'De :attribute moet meer dan :value tekens bevatten.',
'array' => 'De :attribute moet meer dan :value waardes bevatten.',
],
'gte' => [
'numeric' => 'De :attribute moet groter of gelijk zijn aan :value.',
'file' => 'De :attribute moet groter of gelijk zijn aan :value kilobytes.',
'string' => 'De :attribute moet minimaal :value tekens bevatten.',
'array' => 'De :attribute moet :value waardes of meer bevatten.',
],
'image' => ':attribute moet een afbeelding zijn.',
'in' => ':attribute is ongeldig.',
'in_array' => ':attribute bestaat niet in :other.',
'integer' => ':attribute moet een getal zijn.',
'ip' => ':attribute moet een geldig IP-adres zijn.',
'ipv4' => ':attribute moet een geldig IPv4-adres zijn.',
'ipv6' => ':attribute moet een geldig IPv6-adres zijn.',
'json' => ':attribute moet een geldige JSON-string zijn.',
'lt' => [
'numeric' => 'De :attribute moet kleiner zijn dan :value.',
'file' => 'De :attribute moet kleiner zijn dan :value kilobytes.',
'string' => 'De :attribute moet minder dan :value tekens bevatten.',
'array' => 'De :attribute moet minder dan :value waardes bevatten.',
],
'lte' => [
'numeric' => 'De :attribute moet kleiner of gelijk zijn aan :value.',
'file' => 'De :attribute moet kleiner of gelijk zijn aan :value kilobytes.',
'string' => 'De :attribute moet maximaal :value tekens bevatten.',
'array' => 'De :attribute moet :value waardes of minder bevatten.',
],
'max' => [
'numeric' => ':attribute mag niet hoger dan :max zijn.',
'file' => ':attribute mag niet meer dan :max kilobytes zijn.',
'string' => ':attribute mag niet uit meer dan :max tekens bestaan.',
'array' => ':attribute mag niet meer dan :max items bevatten.',
],
'mimes' => ':attribute moet een bestand zijn van het bestandstype :values.',
'mimetypes' => ':attribute moet een bestand zijn van het bestandstype :values.',
'min' => [
'numeric' => ':attribute moet minimaal :min zijn.',
'file' => ':attribute moet minimaal :min kilobytes zijn.',
'string' => ':attribute moet minimaal :min tekens zijn.',
'array' => ':attribute moet minimaal :min items bevatten.',
],
'not_in' => 'Het formaat van :attribute is ongeldig.',
'not_regex' => 'De :attribute formaat is ongeldig.',
'numeric' => ':attribute moet een nummer zijn.',
'present' => ':attribute moet bestaan.',
'regex' => ':attribute formaat is ongeldig.',
'required' => ':attribute is verplicht.',
'required_if' => ':attribute is verplicht indien :other gelijk is aan :value.',
'required_unless' => ':attribute is verplicht tenzij :other gelijk is aan :values.',
'required_with' => ':attribute is verplicht i.c.m. :values',
'required_with_all' => ':attribute is verplicht i.c.m. :values',
'required_without' => ':attribute is verplicht als :values niet ingevuld is.',
'required_without_all' => ':attribute is verplicht als :values niet ingevuld zijn.',
'same' => ':attribute en :other moeten overeenkomen.',
'size' => [
'numeric' => ':attribute moet :size zijn.',
'file' => ':attribute moet :size kilobyte zijn.',
'string' => ':attribute moet :size tekens zijn.',
'array' => ':attribute moet :size items bevatten.',
],
'starts_with' => ':attribute moet starten met een van de volgende: :values',
'string' => ':attribute moet een tekst zijn.',
'timezone' => ':attribute moet een geldige tijdzone zijn.',
'unique' => ':attribute is al in gebruik.',
'uploaded' => 'Het uploaden van :attribute is mislukt.',
'url' => ':attribute moet een geldig URL zijn.',
'uuid' => ':attribute moet een geldig UUID zijn.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [
'address' => 'adres',
'age' => 'leeftijd',
'available' => 'beschikbaar',
'city' => 'stad',
'content' => 'inhoud',
'country' => 'land',
'date' => 'datum',
'day' => 'dag',
'description' => 'omschrijving',
'email' => 'e-mailadres',
'excerpt' => 'uittreksel',
'first_name' => 'voornaam',
'gender' => 'geslacht',
'hour' => 'uur',
'last_name' => 'achternaam',
'message' => 'boodschap',
'minute' => 'minuut',
'mobile' => 'mobiel',
'month' => 'maand',
'name' => 'naam',
'password' => 'wachtwoord',
'password_confirmation' => 'wachtwoordbevestiging',
'phone' => 'telefoonnummer',
'second' => 'seconde',
'sex' => 'geslacht',
'size' => 'grootte',
'subject' => 'onderwerp',
'time' => 'tijd',
'title' => 'titel',
'username' => 'gebruikersnaam',
'year' => 'jaar',
],
];

19
resources/lang/pt_BR/auth.php Executable file
View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'Essas credenciais não correspondem aos nossos registros.',
'throttle' => 'Muitas tentativas de login. Tente novamente em :seconds segundos.',
];

View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Anterior',
'next' => 'Próximo &raquo;',
];

View File

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'A senha e a confirmação devem combinar e possuir pelo menos seis caracteres.',
'reset' => 'Sua senha foi redefinida!',
'sent' => 'Enviamos seu link de redefinição de senha por e-mail!',
'token' => 'Este token de redefinição de senha é inválido.',
'user' => 'Não encontramos um usuário com esse endereço de e-mail.',
];

View File

@ -0,0 +1,119 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'O campo :attribute deve ser aceito.',
'active_url' => 'O campo :attribute não é uma URL válida.',
'after' => 'O campo :attribute deve ser uma data posterior a :date.',
'after_or_equal' => 'O campo :attribute deve ser uma data posterior ou igual a :date.',
'alpha' => 'O campo :attribute só pode conter letras.',
'alpha_dash' => 'O campo :attribute só pode conter letras, números e traços.',
'alpha_num' => 'O campo :attribute só pode conter letras e números.',
'array' => 'O campo :attribute deve ser uma matriz.',
'before' => 'O campo :attribute deve ser uma data anterior :date.',
'before_or_equal' => 'O campo :attribute deve ser uma data anterior ou igual a :date.',
'between' => [
'numeric' => 'O campo :attribute deve ser entre :min e :max.',
'file' => 'O campo :attribute deve ser entre :min e :max kilobytes.',
'string' => 'O campo :attribute deve ser entre :min e :max caracteres.',
'array' => 'O campo :attribute deve ter entre :min e :max itens.',
],
'boolean' => 'O campo :attribute deve ser verdadeiro ou falso.',
'confirmed' => 'O campo :attribute de confirmação não confere.',
'date' => 'O campo :attribute não é uma data válida.',
'date_format' => 'O campo :attribute não corresponde ao formato :format.',
'different' => 'Os campos :attribute e :other devem ser diferentes.',
'digits' => 'O campo :attribute deve ter :digits dígitos.',
'digits_between' => 'O campo :attribute deve ter entre :min e :max dígitos.',
'dimensions' => 'O campo :attribute tem dimensões de imagem inválidas.',
'distinct' => 'O campo :attribute campo tem um valor duplicado.',
'email' => 'O campo :attribute deve ser um endereço de e-mail válido.',
'exists' => 'O campo :attribute selecionado é inválido.',
'file' => 'O campo :attribute deve ser um arquivo.',
'filled' => 'O campo :attribute deve ter um valor.',
'image' => 'O campo :attribute deve ser uma imagem.',
'in' => 'O campo :attribute selecionado é inválido.',
'in_array' => 'O campo :attribute não existe em :other.',
'integer' => 'O campo :attribute deve ser um número inteiro.',
'ip' => 'O campo :attribute deve ser um endereço de IP válido.',
'ipv4' => 'O campo :attribute deve ser um endereço IPv4 válido.',
'ipv6' => 'O campo :attribute deve ser um endereço IPv6 válido.',
'json' => 'O campo :attribute deve ser uma string JSON válida.',
'max' => [
'numeric' => 'O campo :attribute não pode ser superior a :max.',
'file' => 'O campo :attribute não pode ser superior a :max kilobytes.',
'string' => 'O campo :attribute não pode ser superior a :max caracteres.',
'array' => 'O campo :attribute não pode ter mais do que :max itens.',
],
'mimes' => 'O campo :attribute deve ser um arquivo do tipo: :values.',
'mimetypes' => 'O campo :attribute deve ser um arquivo do tipo: :values.',
'min' => [
'numeric' => 'O campo :attribute deve ser pelo menos :min.',
'file' => 'O campo :attribute deve ter pelo menos :min kilobytes.',
'string' => 'O campo :attribute deve ter pelo menos :min caracteres.',
'array' => 'O campo :attribute deve ter pelo menos :min itens.',
],
'not_in' => 'O campo :attribute selecionado é inválido.',
'numeric' => 'O campo :attribute deve ser um número.',
'present' => 'O campo :attribute deve estar presente.',
'regex' => 'O campo :attribute tem um formato inválido.',
'required' => 'O campo :attribute é obrigatório.',
'required_if' => 'O campo :attribute é obrigatório quando :other for :value.',
'required_unless' => 'O campo :attribute é obrigatório exceto quando :other for :values.',
'required_with' => 'O campo :attribute é obrigatório quando :values está presente.',
'required_with_all' => 'O campo :attribute é obrigatório quando :values está presente.',
'required_without' => 'O campo :attribute é obrigatório quando :values não está presente.',
'required_without_all' => 'O campo :attribute é obrigatório quando nenhum dos :values estão presentes.',
'same' => 'Os campos :attribute e :other devem corresponder.',
'size' => [
'numeric' => 'O campo :attribute deve ser :size.',
'file' => 'O campo :attribute deve ser :size kilobytes.',
'string' => 'O campo :attribute deve ser :size caracteres.',
'array' => 'O campo :attribute deve conter :size itens.',
],
'string' => 'O campo :attribute deve ser uma string.',
'timezone' => 'O campo :attribute deve ser uma zona válida.',
'unique' => 'O campo :attribute já está sendo utilizado.',
'uploaded' => 'Ocorreu uma falha no upload do campo :attribute.',
'url' => 'O campo :attribute tem um formato inválido.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [],
];

View File

@ -2,11 +2,17 @@
namespace Tests\Unit\Checkout\Cart; namespace Tests\Unit\Checkout\Cart;
use Codeception\Example;
use Exception;
use Faker\Factory; use Faker\Factory;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
use UnitTester; use UnitTester;
use Webkul\BookingProduct\Models\BookingProduct;
use Webkul\BookingProduct\Models\BookingProductEventTicket;
use Webkul\Core\Helpers\Laravel5Helper; use Webkul\Core\Helpers\Laravel5Helper;
use Webkul\Customer\Models\Customer;
use Webkul\Product\Models\ProductDownloadableLink;
class CartCest class CartCest
{ {
@ -17,8 +23,9 @@ class CartCest
private $virtualProduct2; private $virtualProduct2;
private $downloadableProduct1; private $downloadableProduct1;
private $downloadableProduct2; private $downloadableProduct2;
private $customer;
public function _before(UnitTester $I) public function _before(UnitTester $I): void
{ {
$this->faker = Factory::create(); $this->faker = Factory::create();
@ -56,6 +63,8 @@ class CartCest
$this->downloadableProduct1 = $I->haveProduct(Laravel5Helper::DOWNLOADABLE_PRODUCT); $this->downloadableProduct1 = $I->haveProduct(Laravel5Helper::DOWNLOADABLE_PRODUCT);
$this->downloadableProduct2 = $I->haveProduct(Laravel5Helper::DOWNLOADABLE_PRODUCT); $this->downloadableProduct2 = $I->haveProduct(Laravel5Helper::DOWNLOADABLE_PRODUCT);
$this->customer = $I->have(Customer::class);
} }
public function testCartWithInactiveProducts(UnitTester $I) public function testCartWithInactiveProducts(UnitTester $I)
@ -135,6 +144,210 @@ class CartCest
$I->assertEquals(5, cart()->getCart()->items()->find($cartItemId)->quantity); $I->assertEquals(5, cart()->getCart()->items()->find($cartItemId)->quantity);
} }
/**
* @param UnitTester $I
* @param Example $scenario
*
* @throws Exception
*
* @dataProvider getMergeCartScenarios
*/
public function testMergeCart(UnitTester $I, Example $scenario): void
{
$product1 = $I->haveProduct($scenario['product_type1']);
$product2 = $I->haveProduct($scenario['product_type2']);
if ($scenario['product_type1'] === Laravel5Helper::DOWNLOADABLE_PRODUCT) {
$downloadableLink1 = ProductDownloadableLink::query()->where('product_id', $product1->id)->firstOrFail();
$I->assertNotNull($downloadableLink1);
}
if ($scenario['product_type1'] === Laravel5Helper::BOOKING_EVENT_PRODUCT) {
$bookingProduct = BookingProduct::query()->where('product_id', $product1->id)->firstOrFail();
$I->assertNotNull($bookingProduct);
$bookingTicket1 = BookingProductEventTicket::query()->where('booking_product_id',
$bookingProduct->id)->firstOrFail();
$I->assertNotNull($bookingTicket1);
}
if ($scenario['product_type2'] === Laravel5Helper::DOWNLOADABLE_PRODUCT) {
$downloadableLink2 = ProductDownloadableLink::query()->where('product_id', $product2->id)->firstOrFail();
$I->assertNotNull($downloadableLink2);
}
if ($scenario['product_type2'] === Laravel5Helper::BOOKING_EVENT_PRODUCT) {
$bookingProduct = BookingProduct::query()->where('product_id', $product2->id)->firstOrFail();
$I->assertNotNull($bookingProduct);
$bookingTicket2 = BookingProductEventTicket::query()->where('booking_product_id',
$bookingProduct->id)->firstOrFail();
$I->assertNotNull($bookingTicket2);
}
$I->comment("Check, I'm a guest");
$this->cleanUp();
$I->assertFalse(auth()->guard('customer')->check());
$I->assertNull(cart()->getCart());
$data = [
'_token' => session('_token'),
'quantity' => 1,
'product_id' => $product1->id,
];
if ($scenario['product_type1'] === Laravel5Helper::DOWNLOADABLE_PRODUCT) {
$data['links'] = [$downloadableLink1->id];
}
if ($scenario['product_type1'] === Laravel5Helper::BOOKING_EVENT_PRODUCT) {
$data['booking'] = ['qty' => [$bookingTicket1->id => 1]];
}
$I->comment('A guest is adding a first product of type ' . $product1->type . ' to cart');
cart()->addProduct($product1->id, $data);
$I->assertEquals(1, cart()->getCart()->items->count());
$I->comment('Guest is logging in...then guest is a known customer.');
auth()->guard('customer')->onceUsingId($this->customer->id);
Event::dispatch('customer.after.login', $this->customer['email']);
$I->comment("Let us assume that the customer's shopping cart was empty. The individual product from the guest's shopping cart is transferred to the customer's shopping cart.");
$I->assertEquals(1, cart()->getCart()->items->count());
auth()->guard('customer')->logout();
$data = [
'_token' => session('_token'),
'quantity' => 1,
'product_id' => $product2->id,
];
if ($scenario['product_type2'] === Laravel5Helper::DOWNLOADABLE_PRODUCT) {
$data['links'] = [$downloadableLink2->id];
}
if ($scenario['product_type2'] === Laravel5Helper::BOOKING_EVENT_PRODUCT) {
$data['booking'] = ['qty' => [$bookingTicket2->id => 1]];
}
$I->comment('Guest is adding a product of type ' . $product2->type . ' to cart.');
cart()->addProduct($product2->id, $data);
$I->assertEquals(1, cart()->getCart()->items->count());
$I->comment('And will be logged in.');
auth()->guard('customer')->onceUsingId($this->customer->id);
Event::dispatch('customer.after.login', $this->customer['email']);
$I->assertEquals(2, cart()->getCart()->items->count());
auth()->guard('customer')->logout();
$data = [
'_token' => session('_token'),
'quantity' => 2,
'product_id' => $product1->id,
];
if ($scenario['product_type1'] === Laravel5Helper::DOWNLOADABLE_PRODUCT) {
$data['links'] = [$downloadableLink1->id];
}
if ($scenario['product_type1'] === Laravel5Helper::BOOKING_EVENT_PRODUCT) {
$data['booking'] = ['qty' => [$bookingTicket1->id => 2]];
}
$I->comment('Again, guest is adding another product of type ' . $product1->type . '.');
$I->assertNull(cart()->getCart());
cart()->addProduct($product1->id, $data);
$I->assertEquals(1, cart()->getCart()->items->count());
$I->assertEquals(2, cart()->getCart()->items_qty);
$I->comment('And will be logged in.');
auth()->guard('customer')->onceUsingId($this->customer->id);
Event::dispatch('customer.after.login', $this->customer['email']);
$I->assertEquals(2, cart()->getCart()->items->count());
$I->assertEquals(4, cart()->getCart()->items_qty);
$this->cleanUp();
$I->comment('=== DONE: Added ' . $product1->type . ' to ' . $product2->type . ' ===');
}
private function getMergeCartScenarios(): array
{
return [
[
'product_type1' => Laravel5Helper::SIMPLE_PRODUCT,
'product_type2' => Laravel5Helper::SIMPLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::VIRTUAL_PRODUCT,
'product_type2' => Laravel5Helper::VIRTUAL_PRODUCT,
],
[
'product_type1' => Laravel5Helper::SIMPLE_PRODUCT,
'product_type2' => Laravel5Helper::VIRTUAL_PRODUCT,
],
[
'product_type1' => Laravel5Helper::VIRTUAL_PRODUCT,
'product_type2' => Laravel5Helper::SIMPLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
'product_type2' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
'product_type2' => Laravel5Helper::SIMPLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::SIMPLE_PRODUCT,
'product_type2' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
'product_type2' => Laravel5Helper::VIRTUAL_PRODUCT,
],
[
'product_type1' => Laravel5Helper::VIRTUAL_PRODUCT,
'product_type2' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
'product_type2' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
],
[
'product_type1' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
'product_type2' => Laravel5Helper::SIMPLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::SIMPLE_PRODUCT,
'product_type2' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
],
[
'product_type1' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
'product_type2' => Laravel5Helper::VIRTUAL_PRODUCT,
],
[
'product_type1' => Laravel5Helper::VIRTUAL_PRODUCT,
'product_type2' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
],
[
'product_type1' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
'product_type2' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
'product_type2' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
],
];
}
private function cleanUp(): void
{
$cart = cart()->getCart();
if ($cart) {
foreach ($cart->items as $item) {
cart()->removeItem($item->id);
}
}
session()->forget('cart');
auth()->guard('customer')->logout();
session()->forget('cart');
}
/** /**
* @param int $productId * @param int $productId
* *

View File

@ -1,226 +0,0 @@
<?php
namespace Tests\Unit\Checkout;
use Codeception\Example;
use Exception;
use Illuminate\Support\Facades\Event;
use UnitTester;
use Webkul\BookingProduct\Models\BookingProduct;
use Webkul\BookingProduct\Models\BookingProductEventTicket;
use Webkul\Core\Helpers\Laravel5Helper;
use Webkul\Customer\Models\Customer;
use Webkul\Product\Models\ProductDownloadableLink;
class CartCest
{
private $customer;
public function _before(UnitTester $I): void
{
$this->customer = $I->have(Customer::class);
}
/**
* @param UnitTester $I
* @param Example $scenario
*
* @throws Exception
*
* @dataProvider getMergeCartScenarios
*/
public function testMergeCart(UnitTester $I, Example $scenario): void
{
$product1 = $I->haveProduct($scenario['product_type1']);
$product2 = $I->haveProduct($scenario['product_type2']);
if ($scenario['product_type1'] === Laravel5Helper::DOWNLOADABLE_PRODUCT) {
$downloadableLink1 = ProductDownloadableLink::query()->where('product_id', $product1->id)->firstOrFail();
$I->assertNotNull($downloadableLink1);
}
if ($scenario['product_type1'] === Laravel5Helper::BOOKING_EVENT_PRODUCT) {
$bookingProduct = BookingProduct::query()->where('product_id', $product1->id)->firstOrFail();
$I->assertNotNull($bookingProduct);
$bookingTicket1 = BookingProductEventTicket::query()->where('booking_product_id',
$bookingProduct->id)->firstOrFail();
$I->assertNotNull($bookingTicket1);
}
if ($scenario['product_type2'] === Laravel5Helper::DOWNLOADABLE_PRODUCT) {
$downloadableLink2 = ProductDownloadableLink::query()->where('product_id', $product2->id)->firstOrFail();
$I->assertNotNull($downloadableLink2);
}
if ($scenario['product_type2'] === Laravel5Helper::BOOKING_EVENT_PRODUCT) {
$bookingProduct = BookingProduct::query()->where('product_id', $product2->id)->firstOrFail();
$I->assertNotNull($bookingProduct);
$bookingTicket2 = BookingProductEventTicket::query()->where('booking_product_id',
$bookingProduct->id)->firstOrFail();
$I->assertNotNull($bookingTicket2);
}
$I->comment("Check, I'm a guest");
$I->assertFalse(auth()->guard('customer')->check());
$I->assertNull(cart()->getCart());
$data = [
'_token' => session('_token'),
'quantity' => 1,
'product_id' => $product1->id,
];
if ($scenario['product_type1'] === Laravel5Helper::DOWNLOADABLE_PRODUCT) {
$data['links'] = [$downloadableLink1->id];
}
if ($scenario['product_type1'] === Laravel5Helper::BOOKING_EVENT_PRODUCT) {
$data['booking'] = ['qty' => [$bookingTicket1->id => 1]];
}
$I->comment('A guest is adding a first product of type ' . $product1->type . ' to cart');
cart()->addProduct($product1->id, $data);
$I->assertEquals(1, cart()->getCart()->items->count());
$I->comment('Guest is logging in...then guest is a known customer.');
auth()->guard('customer')->onceUsingId($this->customer->id);
Event::dispatch('customer.after.login', $this->customer['email']);
$I->comment("Let us assume that the customer's shopping cart was empty. The individual product from the guest's shopping cart is transferred to the customer's shopping cart.");
$I->assertEquals(1, cart()->getCart()->items->count());
auth()->guard('customer')->logout();
$data = [
'_token' => session('_token'),
'quantity' => 1,
'product_id' => $product2->id,
];
if ($scenario['product_type2'] === Laravel5Helper::DOWNLOADABLE_PRODUCT) {
$data['links'] = [$downloadableLink2->id];
}
if ($scenario['product_type2'] === Laravel5Helper::BOOKING_EVENT_PRODUCT) {
$data['booking'] = ['qty' => [$bookingTicket2->id => 1]];
}
$I->comment('Guest is adding a product of type ' . $product2->type . ' to cart.');
cart()->addProduct($product2->id, $data);
$I->assertEquals(1, cart()->getCart()->items->count());
$I->comment('And will be logged in.');
auth()->guard('customer')->onceUsingId($this->customer->id);
Event::dispatch('customer.after.login', $this->customer['email']);
$I->assertEquals(2, cart()->getCart()->items->count());
auth()->guard('customer')->logout();
$data = [
'_token' => session('_token'),
'quantity' => 2,
'product_id' => $product1->id,
];
if ($scenario['product_type1'] === Laravel5Helper::DOWNLOADABLE_PRODUCT) {
$data['links'] = [$downloadableLink1->id];
}
if ($scenario['product_type1'] === Laravel5Helper::BOOKING_EVENT_PRODUCT) {
$data['booking'] = ['qty' => [$bookingTicket1->id => 1]];
}
$I->comment('Again, guest is adding another product of type ' . $product1->type . '.');
$I->assertNull(cart()->getCart());
cart()->addProduct($product1->id, $data);
$I->assertEquals(1, cart()->getCart()->items->count());
$I->assertEquals(2, cart()->getCart()->items_qty);
$I->comment('And will be logged in.');
auth()->guard('customer')->onceUsingId($this->customer->id);
Event::dispatch('customer.after.login', $this->customer['email']);
$I->assertEquals(2, cart()->getCart()->items->count());
$I->assertEquals(4, cart()->getCart()->items_qty);
$this->cleanUp();
$I->comment('=== DONE: Added ' . $product1->type . ' to ' . $product2->type . ' ===');
}
private function getMergeCartScenarios(): array
{
return [
[
'product_type1' => Laravel5Helper::SIMPLE_PRODUCT,
'product_type2' => Laravel5Helper::SIMPLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::VIRTUAL_PRODUCT,
'product_type2' => Laravel5Helper::VIRTUAL_PRODUCT,
],
[
'product_type1' => Laravel5Helper::SIMPLE_PRODUCT,
'product_type2' => Laravel5Helper::VIRTUAL_PRODUCT,
],
[
'product_type1' => Laravel5Helper::VIRTUAL_PRODUCT,
'product_type2' => Laravel5Helper::SIMPLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
'product_type2' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
'product_type2' => Laravel5Helper::SIMPLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::SIMPLE_PRODUCT,
'product_type2' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
'product_type2' => Laravel5Helper::VIRTUAL_PRODUCT,
],
[
'product_type1' => Laravel5Helper::VIRTUAL_PRODUCT,
'product_type2' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
'product_type2' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
],
[
'product_type1' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
'product_type2' => Laravel5Helper::SIMPLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::SIMPLE_PRODUCT,
'product_type2' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
],
[
'product_type1' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
'product_type2' => Laravel5Helper::VIRTUAL_PRODUCT,
],
[
'product_type1' => Laravel5Helper::VIRTUAL_PRODUCT,
'product_type2' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
],
[
'product_type1' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
'product_type2' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
],
[
'product_type1' => Laravel5Helper::DOWNLOADABLE_PRODUCT,
'product_type2' => Laravel5Helper::BOOKING_EVENT_PRODUCT,
],
];
}
private function cleanUp(): void
{
$cart = cart()->getCart();
if ($cart) {
foreach ($cart->items as $item) {
cart()->removeItem($item->id);
}
}
session()->forget('cart');
auth()->guard('customer')->logout();
session()->forget('cart');
}
}