Merge branch 'master' into vul-issue

This commit is contained in:
devansh bawari 2021-01-14 21:00:01 +05:30
commit 2d0c8562d8
135 changed files with 6033 additions and 491 deletions

View File

@ -18,7 +18,9 @@
"ext-tokenizer": "*",
"algolia/algoliasearch-client-php": "^2.2",
"astrotomic/laravel-translatable": "^11.0.0",
"aws/aws-sdk-php": "^3.171",
"babenkoivan/elastic-scout-driver": "^1.1",
"bagisto/bagisto-package-generator": "9999999-dev",
"bagistobrasil/bagisto-product-social-share": "^0.1.2",
"barryvdh/laravel-debugbar": "^3.1",
"barryvdh/laravel-dompdf": "0.8.6",
@ -30,6 +32,7 @@
"intervention/image": "^2.4",
"intervention/imagecache": "^2.3",
"kalnoy/nestedset": "5.0.1",
"khaled.alshamaa/ar-php": "^5.5",
"konekt/concord": "^1.2",
"laravel/framework": "^7.0",
"laravel/scout": "^8.0",
@ -74,39 +77,40 @@
"bagisto/laravel-discount": "v0.1.0"
},
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/",
"Webkul\\User\\": "packages/Webkul/User/src",
"Webkul\\Admin\\": "packages/Webkul/Admin/src",
"Webkul\\Ui\\": "packages/Webkul/Ui/src",
"Webkul\\Category\\": "packages/Webkul/Category/src",
"Webkul\\Checkout\\": "packages/Webkul/Checkout/src",
"Webkul\\Attribute\\": "packages/Webkul/Attribute/src",
"Webkul\\Shop\\": "packages/Webkul/Shop/src",
"Webkul\\Core\\": "packages/Webkul/Core/src",
"Webkul\\Customer\\": "packages/Webkul/Customer/src",
"Webkul\\Inventory\\": "packages/Webkul/Inventory/src",
"Webkul\\Product\\": "packages/Webkul/Product/src",
"Webkul\\Theme\\": "packages/Webkul/Theme/src",
"Webkul\\Shipping\\": "packages/Webkul/Shipping/src",
"Webkul\\Payment\\": "packages/Webkul/Payment/src",
"Webkul\\Paypal\\": "packages/Webkul/Paypal/src",
"Webkul\\Sales\\": "packages/Webkul/Sales/src",
"Webkul\\Tax\\": "packages/Webkul/Tax/src",
"Webkul\\API\\": "packages/Webkul/API",
"Webkul\\CatalogRule\\": "packages/Webkul/CatalogRule/src",
"Webkul\\CartRule\\": "packages/Webkul/CartRule/src",
"Webkul\\Rule\\": "packages/Webkul/Rule/src",
"Webkul\\CMS\\": "packages/Webkul/CMS/src",
"Webkul\\Velocity\\": "packages/Webkul/Velocity/src",
"Webkul\\BookingProduct\\": "packages/Webkul/BookingProduct/src",
"Webkul\\SocialLogin\\": "packages/Webkul/SocialLogin/src",
"Webkul\\DebugBar\\": "packages/Webkul/DebugBar/src"
}
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/",
"Webkul\\User\\": "packages/Webkul/User/src",
"Webkul\\Admin\\": "packages/Webkul/Admin/src",
"Webkul\\Ui\\": "packages/Webkul/Ui/src",
"Webkul\\Category\\": "packages/Webkul/Category/src",
"Webkul\\Checkout\\": "packages/Webkul/Checkout/src",
"Webkul\\Attribute\\": "packages/Webkul/Attribute/src",
"Webkul\\Shop\\": "packages/Webkul/Shop/src",
"Webkul\\Core\\": "packages/Webkul/Core/src",
"Webkul\\Customer\\": "packages/Webkul/Customer/src",
"Webkul\\Inventory\\": "packages/Webkul/Inventory/src",
"Webkul\\Product\\": "packages/Webkul/Product/src",
"Webkul\\Theme\\": "packages/Webkul/Theme/src",
"Webkul\\Shipping\\": "packages/Webkul/Shipping/src",
"Webkul\\Payment\\": "packages/Webkul/Payment/src",
"Webkul\\Paypal\\": "packages/Webkul/Paypal/src",
"Webkul\\Sales\\": "packages/Webkul/Sales/src",
"Webkul\\Tax\\": "packages/Webkul/Tax/src",
"Webkul\\API\\": "packages/Webkul/API",
"Webkul\\CatalogRule\\": "packages/Webkul/CatalogRule/src",
"Webkul\\CartRule\\": "packages/Webkul/CartRule/src",
"Webkul\\Rule\\": "packages/Webkul/Rule/src",
"Webkul\\CMS\\": "packages/Webkul/CMS/src",
"Webkul\\Velocity\\": "packages/Webkul/Velocity/src",
"Webkul\\BookingProduct\\": "packages/Webkul/BookingProduct/src",
"Webkul\\SocialLogin\\": "packages/Webkul/SocialLogin/src",
"Webkul\\DebugBar\\": "packages/Webkul/DebugBar/src",
"Webkul\\Marketing\\": "packages/Webkul/Marketing/src"
}
},
"autoload-dev": {
"psr-4": {

1892
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -281,6 +281,7 @@ return [
Webkul\BookingProduct\Providers\BookingProductServiceProvider::class,
Webkul\SocialLogin\Providers\SocialLoginServiceProvider::class,
Webkul\DebugBar\Providers\DebugBarServiceProvider::class,
Webkul\Marketing\Providers\MarketingServiceProvider::class,
],
/*

View File

@ -24,6 +24,7 @@ return [
\Webkul\CMS\Providers\ModuleServiceProvider::class,
\Webkul\Customer\Providers\ModuleServiceProvider::class,
\Webkul\Inventory\Providers\ModuleServiceProvider::class,
\Webkul\Marketing\Providers\ModuleServiceProvider::class,
\Webkul\Payment\Providers\ModuleServiceProvider::class,
\Webkul\Paypal\Providers\ModuleServiceProvider::class,
\Webkul\Product\Providers\ModuleServiceProvider::class,

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddColumnUrlPathToCategoryTranslations extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('category_translations', function (Blueprint $table) {
$table->string('url_path', 2048)
->comment('maintained by database triggers');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('category_translations', function (Blueprint $table) {
$table->dropColumn('url_path');
});
}
}

View File

@ -0,0 +1,70 @@
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
class AddStoredFunctionToGetUrlPathOfCategory extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$dbPrefix = DB::getTablePrefix();
$functionSQL = <<< SQL
DROP FUNCTION IF EXISTS `get_url_path_of_category`;
CREATE FUNCTION get_url_path_of_category(
categoryId INT,
localeCode VARCHAR(255)
)
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE urlPath VARCHAR(255);
-- Category with id 1 is root by default
IF categoryId <> 1
THEN
SELECT
GROUP_CONCAT(parent_translations.slug SEPARATOR '/') INTO urlPath
FROM
${dbPrefix}categories AS node,
${dbPrefix}categories AS parent
JOIN ${dbPrefix}category_translations AS parent_translations ON parent.id = parent_translations.category_id
WHERE
node._lft >= parent._lft
AND node._rgt <= parent._rgt
AND node.id = categoryId
AND parent.id <> 1
AND parent_translations.locale = localeCode
GROUP BY
node.id;
IF urlPath IS NULL
THEN
SET urlPath = (SELECT slug FROM ${dbPrefix}category_translations WHERE ${dbPrefix}category_translations.category_id = categoryId);
END IF;
ELSE
SET urlPath = '';
END IF;
RETURN urlPath;
END;
SQL;
DB::unprepared($functionSQL);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
DB::unprepared('DROP FUNCTION IF EXISTS `get_url_path_of_category`;');
}
}

View File

@ -0,0 +1,103 @@
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
use Webkul\Category\Models\CategoryTranslation;
class AddTriggerToCategoryTranslations extends Migration
{
private const TRIGGER_NAME_INSERT = 'trig_category_translations_insert';
private const TRIGGER_NAME_UPDATE = 'trig_category_translations_update';
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$dbPrefix = DB::getTablePrefix();
$triggerBody = $this->getTriggerBody();
$insertTrigger = <<< SQL
CREATE TRIGGER %s
BEFORE INSERT ON ${dbPrefix}category_translations
FOR EACH ROW
BEGIN
$triggerBody
END;
SQL;
$updateTrigger = <<< SQL
CREATE TRIGGER %s
BEFORE UPDATE ON ${dbPrefix}category_translations
FOR EACH ROW
BEGIN
$triggerBody
END;
SQL;
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_INSERT));
DB::unprepared(sprintf($insertTrigger, self::TRIGGER_NAME_INSERT));
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_UPDATE));
DB::unprepared(sprintf($updateTrigger, self::TRIGGER_NAME_UPDATE));
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_INSERT));
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_UPDATE));
}
/**
* Returns trigger body as string
*
* @return string
*/
private function getTriggerBody()
{
$dbPrefix = DB::getTablePrefix();
return <<<SQL
DECLARE parentUrlPath varchar(255);
DECLARE urlPath varchar(255);
-- Category with id 1 is root by default
IF NEW.category_id <> 1
THEN
SELECT
GROUP_CONCAT(parent_translations.slug SEPARATOR '/') INTO parentUrlPath
FROM
${dbPrefix}categories AS node,
${dbPrefix}categories AS parent
JOIN ${dbPrefix}category_translations AS parent_translations ON parent.id = parent_translations.category_id
WHERE
node._lft >= parent._lft
AND node._rgt <= parent._rgt
AND node.id = (SELECT parent_id FROM categories WHERE id = NEW.category_id)
AND parent.id <> 1
AND parent_translations.locale = NEW.locale
GROUP BY
node.id;
IF parentUrlPath IS NULL
THEN
SET urlPath = NEW.slug;
ELSE
SET urlPath = concat(parentUrlPath, '/', NEW.slug);
END IF;
SET NEW.url_path = urlPath;
END IF;
SQL;
}
}

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
use Webkul\Category\Models\CategoryTranslation;
class AddUrlPathToExistingCategoryTranslations extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$sqlStoredFunction = <<< SQL
SELECT get_url_path_of_category(:category_id, :locale_code) AS url_path;
SQL;
$categoryTranslationsTableName = app(CategoryTranslation::class)->getTable();
foreach (DB::table($categoryTranslationsTableName)->get() as $categoryTranslation) {
$urlPathQueryResult = DB::selectOne($sqlStoredFunction, [
'category_id' => $categoryTranslation->category_id,
'locale_code' => $categoryTranslation->locale,
]);
$url_path = $urlPathQueryResult ? $urlPathQueryResult->url_path : '';
DB::table($categoryTranslationsTableName)
->where('id', $categoryTranslation->id)
->update(['url_path' => $url_path]);
}
}
}

View File

@ -0,0 +1,102 @@
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
class AddTriggerToCategories extends Migration
{
private const TRIGGER_NAME_INSERT = 'trig_categories_insert';
private const TRIGGER_NAME_UPDATE = 'trig_categories_update';
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$triggerBody = $this->getTriggerBody();
$dbPrefix = DB::getTablePrefix();
$insertTrigger = <<< SQL
CREATE TRIGGER %s
AFTER INSERT ON ${dbPrefix}categories
FOR EACH ROW
BEGIN
$triggerBody
END;
SQL;
$updateTrigger = <<< SQL
CREATE TRIGGER %s
AFTER UPDATE ON ${dbPrefix}categories
FOR EACH ROW
BEGIN
$triggerBody
END;
SQL;
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_INSERT));
DB::unprepared(sprintf($insertTrigger, self::TRIGGER_NAME_INSERT));
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_UPDATE));
DB::unprepared(sprintf($updateTrigger, self::TRIGGER_NAME_UPDATE));
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_INSERT));
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_UPDATE));
}
/**
* Returns trigger body as string
*
* @return string
*/
private function getTriggerBody(): string
{
$dbPrefix = DB::getTablePrefix();
return <<< SQL
DECLARE urlPath VARCHAR(255);
DECLARE localeCode VARCHAR(255);
DECLARE done INT;
DECLARE curs CURSOR FOR (SELECT ${dbPrefix}category_translations.locale
FROM ${dbPrefix}category_translations
WHERE category_id = NEW.id);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
IF EXISTS (
SELECT *
FROM ${dbPrefix}category_translations
WHERE category_id = NEW.id
)
THEN
OPEN curs;
SET done = 0;
REPEAT
FETCH curs INTO localeCode;
SELECT get_url_path_of_category(NEW.id, localeCode) INTO urlPath;
UPDATE ${dbPrefix}category_translations
SET url_path = urlPath
WHERE ${dbPrefix}category_translations.category_id = NEW.id;
UNTIL done END REPEAT;
CLOSE curs;
END IF;
SQL;
}
}

View File

@ -0,0 +1,115 @@
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
class AlterTriggerCategoryTranslations extends Migration
{
private const TRIGGER_NAME_INSERT = 'trig_category_translations_insert';
private const TRIGGER_NAME_UPDATE = 'trig_category_translations_update';
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$triggerBody = $this->getTriggerBody();
$dbPrefix = DB::getTablePrefix();
$insertTrigger = <<< SQL
CREATE TRIGGER %s
BEFORE INSERT ON ${dbPrefix}category_translations
FOR EACH ROW
BEGIN
$triggerBody
END;
SQL;
$updateTrigger = <<< SQL
CREATE TRIGGER %s
BEFORE UPDATE ON ${dbPrefix}category_translations
FOR EACH ROW
BEGIN
$triggerBody
END;
SQL;
$this->dropTriggers();
DB::unprepared(sprintf($insertTrigger, self::TRIGGER_NAME_INSERT));
DB::unprepared(sprintf($updateTrigger, self::TRIGGER_NAME_UPDATE));
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
$this->dropTriggers();
}
/**
* Drop the triggers
*/
private function dropTriggers()
{
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_INSERT));
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_UPDATE));
}
/**
* Returns trigger body as string
*
* @return string
*/
private function getTriggerBody()
{
$dbPrefix = DB::getTablePrefix();
return <<<SQL
DECLARE parentUrlPath varchar(255);
DECLARE urlPath varchar(255);
IF NOT EXISTS (
SELECT id
FROM ${dbPrefix}categories
WHERE
id = NEW.category_id
AND parent_id IS NULL
)
THEN
SELECT
GROUP_CONCAT(parent_translations.slug SEPARATOR '/') INTO parentUrlPath
FROM
${dbPrefix}categories AS node,
${dbPrefix}categories AS parent
JOIN ${dbPrefix}category_translations AS parent_translations ON parent.id = parent_translations.category_id
WHERE
node._lft >= parent._lft
AND node._rgt <= parent._rgt
AND node.id = (SELECT parent_id FROM ${dbPrefix}categories WHERE id = NEW.category_id)
AND node.parent_id IS NOT NULL
AND parent.parent_id IS NOT NULL
AND parent_translations.locale = NEW.locale
GROUP BY
node.id;
IF parentUrlPath IS NULL
THEN
SET urlPath = NEW.slug;
ELSE
SET urlPath = concat(parentUrlPath, '/', NEW.slug);
END IF;
SET NEW.url_path = urlPath;
END IF;
SQL;
}
}

View File

@ -0,0 +1,77 @@
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
class AlterStoredFunctionUrlPathCategory extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$dbPrefix = DB::getTablePrefix();
$functionSQL = <<< SQL
DROP FUNCTION IF EXISTS `get_url_path_of_category`;
CREATE FUNCTION get_url_path_of_category(
categoryId INT,
localeCode VARCHAR(255)
)
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE urlPath VARCHAR(255);
IF NOT EXISTS (
SELECT id
FROM ${dbPrefix}categories
WHERE
id = categoryId
AND parent_id IS NULL
)
THEN
SELECT
GROUP_CONCAT(parent_translations.slug SEPARATOR '/') INTO urlPath
FROM
${dbPrefix}categories AS node,
${dbPrefix}categories AS parent
JOIN ${dbPrefix}category_translations AS parent_translations ON parent.id = parent_translations.category_id
WHERE
node._lft >= parent._lft
AND node._rgt <= parent._rgt
AND node.id = categoryId
AND node.parent_id IS NOT NULL
AND parent.parent_id IS NOT NULL
AND parent_translations.locale = localeCode
GROUP BY
node.id;
IF urlPath IS NULL
THEN
SET urlPath = (SELECT slug FROM ${dbPrefix}category_translations WHERE ${dbPrefix}category_translations.category_id = categoryId);
END IF;
ELSE
SET urlPath = '';
END IF;
RETURN urlPath;
END;
SQL;
DB::unprepared($functionSQL);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
DB::unprepared('DROP FUNCTION IF EXISTS `get_url_path_of_category`;');
}
}

View File

@ -0,0 +1,117 @@
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AlterTriggerOnCategories extends Migration
{
private const TRIGGER_NAME_INSERT = 'trig_categories_insert';
private const TRIGGER_NAME_UPDATE = 'trig_categories_update';
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$triggerBody = $this->getTriggerBody();
$dbPrefix = DB::getTablePrefix();
$insertTrigger = <<< SQL
CREATE TRIGGER %s
AFTER INSERT ON ${dbPrefix}categories
FOR EACH ROW
BEGIN
$triggerBody
END;
SQL;
$updateTrigger = <<< SQL
CREATE TRIGGER %s
AFTER UPDATE ON ${dbPrefix}categories
FOR EACH ROW
BEGIN
$triggerBody
END;
SQL;
$this->dropTriggers();
DB::unprepared(sprintf($insertTrigger, self::TRIGGER_NAME_INSERT));
DB::unprepared(sprintf($updateTrigger, self::TRIGGER_NAME_UPDATE));
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
$this->dropTriggers();
}
private function dropTriggers()
{
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_INSERT));
DB::unprepared(sprintf('DROP TRIGGER IF EXISTS %s;', self::TRIGGER_NAME_UPDATE));
}
/**
* Returns trigger body as string
*
* @return string
*/
private function getTriggerBody(): string
{
$dbPrefix = DB::getTablePrefix();
return <<< SQL
DECLARE urlPath VARCHAR(255);
DECLARE localeCode VARCHAR(255);
DECLARE done INT;
DECLARE curs CURSOR FOR (SELECT ${dbPrefix}category_translations.locale
FROM ${dbPrefix}category_translations
WHERE category_id = NEW.id);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
IF EXISTS (
SELECT *
FROM ${dbPrefix}category_translations
WHERE category_id = NEW.id
)
THEN
OPEN curs;
SET done = 0;
REPEAT
FETCH curs INTO localeCode;
SELECT get_url_path_of_category(NEW.id, localeCode) INTO urlPath;
IF NEW.parent_id IS NULL
THEN
SET urlPath = '';
END IF;
UPDATE ${dbPrefix}category_translations
SET url_path = urlPath
WHERE
${dbPrefix}category_translations.category_id = NEW.id
AND ${dbPrefix}category_translations.locale = localeCode;
UNTIL done END REPEAT;
CLOSE curs;
END IF;
SQL;
}
}

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateJobsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('jobs');
}
}

View File

@ -392,51 +392,136 @@ return [
'route' => 'admin.tax-rates.delete',
'sort' => 3,
], [
'key' => 'promotions',
'key' => 'marketing',
'name' => 'admin::app.acl.marketing',
'route' => 'admin.cart-rules.index',
'sort' => 7,
], [
'key' => 'marketing.promotions',
'name' => 'admin::app.acl.promotions',
'route' => 'admin.cart-rules.index',
'sort' => 7,
], [
'key' => 'promotions.cart-rules',
'key' => 'marketing.promotions.cart-rules',
'name' => 'admin::app.acl.cart-rules',
'route' => 'admin.cart-rules.index',
'sort' => 1,
], [
'key' => 'promotions.cart-rules.create',
'key' => 'marketing.promotions.cart-rules.create',
'name' => 'admin::app.acl.create',
'route' => 'admin.cart-rules.create',
'sort' => 1,
], [
'key' => 'promotions.cart-rules.edit',
'key' => 'marketing.promotions.cart-rules.edit',
'name' => 'admin::app.acl.edit',
'route' => 'admin.cart-rules.edit',
'sort' => 2,
], [
'key' => 'promotions.cart-rules.delete',
'key' => 'marketing.promotions.cart-rules.delete',
'name' => 'admin::app.acl.delete',
'route' => 'admin.cart-rules.delete',
'sort' => 3,
], [
'key' => 'promotions.catalog-rules',
'key' => 'marketing.promotions.catalog-rules',
'name' => 'admin::app.acl.catalog-rules',
'route' => 'admin.catalog-rules.index',
'sort' => 1,
], [
'key' => 'promotions.catalog-rules.create',
'key' => 'marketing.promotions.catalog-rules.create',
'name' => 'admin::app.acl.create',
'route' => 'admin.catalog-rules.index',
'sort' => 1,
], [
'key' => 'promotions.catalog-rules.edit',
'key' => 'marketing.promotions.catalog-rules.edit',
'name' => 'admin::app.acl.edit',
'route' => 'admin.catalog-rules.edit',
'sort' => 2,
], [
'key' => 'promotions.catalog-rules.delete',
'key' => 'marketing.promotions.catalog-rules.delete',
'name' => 'admin::app.acl.delete',
'route' => 'admin.catalog-rules.delete',
'sort' => 3,
],
], [
'key' => 'marketing.email-marketing',
'name' => 'admin::app.acl.email-marketing',
'route' => 'admin.email-templates.index',
'sort' => 7,
], [
'key' => 'marketing.email-marketing.email-templates',
'name' => 'admin::app.acl.email-templates',
'route' => 'admin.email-templates.index',
'sort' => 1,
], [
'key' => 'marketing.email-marketing.email-templates.create',
'name' => 'admin::app.acl.create',
'route' => 'admin.email-templates.create',
'sort' => 1,
], [
'key' => 'marketing.email-marketing.email-templates.edit',
'name' => 'admin::app.acl.edit',
'route' => 'admin.email-templates.edit',
'sort' => 2,
], [
'key' => 'marketing.email-marketing.email-templates.delete',
'name' => 'admin::app.acl.delete',
'route' => 'admin.email-templates.delete',
'sort' => 3,
], [
'key' => 'marketing.email-marketing.events',
'name' => 'admin::app.acl.events',
'route' => 'admin.events.index',
'sort' => 1,
], [
'key' => 'marketing.email-marketing.events.create',
'name' => 'admin::app.acl.create',
'route' => 'admin.events.create',
'sort' => 1,
], [
'key' => 'marketing.email-marketing.events.edit',
'name' => 'admin::app.acl.edit',
'route' => 'admin.events.edit',
'sort' => 2,
], [
'key' => 'marketing.email-marketing.events.delete',
'name' => 'admin::app.acl.delete',
'route' => 'admin.events.delete',
'sort' => 3,
], [
'key' => 'marketing.email-marketing.campaigns',
'name' => 'admin::app.acl.campaigns',
'route' => 'admin.campaigns.index',
'sort' => 1,
], [
'key' => 'marketing.email-marketing.campaigns.create',
'name' => 'admin::app.acl.create',
'route' => 'admin.campaigns.create',
'sort' => 1,
], [
'key' => 'marketing.email-marketing.campaigns.edit',
'name' => 'admin::app.acl.edit',
'route' => 'admin.campaigns.edit',
'sort' => 2,
], [
'key' => 'marketing.email-marketing.campaigns.delete',
'name' => 'admin::app.acl.delete',
'route' => 'admin.campaigns.delete',
'sort' => 3,
], [
'key' => 'marketing.email-marketing.subscribers',
'name' => 'admin::app.acl.subscribers',
'route' => 'admin.subscribers.index',
'sort' => 1,
], [
'key' => 'marketing.email-marketing.subscribers.edit',
'name' => 'admin::app.acl.edit',
'route' => 'admin.subscribers.edit',
'sort' => 2,
], [
'key' => 'marketing.email-marketing.subscribers.delete',
'name' => 'admin::app.acl.delete',
'route' => 'admin.subscribers.delete',
'sort' => 3,
]
];
?>

View File

@ -91,12 +91,6 @@ return [
'route' => 'admin.customer.review.index',
'sort' => 3,
'icon-class' => '',
], [
'key' => 'customers.subscribers',
'name' => 'admin::app.layouts.newsletter-subscriptions',
'route' => 'admin.customers.subscribers.index',
'sort' => 4,
'icon-class' => '',
], [
'key' => 'configuration',
'name' => 'admin::app.layouts.configure',
@ -182,23 +176,59 @@ return [
'sort' => 2,
'icon-class' => '',
], [
'key' => 'promotions',
'name' => 'admin::app.layouts.promotions',
'key' => 'marketing',
'name' => 'admin::app.layouts.marketing',
'route' => 'admin.catalog-rules.index',
'sort' => 5,
'icon-class' => 'promotion-icon',
], [
'key' => 'promotions.catalog-rules',
'key' => 'marketing.promotions',
'name' => 'admin::app.layouts.promotions',
'route' => 'admin.catalog-rules.index',
'sort' => 1,
'icon-class' => '',
], [
'key' => 'marketing.promotions.catalog-rules',
'name' => 'admin::app.promotions.catalog-rules.title',
'route' => 'admin.catalog-rules.index',
'sort' => 1,
'icon-class' => '',
], [
'key' => 'promotions.cart-rules',
'key' => 'marketing.promotions.cart-rules',
'name' => 'admin::app.promotions.cart-rules.title',
'route' => 'admin.cart-rules.index',
'sort' => 2,
'icon-class' => '',
], [
'key' => 'marketing.email-marketing',
'name' => 'admin::app.layouts.email-marketing',
'route' => 'admin.email-templates.index',
'sort' => 2,
'icon-class' => '',
], [
'key' => 'marketing.email-marketing.email-templates',
'name' => 'admin::app.layouts.email-templates',
'route' => 'admin.email-templates.index',
'sort' => 1,
'icon-class' => '',
], [
'key' => 'marketing.email-marketing.events',
'name' => 'admin::app.layouts.events',
'route' => 'admin.events.index',
'sort' => 2,
'icon-class' => '',
], [
'key' => 'marketing.email-marketing.campaigns',
'name' => 'admin::app.layouts.campaigns',
'route' => 'admin.campaigns.index',
'sort' => 2,
'icon-class' => '',
], [
'key' => 'marketing.email-marketing.subscribers',
'name' => 'admin::app.layouts.newsletter-subscriptions',
'route' => 'admin.customers.subscribers.index',
'sort' => 3,
'icon-class' => '',
], [
'key' => 'cms',
'name' => 'admin::app.layouts.cms',

View File

@ -17,6 +17,10 @@ class AttributeDataGrid extends DataGrid
->select('id')
->addSelect('id', 'code', 'admin_name', 'type', 'is_required', 'is_unique', 'value_per_locale', 'value_per_channel');
$this->addFilter('is_unique', 'is_unique');
$this->addFilter('value_per_locale', 'value_per_locale');
$this->addFilter('value_per_channel', 'value_per_channel');
$this->setQueryBuilder($queryBuilder);
}

View File

@ -0,0 +1,86 @@
<?php
namespace Webkul\Admin\DataGrids;
use Illuminate\Support\Facades\DB;
use Webkul\Ui\DataGrid\DataGrid;
class CampaignDataGrid extends DataGrid
{
protected $index = 'id';
protected $sortOrder = 'desc';
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('marketing_campaigns')->addSelect('id', 'name', 'subject', 'status');
$this->addFilter('status', 'marketing_campaigns.status');
$this->setQueryBuilder($queryBuilder);
}
public function addColumns()
{
$this->addColumn([
'index' => 'id',
'label' => trans('admin::app.datagrid.id'),
'type' => 'number',
'searchable' => false,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'name',
'label' => trans('admin::app.datagrid.name'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'subject',
'label' => trans('admin::app.datagrid.subject'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'status',
'label' => trans('admin::app.status'),
'type' => 'boolean',
'searchable' => true,
'sortable' => true,
'filterable' => true,
'wrapper' => function ($value) {
if ($value->status == 1) {
return trans('admin::app.datagrid.active');
} else {
return trans('admin::app.datagrid.inactive');
}
},
]);
}
public function prepareActions()
{
$this->addAction([
'title' => trans('admin::app.datagrid.edit'),
'method' => 'GET',
'route' => 'admin.campaigns.edit',
'icon' => 'icon pencil-lg-icon',
]);
$this->addAction([
'title' => trans('admin::app.datagrid.delete'),
'method' => 'POST',
'route' => 'admin.campaigns.delete',
'confirm_text' => trans('ui::app.datagrid.massaction.delete', ['resource' => 'Campaign']),
'icon' => 'icon trash-icon',
]);
}
}

View File

@ -62,6 +62,8 @@ class CartRuleDataGrid extends DataGrid
$queryBuilder->where('cart_rule_channels.channel_id', $this->channel);
}
$this->addFilter('status', 'status');
$this->setQueryBuilder($queryBuilder);
}
@ -122,8 +124,10 @@ class CartRuleDataGrid extends DataGrid
'wrapper' => function ($value) {
if ($value->status == 1) {
return trans('admin::app.datagrid.active');
} else {
} else if ($value->status == 0) {
return trans('admin::app.datagrid.inactive');
} else {
return trans('admin::app.datagrid.draft');
}
},
]);

View File

@ -16,6 +16,9 @@ class CatalogRuleDataGrid extends DataGrid
$queryBuilder = DB::table('catalog_rules')
->addSelect('catalog_rules.id', 'name', 'status', 'starts_from', 'ends_till', 'sort_order');
$this->addFilter('status', 'status');
$this->setQueryBuilder($queryBuilder);
}

View File

@ -24,6 +24,7 @@ class CategoryDataGrid extends DataGrid
->groupBy('cat.id');
$this->addFilter('status', 'cat.status');
$this->addFilter('category_id', 'cat.id');
$this->setQueryBuilder($queryBuilder);

View File

@ -24,6 +24,7 @@ class CustomerDataGrid extends DataGrid
$this->addFilter('full_name', DB::raw('CONCAT(' . DB::getTablePrefix() . 'customers.first_name, " ", ' . DB::getTablePrefix() . 'customers.last_name)'));
$this->addFilter('phone', 'customers.phone');
$this->addFilter('gender', 'customers.gender');
$this->addFilter('status', 'status');
$this->setQueryBuilder($queryBuilder);
}

View File

@ -0,0 +1,79 @@
<?php
namespace Webkul\Admin\DataGrids;
use Illuminate\Support\Facades\DB;
use Webkul\Ui\DataGrid\DataGrid;
class EmailTemplateDataGrid extends DataGrid
{
protected $index = 'id';
protected $sortOrder = 'desc';
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('marketing_templates')->addSelect('id', 'name', 'status');
$this->addFilter('status', 'status');
$this->setQueryBuilder($queryBuilder);
}
public function addColumns()
{
$this->addColumn([
'index' => 'id',
'label' => trans('admin::app.datagrid.id'),
'type' => 'number',
'searchable' => false,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'name',
'label' => trans('admin::app.datagrid.name'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'status',
'label' => trans('admin::app.status'),
'type' => 'boolean',
'searchable' => true,
'sortable' => true,
'filterable' => true,
'wrapper' => function ($value) {
if ($value->status == 'active') {
return trans('admin::app.datagrid.active');
} else if ($value->status == 'inactive') {
return trans('admin::app.datagrid.inactive');
} else if ($value->status == 'draft') {
return trans('admin::app.datagrid.draft');
}
},
]);
}
public function prepareActions()
{
$this->addAction([
'title' => trans('admin::app.datagrid.edit'),
'method' => 'GET',
'route' => 'admin.email-templates.edit',
'icon' => 'icon pencil-lg-icon',
]);
$this->addAction([
'title' => trans('admin::app.datagrid.delete'),
'method' => 'POST',
'route' => 'admin.email-templates.delete',
'confirm_text' => trans('ui::app.datagrid.massaction.delete', ['resource' => 'Email Template']),
'icon' => 'icon trash-icon',
]);
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace Webkul\Admin\DataGrids;
use Illuminate\Support\Facades\DB;
use Webkul\Ui\DataGrid\DataGrid;
class EventDataGrid extends DataGrid
{
protected $index = 'id';
protected $sortOrder = 'desc';
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('marketing_events')->addSelect('id', 'name', 'date');
$this->setQueryBuilder($queryBuilder);
}
public function addColumns()
{
$this->addColumn([
'index' => 'id',
'label' => trans('admin::app.datagrid.id'),
'type' => 'number',
'searchable' => false,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'name',
'label' => trans('admin::app.datagrid.name'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'date',
'label' => trans('admin::app.datagrid.date'),
'type' => 'datetime',
'searchable' => true,
'sortable' => true,
'filterable' => true,
]);
}
public function prepareActions()
{
$this->addAction([
'title' => trans('admin::app.datagrid.edit'),
'method' => 'GET',
'route' => 'admin.events.edit',
'icon' => 'icon pencil-lg-icon',
]);
$this->addAction([
'title' => trans('admin::app.datagrid.delete'),
'method' => 'POST',
'route' => 'admin.events.delete',
'confirm_text' => trans('ui::app.datagrid.massaction.delete', ['resource' => 'Event']),
'icon' => 'icon trash-icon',
]);
}
}

View File

@ -15,6 +15,8 @@ class InventorySourcesDataGrid extends DataGrid
{
$queryBuilder = DB::table('inventory_sources')->addSelect('id', 'code', 'name', 'priority', 'status');
$this->addFilter('status', 'status');
$this->setQueryBuilder($queryBuilder);
}

View File

@ -20,6 +20,7 @@ class UserDataGrid extends DataGrid
$this->addFilter('user_id', 'u.id');
$this->addFilter('user_name', 'u.name');
$this->addFilter('role_name', 'ro.name');
$this->addFilter('status', 'u.status');
$this->setQueryBuilder($queryBuilder);
}

View File

@ -124,7 +124,7 @@ class CustomerGroupController extends Controller
if ($customerGroup->is_user_defined == 0) {
session()->flash('warning', trans('admin::app.customers.customers.group-default'));
} elseif (count($customerGroup->customer) > 0) {
} elseif (count($customerGroup->customers) > 0) {
session()->flash('warning', trans('admin::app.response.customer-associate', ['name' => 'Customer Group']));
} else {
try {

View File

@ -2,10 +2,10 @@
namespace Webkul\Admin\Http\Controllers\Sales;
use PDF;
use Webkul\Admin\Http\Controllers\Controller;
use Webkul\Sales\Repositories\OrderRepository;
use Webkul\Sales\Repositories\InvoiceRepository;
use PDF;
class InvoiceController extends Controller
{
@ -141,8 +141,30 @@ class InvoiceController extends Controller
{
$invoice = $this->invoiceRepository->findOrFail($id);
$pdf = PDF::loadView('admin::sales.invoices.pdf', compact('invoice'))->setPaper('a4');
$html = view('admin::sales.invoices.pdf', compact('invoice'))->render();
return $pdf->download('invoice-' . $invoice->created_at->format('d-m-Y') . '.pdf');
return PDF::loadHTML($this->adjustArabicAndPersianContent($html))
->setPaper('a4')
->download('invoice-' . $invoice->created_at->format('d-m-Y') . '.pdf');
}
/**
* Adjust arabic and persian content.
*
* @param string $html
* @return string
*/
private function adjustArabicAndPersianContent($html)
{
$arabic = new \ArPHP\I18N\Arabic();
$p = $arabic->arIdentify($html);
for ($i = count($p)-1; $i >= 0; $i -= 2) {
$utf8ar = $arabic->utf8Glyphs(substr($html, $p[$i-1], $p[$i] - $p[$i-1]));
$html = substr_replace($html, $utf8ar, $p[$i-1], $p[$i] - $p[$i-1]);
}
return $html;
}
}

View File

@ -583,23 +583,6 @@ Route::group(['middleware' => ['web', 'admin_locale']], function () {
Route::put('/account', 'Webkul\User\Http\Controllers\AccountController@update')->name('admin.account.update');
// Admin Store Front Settings Route
Route::get('/subscribers', 'Webkul\Core\Http\Controllers\SubscriptionController@index')->defaults('_config', [
'view' => 'admin::customers.subscribers.index',
])->name('admin.customers.subscribers.index');
//destroy a newsletter subscription item
Route::post('subscribers/delete/{id}', 'Webkul\Core\Http\Controllers\SubscriptionController@destroy')->name('admin.customers.subscribers.delete');
Route::get('subscribers/edit/{id}', 'Webkul\Core\Http\Controllers\SubscriptionController@edit')->defaults('_config', [
'view' => 'admin::customers.subscribers.edit',
])->name('admin.customers.subscribers.edit');
Route::put('subscribers/update/{id}', 'Webkul\Core\Http\Controllers\SubscriptionController@update')->defaults('_config', [
'redirect' => 'admin.customers.subscribers.index',
])->name('admin.customers.subscribers.update');
//slider index
Route::get('/slider', 'Webkul\Core\Http\Controllers\SliderController@index')->defaults('_config', [
'view' => 'admin::settings.sliders.index',
@ -688,11 +671,11 @@ Route::group(['middleware' => ['web', 'admin_locale']], function () {
Route::prefix('promotions')->group(function () {
Route::get('cart-rules', 'Webkul\CartRule\Http\Controllers\CartRuleController@index')->defaults('_config', [
'view' => 'admin::promotions.cart-rules.index',
'view' => 'admin::marketing.promotions.cart-rules.index',
])->name('admin.cart-rules.index');
Route::get('cart-rules/create', 'Webkul\CartRule\Http\Controllers\CartRuleController@create')->defaults('_config', [
'view' => 'admin::promotions.cart-rules.create',
'view' => 'admin::marketing.promotions.cart-rules.create',
])->name('admin.cart-rules.create');
Route::post('cart-rules/create', 'Webkul\CartRule\Http\Controllers\CartRuleController@store')->defaults('_config', [
@ -700,11 +683,11 @@ Route::group(['middleware' => ['web', 'admin_locale']], function () {
])->name('admin.cart-rules.store');
Route::get('cart-rules/copy/{id}', 'Webkul\CartRule\Http\Controllers\CartRuleController@copy')->defaults('_config', [
'view' => 'admin::promotions.cart-rules.edit',
'view' => 'admin::marketing.promotions.cart-rules.edit',
])->name('admin.cart-rules.copy');
Route::get('cart-rules/edit/{id}', 'Webkul\CartRule\Http\Controllers\CartRuleController@edit')->defaults('_config', [
'view' => 'admin::promotions.cart-rules.edit',
'view' => 'admin::marketing.promotions.cart-rules.edit',
])->name('admin.cart-rules.edit');
Route::post('cart-rules/edit/{id}', 'Webkul\CartRule\Http\Controllers\CartRuleController@update')->defaults('_config', [
@ -720,11 +703,11 @@ Route::group(['middleware' => ['web', 'admin_locale']], function () {
//Catalog rules
Route::get('catalog-rules', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@index')->defaults('_config', [
'view' => 'admin::promotions.catalog-rules.index',
'view' => 'admin::marketing.promotions.catalog-rules.index',
])->name('admin.catalog-rules.index');
Route::get('catalog-rules/create', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@create')->defaults('_config', [
'view' => 'admin::promotions.catalog-rules.create',
'view' => 'admin::marketing.promotions.catalog-rules.create',
])->name('admin.catalog-rules.create');
Route::post('catalog-rules/create', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@store')->defaults('_config', [
@ -732,7 +715,7 @@ Route::group(['middleware' => ['web', 'admin_locale']], function () {
])->name('admin.catalog-rules.store');
Route::get('catalog-rules/edit/{id}', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@edit')->defaults('_config', [
'view' => 'admin::promotions.catalog-rules.edit',
'view' => 'admin::marketing.promotions.catalog-rules.edit',
])->name('admin.catalog-rules.edit');
Route::post('catalog-rules/edit/{id}', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@update')->defaults('_config', [
@ -740,6 +723,95 @@ Route::group(['middleware' => ['web', 'admin_locale']], function () {
])->name('admin.catalog-rules.update');
Route::post('catalog-rules/delete/{id}', 'Webkul\CatalogRule\Http\Controllers\CatalogRuleController@destroy')->name('admin.catalog-rules.delete');
//Marketing campaigns routes
Route::get('campaigns', 'Webkul\Marketing\Http\Controllers\CampaignController@index')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.campaigns.index',
])->name('admin.campaigns.index');
Route::get('campaigns/create', 'Webkul\Marketing\Http\Controllers\CampaignController@create')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.campaigns.create',
])->name('admin.campaigns.create');
Route::post('campaigns/create', 'Webkul\Marketing\Http\Controllers\CampaignController@store')->defaults('_config', [
'redirect' => 'admin.campaigns.index',
])->name('admin.campaigns.store');
Route::get('campaigns/edit/{id}', 'Webkul\Marketing\Http\Controllers\CampaignController@edit')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.campaigns.edit',
])->name('admin.campaigns.edit');
Route::post('campaigns/edit/{id}', 'Webkul\Marketing\Http\Controllers\CampaignController@update')->defaults('_config', [
'redirect' => 'admin.campaigns.index',
])->name('admin.campaigns.update');
Route::post('campaigns/delete/{id}', 'Webkul\Marketing\Http\Controllers\CampaignController@destroy')->name('admin.campaigns.delete');
//Marketing emails templates routes
Route::get('email-templates', 'Webkul\Marketing\Http\Controllers\TemplateController@index')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.templates.index',
])->name('admin.email-templates.index');
Route::get('email-templates/create', 'Webkul\Marketing\Http\Controllers\TemplateController@create')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.templates.create',
])->name('admin.email-templates.create');
Route::post('email-templates/create', 'Webkul\Marketing\Http\Controllers\TemplateController@store')->defaults('_config', [
'redirect' => 'admin.email-templates.index',
])->name('admin.email-templates.store');
Route::get('email-templates/edit/{id}', 'Webkul\Marketing\Http\Controllers\TemplateController@edit')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.templates.edit',
])->name('admin.email-templates.edit');
Route::post('email-templates/edit/{id}', 'Webkul\Marketing\Http\Controllers\TemplateController@update')->defaults('_config', [
'redirect' => 'admin.email-templates.index',
])->name('admin.email-templates.update');
Route::post('email-templates/delete/{id}', 'Webkul\Marketing\Http\Controllers\TemplateController@destroy')->name('admin.email-templates.delete');
//Marketing events routes
Route::get('events', 'Webkul\Marketing\Http\Controllers\EventController@index')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.events.index',
])->name('admin.events.index');
Route::get('events/create', 'Webkul\Marketing\Http\Controllers\EventController@create')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.events.create',
])->name('admin.events.create');
Route::post('events/create', 'Webkul\Marketing\Http\Controllers\EventController@store')->defaults('_config', [
'redirect' => 'admin.events.index',
])->name('admin.events.store');
Route::get('events/edit/{id}', 'Webkul\Marketing\Http\Controllers\EventController@edit')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.events.edit',
])->name('admin.events.edit');
Route::post('events/edit/{id}', 'Webkul\Marketing\Http\Controllers\EventController@update')->defaults('_config', [
'redirect' => 'admin.events.index',
])->name('admin.events.update');
Route::post('events/delete/{id}', 'Webkul\Marketing\Http\Controllers\EventController@destroy')->name('admin.events.delete');
// Admin Store Front Settings Route
Route::get('/subscribers', 'Webkul\Core\Http\Controllers\SubscriptionController@index')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.subscribers.index',
])->name('admin.customers.subscribers.index');
//destroy a newsletter subscription item
Route::post('subscribers/delete/{id}', 'Webkul\Core\Http\Controllers\SubscriptionController@destroy')->name('admin.customers.subscribers.delete');
Route::get('subscribers/edit/{id}', 'Webkul\Core\Http\Controllers\SubscriptionController@edit')->defaults('_config', [
'view' => 'admin::marketing.email-marketing.subscribers.edit',
])->name('admin.customers.subscribers.edit');
Route::put('subscribers/update/{id}', 'Webkul\Core\Http\Controllers\SubscriptionController@update')->defaults('_config', [
'redirect' => 'admin.customers.subscribers.index',
])->name('admin.customers.subscribers.update');
});
Route::prefix('cms')->group(function () {

View File

@ -35,7 +35,7 @@ class Order
/* email to admin */
$configKey = 'emails.general.notifications.emails.general.notifications.new-admin';
if (core()->getConfigData($configKey)) {
$this->prepareMail(env('APP_LOCALE'), new NewAdminNotification($order));
$this->prepareMail(config('app.locale'), new NewAdminNotification($order));
}
} catch (\Exception $e) {
report($e);
@ -112,7 +112,7 @@ class Order
/* email to admin */
$configKey = 'emails.general.notifications.emails.general.notifications.new-inventory-source';
if (core()->getConfigData($configKey)) {
$this->prepareMail(env('APP_LOCALE'), new NewInventorySourceNotification($shipment));
$this->prepareMail(config('app.locale'), new NewInventorySourceNotification($shipment));
}
} catch (\Exception $e) {
report($e);
@ -137,7 +137,7 @@ class Order
/* email to admin */
$configKey = 'emails.general.notifications.emails.general.notifications.new-admin';
if (core()->getConfigData($configKey)) {
$this->prepareMail(env('APP_LOCALE'), new CancelOrderAdminNotification($order));
$this->prepareMail(config('app.locale'), new CancelOrderAdminNotification($order));
}
} catch (\Exception $e) {
report($e);
@ -189,4 +189,4 @@ class Order
app()->setLocale($locale);
Mail::queue($notification);
}
}
}

View File

@ -75,7 +75,11 @@ return [
'tax-categories' => 'فئات الضرائب',
'tax-rates' => 'المعدلات الضريبية',
'refunds' => 'المبالغ المستردة',
'marketing' => 'Marketing',
'promotions' => 'الترقيات',
'email-marketing' => 'Email Marketing',
'campaigns' => 'Campaigns',
'email-templates' => 'Email Templates',
'discount' => 'خصم',
'cms' => 'CMS'
],
@ -111,6 +115,7 @@ return [
'edit' => 'تعديل',
'create' => 'أضف',
'delete' => 'حذف',
'marketing' => 'Marketing',
'promotions' => 'الترقيات',
'cart-rules' => 'قواعد سلة التسوق',
'catalog-rules' => 'قواعد الكتالوج',
@ -1130,6 +1135,68 @@ return [
]
],
'marketing' => [
'templates' => [
'title' => 'Email Templates',
'add-title' => 'Add Email Template',
'edit-title' => 'Edit Email Template',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'content' => 'Content',
'create-success' => 'Email template created successfully.',
'update-success' => 'Email template updated successfully.',
'delete-success' => 'Email template deleted successfully',
],
'campaigns' => [
'title' => 'Campaigns',
'add-title' => 'Add Campaign',
'edit-title' => 'Edit Campaign',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'subject' => 'Subject',
'email-template' => 'Email Template',
'audience' => 'Audience',
'channel' => 'Channel',
'customer-group' => 'Customer Group',
'schedule' => 'Schedule',
'schedule-type' => 'Schedule Type',
'once' => 'Once',
'events' => 'Events',
'schedule-date' => 'Schedule Date',
'spooling' => 'Spooling',
'event' => 'Event',
'birthday' => 'Birthday',
'create-success' => 'Campaign created successfully.',
'update-success' => 'Campaign updated successfully.',
'delete-success' => 'Campaign deleted successfully',
],
'events' => [
'title' => 'Events',
'add-title' => 'Add Event',
'edit-title' => 'Edit Event',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'description' => 'Description',
'date' => 'Date',
'create-success' => 'Event created successfully.',
'update-success' => 'Event updated successfully.',
'delete-success' => 'Event deleted successfully.',
'edit-error' => 'Can not edit this event.'
]
],
'error' => [
'go-to-home' => 'إذهب إلى البيت',
'in-maitainace' => 'في الصيانة',

View File

@ -72,9 +72,13 @@ return [
'roles' => 'Rollen',
'sliders' => 'Slider',
'taxes' => 'Steuern',
'marketing' => 'Marketing',
'promotions' => 'Promotions',
'email-marketing' => 'Email Marketing',
'campaigns' => 'Campaigns',
'email-templates' => 'Email Templates',
'tax-categories' => 'Steuer-Kategorien',
'tax-rates' => 'Steuersätze',
'promotions' => 'Promotions',
'discount' => 'Rabatt',
'cms' => 'CMS',
],
@ -110,6 +114,7 @@ return [
'edit' => 'Bearbeiten',
'create' => 'Hinzufügen',
'delete' => 'Löschen',
'marketing' => 'Marketing',
'promotions' => 'Promotions',
'cart-rules' => 'Warenkorbregeln',
'catalog-rules' => 'Katalogregeln',
@ -1130,6 +1135,69 @@ return [
'attribute_family' => 'Attributgruppe',
],
],
'marketing' => [
'templates' => [
'title' => 'Email Templates',
'add-title' => 'Add Email Template',
'edit-title' => 'Edit Email Template',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'content' => 'Content',
'create-success' => 'Email template created successfully.',
'update-success' => 'Email template updated successfully.',
'delete-success' => 'Email template deleted successfully',
],
'campaigns' => [
'title' => 'Campaigns',
'add-title' => 'Add Campaign',
'edit-title' => 'Edit Campaign',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'subject' => 'Subject',
'email-template' => 'Email Template',
'audience' => 'Audience',
'channel' => 'Channel',
'customer-group' => 'Customer Group',
'schedule' => 'Schedule',
'schedule-type' => 'Schedule Type',
'once' => 'Once',
'events' => 'Events',
'schedule-date' => 'Schedule Date',
'spooling' => 'Spooling',
'event' => 'Event',
'birthday' => 'Birthday',
'create-success' => 'Campaign created successfully.',
'update-success' => 'Campaign updated successfully.',
'delete-success' => 'Campaign deleted successfully',
],
'events' => [
'title' => 'Events',
'add-title' => 'Add Event',
'edit-title' => 'Edit Event',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'description' => 'Description',
'date' => 'Date',
'create-success' => 'Event created successfully.',
'update-success' => 'Event updated successfully.',
'delete-success' => 'Event deleted successfully.',
'edit-error' => 'Can not edit this event.'
]
],
'error' =>
[
'go-to-home' => 'HOME ÖFFNEN',

View File

@ -75,7 +75,12 @@ return [
'taxes' => 'Taxes',
'tax-categories' => 'Tax Categories',
'tax-rates' => 'Tax Rates',
'marketing' => 'Marketing',
'promotions' => 'Promotions',
'email-marketing' => 'Email Marketing',
'campaigns' => 'Campaigns',
'email-templates' => 'Email Templates',
'events' => 'Events',
'discount' => 'Discount',
'cms' => 'CMS'
],
@ -111,9 +116,15 @@ return [
'edit' => 'Edit',
'create' => 'Add',
'delete' => 'Delete',
'marketing' => 'Marketing',
'promotions' => 'Promotions',
'cart-rules' => 'Cart Rules',
'catalog-rules' => 'Catalog Rules',
'email-marketing' => 'Email Marketing',
'email-templates' => 'Email Templates',
'campaigns' => 'Campaigns',
'subscribers' => 'Newsletter Subscribers',
'events' => 'Events'
],
'dashboard' => [
@ -213,6 +224,7 @@ return [
'end' => 'End',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'true' => 'True',
'false' => 'False',
'approved' => 'Approved',
@ -227,7 +239,9 @@ return [
'view' => 'View',
'rtl' => 'RTL',
'ltr' => 'LTR',
'update-status' => 'Update Status'
'update-status' => 'Update Status',
'subject' => 'Subject',
'date' => 'Date'
],
'account' => [
@ -981,8 +995,8 @@ return [
],
'subscribers' => [
'title' => 'News Letter Subscribers',
'title-edit' => 'Edit News Letter Subscriber',
'title' => 'Newsletter Subscribers',
'title-edit' => 'Edit Newsletter Subscriber',
'email' => 'Email',
'is_subscribed' => 'Subscribed',
'edit-btn-title' => 'Update Subscriber',
@ -1129,6 +1143,68 @@ return [
]
],
'marketing' => [
'templates' => [
'title' => 'Email Templates',
'add-title' => 'Add Email Template',
'edit-title' => 'Edit Email Template',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'content' => 'Content',
'create-success' => 'Email template created successfully.',
'update-success' => 'Email template updated successfully.',
'delete-success' => 'Email template deleted successfully',
],
'campaigns' => [
'title' => 'Campaigns',
'add-title' => 'Add Campaign',
'edit-title' => 'Edit Campaign',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'subject' => 'Subject',
'email-template' => 'Email Template',
'audience' => 'Audience',
'channel' => 'Channel',
'customer-group' => 'Customer Group',
'schedule' => 'Schedule',
'schedule-type' => 'Schedule Type',
'once' => 'Once',
'events' => 'Events',
'schedule-date' => 'Schedule Date',
'spooling' => 'Spooling',
'event' => 'Event',
'birthday' => 'Birthday',
'create-success' => 'Campaign created successfully.',
'update-success' => 'Campaign updated successfully.',
'delete-success' => 'Campaign deleted successfully',
],
'events' => [
'title' => 'Events',
'add-title' => 'Add Event',
'edit-title' => 'Edit Event',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'description' => 'Description',
'date' => 'Date',
'create-success' => 'Event created successfully.',
'update-success' => 'Event updated successfully.',
'delete-success' => 'Event deleted successfully.',
'edit-error' => 'Can not edit this event.'
]
],
'error' => [
'go-to-home' => 'GO TO HOME',
'in-maitainace' => 'In Maintenance',
@ -1302,8 +1378,8 @@ return [
'money-transfer' => 'Money Transfer',
'paypal-standard' => 'PayPal Standard',
'business-account' => 'Business Account',
'newsletter' => 'NewsLetter Subscription',
'newsletter-subscription' => 'Allow NewsLetter Subscription',
'newsletter' => 'Newsletter Subscription',
'newsletter-subscription' => 'Allow Newsletter Subscription',
'email' => 'Email Verification',
'email-verification' => 'Allow Email Verification',
'sort_order' => 'Sort Order',

View File

@ -73,7 +73,11 @@ return [
'taxes' => 'Impuestos',
'tax-categories' => 'Categorías de impuestos',
'tax-rates' => 'Tasas de impuestos',
'marketing' => 'Marketing',
'promotions' => 'Promociones',
'email-marketing' => 'Email Marketing',
'campaigns' => 'Campaigns',
'email-templates' => 'Email Templates',
'discount' => 'Descuento',
'cms' => 'CMS'
],
@ -109,6 +113,7 @@ return [
'edit' => 'Editar',
'create' => 'Agregar',
'delete' => 'Borrar',
'marketing' => 'Marketing',
'promotions' => 'Promociones',
'cart-rules' => 'Reglas del carrito',
'catalog-rules' => 'Reglas del catálogo',
@ -1122,6 +1127,68 @@ return [
]
],
'marketing' => [
'templates' => [
'title' => 'Email Templates',
'add-title' => 'Add Email Template',
'edit-title' => 'Edit Email Template',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'content' => 'Content',
'create-success' => 'Email template created successfully.',
'update-success' => 'Email template updated successfully.',
'delete-success' => 'Email template deleted successfully',
],
'campaigns' => [
'title' => 'Campaigns',
'add-title' => 'Add Campaign',
'edit-title' => 'Edit Campaign',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'subject' => 'Subject',
'email-template' => 'Email Template',
'audience' => 'Audience',
'channel' => 'Channel',
'customer-group' => 'Customer Group',
'schedule' => 'Schedule',
'schedule-type' => 'Schedule Type',
'once' => 'Once',
'events' => 'Events',
'schedule-date' => 'Schedule Date',
'spooling' => 'Spooling',
'event' => 'Event',
'birthday' => 'Birthday',
'create-success' => 'Campaign created successfully.',
'update-success' => 'Campaign updated successfully.',
'delete-success' => 'Campaign deleted successfully',
],
'events' => [
'title' => 'Events',
'add-title' => 'Add Event',
'edit-title' => 'Edit Event',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'description' => 'Description',
'date' => 'Date',
'create-success' => 'Event created successfully.',
'update-success' => 'Event updated successfully.',
'delete-success' => 'Event deleted successfully.',
'edit-error' => 'Can not edit this event.'
]
],
'error' => [
'go-to-home' => 'REGRESAR AL INICIO',
'in-maitainace' => 'En mantenimiento',

View File

@ -74,7 +74,11 @@ return [
'taxes' => 'مالیات',
'tax-categories' => 'دسته بندی مالیات',
'tax-rates' => 'نرخ مالیات',
'promotion' => 'تبلیغات',
'marketing' => 'Marketing',
'promotions' => 'تبلیغات',
'email-marketing' => 'Email Marketing',
'campaigns' => 'Campaigns',
'email-templates' => 'Email Templates',
'discount' => 'تخفیف',
'cms' => 'CMS'
],
@ -110,7 +114,8 @@ return [
'edit' => 'ویاریش',
'create' => 'افزودن',
'delete' => 'حذف',
'promotion' => 'تبلیغات',
'marketing' => 'Marketing',
'promotions' => 'تبلیغات',
'cart-rules' => 'قوانین سبد خرید',
'catalog-rules' => 'قوانین فهرست',
],
@ -992,7 +997,7 @@ return [
]
],
'promotion' => [
'promotions' => [
'cart-rules' => [
'title' => 'قوانین سبد خرید',
'add-title' => 'قانون سبد خرید را اضافه کنید',
@ -1128,6 +1133,70 @@ return [
]
],
'marketing' => [
'templates' => [
'title' => 'Email Templates',
'add-title' => 'Add Email Template',
'edit-title' => 'Edit Email Template',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'content' => 'Content',
'create-success' => 'Email template created successfully.',
'update-success' => 'Email template updated successfully.',
'delete-success' => 'Email template deleted successfully',
],
'campaigns' => [
'title' => 'Campaigns',
'add-title' => 'Add Campaign',
'edit-title' => 'Edit Campaign',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'subject' => 'Subject',
'email-template' => 'Email Template',
'audience' => 'Audience',
'channel' => 'Channel',
'customer-group' => 'Customer Group',
'schedule' => 'Schedule',
'schedule-type' => 'Schedule Type',
'once' => 'Once',
'events' => 'Events',
'schedule-date' => 'Schedule Date',
'spooling' => 'Spooling',
'event' => 'Event',
'birthday' => 'Birthday',
'create-success' => 'Campaign created successfully.',
'update-success' => 'Campaign updated successfully.',
'delete-success' => 'Campaign deleted successfully',
],
'events' => [
'title' => 'Events',
'add-title' => 'Add Event',
'edit-title' => 'Edit Event',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'description' => 'Description',
'date' => 'Date',
'create-success' => 'Event created successfully.',
'update-success' => 'Event updated successfully.',
'delete-success' => 'Event deleted successfully.',
'edit-error' => 'Can not edit this event.'
]
],
'error' => [
'go-to-home' => 'رفتن به خانه',
'in-maitainace' => 'در حال تعمیر و نگهداری',

View File

@ -74,7 +74,11 @@ return [
'taxes' => 'IVA',
'tax-categories' => 'Categorie IVA',
'tax-rates' => 'Aliquote IVA',
'marketing' => 'Marketing',
'promotions' => 'Promozioni',
'email-marketing' => 'Email Marketing',
'campaigns' => 'Campaigns',
'email-templates' => 'Email Templates',
'discount' => 'Sconti',
'cms' => 'CMS'
],
@ -110,6 +114,7 @@ return [
'edit' => 'Modifica',
'create' => 'Aggiungi',
'delete' => 'Elimina',
'marketing' => 'Marketing',
'promotions' => 'Promozioni',
'cart-rules' => 'Regole Carrello',
'catalog-rules' => 'Regole Catalogo',
@ -1133,6 +1138,68 @@ return [
]
],
'marketing' => [
'templates' => [
'title' => 'Email Templates',
'add-title' => 'Add Email Template',
'edit-title' => 'Edit Email Template',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'content' => 'Content',
'create-success' => 'Email template created successfully.',
'update-success' => 'Email template updated successfully.',
'delete-success' => 'Email template deleted successfully',
],
'campaigns' => [
'title' => 'Campaigns',
'add-title' => 'Add Campaign',
'edit-title' => 'Edit Campaign',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'subject' => 'Subject',
'email-template' => 'Email Template',
'audience' => 'Audience',
'channel' => 'Channel',
'customer-group' => 'Customer Group',
'schedule' => 'Schedule',
'schedule-type' => 'Schedule Type',
'once' => 'Once',
'events' => 'Events',
'schedule-date' => 'Schedule Date',
'spooling' => 'Spooling',
'event' => 'Event',
'birthday' => 'Birthday',
'create-success' => 'Campaign created successfully.',
'update-success' => 'Campaign updated successfully.',
'delete-success' => 'Campaign deleted successfully',
],
'events' => [
'title' => 'Events',
'add-title' => 'Add Event',
'edit-title' => 'Edit Event',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'description' => 'Description',
'date' => 'Date',
'create-success' => 'Event created successfully.',
'update-success' => 'Event updated successfully.',
'delete-success' => 'Event deleted successfully.',
'edit-error' => 'Can not edit this event.'
]
],
'error' => [
'go-to-home' => 'TORNA A HOME',
'in-maitainace' => 'In Manutezione',

View File

@ -74,7 +74,11 @@ return [
'taxes' => 'BTW',
'tax-categories' => 'BTW-groepen',
'tax-rates' => 'BTW-tarieven',
'marketing' => 'Marketing',
'promotions' => 'Promoties',
'email-marketing' => 'Email Marketing',
'campaigns' => 'Campaigns',
'email-templates' => 'Email Templates',
'discount' => 'Korting',
'cms' => 'CMS'
],
@ -110,6 +114,7 @@ return [
'edit' => 'Edit',
'create' => 'Add',
'delete' => 'Verwijder',
'marketing' => 'Marketing',
'promotions' => 'Promoties',
'cart-rules' => 'Cart Rules',
'catalog-rules' => 'Catalog Rules',
@ -449,7 +454,7 @@ return [
'refunded' => 'Teruggestort',
'date' => 'Refund Date',
'customer-name' => 'klantnaam',
'status' => 'Toestand',
'status' => 'Status',
'action' => 'Actie',
'view-title' => 'Terugbetaling #:refund_id',
'invalid-refund-amount-error' => 'Het restitutiebedrag mag niet nul zijn.'
@ -690,7 +695,7 @@ return [
'save-btn-title' => 'Opslaan',
'description' => 'Description',
'active' => 'Actief',
'status' => 'Toestand'
'status' => 'Status'
]
]
],
@ -964,7 +969,7 @@ return [
'addresses' => 'Addresses',
'mass-destroy-success' => 'Klanten zijn succesvol verwijderd',
'mass-update-success' => 'Klanten succesvol bijgewerkt',
'status' => 'Toestand',
'status' => 'Status',
'active' => 'Actief',
'inactive' => 'Niet geactiveerd'
],
@ -973,7 +978,7 @@ return [
'title' => 'Recensies',
'edit-title' => 'Review bewerken',
'rating' => 'Beoordeling',
'status' => 'Toestand',
'status' => 'Status',
'comment' => 'Commentaar',
'pending' => 'In afwachting',
'approved' => 'Goedkeuren',
@ -1002,7 +1007,7 @@ return [
'rule-information' => 'Regelinformatie',
'name' => 'Naam',
'description' => 'Beschrijving',
'status' => 'Toestand',
'status' => 'Status',
'is-active' => 'Winkelwagenregel is actief',
'channels' => 'Kanalen',
'customer-groups' => 'Klantengroepen',
@ -1088,7 +1093,7 @@ return [
'rule-information' => 'Regelinformatie',
'name' => 'Naam',
'description' => 'Beschrijving',
'status' => 'Toestand',
'status' => 'Status',
'is-active' => 'Catalogusregel is actief',
'channels' => 'Kanalen',
'customer-groups' => 'Klantengroepen',
@ -1129,6 +1134,68 @@ return [
]
],
'marketing' => [
'templates' => [
'title' => 'Email Templates',
'add-title' => 'Add Email Template',
'edit-title' => 'Edit Email Template',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'content' => 'Content',
'create-success' => 'Email template created successfully.',
'update-success' => 'Email template updated successfully.',
'delete-success' => 'Email template deleted successfully',
],
'campaigns' => [
'title' => 'Campaigns',
'add-title' => 'Add Campaign',
'edit-title' => 'Edit Campaign',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'subject' => 'Subject',
'email-template' => 'Email Template',
'audience' => 'Audience',
'channel' => 'Channel',
'customer-group' => 'Customer Group',
'schedule' => 'Schedule',
'schedule-type' => 'Schedule Type',
'once' => 'Once',
'events' => 'Events',
'schedule-date' => 'Schedule Date',
'spooling' => 'Spooling',
'event' => 'Event',
'birthday' => 'Birthday',
'create-success' => 'Campaign created successfully.',
'update-success' => 'Campaign updated successfully.',
'delete-success' => 'Campaign deleted successfully',
],
'events' => [
'title' => 'Events',
'add-title' => 'Add Event',
'edit-title' => 'Edit Event',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'description' => 'Description',
'date' => 'Date',
'create-success' => 'Event created successfully.',
'update-success' => 'Event updated successfully.',
'delete-success' => 'Event deleted successfully.',
'edit-error' => 'Can not edit this event.'
]
],
'error' => [
'go-to-home' => 'GA NAAR HUIS',
'in-maitainace' => 'In onderhoud',
@ -1285,8 +1352,8 @@ return [
'title' => 'Titel',
'description' => 'Omschrijving',
'rate' => 'Tarief',
'status' => 'Toestand',
'calculate-tax' => 'Beregn skat',
'status' => 'Status',
'calculate-tax' => 'BTW berekenen',
'type' => 'Type',
'payment-methods' => 'Betaalmethodes',
'cash-on-delivery' => 'Rembours',

View File

@ -73,7 +73,11 @@ return [
'taxes' => 'Podatki',
'tax-categories' => 'Kategorie podatkowe',
'tax-rates' => 'Stawki podatkowe',
'marketing' => 'Marketing',
'promotions' => 'Promocje',
'email-marketing' => 'Email Marketing',
'campaigns' => 'Campaigns',
'email-templates' => 'Email Templates',
'discount' => 'Rabat',
'cms' => 'System CMS'
],
@ -109,6 +113,7 @@ return [
'edit' => 'Edytuj',
'create' => 'Dodaj',
'delete' => 'Usuń',
'marketing' => 'Marketing',
'promotions' => 'Promocje',
'cart-rules' => 'Zasady koszyka',
'catalog-rules' => 'Zasady katalogu',
@ -1130,6 +1135,68 @@ return [
]
],
'marketing' => [
'templates' => [
'title' => 'Email Templates',
'add-title' => 'Add Email Template',
'edit-title' => 'Edit Email Template',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'content' => 'Content',
'create-success' => 'Email template created successfully.',
'update-success' => 'Email template updated successfully.',
'delete-success' => 'Email template deleted successfully',
],
'campaigns' => [
'title' => 'Campaigns',
'add-title' => 'Add Campaign',
'edit-title' => 'Edit Campaign',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'subject' => 'Subject',
'email-template' => 'Email Template',
'audience' => 'Audience',
'channel' => 'Channel',
'customer-group' => 'Customer Group',
'schedule' => 'Schedule',
'schedule-type' => 'Schedule Type',
'once' => 'Once',
'events' => 'Events',
'schedule-date' => 'Schedule Date',
'spooling' => 'Spooling',
'event' => 'Event',
'birthday' => 'Birthday',
'create-success' => 'Campaign created successfully.',
'update-success' => 'Campaign updated successfully.',
'delete-success' => 'Campaign deleted successfully',
],
'events' => [
'title' => 'Events',
'add-title' => 'Add Event',
'edit-title' => 'Edit Event',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'description' => 'Description',
'date' => 'Date',
'create-success' => 'Event created successfully.',
'update-success' => 'Event updated successfully.',
'delete-success' => 'Event deleted successfully.',
'edit-error' => 'Can not edit this event.'
]
],
'error' => [
'go-to-home' => 'IDŹ DO GŁÓWNEJ',
'in-maitainace' => 'W konserwacji',

View File

@ -74,7 +74,11 @@ return [
'taxes' => 'Impostos',
'tax-categories' => 'Categorias de Impostos',
'tax-rates' => 'Impostos de Impostos',
'promotion' => 'Promoções',
'marketing' => 'Marketing',
'promotions' => 'Promoções',
'email-marketing' => 'Email Marketing',
'campaigns' => 'Campaigns',
'email-templates' => 'Email Templates',
'discount' => 'Desconto',
'cms' => 'CMS'
],
@ -110,6 +114,7 @@ return [
'edit' => 'Edit',
'create' => 'Add',
'delete' => 'Delete',
'marketing' => 'Marketing',
'promotions' => 'Promoções',
'cart-rules' => 'Regras do Carrinho',
'catalog-rules' => 'Regras do Catálogo',
@ -993,7 +998,7 @@ return [
]
],
'promotion' => [
'promotions' => [
'cart-rules' => [
'title' => 'Regras do carrinho',
'add-title' => 'Adicionar regra de carrinho',
@ -1129,6 +1134,68 @@ return [
]
],
'marketing' => [
'templates' => [
'title' => 'Email Templates',
'add-title' => 'Add Email Template',
'edit-title' => 'Edit Email Template',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'content' => 'Content',
'create-success' => 'Email template created successfully.',
'update-success' => 'Email template updated successfully.',
'delete-success' => 'Email template deleted successfully',
],
'campaigns' => [
'title' => 'Campaigns',
'add-title' => 'Add Campaign',
'edit-title' => 'Edit Campaign',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'subject' => 'Subject',
'email-template' => 'Email Template',
'audience' => 'Audience',
'channel' => 'Channel',
'customer-group' => 'Customer Group',
'schedule' => 'Schedule',
'schedule-type' => 'Schedule Type',
'once' => 'Once',
'events' => 'Events',
'schedule-date' => 'Schedule Date',
'spooling' => 'Spooling',
'event' => 'Event',
'birthday' => 'Birthday',
'create-success' => 'Campaign created successfully.',
'update-success' => 'Campaign updated successfully.',
'delete-success' => 'Campaign deleted successfully',
],
'events' => [
'title' => 'Events',
'add-title' => 'Add Event',
'edit-title' => 'Edit Event',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'description' => 'Description',
'date' => 'Date',
'create-success' => 'Event created successfully.',
'update-success' => 'Event updated successfully.',
'delete-success' => 'Event deleted successfully.',
'edit-error' => 'Can not edit this event.'
]
],
'error' => [
'go-to-home' => 'IR PARA PÁGINA INICIAL',
'in-maitainace' => 'Em manutenção',

View File

@ -72,7 +72,11 @@ return [
'taxes' => 'Vergiler',
'tax-categories' => 'Vergi Kategorileri',
'tax-rates' => 'Vergi Oranları',
'marketing' => 'Marketing',
'promotions' => 'Promosyon',
'email-marketing' => 'Email Marketing',
'campaigns' => 'Campaigns',
'email-templates' => 'Email Templates',
'discount' => 'İndirim',
'cms' => 'CMS'
],
@ -108,6 +112,7 @@ return [
'edit' => 'Düzenle',
'create' => 'Oluştur',
'delete' => 'Sil',
'marketing' => 'Marketing',
'promotions' => 'Promosyonlar',
'cart-rules' => 'Alışveriş Sepeti Kuralları',
'catalog-rules' => 'Katalog Kuralları',
@ -1117,6 +1122,68 @@ return [
]
],
'marketing' => [
'templates' => [
'title' => 'Email Templates',
'add-title' => 'Add Email Template',
'edit-title' => 'Edit Email Template',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'draft' => 'Draft',
'content' => 'Content',
'create-success' => 'Email template created successfully.',
'update-success' => 'Email template updated successfully.',
'delete-success' => 'Email template deleted successfully',
],
'campaigns' => [
'title' => 'Campaigns',
'add-title' => 'Add Campaign',
'edit-title' => 'Edit Campaign',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'status' => 'Status',
'active' => 'Active',
'inactive' => 'Inactive',
'subject' => 'Subject',
'email-template' => 'Email Template',
'audience' => 'Audience',
'channel' => 'Channel',
'customer-group' => 'Customer Group',
'schedule' => 'Schedule',
'schedule-type' => 'Schedule Type',
'once' => 'Once',
'events' => 'Events',
'schedule-date' => 'Schedule Date',
'spooling' => 'Spooling',
'event' => 'Event',
'birthday' => 'Birthday',
'create-success' => 'Campaign created successfully.',
'update-success' => 'Campaign updated successfully.',
'delete-success' => 'Campaign deleted successfully',
],
'events' => [
'title' => 'Events',
'add-title' => 'Add Event',
'edit-title' => 'Edit Event',
'save-btn-title' => 'Save',
'general' => 'General',
'name' => 'Name',
'description' => 'Description',
'date' => 'Date',
'create-success' => 'Event created successfully.',
'update-success' => 'Event updated successfully.',
'delete-success' => 'Event deleted successfully.',
'edit-error' => 'Can not edit this event.'
]
],
'error' => [
'go-to-home' => 'ANA SAYFAYA GİT',
'in-maitainace' => 'Bakım Modunda',

View File

@ -1,4 +1 @@
<input type="text" v-validate="'{{$validations}}'" class="control" id="{{ $attribute->code }}" name="{{ $attribute->code }}" value="{{ old($attribute->code) ?: $product[$attribute->code] }}" {{ in_array($attribute->code, ['sku', 'url_key']) ? 'v-slugify' : '' }} data-vv-as="&quot;{{ $attribute->admin_name }}&quot;" {{ $attribute->code == 'name' && ! $product[$attribute->code] ? 'v-slugify-target=\'url_key\'' : '' }} />
<input type="text" v-validate="'{{$validations}}'" class="control" id="{{ $attribute->code }}" name="{{ $attribute->code }}" value="{{ old($attribute->code) ?: $product[$attribute->code] }}" {{ in_array($attribute->code, ['sku', 'url_key']) ? 'v-slugify' : '' }} data-vv-as="&quot;{{ $attribute->admin_name }}&quot;" {{ $attribute->code == 'name' && ! $product[$attribute->code] ? 'v-slugify-target=\'url_key\'' : '' }} />

View File

@ -0,0 +1,124 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.marketing.campaigns.add-title') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.campaigns.store') }}" @submit.prevent="onSubmit" enctype="multipart/form-data">
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="window.location = history.length > 1 ? document.referrer : '{{ route('admin.dashboard.index') }}'"></i>
{{ __('admin::app.marketing.campaigns.add-title') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.marketing.campaigns.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
{!! view_render_event('bagisto.admin.marketing.templates.create.before') !!}
<accordian :title="'{{ __('admin::app.marketing.campaigns.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.marketing.campaigns.name') }}</label>
<input v-validate="'required'" class="control" id="name" name="name" value="{{ old('name') }}" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.name') }}&quot;"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
<div class="control-group" :class="[errors.has('subject') ? 'has-error' : '']">
<label for="subject" class="required">{{ __('admin::app.marketing.campaigns.subject') }}</label>
<input v-validate="'required'" class="control" id="subject" name="subject" value="{{ old('subject') }}" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.subject') }}&quot;"/>
<span class="control-error" v-if="errors.has('subject')">@{{ errors.first('subject') }}</span>
</div>
<div class="control-group" :class="[errors.has('marketing_event_id') ? 'has-error' : '']">
<label for="event" class="required">{{ __('admin::app.marketing.campaigns.event') }}</label>
<select class="control" v-validate="'required'" id="marketing_event_id" name="marketing_event_id" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.event') }}&quot;">
@foreach (app('Webkul\Marketing\Repositories\EventRepository')->all() as $event)
<option value="{{ $event->id }}" {{ old('marketing_event_id') == $event->id ? 'selected' : '' }}>
{{ $event->name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('marketing_event_id')">@{{ errors.first('marketing_event_id') }}</span>
</div>
<div class="control-group" :class="[errors.has('marketing_template_id') ? 'has-error' : '']">
<label for="marketing_template_id" class="required">{{ __('admin::app.marketing.campaigns.email-template') }}</label>
<select v-validate="'required'" class="control" id="marketing_template_id" name="marketing_template_id" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.email-template') }}&quot;">
@foreach (app('Webkul\Marketing\Repositories\TemplateRepository')->all() as $template)
<option value="{{ $template->id }}" {{ old('marketing_template_id') == $template->id ? 'selected' : '' }}>
{{ $template->name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('marketing_template_id')">@{{ errors.first('marketing_template_id') }}</span>
</div>
<div class="control-group" :class="[errors.has('status') ? 'has-error' : '']">
<label for="status" class="required">{{ __('admin::app.marketing.campaigns.status') }}</label>
<select class="control" v-validate="'required'" id="status" name="status" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.display-mode') }}&quot;">
<option value="0" {{ old('status') == 0 ? 'selected' : '' }}>
{{ __('admin::app.marketing.campaigns.inactive') }}
</option>
<option value="1" {{ old('status') == 1 ? 'selected' : '' }}>
{{ __('admin::app.marketing.campaigns.active') }}
</option>
</select>
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
</div>
</div>
</accordian>
<accordian :title="'{{ __('admin::app.marketing.campaigns.audience') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('channel_id') ? 'has-error' : '']">
<label for="channel_id" class="required">{{ __('admin::app.marketing.campaigns.channel') }}</label>
<select v-validate="'required'" class="control" id="channel_id" name="channel_id" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.channel') }}&quot;">
@foreach (app('Webkul\Core\Repositories\ChannelRepository')->all() as $channel)
<option value="{{ $channel->id }}" {{ old('channel_id') == $channel->id ? 'selected' : '' }}>
{{ $channel->name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('channel_id')">@{{ errors.first('channel_id') }}</span>
</div>
<div class="control-group" :class="[errors.has('customer_group_id') ? 'has-error' : '']">
<label for="customer_group_id" class="required">{{ __('admin::app.marketing.campaigns.customer-group') }}</label>
<select v-validate="'required'" class="control" id="customer_group_id" name="customer_group_id" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.customer-group') }}&quot;">
@foreach (app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $customerGroup)
<option value="{{ $customerGroup->id }}" {{ old('customer_group_id') == $customerGroup->id ? 'selected' : '' }}>
{{ $customerGroup->name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('customer_group_id')">@{{ errors.first('customer_group_id') }}</span>
</div>
</div>
</accordian>
{!! view_render_event('bagisto.admin.marketing.templates.create.after') !!}
</div>
</div>
</form>
</div>
@stop

View File

@ -0,0 +1,129 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.marketing.campaigns.edit-title') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.campaigns.update', $campaign->id) }}" @submit.prevent="onSubmit" enctype="multipart/form-data">
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="window.location = history.length > 1 ? document.referrer : '{{ route('admin.dashboard.index') }}'"></i>
{{ __('admin::app.marketing.campaigns.edit-title') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.marketing.campaigns.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
{!! view_render_event('bagisto.admin.marketing.templates.create.before') !!}
<accordian :title="'{{ __('admin::app.marketing.campaigns.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.marketing.campaigns.name') }}</label>
<input v-validate="'required'" class="control" id="name" name="name" value="{{ old('name') ?: $campaign->name }}" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.name') }}&quot;"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
<div class="control-group" :class="[errors.has('subject') ? 'has-error' : '']">
<label for="subject" class="required">{{ __('admin::app.marketing.campaigns.subject') }}</label>
<input v-validate="'required'" class="control" id="subject" name="subject" value="{{ old('subject') ?: $campaign->subject }}" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.subject') }}&quot;"/>
<span class="control-error" v-if="errors.has('subject')">@{{ errors.first('subject') }}</span>
</div>
<div class="control-group" :class="[errors.has('marketing_event_id') ? 'has-error' : '']">
<label for="marketing_event_id" class="required">{{ __('admin::app.marketing.campaigns.event') }}</label>
<?php $selectedOption = old('marketing_event_id') ?: $campaign->marketing_event_id ?>
<select class="control" v-validate="'required'" id="marketing_event_id" name="marketing_event_id" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.event') }}&quot;">
@foreach (app('Webkul\Marketing\Repositories\EventRepository')->all() as $event)
<option value="{{ $event->id }}" {{ $selectedOption == $event->id ? 'selected' : '' }}>
{{ $event->name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('marketing_event_id')">@{{ errors.first('marketing_event_id') }}</span>
</div>
<div class="control-group" :class="[errors.has('marketing_template_id') ? 'has-error' : '']">
<label for="marketing_template_id" class="required">{{ __('admin::app.marketing.campaigns.email-template') }}</label>
<?php $selectedOption = old('marketing_template_id') ?: $campaign->marketing_template_id ?>
<select v-validate="'required'" class="control" id="marketing_template_id" name="marketing_template_id" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.email-template') }}&quot;">
@foreach (app('Webkul\Marketing\Repositories\TemplateRepository')->all() as $template)
<option value="{{ $template->id }}" {{ $selectedOption == $template->id ? 'selected' : '' }}>
{{ $template->name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('marketing_template_id')">@{{ errors.first('marketing_template_id') }}</span>
</div>
<div class="control-group" :class="[errors.has('status') ? 'has-error' : '']">
<label for="status" class="required">{{ __('admin::app.marketing.campaigns.status') }}</label>
<?php $selectedOption = old('status') ?: $campaign->status ?>
<select class="control" v-validate="'required'" id="status" name="status" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.display-mode') }}&quot;">
<option value="0" {{ $selectedOption == 0 ? 'selected' : '' }}>
{{ __('admin::app.marketing.campaigns.inactive') }}
</option>
<option value="1" {{ $selectedOption == 1 ? 'selected' : '' }}>
{{ __('admin::app.marketing.campaigns.active') }}
</option>
</select>
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
</div>
</div>
</accordian>
<accordian :title="'{{ __('admin::app.marketing.campaigns.audience') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('channel_id') ? 'has-error' : '']">
<label for="channel_id" class="required">{{ __('admin::app.marketing.campaigns.channel') }}</label>
<?php $selectedOption = old('channel_id') ?: $campaign->channel_id ?>
<select v-validate="'required'" class="control" id="channel_id" name="channel_id" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.channel') }}&quot;">
@foreach (app('Webkul\Core\Repositories\ChannelRepository')->all() as $channel)
<option value="{{ $channel->id }}" {{ $selectedOption == $channel->id ? 'selected' : '' }}>
{{ $channel->name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('channel_id')">@{{ errors.first('channel_id') }}</span>
</div>
<div class="control-group" :class="[errors.has('customer_group_id') ? 'has-error' : '']">
<label for="customer_group_id" class="required">{{ __('admin::app.marketing.campaigns.customer-group') }}</label>
<?php $selectedOption = old('customer_group_id') ?: $campaign->customer_group_id ?>
<select v-validate="'required'" class="control" id="customer_group_id" name="customer_group_id" data-vv-as="&quot;{{ __('admin::app.marketing.campaigns.customer-group') }}&quot;">
@foreach (app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $customerGroup)
<option value="{{ $customerGroup->id }}" {{ $selectedOption == $customerGroup->id ? 'selected' : '' }}>
{{ $customerGroup->name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('customer_group_id')">@{{ errors.first('customer_group_id') }}</span>
</div>
</div>
</accordian>
{!! view_render_event('bagisto.admin.marketing.templates.create.after') !!}
</div>
</div>
</form>
</div>
@stop

View File

@ -0,0 +1,27 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.marketing.campaigns.title') }}
@stop
@section('content')
<div class="content">
<div class="page-header">
<div class="page-title">
<h1>{{ __('admin::app.marketing.campaigns.title') }}</h1>
</div>
<div class="page-action">
<a href="{{ route('admin.campaigns.create') }}" class="btn btn-lg btn-primary">
{{ __('admin::app.marketing.campaigns.add-title') }}
</a>
</div>
</div>
<div class="page-content">
{!! app('Webkul\Admin\DataGrids\CampaignDataGrid')->render() !!}
</div>
</div>
@stop

View File

@ -0,0 +1,64 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.marketing.events.add-title') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.events.store') }}" @submit.prevent="onSubmit" enctype="multipart/form-data">
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="window.location = history.length > 1 ? document.referrer : '{{ route('admin.dashboard.index') }}'"></i>
{{ __('admin::app.marketing.events.add-title') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.marketing.events.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
{!! view_render_event('bagisto.admin.marketing.events.create.before') !!}
<accordian :title="'{{ __('admin::app.marketing.events.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.marketing.events.name') }}</label>
<input v-validate="'required'" class="control" id="name" name="name" value="{{ old('name') }}" data-vv-as="&quot;{{ __('admin::app.marketing.events.name') }}&quot;"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
<div class="control-group" :class="[errors.has('description') ? 'has-error' : '']">
<label for="description" class="required">{{ __('admin::app.marketing.events.description') }}</label>
<textarea v-validate="'required'" class="control" id="description" name="description" data-vv-as="&quot;{{ __('admin::app.marketing.events.description') }}&quot;">{{ old('description') }}</textarea>
<span class="control-error" v-if="errors.has('description')">@{{ errors.first('description') }}</span>
</div>
<div class="control-group" :class="[errors.has('date') ? 'has-error' : '']">
<label for="date" class="required">{{ __('admin::app.marketing.events.date') }}</label>
<date>
<input type="text" name="date" class="control" v-validate="'required'" value="{{ old('date') }}" data-vv-as="&quot;{{ __('admin::app.marketing.events.date') }}&quot;">
</date>
<span class="control-error" v-if="errors.has('date')">@{{ errors.first('date') }}</span>
</div>
</div>
</accordian>
{!! view_render_event('bagisto.admin.marketing.events.create.after') !!}
</div>
</div>
</form>
</div>
@stop

View File

@ -0,0 +1,65 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.marketing.events.edit-title') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.events.update', $event->id) }}" @submit.prevent="onSubmit" enctype="multipart/form-data">
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="window.location = history.length > 1 ? document.referrer : '{{ route('admin.dashboard.index') }}'"></i>
{{ __('admin::app.marketing.events.edit-title') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.marketing.events.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
{!! view_render_event('bagisto.admin.marketing.events.create.before') !!}
<accordian :title="'{{ __('admin::app.marketing.events.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.marketing.events.name') }}</label>
<input v-validate="'required'" class="control" id="name" name="name" value="{{ old('name') ?: $event->name }}" data-vv-as="&quot;{{ __('admin::app.marketing.events.name') }}&quot;"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
<div class="control-group" :class="[errors.has('description') ? 'has-error' : '']">
<label for="description" class="required">{{ __('admin::app.marketing.events.description') }}</label>
<textarea v-validate="'required'" class="control" id="description" name="description" data-vv-as="&quot;{{ __('admin::app.marketing.events.description') }}&quot;">{{ old('description') ?: $event->description }}</textarea>
<span class="control-error" v-if="errors.has('description')">@{{ errors.first('description') }}</span>
</div>
<div class="control-group" :class="[errors.has('date') ? 'has-error' : '']">
<label for="date" class="required">{{ __('admin::app.marketing.events.date') }}</label>
<date>
<input type="text" name="date" class="control" v-validate="'required'" value="{{ old('date') ?: $event->date }}" data-vv-as="&quot;{{ __('admin::app.marketing.events.date') }}&quot;">
</date>
<span class="control-error" v-if="errors.has('date')">@{{ errors.first('date') }}</span>
</div>
</div>
</accordian>
{!! view_render_event('bagisto.admin.marketing.events.create.after') !!}
</div>
</div>
</form>
</div>
@stop

View File

@ -0,0 +1,27 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.marketing.events.title') }}
@stop
@section('content')
<div class="content">
<div class="page-header">
<div class="page-title">
<h1>{{ __('admin::app.marketing.events.title') }}</h1>
</div>
<div class="page-action">
<a href="{{ route('admin.events.create') }}" class="btn btn-lg btn-primary">
{{ __('admin::app.marketing.events.add-title') }}
</a>
</div>
</div>
<div class="page-content">
{!! app('Webkul\Admin\DataGrids\EventDataGrid')->render() !!}
</div>
</div>
@stop

View File

@ -0,0 +1,89 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.marketing.templates.add-title') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.email-templates.store') }}" @submit.prevent="onSubmit" enctype="multipart/form-data">
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="window.location = history.length > 1 ? document.referrer : '{{ route('admin.dashboard.index') }}'"></i>
{{ __('admin::app.marketing.templates.add-title') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.marketing.templates.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
{!! view_render_event('bagisto.admin.marketing.templates.create.before') !!}
<accordian :title="'{{ __('admin::app.marketing.templates.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.marketing.templates.name') }}</label>
<input v-validate="'required'" class="control" id="name" name="name" value="{{ old('name') }}" data-vv-as="&quot;{{ __('admin::app.marketing.templates.name') }}&quot;"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
<div class="control-group" :class="[errors.has('status') ? 'has-error' : '']">
<label for="status" class="required">{{ __('admin::app.marketing.templates.status') }}</label>
<select class="control" v-validate="'required'" id="status" name="status" data-vv-as="&quot;{{ __('admin::app.marketing.templates.display-mode') }}&quot;">
<option value="active" {{ old('status') == 'active' ? 'selected' : '' }}>
{{ __('admin::app.marketing.templates.active') }}
</option>
<option value="inactive" {{ old('status') == 'inactive' ? 'selected' : '' }}>
{{ __('admin::app.marketing.templates.inactive') }}
</option>
<option value="draft" {{ old('status') == 'draft' ? 'selected' : '' }}>
{{ __('admin::app.marketing.templates.draft') }}
</option>
</select>
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
</div>
<div class="control-group" :class="[errors.has('content') ? 'has-error' : '']">
<label for="content" class="required">{{ __('admin::app.marketing.templates.content') }}</label>
<textarea v-validate="'required'" class="control" id="content" name="content" data-vv-as="&quot;{{ __('admin::app.marketing.templates.content') }}&quot;">{{ old('content') }}</textarea>
<span class="control-error" v-if="errors.has('content')">@{{ errors.first('content') }}</span>
</div>
</div>
</accordian>
{!! view_render_event('bagisto.admin.marketing.templates.create.after') !!}
</div>
</div>
</form>
</div>
@stop
@push('scripts')
<script src="{{ asset('vendor/webkul/admin/assets/js/tinyMCE/tinymce.min.js') }}"></script>
<script>
$(document).ready(function () {
tinymce.init({
selector: 'textarea#content',
height: 200,
width: "100%",
plugins: 'image imagetools media wordcount save fullscreen code table lists link hr',
toolbar1: 'formatselect | bold italic strikethrough forecolor backcolor link hr | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat | code | table',
image_advtab: true
});
});
</script>
@endpush

View File

@ -0,0 +1,90 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.marketing.templates.edit-title') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.email-templates.update', $template->id) }}" @submit.prevent="onSubmit" enctype="multipart/form-data">
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="window.location = history.length > 1 ? document.referrer : '{{ route('admin.dashboard.index') }}'"></i>
{{ __('admin::app.marketing.templates.edit-title') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.marketing.templates.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
{!! view_render_event('bagisto.admin.marketing.templates.create.before') !!}
<accordian :title="'{{ __('admin::app.marketing.templates.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.marketing.templates.name') }}</label>
<input v-validate="'required'" class="control" id="name" name="name" value="{{ old('name') ?: $template->name }}" data-vv-as="&quot;{{ __('admin::app.marketing.templates.name') }}&quot;"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
<div class="control-group" :class="[errors.has('status') ? 'has-error' : '']">
<label for="status" class="required">{{ __('admin::app.marketing.templates.status') }}</label>
<?php $selectedOption = old('status') ?: $template->status ?>
<select class="control" v-validate="'required'" id="status" name="status" data-vv-as="&quot;{{ __('admin::app.marketing.templates.display-mode') }}&quot;">
<option value="active" {{ $selectedOption == 'active' ? 'selected' : '' }}>
{{ __('admin::app.marketing.templates.active') }}
</option>
<option value="inactive" {{ $selectedOption == 'inactive' ? 'selected' : '' }}>
{{ __('admin::app.marketing.templates.inactive') }}
</option>
<option value="draft" {{ $selectedOption == 'draft' ? 'selected' : '' }}>
{{ __('admin::app.marketing.templates.draft') }}
</option>
</select>
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
</div>
<div class="control-group" :class="[errors.has('content') ? 'has-error' : '']">
<label for="content" class="required">{{ __('admin::app.marketing.templates.content') }}</label>
<textarea v-validate="'required'" class="control" id="content" name="content" data-vv-as="&quot;{{ __('admin::app.marketing.templates.content') }}&quot;">{{ old('content') ?: $template->content }}</textarea>
<span class="control-error" v-if="errors.has('content')">@{{ errors.first('content') }}</span>
</div>
</div>
</accordian>
{!! view_render_event('bagisto.admin.marketing.templates.create.after') !!}
</div>
</div>
</form>
</div>
@stop
@push('scripts')
<script src="{{ asset('vendor/webkul/admin/assets/js/tinyMCE/tinymce.min.js') }}"></script>
<script>
$(document).ready(function () {
tinymce.init({
selector: 'textarea#content',
height: 200,
width: "100%",
plugins: 'image imagetools media wordcount save fullscreen code table lists link hr',
toolbar1: 'formatselect | bold italic strikethrough forecolor backcolor link hr | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat | code | table',
image_advtab: true
});
});
</script>
@endpush

View File

@ -0,0 +1,27 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.marketing.templates.title') }}
@stop
@section('content')
<div class="content">
<div class="page-header">
<div class="page-title">
<h1>{{ __('admin::app.marketing.templates.title') }}</h1>
</div>
<div class="page-action">
<a href="{{ route('admin.email-templates.create') }}" class="btn btn-lg btn-primary">
{{ __('admin::app.marketing.templates.add-title') }}
</a>
</div>
</div>
<div class="page-content">
{!! app('Webkul\Admin\DataGrids\EmailTemplateDataGrid')->render() !!}
</div>
</div>
@stop

View File

@ -260,11 +260,11 @@
</div>
@endif
</td>
<td>{{ core()->formatBasePrice($item->base_price) }}</td>
<td>{!! core()->formatBasePrice($item->base_price, true) !!}</td>
<td class="text-center">{{ $item->qty }}</td>
<td class="text-center">{{ core()->formatBasePrice($item->base_total) }}</td>
<td class="text-center">{{ core()->formatBasePrice($item->base_tax_amount) }}</td>
<td class="text-center">{{ core()->formatBasePrice($item->base_total + $item->base_tax_amount) }}</td>
<td class="text-center">{!! core()->formatBasePrice($item->base_total, true) !!}</td>
<td class="text-center">{!! core()->formatBasePrice($item->base_tax_amount, true) !!}</td>
<td class="text-center">{!! core()->formatBasePrice($item->base_total + $item->base_tax_amount, true) !!}</td>
</tr>
@endforeach
@ -277,31 +277,31 @@
<tr>
<td>{{ __('admin::app.sales.orders.subtotal') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($invoice->base_sub_total) }}</td>
<td>{!! core()->formatBasePrice($invoice->base_sub_total, true) !!}</td>
</tr>
<tr>
<td>{{ __('admin::app.sales.orders.shipping-handling') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($invoice->base_shipping_amount) }}</td>
<td>{!! core()->formatBasePrice($invoice->base_shipping_amount, true) !!}</td>
</tr>
<tr>
<td>{{ __('admin::app.sales.orders.tax') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($invoice->base_tax_amount) }}</td>
<td>{!! core()->formatBasePrice($invoice->base_tax_amount, true) !!}</td>
</tr>
<tr>
<td>{{ __('admin::app.sales.orders.discount') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($invoice->base_discount_amount) }}</td>
<td>{!! core()->formatBasePrice($invoice->base_discount_amount, true) !!}</td>
</tr>
<tr>
<td><strong>{{ __('admin::app.sales.orders.grand-total') }}</strong></td>
<td><strong>-</strong></td>
<td><strong>{{ core()->formatBasePrice($invoice->base_grand_total) }}</strong></td>
<td><strong>{!! core()->formatBasePrice($invoice->base_grand_total, true) !!}</strong></td>
</tr>
</table>

View File

@ -61,7 +61,7 @@
{{ __('admin::app.settings.channels.name') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<input v-validate="'required'" class="control" id="name" name="{{$locale}}[name]" data-vv-as="&quot;{{ __('admin::app.settings.channels.name') }}&quot;" value="{{ old($locale)['name'] ?? ($channel->translate($locale)['name'] ?? '') }}"/>
<input v-validate="'required'" class="control" id="name" name="{{$locale}}[name]" data-vv-as="&quot;{{ __('admin::app.settings.channels.name') }}&quot;" value="{{ old($locale)['name'] ?? ($channel->translate($locale)['name'] ?? $channel->name) }}"/>
<span class="control-error" v-if="errors.has('{{$locale}}[name]')">@{{ errors.first('{!!$locale!!}[page_title]') }}</span>
</div>
@ -70,7 +70,7 @@
{{ __('admin::app.settings.channels.description') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<textarea class="control" id="description" name="{{$locale}}[description]">{{ old($locale)['description'] ?? ($channel->translate($locale)['description'] ?? '') }}</textarea>
<textarea class="control" id="description" name="{{$locale}}[description]">{{ old($locale)['description'] ?? ($channel->translate($locale)['description'] ?? $channel->description) }}</textarea>
</div>
<div class="control-group" :class="[errors.has('inventory_sources[]') ? 'has-error' : '']">
@ -190,7 +190,7 @@
{{ __('admin::app.settings.channels.home_page_content') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<textarea class="control" id="home_page_content" name="{{$locale}}[home_page_content]">{{ old($locale)['home_page_content'] ?? ($channel->translate($locale)['home_page_content'] ?? '') }}</textarea>
<textarea class="control" id="home_page_content" name="{{$locale}}[home_page_content]">{{ old($locale)['home_page_content'] ?? ($channel->translate($locale)['home_page_content'] ?? $channel->home_page_content) }}</textarea>
</div>
<div class="control-group">
@ -198,7 +198,7 @@
{{ __('admin::app.settings.channels.footer_content') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<textarea class="control" id="footer_content" name="{{$locale}}[footer_content]">{{ old($locale)['footer_content'] ?? ($channel->translate($locale)['footer_content'] ?? '') }}</textarea>
<textarea class="control" id="footer_content" name="{{$locale}}[footer_content]">{{ old($locale)['footer_content'] ?? ($channel->translate($locale)['footer_content'] ?? $channel->footer_content) }}</textarea>
</div>
<div class="control-group">
@ -217,7 +217,7 @@
</accordian>
@php
$home_seo = $channel->translate($locale)['home_seo'] ?? '{}';
$home_seo = $channel->translate($locale)['home_seo'] ?? $channel->home_seo;
$seo = json_decode($home_seo);
@endphp
@ -276,7 +276,7 @@
{{ __('admin::app.settings.channels.maintenance-mode-text') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<input class="control" id="maintenance-mode-text" name="{{$locale}}[maintenance_mode_text]" value="{{ old('maintenance_mode_text') ?? ($channel->translate($locale)['maintenance_mode_text'] ?? '') }}"/>
<input class="control" id="maintenance-mode-text" name="{{$locale}}[maintenance_mode_text]" value="{{ old('maintenance_mode_text') ?? ($channel->translate($locale)['maintenance_mode_text'] ?? $channel->maintenance_mode_text) }}"/>
</div>
<div class="control-group">

View File

@ -180,7 +180,6 @@ class CartRuleController extends Controller
'customer_groups' => 'required|array|min:1',
'coupon_type' => 'required',
'use_auto_generation' => 'required_if:coupon_type,==,1',
'coupon_code' => 'required_if:use_auto_generation,==,0|unique:cart_rule_coupons,code,' . $id,
'starts_from' => 'nullable|date',
'ends_till' => 'nullable|date|after_or_equal:starts_from',
'action_type' => 'required',
@ -189,6 +188,12 @@ class CartRuleController extends Controller
$cartRule = $this->cartRuleRepository->findOrFail($id);
if ($cartRule->coupon_type) {
$this->validate(request(), [
'coupon_code' => 'required_if:use_auto_generation,==,0|unique:cart_rule_coupons,code,' . $cartRule->cart_rule_coupon->id,
]);
}
Event::dispatch('promotions.cart_rule.update.before', $cartRule);
$cartRule = $this->cartRuleRepository->update(request()->all(), $id);

View File

@ -24,6 +24,7 @@ return [
\Webkul\CMS\Providers\ModuleServiceProvider::class,
\Webkul\Customer\Providers\ModuleServiceProvider::class,
\Webkul\Inventory\Providers\ModuleServiceProvider::class,
\Webkul\Marketing\Providers\ModuleServiceProvider::class,
\Webkul\Payment\Providers\ModuleServiceProvider::class,
\Webkul\Paypal\Providers\ModuleServiceProvider::class,
\Webkul\Product\Providers\ModuleServiceProvider::class,

View File

@ -3,8 +3,8 @@
namespace Webkul\Core\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Artisan;
class Install extends Command
{
@ -33,20 +33,15 @@ class Install extends Command
}
/**
* Install and configure bagisto
* Install and configure bagisto.
*/
public function handle()
{
// check for .env
$this->checkForEnvFile();
// cached new changes
$this->warn('Step: Caching new changes...');
$cached = $this->call('config:cache');
$this->info($cached);
// waiting for 2 seconds
$this->warn('Please wait...');
sleep(2);
// loading values at runtime
$this->loadEnvConfigAtRuntime();
// running `php artisan migrate`
$this->warn('Step: Migrating all tables into database...');
@ -54,25 +49,31 @@ class Install extends Command
$this->info($migrate);
// running `php artisan db:seed`
$this->warn('Step: seeding basic data for bagisto kickstart...');
$this->warn('Step: Seeding basic data for Bagisto kickstart...');
$result = $this->call('db:seed');
$this->info($result);
// running `php artisan vendor:publish --all`
$this->warn('Step: Publishing Assets and Configurations...');
$this->warn('Step: Publishing assets and configurations...');
$result = $this->call('vendor:publish', ['--all']);
$this->info($result);
// running `php artisan storage:link`
$this->warn('Step: Linking Storage directory...');
$this->warn('Step: Linking storage directory...');
$result = $this->call('storage:link');
$this->info($result);
// optimizing stuffs
$this->warn('Step: Optimizing...');
$result = $this->call('optimize');
$this->info($result);
// running `composer dump-autoload`
$this->warn('Step: Composer Autoload...');
$this->warn('Step: Composer autoload...');
$result = shell_exec('composer dump-autoload');
$this->info($result);
// final information
$this->info('-----------------------------');
$this->info('Congratulations!');
$this->info('The installation has been finished and you can now use Bagisto.');
@ -85,28 +86,30 @@ class Install extends Command
/**
* Checking .env file and if not found then create .env file.
* Then ask for database name, password & username to set
* On .env file so that we can easily migrate to our db
* On .env file so that we can easily migrate to our db.
*/
public function checkForEnvFile()
protected function checkForEnvFile()
{
$envExists = File::exists(base_path() . '/.env');
if (! $envExists) {
$this->info('Creating the environment configuration file.');
$this->createEnvFile();
} else {
$this->call('key:generate');
$this->info('Great! your environment configuration file already exists.');
}
$this->call('key:generate');
}
/**
* Create a new .env file.
*/
public function createEnvFile()
protected function createEnvFile()
{
try {
File::copy('.env.example', '.env');
Artisan::call('key:generate');
$default_app_url = 'http://localhost:8000';
$input_app_url = $this->ask('Please Enter the APP URL : ');
$this->envUpdate('APP_URL=', $input_app_url ? $input_app_url : $default_app_url );
@ -125,7 +128,6 @@ class Install extends Command
$currency = $this->choice('Please enter the default currency', ['USD', 'EUR'], 'USD');
$this->envUpdate('APP_CURRENCY=', $currency);
$this->addDatabaseDetails();
} catch (\Exception $e) {
$this->error('Error in creating .env file, please create it manually and then run `php artisan migrate` again.');
@ -135,21 +137,65 @@ class Install extends Command
/**
* Add the database credentials to the .env file.
*/
public function addDatabaseDetails()
protected function addDatabaseDetails()
{
$dbName = $this->ask('What is the database name to be used by bagisto?');
$dbUser = $this->anticipate('What is your database username?', ['root']);
$dbPass = $this->secret('What is your database password?');
$this->envUpdate('DB_DATABASE=', $dbName);
$dbUser = $this->anticipate('What is your database username?', ['root']);
$this->envUpdate('DB_USERNAME=', $dbUser);
$dbPass = $this->secret('What is your database password?');
$this->envUpdate('DB_PASSWORD=', $dbPass);
}
/**
* Load `.env` config at runtime.
*/
protected function loadEnvConfigAtRuntime()
{
$this->warn('Loading configs...');
/* environment directly checked from `.env` so changing in config won't reflect */
app()['env'] = $this->getEnvAtRuntime('APP_ENV');
/* setting for the first time and then `.env` values will be incharged */
config(['database.connections.mysql.database' => $this->getEnvAtRuntime('DB_DATABASE')]);
config(['database.connections.mysql.username' => $this->getEnvAtRuntime('DB_USERNAME')]);
config(['database.connections.mysql.password' => $this->getEnvAtRuntime('DB_PASSWORD')]);
DB::purge('mysql');
$this->info('Configuration loaded..');
}
/**
* Check key in `.env` file because it will help to find values at runtime.
*/
protected static function getEnvAtRuntime($key)
{
$path = base_path() . '/.env';
$data = file($path);
if ($data) {
foreach ($data as $line) {
$line = preg_replace('/\s+/', '', $line);
$rowValues = explode('=', $line);
if (strlen($line) !== 0) {
if (strpos($key, $rowValues[0]) !== false) {
return $rowValues[1];
}
}
}
}
return false;
}
/**
* Update the .env values.
*/
public static function envUpdate($key, $value)
protected static function envUpdate($key, $value)
{
$path = base_path() . '/.env';
$data = file($path);

View File

@ -554,13 +554,15 @@ class Core
}
/**
* Format price with base currency symbol
* Format price with base currency symbol. This method also give ability to encode
* the base currency symbol and its optional.
*
* @param float $price
* @param float $price
* @param bool $isEncoded
*
* @return string
*/
public function formatBasePrice($price)
public function formatBasePrice($price, $isEncoded = false)
{
if (is_null($price)) {
$price = 0;
@ -570,15 +572,17 @@ class Core
if ($symbol = $this->getBaseCurrency()->symbol) {
if ($this->currencySymbol($this->getBaseCurrencyCode()) == $symbol) {
return $formater->formatCurrency($price, $this->getBaseCurrencyCode());
$content = $formater->formatCurrency($price, $this->getBaseCurrencyCode());
} else {
$formater->setSymbol(\NumberFormatter::CURRENCY_SYMBOL, $symbol);
return $formater->format($this->convertPrice($price));
$content = $formater->format($this->convertPrice($price));
}
} else {
return $formater->formatCurrency($price, $this->getBaseCurrencyCode());
$content = $formater->formatCurrency($price, $this->getBaseCurrencyCode());
}
return ! $isEncoded ? $content : htmlentities($content);
}
/**

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddCustomerIdColumnInSubscribersListTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('subscribers_list', function (Blueprint $table) {
$table->integer('customer_id')->unsigned()->nullable();
$table->foreign('customer_id')->references('id')->on('customers')->onDelete('set null');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('subscribers_list', function (Blueprint $table) {
//
});
}
}

View File

@ -19,6 +19,7 @@ class SubscribersList extends Model implements SubscribersListContract
'email',
'is_subscribed',
'token',
'customer_id',
'channel_id',
];

View File

@ -4,8 +4,11 @@ namespace Webkul\Customer\Http\Controllers;
use Hash;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Mail;
use Webkul\Shop\Mail\SubscriptionEmail;
use Webkul\Customer\Repositories\CustomerRepository;
use Webkul\Product\Repositories\ProductReviewRepository;
use Webkul\Core\Repositories\SubscribersListRepository;
class CustomerController extends Controller
{
@ -30,16 +33,25 @@ class CustomerController extends Controller
*/
protected $productReviewRepository;
/**
* SubscribersListRepository
*
* @var \Webkul\Core\Repositories\SubscribersListRepository
*/
protected $subscriptionRepository;
/**
* Create a new controller instance.
*
* @param \Webkul\Customer\Repositories\CustomerRepository $customer
* @param \Webkul\Product\Repositories\ProductReviewRepository $productReview
* @param \Webkul\Customer\Repositories\CustomerRepository $customerRepository
* @param \Webkul\Product\Repositories\ProductReviewRepository $productReviewRepository
* @param \Webkul\Core\Repositories\SubscribersListRepository $subscriptionRepository
* @return void
*/
public function __construct(
CustomerRepository $customerRepository,
ProductReviewRepository $productReviewRepository
ProductReviewRepository $productReviewRepository,
SubscribersListRepository $subscriptionRepository
)
{
$this->middleware('customer');
@ -49,6 +61,8 @@ class CustomerController extends Controller
$this->customerRepository = $customerRepository;
$this->productReviewRepository = $productReviewRepository;
$this->subscriptionRepository = $subscriptionRepository;
}
/**
@ -102,10 +116,13 @@ class CustomerController extends Controller
unset($data['date_of_birth']);
}
$data['subscribed_to_news_letter'] = isset($data['subscribed_to_news_letter']) ? 1 : 0;
if (isset ($data['oldpassword'])) {
if ($data['oldpassword'] != "" || $data['oldpassword'] != null) {
if (Hash::check($data['oldpassword'], auth()->guard('customer')->user()->password)) {
$isPasswordChanged = true;
$data['password'] = bcrypt($data['password']);
} else {
session()->flash('warning', trans('shop::app.customer.account.profile.unmatch'));
@ -120,13 +137,47 @@ class CustomerController extends Controller
Event::dispatch('customer.update.before');
if ($customer = $this->customerRepository->update($data, $id)) {
if ($isPasswordChanged) {
Event::dispatch('user.admin.update-password', $customer);
}
Event::dispatch('customer.update.after', $customer);
if ($data['subscribed_to_news_letter']) {
$subscription = $this->subscriptionRepository->findOneWhere(['email' => $data['email']]);
if ($subscription) {
$this->subscriptionRepository->update([
'customer_id' => $customer->id,
'is_subscribed' => 1,
], $subscription->id);
} else {
$this->subscriptionRepository->create([
'email' => $data['email'],
'customer_id' => $customer->id,
'channel_id' => core()->getCurrentChannel()->id,
'is_subscribed' => 1,
'token' => $token = uniqid(),
]);
try {
Mail::queue(new SubscriptionEmail([
'email' => $data['email'],
'token' => $token,
]));
} catch (\Exception $e) { }
}
} else {
$subscription = $this->subscriptionRepository->findOneWhere(['email' => $data['email']]);
if ($subscription) {
$this->subscriptionRepository->update([
'customer_id' => $customer->id,
'is_subscribed' => 0,
], $subscription->id);
}
}
Session()->flash('success', trans('shop::app.customer.account.profile.edit-success'));
return redirect()->route($this->_config['redirect']);

View File

@ -3,13 +3,14 @@
namespace Webkul\Customer\Http\Controllers;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Mail;
use Webkul\Customer\Mail\RegistrationEmail;
use Webkul\Customer\Mail\VerificationEmail;
use Webkul\Shop\Mail\SubscriptionEmail;
use Webkul\Customer\Repositories\CustomerRepository;
use Webkul\Customer\Repositories\CustomerGroupRepository;
use Webkul\Core\Repositories\SubscribersListRepository;
use Cookie;
class RegistrationController extends Controller
@ -35,17 +36,26 @@ class RegistrationController extends Controller
*/
protected $customerGroupRepository;
/**
* SubscribersListRepository
*
* @var \Webkul\Core\Repositories\SubscribersListRepository
*/
protected $subscriptionRepository;
/**
* Create a new Repository instance.
*
* @param \Webkul\Customer\Repositories\CustomerRepository $customer
* @param \Webkul\Customer\Repositories\CustomerGroupRepository $customerGroupRepository
*
* @param \Webkul\Core\Repositories\SubscribersListRepository $subscriptionRepository
*
* @return void
*/
public function __construct(
CustomerRepository $customerRepository,
CustomerGroupRepository $customerGroupRepository
CustomerGroupRepository $customerGroupRepository,
SubscribersListRepository $subscriptionRepository
)
{
$this->_config = request('_config');
@ -53,6 +63,8 @@ class RegistrationController extends Controller
$this->customerRepository = $customerRepository;
$this->customerGroupRepository = $customerGroupRepository;
$this->subscriptionRepository = $subscriptionRepository;
}
/**
@ -79,22 +91,13 @@ class RegistrationController extends Controller
'password' => 'confirmed|min:6|required',
]);
$data = request()->input();
$data['password'] = bcrypt($data['password']);
$data['api_token'] = Str::random(80);
if (core()->getConfigData('customer.settings.email.verification')) {
$data['is_verified'] = 0;
} else {
$data['is_verified'] = 1;
}
$data['customer_group_id'] = $this->customerGroupRepository->findOneWhere(['code' => 'general'])->id;
$verificationData['email'] = $data['email'];
$verificationData['token'] = md5(uniqid(rand(), true));
$data['token'] = $verificationData['token'];
$data = array_merge(request()->input(), [
'password' => bcrypt(request()->input('password')),
'api_token' => Str::random(80),
'is_verified' => core()->getConfigData('customer.settings.email.verification') ? 0 : 1,
'customer_group_id' => $this->customerGroupRepository->findOneWhere(['code' => 'general'])->id,
'token' => md5(uniqid(rand(), true)),
]);
Event::dispatch('customer.registration.before');
@ -102,41 +105,66 @@ class RegistrationController extends Controller
Event::dispatch('customer.registration.after', $customer);
if ($customer) {
if (core()->getConfigData('customer.settings.email.verification')) {
try {
$configKey = 'emails.general.notifications.emails.general.notifications.verification';
if (core()->getConfigData($configKey)) {
Mail::queue(new VerificationEmail($verificationData));
}
session()->flash('success', trans('shop::app.customer.signup-form.success-verify'));
} catch (\Exception $e) {
report($e);
session()->flash('info', trans('shop::app.customer.signup-form.success-verify-email-unsent'));
}
} else {
try {
$configKey = 'emails.general.notifications.emails.general.notifications.registration';
if (core()->getConfigData($configKey)) {
Mail::queue(new RegistrationEmail(request()->all()));
}
session()->flash('success', trans('shop::app.customer.signup-form.success-verify')); //customer registered successfully
} catch (\Exception $e) {
report($e);
session()->flash('info', trans('shop::app.customer.signup-form.success-verify-email-unsent'));
}
session()->flash('success', trans('shop::app.customer.signup-form.success'));
}
return redirect()->route($this->_config['redirect']);
} else {
if (! $customer) {
session()->flash('error', trans('shop::app.customer.signup-form.failed'));
return redirect()->back();
}
if (isset($data['is_subscribed'])) {
$subscription = $this->subscriptionRepository->findOneWhere(['email' => $data['email']]);
if ($subscription) {
$this->subscriptionRepository->update([
'customer_id' => $customer->id,
], $subscription->id);
} else {
$this->subscriptionRepository->create([
'email' => $data['email'],
'customer_id' => $customer->id,
'channel_id' => core()->getCurrentChannel()->id,
'is_subscribed' => 1,
'token' => $token = uniqid(),
]);
try {
Mail::queue(new SubscriptionEmail([
'email' => $data['email'],
'token' => $token,
]));
} catch (\Exception $e) { }
}
}
if (core()->getConfigData('customer.settings.email.verification')) {
try {
if (core()->getConfigData('emails.general.notifications.emails.general.notifications.verification')) {
Mail::queue(new VerificationEmail(['email' => $data['email'], 'token' => $data['token']]));
}
session()->flash('success', trans('shop::app.customer.signup-form.success-verify'));
} catch (\Exception $e) {
report($e);
session()->flash('info', trans('shop::app.customer.signup-form.success-verify-email-unsent'));
}
} else {
try {
if (core()->getConfigData('emails.general.notifications.emails.general.notifications.registration')) {
Mail::queue(new RegistrationEmail(request()->all()));
}
session()->flash('success', trans('shop::app.customer.signup-form.success-verify'));
} catch (\Exception $e) {
report($e);
session()->flash('info', trans('shop::app.customer.signup-form.success-verify-email-unsent'));
}
session()->flash('success', trans('shop::app.customer.signup-form.success'));
}
return redirect()->route($this->_config['redirect']);
}
/**
@ -166,8 +194,10 @@ class RegistrationController extends Controller
*/
public function resendVerificationEmail($email)
{
$verificationData['email'] = $email;
$verificationData['token'] = md5(uniqid(rand(), true));
$verificationData = [
'email' => $email,
'token' => md5(uniqid(rand(), true)),
];
$customer = $this->customerRepository->findOneByField('email', $email);
@ -185,6 +215,7 @@ class RegistrationController extends Controller
}
} catch (\Exception $e) {
report($e);
session()->flash('error', trans('shop::app.customer.signup-form.verification-not-sent'));
return redirect()->back();

View File

@ -59,6 +59,10 @@ class WishlistController extends Controller
{
$wishlistItems = $this->wishlistRepository->getCustomerWhishlist();
if (! core()->getConfigData('general.content.shop.wishlist_option')) {
abort(404);
}
return view($this->_config['view'])->with('items', $wishlistItems);
}

View File

@ -11,9 +11,9 @@ class CustomerGroup extends Model implements CustomerGroupContract
protected $fillable = ['name', 'code', 'is_user_defined'];
/**
* Get the customer for this group.
* Get the customers for this group.
*/
public function customer()
public function customers()
{
return $this->hasMany(CustomerProxy::modelClass());
}

View File

@ -0,0 +1,53 @@
<?php
namespace Webkul\Marketing\Console\Commands;
use Illuminate\Console\Command;
use Webkul\Marketing\Helpers\Campaign;
class EmailsCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'campaign:process';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Process campaigns and send emails to the subscribed customers.';
/**
* Campaign object
*
* @var \Webkul\Marketing\Helpers\Campaign
*/
protected $campaignHelper;
/**
* Create a new command instance.
*
* @param \Webkul\Marketing\Repositories\Campaign $campaignHelper
* @return void
*/
public function __construct(Campaign $campaignHelper)
{
$this->campaignHelper = $campaignHelper;
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->campaignHelper->process();
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace Webkul\Marketing\Contracts;
interface Campaign
{
}

View File

@ -0,0 +1,7 @@
<?php
namespace Webkul\Marketing\Contracts;
interface Event
{
}

View File

@ -0,0 +1,7 @@
<?php
namespace Webkul\Marketing\Contracts;
interface Template
{
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMarketingTemplatesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('marketing_templates', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('status');
$table->text('content');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('marketing_templates');
}
}

View File

@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMarketingEventsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('marketing_events', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->text('description')->nullable();
$table->date('date')->nullable();
$table->timestamps();
});
DB::table('marketing_events')->insert([
'name' => 'Birthday',
'description' => 'Birthday',
]);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('marketing_events');
}
}

View File

@ -0,0 +1,50 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMarketingCampaignsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('marketing_campaigns', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('subject');
$table->boolean('status')->default(0);
$table->string('type');
$table->string('mail_to');
$table->string('spooling')->nullable();
$table->integer('channel_id')->unsigned()->nullable();
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('set null');
$table->integer('customer_group_id')->unsigned()->nullable();
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('set null');
$table->integer('marketing_template_id')->unsigned()->nullable();
$table->foreign('marketing_template_id')->references('id')->on('marketing_templates')->onDelete('set null');
$table->integer('marketing_event_id')->unsigned()->nullable();
$table->foreign('marketing_event_id')->references('id')->on('marketing_events')->onDelete('set null');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('marketing_campaigns');
}
}

View File

@ -0,0 +1,134 @@
<?php
namespace Webkul\Marketing\Helpers;
use Carbon\Carbon;
use Illuminate\Support\Facades\Mail;
use Webkul\Marketing\Repositories\EventRepository;
use Webkul\Marketing\Repositories\CampaignRepository;
use Webkul\Marketing\Repositories\TemplateRepository;
use Webkul\Marketing\Mail\NewsletterMail;
class Campaign
{
/**
* EventRepository object
*
* @var \Webkul\Marketing\Repositories\EventRepository
*/
protected $eventRepository;
/**
* CampaignRepository object
*
* @var \Webkul\Marketing\Repositories\CampaignRepository
*/
protected $campaignRepository;
/**
* TemplateRepository object
*
* @var \Webkul\Marketing\Repositories\TemplateRepository
*/
protected $templateRepository;
/**
* Create a new helper instance.
*
* @param \Webkul\Marketing\Repositories\EventRepository $eventRepository
* @param \Webkul\Marketing\Repositories\CampaignRepository $campaignRepository
* @param \Webkul\Marketing\Repositories\TemplateRepository $templateRepository
*
* @return void
*/
public function __construct(
EventRepository $eventRepository,
CampaignRepository $campaignRepository,
CampaignRepository $templateRepository
)
{
$this->eventRepository = $eventRepository;
$this->campaignRepository = $campaignRepository;
$this->templateRepository = $templateRepository;
}
/**
* @return void
*/
public function process(): void
{
$campaigns = $this->campaignRepository->getModel()
->leftJoin('marketing_events', 'marketing_campaigns.marketing_event_id', 'marketing_events.id')
->select('marketing_campaigns.*')
->where('status', 1)
->where(function ($query) {
$query->where('marketing_events.date', Carbon::now()->format('Y-m-d'))
->orWhereNull('marketing_events.date');
})
->get();
foreach ($campaigns as $campaign) {
if ($campaign->event->name == 'Birthday') {
$emails = $this->getBirthdayEmails($campaign);
} else {
$emails = $this->getEmailAddresses($campaign);
}
foreach ($emails as $email) {
Mail::queue(new NewsletterMail($email, $campaign));
}
}
}
/**
* Build the message.
*
* @param \Webkul\Marketing\Contracts\Campaign $campaign
* @return array
*/
public function getEmailAddresses($campaign)
{
$newsletterEmails = app('\Webkul\Core\Repositories\SubscribersListRepository')->getModel()
->where('is_subscribed', 1)
->where('channel_id', $campaign->channel_id)
->get('email');
$customerGroupEmails = $campaign->customer_group->customers()->where('subscribed_to_news_letter', 1)->get('email');
$emails = [];
foreach ($newsletterEmails as $row) {
$emails[] = $row->email;
}
foreach ($customerGroupEmails as $row) {
$emails[] = $row->email;
}
return array_unique($emails);
}
/**
* Return customer's emails who has a birthday today
*
* @param \Webkul\Marketing\Contracts\Campaign $campaign
* @return array
*/
public function getBirthdayEmails($campaign)
{
$customerGroupEmails = $campaign->customer_group->customers()
->whereRaw('DATE_FORMAT(date_of_birth, "%m-%d") = ?', [Carbon::now()->format('m-d')])
->where('subscribed_to_news_letter', 1)
->get('email');
$emails = [];
foreach ($customerGroupEmails as $row) {
$emails[] = $row->email;
}
return $emails;
}
}

View File

@ -0,0 +1,149 @@
<?php
namespace Webkul\Marketing\Http\Controllers;
use Illuminate\Support\Facades\Event;
use Webkul\Marketing\Repositories\CampaignRepository;
class CampaignController extends Controller
{
/**
* Contains route related configuration
*
* @var array
*/
protected $_config;
/**
* CampaignRepository object
*
* @var \Webkul\Core\Repositories\CampaignRepository
*/
protected $campaignRepository;
/**
* Create a new controller instance.
*
* @param \Webkul\Core\Repositories\CampaignRepository $campaignRepository
* @return void
*/
public function __construct(CampaignRepository $campaignRepository)
{
$this->campaignRepository = $campaignRepository;
$this->_config = request('_config');
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\View\View
*/
public function index()
{
return view($this->_config['view']);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\View\View
*/
public function create()
{
return view($this->_config['view']);
}
/**
* Store a newly created resource in storage.
*
* @return \Illuminate\Http\Response
*/
public function store()
{
$this->validate(request(), [
'name' => 'required',
'subject' => 'required',
'status' => 'required',
'marketing_template_id' => 'required',
'marketing_event_id' => 'required_if:schedule_type,event',
]);
Event::dispatch('marketing.campaigns.create.before');
$locale = $this->campaignRepository->create(request()->all());
Event::dispatch('marketing.campaigns.create.after', $locale);
session()->flash('success', trans('admin::app.marketing.campaigns.create-success'));
return redirect()->route($this->_config['redirect']);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\View\View
*/
public function edit($id)
{
$campaign = $this->campaignRepository->findOrFail($id);
return view($this->_config['view'], compact('campaign'));
}
/**
* Update the specified resource in storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update($id)
{
$this->validate(request(), [
'name' => 'required',
'subject' => 'required',
'status' => 'required',
'marketing_template_id' => 'required',
'marketing_event_id' => 'required_if:schedule_type,event',
]);
Event::dispatch('marketing.campaigns.update.before', $id);
$locale = $this->campaignRepository->update(request()->all(), $id);
Event::dispatch('marketing.campaigns.update.after', $locale);
session()->flash('success', trans('admin::app.marketing.campaigns.update-success'));
return redirect()->route($this->_config['redirect']);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$locale = $this->campaignRepository->findOrFail($id);
try {
Event::dispatch('marketing.campaigns.delete.before', $id);
$this->campaignRepository->delete($id);
Event::dispatch('marketing.campaigns.delete.after', $id);
session()->flash('success', trans('admin::app.marketing.campaigns.delete-success'));
return response()->json(['message' => true], 200);
} catch(\Exception $e) {
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Email Campaign']));
}
return response()->json(['message' => false], 400);
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Webkul\Marketing\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

View File

@ -0,0 +1,151 @@
<?php
namespace Webkul\Marketing\Http\Controllers;
use Illuminate\Support\Facades\Event;
use Webkul\Marketing\Repositories\EventRepository;
class EventController extends Controller
{
/**
* Contains route related configuration
*
* @var array
*/
protected $_config;
/**
* EventRepository object
*
* @var \Webkul\Marketing\Repositories\EventRepository
*/
protected $eventRepository;
/**
* Create a new controller instance.
*
* @param \Webkul\Marketing\Repositories\EventRepository $eventRepository
* @return void
*/
public function __construct(EventRepository $eventRepository)
{
$this->eventRepository = $eventRepository;
$this->_config = request('_config');
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\View\View
*/
public function index()
{
return view($this->_config['view']);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\View\View
*/
public function create()
{
return view($this->_config['view']);
}
/**
* Store a newly created resource in storage.
*
* @return \Illuminate\Http\Response
*/
public function store()
{
$this->validate(request(), [
'name' => 'required',
'description' => 'required',
'date' => 'date|required',
]);
Event::dispatch('marketing.events.create.before');
$locale = $this->eventRepository->create(request()->all());
Event::dispatch('marketing.events.create.after', $locale);
session()->flash('success', trans('admin::app.marketing.events.create-success'));
return redirect()->route($this->_config['redirect']);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\View\View
*/
public function edit($id)
{
if ($id == 1) {
session()->flash('error', trans('admin::app.marketing.events.edit-error'));
return redirect()->back();
} else {
$event = $this->eventRepository->findOrFail($id);
return view($this->_config['view'], compact('event'));
}
}
/**
* Update the specified resource in storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update($id)
{
$this->validate(request(), [
'name' => 'required',
'description' => 'required',
'date' => 'date|required',
]);
Event::dispatch('marketing.events.update.before', $id);
$locale = $this->eventRepository->update(request()->all(), $id);
Event::dispatch('marketing.events.update.after', $locale);
session()->flash('success', trans('admin::app.marketing.events.update-success'));
return redirect()->route($this->_config['redirect']);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$locale = $this->eventRepository->findOrFail($id);
try {
Event::dispatch('marketing.events.delete.before', $id);
$this->eventRepository->delete($id);
Event::dispatch('marketing.events.delete.after', $id);
session()->flash('success', trans('admin::app.marketing.events.delete-success'));
return response()->json(['message' => true], 200);
} catch(\Exception $e) {
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Event']));
}
return response()->json(['message' => false], 400);
}
}

View File

@ -0,0 +1,145 @@
<?php
namespace Webkul\Marketing\Http\Controllers;
use Illuminate\Support\Facades\Event;
use Webkul\Marketing\Repositories\TemplateRepository;
class TemplateController extends Controller
{
/**
* Contains route related configuration
*
* @var array
*/
protected $_config;
/**
* TemplateRepository object
*
* @var \Webkul\Core\Repositories\TemplateRepository
*/
protected $templateRepository;
/**
* Create a new controller instance.
*
* @param \Webkul\Core\Repositories\TemplateRepository $templateRepository
* @return void
*/
public function __construct(TemplateRepository $templateRepository)
{
$this->templateRepository = $templateRepository;
$this->_config = request('_config');
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\View\View
*/
public function index()
{
return view($this->_config['view']);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\View\View
*/
public function create()
{
return view($this->_config['view']);
}
/**
* Store a newly created resource in storage.
*
* @return \Illuminate\Http\Response
*/
public function store()
{
$this->validate(request(), [
'name' => 'required',
'status' => 'required|in:active,inactive,draft',
'content' => 'required',
]);
Event::dispatch('marketing.templates.create.before');
$locale = $this->templateRepository->create(request()->all());
Event::dispatch('marketing.templates.create.after', $locale);
session()->flash('success', trans('admin::app.marketing.templates.create-success'));
return redirect()->route($this->_config['redirect']);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\View\View
*/
public function edit($id)
{
$template = $this->templateRepository->findOrFail($id);
return view($this->_config['view'], compact('template'));
}
/**
* Update the specified resource in storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update($id)
{
$this->validate(request(), [
'name' => 'required',
'status' => 'required|in:active,inactive,draft',
'content' => 'required',
]);
Event::dispatch('marketing.templates.update.before', $id);
$locale = $this->templateRepository->update(request()->all(), $id);
Event::dispatch('marketing.templates.update.after', $locale);
session()->flash('success', trans('admin::app.marketing.templates.update-success'));
return redirect()->route($this->_config['redirect']);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$locale = $this->templateRepository->findOrFail($id);
try {
Event::dispatch('marketing.templates.delete.before', $id);
$this->templateRepository->delete($id);
Event::dispatch('marketing.templates.delete.after', $id);
session()->flash('success', trans('admin::app.marketing.templates.delete-success'));
return response()->json(['message' => true], 200);
} catch(\Exception $e) {
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Email Template']));
}
return response()->json(['message' => false], 400);
}
}

View File

@ -0,0 +1,3 @@
<?php
?>

View File

@ -0,0 +1,52 @@
<?php
namespace Webkul\Marketing\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class NewsletterMail extends Mailable
{
use Queueable, SerializesModels;
/**
* @var string
*/
public $email;
/**
* The campaign instance.
*
* @var \Webkul\Marketing\Contracts\Campaign
*/
public $campaign;
/**
* Create a new message instance.
*
* @param string $email
* @param \Webkul\Marketing\Contracts\Campaign $campaign
* @return void
*/
public function __construct($email, $campaign)
{
$this->email = $email;
$this->campaign = $campaign;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from(core()->getSenderEmailDetails()['email'], core()->getSenderEmailDetails()['name'])
->to([$this->email])
->subject($this->campaign->subject)
->html($this->campaign->email_template->content);
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace Webkul\Marketing\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Core\Models\ChannelProxy;
use Webkul\Customer\Models\CustomerGroupProxy;
use Webkul\Marketing\Contracts\Campaign as CampaignContract;
class Campaign extends Model implements CampaignContract
{
protected $table = 'marketing_campaigns';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'subject',
'status',
'channel_id',
'customer_group_id',
'marketing_template_id',
'spooling',
'marketing_event_id',
];
/**
* Get the event
*/
public function event()
{
return $this->belongsTo(EventProxy::modelClass(), 'marketing_event_id');
}
/**
* Get the channel
*/
public function channel()
{
return $this->belongsTo(ChannelProxy::modelClass(), 'channel_id');
}
/**
* Get the customer group
*/
public function customer_group()
{
return $this->belongsTo(CustomerGroupProxy::modelClass(), 'customer_group_id');
}
/**
* Get the email template
*/
public function email_template()
{
return $this->belongsTo(TemplateProxy::modelClass(), 'marketing_template_id');
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace Webkul\Marketing\Models;
use Konekt\Concord\Proxies\ModelProxy;
class CampaignProxy extends ModelProxy
{
}

View File

@ -0,0 +1,23 @@
<?php
namespace Webkul\Marketing\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Product\Models\ProductProxy;
use Webkul\Marketing\Contracts\Event as EventContract;
class Event extends Model implements EventContract
{
protected $table = 'marketing_events';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'description',
'date',
];
}

View File

@ -0,0 +1,10 @@
<?php
namespace Webkul\Marketing\Models;
use Konekt\Concord\Proxies\ModelProxy;
class EventProxy extends ModelProxy
{
}

View File

@ -0,0 +1,23 @@
<?php
namespace Webkul\Marketing\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Product\Models\ProductProxy;
use Webkul\Marketing\Contracts\Template as TemplateContract;
class Template extends Model implements TemplateContract
{
protected $table = 'marketing_templates';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'status',
'content',
];
}

View File

@ -0,0 +1,10 @@
<?php
namespace Webkul\Marketing\Models;
use Konekt\Concord\Proxies\ModelProxy;
class TemplateProxy extends ModelProxy
{
}

View File

@ -0,0 +1,39 @@
<?php
namespace Webkul\Marketing\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Event;
use Webkul\Marketing\Console\Commands\EmailsCommand;
class MarketingServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
$this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
$this->loadRoutesFrom(__DIR__ . '/../Http/routes.php');
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'marketing');
$this->loadViewsFrom(__DIR__ . '/../Resources/views', 'marketing');
}
/**
* Register services.
*
* @return void
*/
public function register()
{
if ($this->app->runningInConsole()) {
$this->commands([EmailsCommand::class]);
}
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Webkul\Marketing\Providers;
use Webkul\Core\Providers\CoreModuleServiceProvider;
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
\Webkul\Marketing\Models\Campaign::class,
\Webkul\Marketing\Models\Template::class,
\Webkul\Marketing\Models\Event::class,
];
}

View File

@ -0,0 +1,18 @@
<?php
namespace Webkul\Marketing\Repositories;
use Webkul\Core\Eloquent\Repository;
class CampaignRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\Marketing\Contracts\Campaign';
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Webkul\Marketing\Repositories;
use Webkul\Core\Eloquent\Repository;
class EventRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\Marketing\Contracts\Event';
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Webkul\Marketing\Repositories;
use Webkul\Core\Eloquent\Repository;
class TemplateRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\Marketing\Contracts\Template';
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/js/shop.js": "/js/shop.js?id=fd3e9e2c897df46dd84c",
"/css/shop.css": "/css/shop.css?id=45a1e46876af32f30871"
"/css/shop.css": "/css/shop.css?id=5f874d3390a80dcc95dd"
}

View File

@ -53,7 +53,10 @@ class ProductsCategoriesProxyController extends Controller
{
$slugOrPath = trim($request->getPathInfo(), '/');
if (preg_match('/^([a-z0-9-]+\/?)+$/', $slugOrPath)) {
$slugOrPath = urldecode($slugOrPath);
// support url for chinese, japanese, arbic and english with numbers.
if (preg_match('/^([\x{0621}-\x{064A}\x{4e00}-\x{9fa5}\x{3402}-\x{FA6D}\x{3041}-\x{30A0}\x{30A0}-\x{31FF}_a-z0-9-]+\/?)+$/u', $slugOrPath)) {
if ($category = $this->categoryRepository->findByPath($slugOrPath)) {
@ -71,7 +74,7 @@ class ProductsCategoriesProxyController extends Controller
}
$sliderRepository = app('Webkul\Core\Repositories\SliderRepository');
$sliderData = $sliderRepository
->where('channel_id', core()->getCurrentChannel()->id)
->where('locale', core()->getCurrentLocale()->code)

View File

@ -2553,21 +2553,24 @@ section.cart {
margin-bottom: 10px;
}
.quantity-container {
display: flex !important;
}
button {
width: 40px;
height: 38px;
font-size: 16px;
background: #ffffff;
border: 1px solid #C7C7C7;
float: left;
cursor: pointer;
&.decrease {
border-radius: 3px 0px 0px 3px;
border-radius: 3px;
}
&.increase {
border-radius: 0px 3px 3px 0px;
border-radius: 3px;
}
}

View File

@ -126,6 +126,7 @@ return [
'conditions' => 'Conditions',
'using' => 'by using this website',
'agreement' => 'Agreement',
'subscribe-to-newsletter' => 'Subscribe to newsletter',
'success' => 'Account created successfully.',
'success-verify' => 'Account created successfully, an e-mail has been sent for verification.',
'success-verify-email-unsent' => 'Account created successfully, but verification e-mail unsent.',

View File

@ -219,10 +219,10 @@
return false;
},
validateForm: function(scope) {
validateForm: async function(scope) {
var this_this = this;
this.$validator.validateAll(scope).then(function (result) {
await this.$validator.validateAll(scope).then(function (result) {
if (result) {
if (scope == 'address-form') {
this_this.saveAddress();
@ -286,7 +286,7 @@
.catch(function (error) {})
},
saveAddress: function() {
saveAddress: async function() {
var this_this = this;
this.disable_button = true;
@ -327,7 +327,7 @@
})
},
saveShipping: function() {
saveShipping: async function() {
var this_this = this;
this.disable_button = true;
@ -351,7 +351,7 @@
})
},
savePayment: function() {
savePayment: async function() {
var this_this = this;
this.disable_button = true;
@ -373,7 +373,7 @@
});
},
placeOrder: function() {
placeOrder: async function() {
var this_this = this;
this.disable_button = true;
@ -610,4 +610,4 @@
})
</script>
@endpush
@endpush

Some files were not shown because too many files have changed in this diff Show More