Merge branch 'trunk'
This commit is contained in:
commit
3b11316017
1066 changed files with 221832 additions and 89713 deletions
|
|
@ -3,9 +3,9 @@ root = true
|
|||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
|
|
@ -14,8 +14,8 @@ trim_trailing_whitespace = false
|
|||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[*.vue]
|
||||
indent_size = 2
|
||||
|
||||
[docker-compose.yml]
|
||||
indent_size = 4
|
||||
|
||||
[*.vue]
|
||||
indent_size = 2
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ DB_PASSWORD_OLD=
|
|||
MIGRATIONPAGINATION=20000
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
QUEUE_CONNECTION=sync
|
||||
CACHE_DRIVER=apc
|
||||
QUEUE_CONNECTION=database
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
|
|
|
|||
|
|
@ -37,5 +37,19 @@
|
|||
"semi": ["error", "always"],
|
||||
"vue/script-indent": ["error", 2, { "baseIndent": 0, "switchCase": 1 }],
|
||||
"vue/one-component-per-file": "off"
|
||||
},
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"node": {
|
||||
"extensions": [".js", ".vue", ".ts", ".d.ts"]
|
||||
},
|
||||
"alias": {
|
||||
"extensions": [".vue", ".js", ".ts", ".scss", ".d.ts"],
|
||||
"map": [
|
||||
["~", "./resources/assets"],
|
||||
["@", "./node_modules"]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
.gitattributes
vendored
14
.gitattributes
vendored
|
|
@ -1,5 +1,11 @@
|
|||
* text=auto
|
||||
*.css linguist-vendored
|
||||
*.scss linguist-vendored
|
||||
*.js linguist-vendored
|
||||
* text=auto eol=lf
|
||||
|
||||
*.blade.php diff=html
|
||||
*.css diff=css
|
||||
*.html diff=html
|
||||
*.md diff=markdown
|
||||
*.php diff=php
|
||||
|
||||
/.github export-ignore
|
||||
CHANGELOG.md export-ignore
|
||||
.styleci.yml export-ignore
|
||||
|
|
|
|||
37
.gitignore
vendored
37
.gitignore
vendored
|
|
@ -1,26 +1,27 @@
|
|||
/node_modules
|
||||
/public/hot
|
||||
/public/storage
|
||||
/public/build
|
||||
/public/medias
|
||||
/public/uploads
|
||||
/public/cache
|
||||
/public/sitemap.xml
|
||||
/storage/*.key
|
||||
/vendor
|
||||
.vscode/
|
||||
.idea/
|
||||
.env
|
||||
.env.testing
|
||||
.env.backup
|
||||
.env.production
|
||||
.phpunit.result.cache
|
||||
.stylelintcache
|
||||
/.fleet
|
||||
/.idea
|
||||
/.phpunit.cache
|
||||
/.vscode
|
||||
/node_modules
|
||||
/bootstrap
|
||||
/public/build
|
||||
/public/cache
|
||||
/public/hot
|
||||
/public/sitemap.xml
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/vendor
|
||||
auth.json
|
||||
docker-compose.override.yml
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
storage/crm_migration.csv
|
||||
MIG/errors_sql.txt
|
||||
public/js
|
||||
public/css
|
||||
public/assets
|
||||
auth.json
|
||||
.npmrc
|
||||
.phpdoc
|
||||
|
|
|
|||
|
|
@ -1,19 +1,23 @@
|
|||
include:
|
||||
- project: 'ldc-web/shared-ci'
|
||||
ref: 'main'
|
||||
file: 'lint/phpcs7.3.yml'
|
||||
- project: 'ldc-web/shared-ci'
|
||||
ref: 'main'
|
||||
file: 'security/composer7.3.yml'
|
||||
- project: 'ldc-web/shared-ci'
|
||||
ref: 'main'
|
||||
file: 'build/composer7.3.yml'
|
||||
- project: 'ldc-web/shared-ci'
|
||||
ref: 'main'
|
||||
file: 'test/test.yml'
|
||||
- project: "ldc-web/shared-ci"
|
||||
ref: "main"
|
||||
file: "lint/lint.yml"
|
||||
- project: "ldc-web/shared-ci"
|
||||
ref: "main"
|
||||
file: "security/security.yml"
|
||||
- project: "ldc-web/shared-ci"
|
||||
ref: "main"
|
||||
file: "build/build.yml"
|
||||
- project: "ldc-web/shared-ci"
|
||||
ref: "main"
|
||||
file: "test/test.yml"
|
||||
- project: "ldc-web/shared-ci"
|
||||
ref: "main"
|
||||
file: "deploy/deploy.yml"
|
||||
|
||||
stages:
|
||||
- lint
|
||||
- security
|
||||
- build
|
||||
- test
|
||||
- lint
|
||||
- security
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
|
|
|||
4
.gitmodules
vendored
4
.gitmodules
vendored
|
|
@ -1,3 +1,3 @@
|
|||
[submodule "clients/V2"]
|
||||
path = clients/V2
|
||||
[submodule "client"]
|
||||
path = client
|
||||
url = git@lab.s-web.fr:ldc-web/projets/crm-client.git
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
{
|
||||
"extends": [
|
||||
"stylelint-config-prettier",
|
||||
"stylelint-config-standard-scss",
|
||||
"stylelint-config-sass-guidelines",
|
||||
"stylelint-config-idiomatic-order"
|
||||
],
|
||||
"plugins": ["stylelint-scss"],
|
||||
"files": ["**/*.css", "**/*.scss"],
|
||||
"plugins": [
|
||||
"stylelint-scss"
|
||||
],
|
||||
"files": [
|
||||
"**/*.css",
|
||||
"**/*.scss"
|
||||
],
|
||||
"ignoreFiles": [
|
||||
"**/vendor/*.css",
|
||||
"**/vendor/**/*.css",
|
||||
|
|
@ -19,16 +23,14 @@
|
|||
],
|
||||
"customSyntax": "postcss-scss",
|
||||
"rules": {
|
||||
"indentation": 4,
|
||||
"string-quotes": "double",
|
||||
"declaration-property-value-no-unknown": true,
|
||||
"selector-max-id": null,
|
||||
"color-no-invalid-hex": true,
|
||||
"order/properties-alphabetical-order": null,
|
||||
"max-nesting-depth": 5,
|
||||
"selector-max-compound-selectors": 5,
|
||||
"declaration-colon-space-after": "always-single-line",
|
||||
"function-parentheses-space-inside": "never-single-line",
|
||||
"declaration-colon-newline-after": null,
|
||||
"value-list-comma-newline-after": null,
|
||||
"scss/double-slash-comment-empty-line-before": [
|
||||
"always",
|
||||
{
|
||||
|
|
|
|||
20
.vscode/extensions.json
vendored
Normal file
20
.vscode/extensions.json
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode",
|
||||
"rvest.vs-code-prettier-eslint",
|
||||
"onecentlin.laravel-extension-pack",
|
||||
"johnpapa.vscode-peacock",
|
||||
"xdebug.php-debug",
|
||||
"neilbrayfield.php-docblocker",
|
||||
"bmewburn.vscode-intelephense-client",
|
||||
"valeryanm.vscode-phpsab",
|
||||
"syler.sass-indented",
|
||||
"sibiraj-s.vscode-scss-formatter",
|
||||
"mrmlnc.vscode-scss",
|
||||
"stylelint.vscode-stylelint",
|
||||
"vue.vscode-typescript-vue-plugin",
|
||||
"wscats.vue",
|
||||
"vue.volar",
|
||||
"misterj.vue-volar-extention-pack"
|
||||
]
|
||||
}
|
||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
|
@ -22,5 +22,5 @@
|
|||
"commandCenter.border": "#15202b99"
|
||||
},
|
||||
"peacock.remoteColor": "#73b137",
|
||||
"intelephense.environment.phpVersion": "7.4"
|
||||
"intelephense.environment.phpVersion": "8.2"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-7.3:latest
|
||||
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-8.2:latest
|
||||
COPY --chown=www-data:www-data . /app/srcs
|
||||
COPY --chown=www-data:www-data ./public /app/srcs/public
|
||||
COPY --chown=www-data:www-data ./vendor /app/srcs/vendor
|
||||
USER root
|
||||
RUN chmod -R 755 /app/srcs/storage
|
||||
USER www-data
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ error_reporting(E_ALL);
|
|||
|
||||
require_once 'Db.php';
|
||||
require_once 'CPlatosChiffrement.class.php';
|
||||
// FIXME: utiliser crm V2
|
||||
require_once 'LDCCRM_V1.php';
|
||||
|
||||
$db = new Database('localhost', 'ldc-crm', 'ldc-crmadm', 'wai6dahB');
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
/**
|
||||
* Creates a new user
|
||||
*/
|
||||
class CreateAdmin extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'user:create';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a backend admin user';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$email = null;
|
||||
while (is_null($email)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
|
||||
$validator = Validator::make(['email' => $tmp], [
|
||||
'email' => 'required|unique:users,email|email:rfc,dns'
|
||||
]);
|
||||
$validator->validate();
|
||||
$email = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid email %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$firstname = null;
|
||||
while (is_null($firstname)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user firstname', 'Admin');
|
||||
$validator = Validator::make(['firstname' => $tmp], [
|
||||
'firstname' => 'required|min:5,max:255'
|
||||
]);
|
||||
$validator->validate();
|
||||
$firstname = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid firstname %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$lastname = null;
|
||||
while (is_null($lastname)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user lastname', 'Saïtama');
|
||||
$validator = Validator::make(['lastname' => $tmp], [
|
||||
'lastname' => 'required|min:5,max:255'
|
||||
]);
|
||||
$validator->validate();
|
||||
$lastname = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid lastname %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$password = $this->secret('Type the wanted user password');
|
||||
|
||||
$admin = new User([
|
||||
'lastname' => $lastname,
|
||||
'firstname' => $firstname,
|
||||
'email' => $email,
|
||||
'password' => $password
|
||||
]);
|
||||
$admin->saveOrFail();
|
||||
|
||||
$this->info('User created.');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -35,10 +35,11 @@ class DeleteUnconfirmedCustomers extends Command
|
|||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): int
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Collection $customersLogins */
|
||||
$customersLogins = CustomerLogin::whereStatus(false)
|
||||
$customersLogins = CustomerLogin::query()
|
||||
->where('status', false)
|
||||
->where('created_at', '<', Carbon::now()->subDay(1))
|
||||
->with(['brand', 'customer'])
|
||||
->get();
|
||||
|
|
|
|||
|
|
@ -7,18 +7,20 @@ use App\Enums\ApiStatus;
|
|||
use App\Enums\ArcadiaOrderType;
|
||||
use App\Enums\Country;
|
||||
use App\Enums\QuestionType;
|
||||
use App\Exceptions\Api\V2\ApiErrorException;
|
||||
use App\Exceptions\Api\V2\CrmException;
|
||||
use App\Exceptions\Api\V4\ApiErrorException;
|
||||
use App\Exceptions\Api\V4\CrmException;
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class GenerateCrmClient extends Command
|
||||
class GenerateClient extends Command
|
||||
{
|
||||
private const TARGET = 'clients/V2/src';
|
||||
private const TARGET = 'client/src';
|
||||
private const CLIENTNAMESPACE = 'LDC\\LDCCRM';
|
||||
|
||||
/**
|
||||
|
|
@ -33,15 +35,16 @@ class GenerateCrmClient extends Command
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Generate the crm v2 client in clients/V2 folder';
|
||||
protected $description = 'Generate the crm V4 client in client folder';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): int
|
||||
{
|
||||
$this->copyTraits();
|
||||
$this->copyEnums();
|
||||
$this->copyExceptions();
|
||||
$this->copyRoutesList();
|
||||
|
|
@ -54,7 +57,7 @@ class GenerateCrmClient extends Command
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
private function copyApiConfigInfo()
|
||||
private function copyApiConfigInfo(): void
|
||||
{
|
||||
$this->info('Copy Api Config');
|
||||
$rootTarget = app_path('../' . self::TARGET);
|
||||
|
|
@ -72,13 +75,13 @@ class GenerateCrmClient extends Command
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
private function copyRoutesList()
|
||||
private function copyRoutesList(): void
|
||||
{
|
||||
$this->info('Copy Routes');
|
||||
$routes = [];
|
||||
/** @var \Illuminate\Routing\Route */
|
||||
foreach (Route::getRoutes() as $route) {
|
||||
if (\strpos($route->getPrefix(), 'v2') !== false) {
|
||||
if (\strpos($route->getPrefix(), 'v4') !== false) {
|
||||
$routes[$route->getName()] = [
|
||||
'uri' => $route->uri(),
|
||||
'methods' => $route->methods()
|
||||
|
|
@ -104,15 +107,36 @@ class GenerateCrmClient extends Command
|
|||
{
|
||||
$this->info('Copy Exceptions');
|
||||
$rootTarget = app_path('../' . self::TARGET);
|
||||
$this->copyToFolder([
|
||||
$classes = [
|
||||
CrmException::class,
|
||||
ApiErrorException::class
|
||||
], 'Exceptions');
|
||||
$this->replaceInPhpFile(
|
||||
"$rootTarget/Exceptions/ApiErrorException.php",
|
||||
'App\Enums\ApiError',
|
||||
'LDC\LDCCRM\Enums\ApiError'
|
||||
);
|
||||
];
|
||||
$this->copyToFolder($classes, 'Exceptions');
|
||||
foreach ($classes as $class) {
|
||||
$classBasename = class_basename($class);
|
||||
$dest = "$rootTarget/Exceptions/$classBasename.php";
|
||||
$this->replaceInPhpFile($dest, 'App\\', self::CLIENTNAMESPACE . '\\');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy base enums classes
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function copyTraits(): void
|
||||
{
|
||||
$this->info('Copy Traits');
|
||||
$rootTarget = app_path('../' . self::TARGET);
|
||||
$classes = [
|
||||
BaseEnum::class
|
||||
];
|
||||
$this->copyToFolder($classes, 'Traits');
|
||||
foreach ($classes as $class) {
|
||||
$classBasename = class_basename($class);
|
||||
$dest = "$rootTarget/Traits/$classBasename.php";
|
||||
$this->replaceInPhpFile($dest, 'App\\', self::CLIENTNAMESPACE . '\\');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -123,7 +147,8 @@ class GenerateCrmClient extends Command
|
|||
private function copyEnums(): void
|
||||
{
|
||||
$this->info('Copy Enums');
|
||||
$classes = [
|
||||
$rootTarget = app_path('../' . self::TARGET);
|
||||
$classes = [
|
||||
ApiError::class,
|
||||
ApiStatus::class,
|
||||
ArcadiaOrderType::class,
|
||||
|
|
@ -131,11 +156,10 @@ class GenerateCrmClient extends Command
|
|||
QuestionType::class
|
||||
];
|
||||
$this->copyToFolder($classes, 'Enums');
|
||||
$rootTarget = app_path('../' . self::TARGET);
|
||||
foreach ($classes as $class) {
|
||||
$classBasename = class_basename($class);
|
||||
$dest = "$rootTarget/Enums/$classBasename.php";
|
||||
$this->replaceInPhpFile($dest, 'BaseEnumRoutable', 'BaseEnum');
|
||||
$this->replaceInPhpFile($dest, 'App\\', self::CLIENTNAMESPACE . '\\');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -148,9 +172,10 @@ class GenerateCrmClient extends Command
|
|||
*/
|
||||
private function copyToFolder(array $classes, string $folder): void
|
||||
{
|
||||
$rootTarget = app_path('../' . self::TARGET);
|
||||
$rootTarget = app_path('../' . self::TARGET);
|
||||
$folderNamespace = \str_replace('/', '\\', $folder);
|
||||
foreach ($classes as $class) {
|
||||
$classFileName = \str_replace("App\\$folder\\", '', sprintf('%s.php', $class));
|
||||
$classFileName = \str_replace("App\\$folderNamespace\\", '', sprintf('%s.php', $class));
|
||||
$classFileName = \str_replace('\\', '/', $classFileName);
|
||||
$classBasename = class_basename($class);
|
||||
$source = \app_path("$folder/$classFileName");
|
||||
|
|
@ -175,11 +200,15 @@ class GenerateCrmClient extends Command
|
|||
{
|
||||
$fContent = File::get($source);
|
||||
|
||||
// Remove trailing \Api\V2 .
|
||||
if ($pos = strpos($fContent, '\Api\V2')) {
|
||||
$fContent = substr_replace($fContent, '', $pos, strlen('\Api\V2'));
|
||||
// Remove trailing \Api\V4 .
|
||||
if ($pos = strpos($fContent, '\Api\V4')) {
|
||||
$fContent = substr_replace($fContent, '', $pos, strlen('\Api\V4'));
|
||||
}
|
||||
|
||||
// Remove trailing \Api .
|
||||
$fContent = Str::of($fContent)->replaceMatches("/\\\(Api)([\s;\\\])/", '$2');
|
||||
$fContent = Str::of($fContent)->replaceMatches("/\\\Traits\\\Enums/", '\Traits');
|
||||
|
||||
// Replace namespace top level.
|
||||
$pos = strpos($fContent, $search);
|
||||
if ($pos !== false) {
|
||||
|
|
@ -12,6 +12,7 @@ use Illuminate\Console\Command;
|
|||
* Author URI: vincent.bridier@ldc.fr
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
*/
|
||||
class LdcWebStatusChecker extends Command
|
||||
{
|
||||
|
|
@ -34,7 +35,7 @@ class LdcWebStatusChecker extends Command
|
|||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): mixed
|
||||
{
|
||||
$data = [];
|
||||
$data['uuid'] = config('ldcweb.project_uuid');
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ namespace App\Console\Commands;
|
|||
|
||||
use App\Lib\MigrateOldData;
|
||||
use App\Models\Brand;
|
||||
use Exception;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
|
|
@ -33,20 +32,20 @@ class MigrateCrmUsers extends Command
|
|||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): int
|
||||
{
|
||||
try {
|
||||
$table = $this->ask('What is the tmp table name with users data ?');
|
||||
|
||||
try {
|
||||
DB::connection(config('database.oldDB'))->table($table)->exists();
|
||||
} catch (Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
$this->error(sprintf('%s table not found on old crm database', $table));
|
||||
return -1;
|
||||
}
|
||||
|
||||
$brandname = $this->ask('What is the brand name ?');
|
||||
$brand = Brand::where('name', 'LIKE', "%$brandname%")->first();
|
||||
$brand = Brand::query()->where('name', 'LIKE', "%$brandname%")->first();
|
||||
if (!$brand) {
|
||||
if (!$this->confirm(sprintf('Would you like to use %s ? ', $brandname))) {
|
||||
$this->info('Command cancelled');
|
||||
|
|
@ -64,10 +63,10 @@ class MigrateCrmUsers extends Command
|
|||
|
||||
$mgOldData = new MigrateOldData();
|
||||
$mgOldData->runMigration($brand, $table);
|
||||
} catch (Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
$this->error(sprintf('Failed %s', $e));
|
||||
return -1;
|
||||
}//end try
|
||||
} //end try
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class StartStatJobs extends Command
|
|||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): int
|
||||
{
|
||||
\dispatch(new JobsStartStatJobs())->afterResponse();
|
||||
return 0;
|
||||
|
|
|
|||
35
app/Console/Commands/TestMail.php
Normal file
35
app/Console/Commands/TestMail.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class TestMail extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'uwil:mail:test';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Send test email to equipe.web@ldc.fr';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Mail::raw(sprintf('UWIL mail-test from %s %s', \config('app.name'), \config('app.url')), function ($msg) {
|
||||
$msg->to('equipe.web@ldc.fr')->subject('Test Email');
|
||||
});
|
||||
}
|
||||
}
|
||||
231
app/Console/Commands/UserCreate.php
Normal file
231
app/Console/Commands/UserCreate.php
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Enums\Users\RoleEnum;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class UserCreate extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'uwil:user:create';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a backend admin user';
|
||||
|
||||
/**
|
||||
* The first name of the new user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $first_name;
|
||||
|
||||
/**
|
||||
* The last name of the new user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $last_name;
|
||||
|
||||
/**
|
||||
* The email of the new user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $email;
|
||||
|
||||
/**
|
||||
* The password of the new user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $password;
|
||||
|
||||
/**
|
||||
* The role of the new user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $role;
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$this->first_name = null;
|
||||
$this->addFirstName();
|
||||
|
||||
$this->last_name = null;
|
||||
$this->addLastName();
|
||||
|
||||
$this->email = null;
|
||||
$this->addEmail();
|
||||
|
||||
$this->password = null;
|
||||
$this->addPassword();
|
||||
|
||||
$this->role = null;
|
||||
$this->addRole();
|
||||
|
||||
$user = new User([
|
||||
'first_name' => $this->first_name,
|
||||
'last_name' => $this->last_name,
|
||||
'email' => $this->email,
|
||||
'password' => $this->password,
|
||||
'role' => $this->role,
|
||||
'published' => true,
|
||||
'published_at' => Carbon::now(),
|
||||
]);
|
||||
$user->saveOrFail();
|
||||
|
||||
$this->info('User created 👌');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a first name to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addFirstName(): void
|
||||
{
|
||||
while (is_null($this->first_name)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user first name', 'Admin');
|
||||
$validator = Validator::make(['first_name' => $tmp], [
|
||||
'first_name' => 'required|min:3|max:255'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->first_name = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid first name %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a last name to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addLastName(): void
|
||||
{
|
||||
while (is_null($this->last_name)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user last name', 'Saïtama');
|
||||
$validator = Validator::make(['last_name' => $tmp], [
|
||||
'last_name' => 'required|min:3|max:255'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->last_name = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid last_name %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an email to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addEmail(): void
|
||||
{
|
||||
while (is_null($this->email)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
|
||||
$validator = Validator::make(['email' => $tmp], [
|
||||
'email' => 'required|unique:users,email|email:rfc,dns'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->email = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid email %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a password to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addPassword(): void
|
||||
{
|
||||
while (
|
||||
($this->password = $this->secret(
|
||||
(!\is_null($this->password) ? 'Failed to confirm, ' : '') . 'Type the wanted user password'
|
||||
)) !== $this->secret('Confirm the password')
|
||||
) {
|
||||
continue;
|
||||
}; //end while
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a role to the user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addRole(): void
|
||||
{
|
||||
while (is_null($this->role)) {
|
||||
try {
|
||||
$tmp = $this->choice(
|
||||
'Select his role',
|
||||
[RoleEnum::conceptor->name, RoleEnum::admin->name, RoleEnum::visitor->name],
|
||||
RoleEnum::visitor->name,
|
||||
$maxAttempts = null,
|
||||
$allowMultipleSelections = false
|
||||
);
|
||||
if ($tmp === RoleEnum::conceptor->name) {
|
||||
$tmp = RoleEnum::conceptor;
|
||||
}
|
||||
if ($tmp === RoleEnum::admin->name) {
|
||||
$tmp = RoleEnum::admin;
|
||||
}
|
||||
if ($tmp === RoleEnum::visitor->name) {
|
||||
$tmp = RoleEnum::visitor;
|
||||
}
|
||||
$validator = Validator::make(['role' => $tmp], [
|
||||
'role' => 'required'
|
||||
]);
|
||||
$validator->validate();
|
||||
$this->role = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please choose from the selection',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
} //end try
|
||||
}; //end while
|
||||
}
|
||||
}
|
||||
|
|
@ -7,9 +7,6 @@ use App\Jobs\StartStatJobs;
|
|||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
|
|
@ -25,10 +22,12 @@ class Kernel extends ConsoleKernel
|
|||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
protected function schedule(Schedule $schedule): void
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
$schedule->job(StartStatJobs::class)->dailyAt('03:30');
|
||||
$schedule->command(DeleteUnconfirmedCustomers::class)->dailyAt('05:30');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -36,7 +35,7 @@ class Kernel extends ConsoleKernel
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function commands()
|
||||
protected function commands(): void
|
||||
{
|
||||
$this->load(__DIR__ . '/Commands');
|
||||
|
||||
|
|
|
|||
46
app/Enums/ActivityLogs/ActivityLogsEventEnum.php
Normal file
46
app/Enums/ActivityLogs/ActivityLogsEventEnum.php
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\ActivityLogs;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum ActivityLogsEventEnum: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case created = 1;
|
||||
case updated = 2;
|
||||
case duplicated = 3;
|
||||
case deleted = 4;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::created->name => 'Création',
|
||||
self::updated->name => 'Mise à jour',
|
||||
self::duplicated->name => 'Duplication',
|
||||
self::deleted->name => 'Suppression',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Custom added classes definition
|
||||
*/
|
||||
private const BOOTSTRAPCLASS = [
|
||||
self::created->name => 'success',
|
||||
self::updated->name => 'warning',
|
||||
self::duplicated->name => 'secondary',
|
||||
self::deleted->name => 'danger',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get Class
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function bootstrapClass(): string
|
||||
{
|
||||
return self::BOOTSTRAPCLASS[$this->name];
|
||||
}
|
||||
}
|
||||
|
|
@ -2,113 +2,43 @@
|
|||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
/**
|
||||
* This describes an API error.
|
||||
*
|
||||
* @method static self modelNotFound()
|
||||
* The request model was not found (typically the customer)
|
||||
*
|
||||
* @method static self validationFailed()
|
||||
* This means some data could not be validated,
|
||||
* you may have to look into message to get the details
|
||||
*
|
||||
* @method static self customerExists()
|
||||
* The customer already exists
|
||||
*
|
||||
* @method static self customerNotActivated()
|
||||
* The customer account is not activated and cannot perform
|
||||
* this action
|
||||
*
|
||||
* @method static self customerAlreadyActive()
|
||||
* You have requested to activate a customer account,
|
||||
* but it is already active
|
||||
*
|
||||
* @method static self singleOptinCustomerExists()
|
||||
* You have requested to create a single optin for an email,
|
||||
* but it already exists
|
||||
*
|
||||
* @method static self apiAuthFailed()
|
||||
* The authentification to the api failed. You may have to
|
||||
* check into config or .env file for your service credentials
|
||||
*
|
||||
* @method static self authFailed()
|
||||
* The authentification for this customer failed because of wrong credentials
|
||||
*
|
||||
* @method static self methodNotAllowed()
|
||||
* This http method is not allowed
|
||||
*
|
||||
* @method static self wrongTimeStamp()
|
||||
* The timestamp given is wrong. This would happen in case if
|
||||
* a replay attack scenario. Timestamps are provided in headers
|
||||
* and in the http body
|
||||
*
|
||||
* @method static self missingParameter()
|
||||
* The request is missing some parameters
|
||||
*
|
||||
* @method static self throttleRequestsException()
|
||||
* Too many requests have been attempted. The is a throttle security.
|
||||
* Normally you should not trigger this.
|
||||
* If this happens fill a ticket on https://supportweb.ldc.fr
|
||||
* with some technical details
|
||||
*
|
||||
* @method static self authorizationException()
|
||||
* You are maybe trying to access data that is out of your range.
|
||||
* This should not happen normally, it is here to allow you to handle this case.
|
||||
* If this happens fill a ticket on https://supportweb.ldc.fr
|
||||
* with some technical details
|
||||
*
|
||||
* @package LDCCrmClient
|
||||
* @subpackage enums
|
||||
*/
|
||||
class ApiError extends BaseEnumRoutable
|
||||
enum ApiError: int
|
||||
{
|
||||
/**
|
||||
* Valeurs des possibilités de cet énumération (value)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function values(): array
|
||||
{
|
||||
return [
|
||||
'modelNotFound' => 101,
|
||||
'validationFailed' => 102,
|
||||
'customerExists' => 103,
|
||||
'customerAlreadyActive' => 110,
|
||||
'customerNotActivated' => 116,
|
||||
'authFailed' => 117,
|
||||
'apiAuthFailed' => 119,
|
||||
'singleOptinCustomerExists' => 120,
|
||||
'methodNotAllowed' => 150,
|
||||
'wrongTimeStamp' => 151,
|
||||
'missingParameter' => 400,
|
||||
'authorizationException' => 403,
|
||||
'throttleRequestsException' => 429
|
||||
];
|
||||
}
|
||||
use BaseEnum;
|
||||
|
||||
case modelNotFound = 101;
|
||||
case validationFailed = 102;
|
||||
case customerExists = 103;
|
||||
case customerAlreadyActive = 110;
|
||||
case customerNotActivated = 116;
|
||||
case authFailed = 117;
|
||||
case apiAuthFailed = 119;
|
||||
case singleOptinCustomerExists = 120;
|
||||
case methodNotAllowed = 150;
|
||||
case wrongTimeStamp = 151;
|
||||
case missingParameter = 400;
|
||||
case authorizationException = 403;
|
||||
case throttleRequestsException = 429;
|
||||
|
||||
/**
|
||||
* Libellés des possibilités de cet énumération (label)
|
||||
*
|
||||
* @return array
|
||||
* Optionnal labels definition
|
||||
*/
|
||||
public static function labels(): array
|
||||
{
|
||||
return [
|
||||
'modelNotFound' => '%s introuvable.',
|
||||
'validationFailed' => 'Impossible de valider les données',
|
||||
'customerExists' => 'L\'utilisateur est déjà enregistré sur ce site',
|
||||
'customerNotActivated' => 'Le compte n\'est pas activé',
|
||||
'customerAlreadyActive' => 'Le compte est déjà activé',
|
||||
'singleOptinCustomerExists' => 'Le single optin ne peut être ajouté car un compte existe.',
|
||||
'authFailed' => 'Echec de l\'authentification du compte',
|
||||
'apiAuthFailed' => 'Echec de l\'authentification client à l\'Api LDC-CRM pour ce service',
|
||||
'methodNotAllowed' => 'This method is not allowed for this request',
|
||||
'wrongTimeStamp' => 'Your request is malformed, please check timestamp header and parameter',
|
||||
'missingParameter' => 'The request is missing some parameters',
|
||||
'authorizationException' => 'You are not autorized to access this',
|
||||
'throttleRequestsException' => 'Throttle: too many request have been attempted, please retry later'
|
||||
];
|
||||
}
|
||||
private const LABELS = [
|
||||
self::modelNotFound->name => '%s introuvable.',
|
||||
self::validationFailed->name => 'Impossible de valider les données',
|
||||
self::customerExists->name => 'L\'utilisateur est déjà enregistré sur ce site',
|
||||
self::customerNotActivated->name => 'Le compte n\'est pas activé',
|
||||
self::customerAlreadyActive->name => 'Le compte est déjà activé',
|
||||
self::singleOptinCustomerExists->name => 'Le single optin ne peut être ajouté car un compte existe.',
|
||||
self::authFailed->name => 'Echec de l\'authentification du compte',
|
||||
self::apiAuthFailed->name => 'Echec de l\'authentification client à l\'Api LDC-CRM pour ce service',
|
||||
self::methodNotAllowed->name => 'This method is not allowed for this request',
|
||||
self::wrongTimeStamp->name => 'Your request is malformed, please check timestamp header and
|
||||
parameter',
|
||||
self::missingParameter->name => 'The request is missing some parameters',
|
||||
self::authorizationException->name => 'You are not autorized to access this',
|
||||
self::throttleRequestsException->name => 'Throttle: too many request have been attempted, please retry later'
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,15 +2,12 @@
|
|||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self OK()
|
||||
* @method static self KO()
|
||||
*
|
||||
* @package LDCCrmClient
|
||||
* @subpackage enums
|
||||
*/
|
||||
class ApiStatus extends BaseEnumRoutable
|
||||
enum ApiStatus: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case OK = 1;
|
||||
case KO = 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,27 +2,12 @@
|
|||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self default()
|
||||
* @method static self game()
|
||||
*
|
||||
* @package LDCCrmClient
|
||||
* @subpackage enums
|
||||
*/
|
||||
class ArcadiaMailType extends BaseEnumRoutable
|
||||
enum ArcadiaMailType: int
|
||||
{
|
||||
/**
|
||||
* Valeurs des possibilités de cet énumération (value)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function values(): array
|
||||
{
|
||||
return [
|
||||
'default' => 1,
|
||||
'game' => 2
|
||||
];
|
||||
}
|
||||
use BaseEnum;
|
||||
|
||||
case default = 1;
|
||||
case game = 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,27 +2,12 @@
|
|||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self cb()
|
||||
* @method static self check()
|
||||
*
|
||||
* @package LDCCrmClient
|
||||
* @subpackage enums
|
||||
*/
|
||||
class ArcadiaOrderType extends BaseEnumRoutable
|
||||
enum ArcadiaOrderType: int
|
||||
{
|
||||
/**
|
||||
* Valeurs des possibilités de cet énumération (value)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function values(): array
|
||||
{
|
||||
return [
|
||||
'cb' => 0,
|
||||
'check' => 1
|
||||
];
|
||||
}
|
||||
use BaseEnum;
|
||||
|
||||
case cb = 0;
|
||||
case check = 1;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -2,42 +2,22 @@
|
|||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self singleOptin()
|
||||
* @method static self customer()
|
||||
* @method static self both()
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CustomerExportType extends BaseEnumRoutable
|
||||
enum CustomerExportType: int
|
||||
{
|
||||
/**
|
||||
* Valeurs des possibilités de cet énumération (value)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function values(): array
|
||||
{
|
||||
return [
|
||||
'singleOptin' => 1,
|
||||
'customer' => 2,
|
||||
'both' => 3
|
||||
];
|
||||
}
|
||||
use BaseEnum;
|
||||
|
||||
case singleOptin = 1;
|
||||
case customer = 2;
|
||||
case both = 3;
|
||||
|
||||
/**
|
||||
* Libellés des possibilités de cet énumération (label)
|
||||
*
|
||||
* @return array
|
||||
* Optionnal labels definition
|
||||
*/
|
||||
public static function labels(): array
|
||||
{
|
||||
return [
|
||||
'singleOptin' => trans('Les single optins uniquement'),
|
||||
'customer' => trans('Les clients uniquement acceptant de recevoir les newsletters'),
|
||||
'both' => trans('La totalité des client acceptant de recevoir les newsletters')
|
||||
];
|
||||
}
|
||||
private const LABELS = [
|
||||
self::singleOptin->name => 'Les single optins uniquement',
|
||||
self::customer->name => 'Les clients uniquement acceptant de recevoir les newsletters',
|
||||
self::both->name => 'La totalité des client acceptant de recevoir les newsletters',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
16
app/Enums/Pagination/ItemsPerPaginationEnum.php
Normal file
16
app/Enums/Pagination/ItemsPerPaginationEnum.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Pagination;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum ItemsPerPaginationEnum: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case five = 5;
|
||||
case twelve = 12;
|
||||
case twentyfive = 25;
|
||||
case fifty = 50;
|
||||
case onehundred = 100;
|
||||
}
|
||||
|
|
@ -2,29 +2,13 @@
|
|||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self select()
|
||||
* @method static self radio()
|
||||
* @method static self checkbox()
|
||||
*
|
||||
* @package LDCCrmClient
|
||||
* @subpackage enums
|
||||
*/
|
||||
class QuestionType extends BaseEnumRoutable
|
||||
enum QuestionType: int
|
||||
{
|
||||
/**
|
||||
* Valeurs des possibilités de cet énumération (value)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function values(): array
|
||||
{
|
||||
return [
|
||||
'select' => 1,
|
||||
'radio' => 2,
|
||||
'checkbox' => 3
|
||||
];
|
||||
}
|
||||
use BaseEnum;
|
||||
|
||||
case select = 1;
|
||||
case radio = 2;
|
||||
case checkbox = 3;
|
||||
}
|
||||
|
|
|
|||
21
app/Enums/Theme/BootstrapThemeEnum.php
Normal file
21
app/Enums/Theme/BootstrapThemeEnum.php
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Theme;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum BootstrapThemeEnum: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case light = 1;
|
||||
case dark = 2;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::light->name => 'Light',
|
||||
self::dark->name => 'Dark',
|
||||
];
|
||||
}
|
||||
23
app/Enums/Users/RoleEnum.php
Normal file
23
app/Enums/Users/RoleEnum.php
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Users;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum RoleEnum: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case conceptor = 1;
|
||||
case admin = 2;
|
||||
case visitor = 3;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::conceptor->name => 'Concepteur',
|
||||
self::admin->name => 'Administrateur',
|
||||
self::visitor->name => 'Visiteur',
|
||||
];
|
||||
}
|
||||
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* This class Exception is used to skip a row import from
|
||||
* database migration (2016 -> 2020)
|
||||
*
|
||||
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
|
||||
*/
|
||||
class AbortRowImportException extends Exception
|
||||
class AbortRowImportException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ use Throwable;
|
|||
/**
|
||||
* This would be thrown if any of the case
|
||||
* referenced in \App\Enums\ApiError would
|
||||
* occur within the crm
|
||||
* occur within the crm.
|
||||
*
|
||||
* On the client an ApiErrorException would
|
||||
* also be throw with the ApiError corresponding to
|
||||
* the situation
|
||||
* the situation.
|
||||
*
|
||||
* @package LDCCrmClient
|
||||
* @subpackage exceptions
|
||||
|
|
@ -34,7 +34,7 @@ class ApiErrorException extends Exception
|
|||
/**
|
||||
* This is an explicit error message,
|
||||
* ou may print this to the front or not depending
|
||||
* on $error value
|
||||
* on $error value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
|
@ -52,10 +52,10 @@ class ApiErrorException extends Exception
|
|||
/**
|
||||
* Create a new exception base on ApiError enum.
|
||||
*
|
||||
* @param ApiError $error
|
||||
* @param integer $httpCode
|
||||
* @param string $message
|
||||
* @param Throwable|null $previous
|
||||
* @param \App\Enums\ApiError $error
|
||||
* @param integer $httpCode
|
||||
* @param string $message
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct(ApiError $error, int $httpCode = 400, string $message = '', Throwable $previous = null)
|
||||
{
|
||||
|
|
@ -63,16 +63,16 @@ class ApiErrorException extends Exception
|
|||
$this->message = $message;
|
||||
$this->httpCode = $httpCode;
|
||||
parent::__construct(
|
||||
strlen($this->message) ? $this->message : $error->label,
|
||||
$error->value,
|
||||
strlen($this->message) ? $this->message : $error->label(),
|
||||
$error->value(),
|
||||
$previous
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Api Error
|
||||
* Get the Api Error.
|
||||
*
|
||||
* @return ApiError
|
||||
* @return \App\Enums\ApiError
|
||||
*/
|
||||
public function getApiError(): ApiError
|
||||
{
|
||||
|
|
@ -80,7 +80,7 @@ class ApiErrorException extends Exception
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the http code
|
||||
* Get the http code.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
|
|
@ -95,7 +95,7 @@ class ApiErrorException extends Exception
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public function report()
|
||||
public function report(): void
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
Log::debug(sprintf('CRM API: %s', $this->getMessage()));
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use Illuminate\Support\Facades\Log;
|
|||
*
|
||||
* @package LDCCrmClient
|
||||
* @subpackage exceptions
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CrmException extends Exception
|
||||
{
|
||||
|
|
@ -22,7 +21,7 @@ class CrmException extends Exception
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public function report()
|
||||
public function report(): void
|
||||
{
|
||||
Log::critical(sprintf('CRM API: %s', $this->getMessage()));
|
||||
}
|
||||
|
|
|
|||
102
app/Exceptions/Api/V4/ApiErrorException.php
Normal file
102
app/Exceptions/Api/V4/ApiErrorException.php
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
|
||||
namespace App\Exceptions\Api\V4;
|
||||
|
||||
use App\Enums\ApiError;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* This would be thrown if any of the case
|
||||
* referenced in \App\Enums\ApiError would
|
||||
* occur within the crm.
|
||||
*
|
||||
* On the client an ApiErrorException would
|
||||
* also be throw with the ApiError corresponding to
|
||||
* the situation.
|
||||
*
|
||||
* @package LDCCrmClient
|
||||
* @subpackage exceptions
|
||||
*/
|
||||
class ApiErrorException extends \RuntimeException
|
||||
{
|
||||
/**
|
||||
* Api Error
|
||||
* This value makes the error more explicit.
|
||||
* Handling these errors are normal as inputs or
|
||||
* request may be undesired or refused by the crm.
|
||||
*
|
||||
* @var \App\Enums\ApiError
|
||||
*/
|
||||
protected $error;
|
||||
|
||||
/**
|
||||
* This is an explicit error message,
|
||||
* ou may print this to the front or not depending
|
||||
* on $error value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $message;
|
||||
|
||||
/**
|
||||
* This is the http code returned by the crm.
|
||||
* This value could be used to handle errors.
|
||||
* But please take in consideration $error first.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $httpCode;
|
||||
|
||||
/**
|
||||
* Create a new exception base on ApiError enum.
|
||||
*
|
||||
* @param \App\Enums\ApiError $error
|
||||
* @param integer $httpCode
|
||||
* @param string $message
|
||||
* @param \Throwable|null $previous
|
||||
*/
|
||||
public function __construct(ApiError $error, int $httpCode = 400, string $message = '', \Throwable $previous = null)
|
||||
{
|
||||
$this->error = $error;
|
||||
$this->message = $message;
|
||||
$this->httpCode = $httpCode;
|
||||
parent::__construct(
|
||||
strlen($this->message) ? $this->message : $error->label(),
|
||||
$error->value(),
|
||||
$previous
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Api Error.
|
||||
*
|
||||
* @return \App\Enums\ApiError
|
||||
*/
|
||||
public function getApiError(): ApiError
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the http code.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getStatusCode(): int
|
||||
{
|
||||
return $this->httpCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used by laravel only.
|
||||
* It uses Log class to print the error.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function report(): void
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
Log::debug(sprintf('CRM API: %s', $this->getMessage()));
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
28
app/Exceptions/Api/V4/CrmException.php
Normal file
28
app/Exceptions/Api/V4/CrmException.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace App\Exceptions\Api\V4;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* This is a critical error.
|
||||
* The request could not be handled. You may dump any value you can
|
||||
* get before submitting a ticker to https://support.uwil.fr/
|
||||
*
|
||||
* @package LDCCrmClient
|
||||
* @subpackage exceptions
|
||||
*
|
||||
*/
|
||||
class CrmException extends \RuntimeException
|
||||
{
|
||||
/**
|
||||
* This is used by laravel only.
|
||||
* It uses Log class to print the error.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function report(): void
|
||||
{
|
||||
Log::critical(sprintf('CRM API: %s', $this->getMessage()));
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,10 @@ namespace App\Exceptions;
|
|||
|
||||
use App\Enums\ApiError;
|
||||
use App\Enums\ApiStatus;
|
||||
use App\Exceptions\Api\V2\ApiErrorException;
|
||||
use App\Exceptions\Api\V2\ApiErrorException as V2ApiErrorException;
|
||||
use App\Exceptions\Api\V4\ApiErrorException as V4ApiErrorException;
|
||||
use App\Http\Resources\Api\V2\ApiResponse as V2ApiResponse;
|
||||
use App\Http\Resources\Api\V4\ApiResponse as V4ApiResponse;
|
||||
use App\Lib\Helper;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
|
|
@ -15,6 +17,7 @@ use Illuminate\Http\JsonResponse;
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
|
|
@ -44,7 +47,7 @@ class Handler extends ExceptionHandler
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
public function register(): void
|
||||
{
|
||||
$this->reportable(function (\Throwable $e) {
|
||||
if (app()->bound('sentry')) {
|
||||
|
|
@ -60,10 +63,10 @@ class Handler extends ExceptionHandler
|
|||
* @param \Throwable $e
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function render($request, \Throwable $e)
|
||||
public function render(mixed $request, \Throwable $e): Response
|
||||
{
|
||||
if (Helper::isRequestForApiV2($request) and $request->isJson()) {
|
||||
return $this->handleApiV2Exception($request, $e);
|
||||
if ((Helper::isRequestForApiV2($request) || Helper::isRequestForApiV4($request)) and $request->isJson()) {
|
||||
return $this->handleApiException($request, $e);
|
||||
} //end if
|
||||
// @codeCoverageIgnoreStart
|
||||
return parent::render($request, $e);
|
||||
|
|
@ -71,13 +74,13 @@ class Handler extends ExceptionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* Generate a json response for any apiV2 error case
|
||||
* Generate a json response for any apiV4 error case.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Throwable $e
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
private function handleApiV2Exception(Request $request, \Throwable $e): JsonResponse
|
||||
private function handleApiException(Request $request, \Throwable $e): JsonResponse
|
||||
{
|
||||
switch (get_class($e)) {
|
||||
case AuthenticationException::class:
|
||||
|
|
@ -85,24 +88,24 @@ class Handler extends ExceptionHandler
|
|||
return $this->getReponse(
|
||||
$request,
|
||||
401,
|
||||
ApiError::apiAuthFailed()->value,
|
||||
sprintf('%s, %s', ApiError::apiAuthFailed()->label, $e->getMessage())
|
||||
ApiError::apiAuthFailed->value(),
|
||||
sprintf('%s, %s', ApiError::apiAuthFailed->label(), $e->getMessage())
|
||||
);
|
||||
case MethodNotAllowedHttpException::class:
|
||||
/** @var MethodNotAllowedHttpException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
$e->getStatusCode(),
|
||||
ApiError::methodNotAllowed()->value,
|
||||
sprintf('%s, %s', ApiError::methodNotAllowed()->label, $e->getMessage())
|
||||
ApiError::methodNotAllowed->value(),
|
||||
sprintf('%s, %s', ApiError::methodNotAllowed->label(), $e->getMessage())
|
||||
);
|
||||
case ValidationException::class:
|
||||
/** @var ValidationException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
$e->status,
|
||||
ApiError::validationFailed()->value,
|
||||
sprintf(ApiError::validationFailed()->label, $e->getMessage()),
|
||||
ApiError::validationFailed->value(),
|
||||
sprintf(ApiError::validationFailed->label(), $e->getMessage()),
|
||||
['errors' => $e->errors()]
|
||||
);
|
||||
case ModelNotFoundException::class:
|
||||
|
|
@ -110,14 +113,22 @@ class Handler extends ExceptionHandler
|
|||
return $this->getReponse(
|
||||
$request,
|
||||
404,
|
||||
ApiError::modelNotFound()->value,
|
||||
ApiError::modelNotFound->value(),
|
||||
sprintf(
|
||||
ApiError::modelNotFound()->label,
|
||||
ApiError::modelNotFound->label(),
|
||||
\array_slice(explode('\\', $e->getModel()), -1)[0]
|
||||
)
|
||||
);
|
||||
case ApiErrorException::class:
|
||||
/** @var ApiErrorException $e */
|
||||
case V4ApiErrorException::class:
|
||||
/** @var \App\Exceptions\Api\V4\ApiErrorException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
$e->getStatusCode(),
|
||||
$e->getCode(),
|
||||
$e->getMessage()
|
||||
);
|
||||
case V2ApiErrorException::class:
|
||||
/** @var \App\Exceptions\Api\V2\ApiErrorException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
$e->getStatusCode(),
|
||||
|
|
@ -129,16 +140,16 @@ class Handler extends ExceptionHandler
|
|||
return $this->getReponse(
|
||||
$request,
|
||||
429,
|
||||
ApiError::throttleRequestsException()->value,
|
||||
ApiError::throttleRequestsException()->label
|
||||
ApiError::throttleRequestsException->value(),
|
||||
ApiError::throttleRequestsException->label()
|
||||
);
|
||||
case AuthorizationException::class:
|
||||
/** @var AuthorizationException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
403,
|
||||
ApiError::authorizationException()->value,
|
||||
ApiError::authorizationException()->label
|
||||
ApiError::authorizationException->value(),
|
||||
ApiError::authorizationException->label()
|
||||
);
|
||||
} //end switch
|
||||
// @codeCoverageIgnoreStart
|
||||
|
|
@ -151,7 +162,7 @@ class Handler extends ExceptionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* Generate an ApiV2 json response
|
||||
* Generate an ApiV4 json response.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param integer $httpCode
|
||||
|
|
@ -167,9 +178,15 @@ class Handler extends ExceptionHandler
|
|||
string $message,
|
||||
array $data = []
|
||||
): JsonResponse {
|
||||
return (new V2ApiResponse(
|
||||
if (Helper::isRequestForApiV2($request)) {
|
||||
return (new V2ApiResponse(
|
||||
(object)array_merge($data, ['message' => $message, 'code' => $apiCode]),
|
||||
ApiStatus::KO
|
||||
))->toResponse($request)->setStatusCode($httpCode);
|
||||
}
|
||||
return (new V4ApiResponse(
|
||||
(object)array_merge($data, ['message' => $message, 'code' => $apiCode]),
|
||||
ApiStatus::KO()
|
||||
ApiStatus::KO
|
||||
))->toResponse($request)->setStatusCode($httpCode);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,363 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\StatusResource;
|
||||
use App\Mail\CourrierArcadiaError;
|
||||
use App\Models\Customer;
|
||||
use DOMDocument;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ArcadiaController extends Controller
|
||||
{
|
||||
/**
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function outgoingMail(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'crm_id' => 'required',
|
||||
'fields' => 'required|json',
|
||||
'type' => 'required',
|
||||
'shipping' => 'required_if:type,default|json'
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return new StatusResource([
|
||||
'status' => 'KO',
|
||||
'code' => 201,
|
||||
'message' => 'Error on required fields.',
|
||||
'errors' => $validator->errors()
|
||||
]);
|
||||
}
|
||||
|
||||
$brandId = $request->brand_id;
|
||||
$crmId = $request->crm_id;
|
||||
$fields = json_decode($request->fields);
|
||||
$type = $request->type;
|
||||
$shipping = $type === 'default' ? json_decode($request->shipping) : false;
|
||||
|
||||
$customer = Customer::where('id', $crmId)->first();
|
||||
if (!$customer) {
|
||||
return new StatusResource(['status' => 'KO', 'code' => 202, 'message' => 'User not found.']);
|
||||
}
|
||||
|
||||
$CustomerInfo = $customer->infos()->where('brand_id', $brandId)->first();
|
||||
|
||||
if (!$CustomerInfo) {
|
||||
return new StatusResource(['status' => 'KO', 'code' => 202, 'message' => 'User not found.']);
|
||||
}
|
||||
|
||||
$check = $this->checkRequiredFields($fields, $type);
|
||||
if ($check['status'] !== 'OK') {
|
||||
return new StatusResource($check);
|
||||
}
|
||||
|
||||
if ($type === 'default') {
|
||||
$check = $this->checkShippingRequiredFields($shipping);
|
||||
if ($check['status'] !== 'OK') {
|
||||
return new StatusResource($check);
|
||||
}
|
||||
}
|
||||
|
||||
$xml = $this->makeXml($fields, $type, $customer, $CustomerInfo, $shipping);
|
||||
|
||||
try {
|
||||
Storage::disk('arcadia')->put(date("Ymd_His") . microtime(true) . ".xml", $xml);
|
||||
return new StatusResource(['status' => 'OK']);
|
||||
} catch (\Exception $e) {
|
||||
Log::critical("ARCADIA XML CREATION FAILED : " . $e->getMessage());
|
||||
Mail::to(config('mail.MAIL_ADMIN'))->send(new CourrierArcadiaError(
|
||||
"ARCADIA XML CREATION FAILED",
|
||||
"Une erreur est survenue lors de la création du fichier XML : " . $e->getMessage(),
|
||||
$xml ?: ''
|
||||
));
|
||||
return new StatusResource(['status' => 'KO', 'code' => 204, 'message' => 'Arcadia XML Creation failed.']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $fields
|
||||
* @return array
|
||||
*/
|
||||
private function checkShippingRequiredFields($fields)
|
||||
{
|
||||
$test = [
|
||||
'firstname',
|
||||
'lastname',
|
||||
'address',
|
||||
'city',
|
||||
'postcode'
|
||||
];
|
||||
|
||||
foreach ($test as $t) {
|
||||
if (!array_key_exists($t, $fields)) {
|
||||
$errors[] = ['field' => $t, 'error' => 'required'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
return ['status' => 'KO', 'code' => 203, 'message' => $errors];
|
||||
}
|
||||
|
||||
return ['status' => 'OK'];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $fields
|
||||
* @param mixed $type
|
||||
* @return array
|
||||
*/
|
||||
// phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh, Squiz.Commenting.FunctionComment.Missing
|
||||
private function checkRequiredFields($fields, $type): array
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$key = array_search('operation', array_column($fields->root, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$errors[] = ['field' => 'operation', 'error' => 'required'];
|
||||
}
|
||||
|
||||
$key = array_search('support_code', array_column($fields->orderLine, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$errors[] = ['field' => 'support_code', 'error' => 'required'];
|
||||
}
|
||||
|
||||
$key = array_search('label_type_support', array_column($fields->orderLine, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$errors[] = ['field' => 'label_type_support', 'error' => 'required'];
|
||||
}
|
||||
|
||||
$key = array_search('order_date', array_column($fields->root, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$errors[] = ['field' => 'order_date', 'error' => 'required'];
|
||||
}
|
||||
|
||||
$regex = join('', [
|
||||
'/^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|',
|
||||
'((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))',
|
||||
'|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]',
|
||||
'|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/'
|
||||
]);
|
||||
if (!preg_match($regex, $fields->root[$key]->fieldValue)) {
|
||||
$errors[] = ['field' => 'order_date', 'error' => 'format must be DD/MM/YYYY'];
|
||||
}
|
||||
|
||||
if ($type === 'default') {
|
||||
$key = array_search('order_num', array_column($fields->root, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$errors[] = ['field' => 'order_num', 'error' => 'required for default type'];
|
||||
}
|
||||
|
||||
if (!is_numeric($fields->root[$key]->fieldValue) || strlen($fields->root[$key]->fieldValue) !== 9) {
|
||||
$errors[] = ['field' => 'order_num', 'error' => 'format must be 9 numeric characters'];
|
||||
}
|
||||
|
||||
$key = array_search('state_order_cb', array_column($fields->root, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$errors[] = ['field' => 'state_order_cb', 'error' => 'required for default type'];
|
||||
}
|
||||
|
||||
if ($fields->root[$key]->fieldValue !== 1 && $fields->root[$key]->fieldValue !== 'Null') {
|
||||
$errors[] = ['field' => 'state_order_cb', 'error' => 'value must be 1 or Null (Yes Null not NULL)'];
|
||||
}
|
||||
|
||||
$orderCB = $fields->root[$key]->fieldValue;
|
||||
|
||||
$key = array_search('state_order_check', array_column($fields->root, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$errors[] = ['field' => 'state_order_check', 'error' => 'required for default type'];
|
||||
}
|
||||
|
||||
if ($fields->root[$key]->fieldValue !== 1 && $fields->root[$key]->fieldValue !== 'Null') {
|
||||
$errors[] = ['field' => 'state_order_check', 'error' => 'value must be 1 or Null (Yes Null not NULL)'];
|
||||
}
|
||||
|
||||
$orderCheck = $fields->root[$key]->fieldValue;
|
||||
|
||||
if ($orderCB === $orderCheck) {
|
||||
$errors[] = [
|
||||
'field' => 'state_order',
|
||||
'error' => 'state_order_cb and state_order_check values must be different'
|
||||
];
|
||||
}
|
||||
|
||||
$key = array_search('package_unit_weight', array_column($fields->orderLine, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$errors[] = ['field' => 'package_unit_weight', 'error' => 'required for default type'];
|
||||
}
|
||||
} elseif ($type === 'game') {
|
||||
$key = array_search('code_unique', array_column($fields->orderLine, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$errors[] = ['field' => 'code_unique', 'error' => 'required for game type'];
|
||||
}
|
||||
}//end if
|
||||
|
||||
if (!empty($errors)) {
|
||||
return ['status' => 'KO', 'code' => 203, 'message' => $errors];
|
||||
}
|
||||
|
||||
return ['status' => 'OK'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $fields
|
||||
* @param mixed $type
|
||||
* @param mixed $customer
|
||||
* @param mixed $customerInfos
|
||||
* @param mixed $shipping
|
||||
* @return string|false
|
||||
*/
|
||||
// phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh, Squiz.Commenting.FunctionComment.Missing
|
||||
private function makeXml($fields, $type, $customer, $customerInfos, $shipping)
|
||||
{
|
||||
$pivot = [
|
||||
'order_num' => 'Num_Commande',
|
||||
// Required if type = default - format 9 numeric characters.
|
||||
'order_date' => 'Date_Commande',
|
||||
// Required - format : DD/MM/YYYY .
|
||||
'operation' => 'Operation',
|
||||
// Required.
|
||||
'support_code' => 'Code_Support',
|
||||
// Required.
|
||||
'label_type_support' => 'Libelle_Type_Support',
|
||||
// Required.
|
||||
'package_unit_weight' => 'Poids_Unitaire_Colis',
|
||||
// Required if type = default.
|
||||
'qty' => 'Quantite',
|
||||
'code_on_pack' => 'Code_on_Pack',
|
||||
'code_unique' => 'Code_Unique',
|
||||
// Required if type = game.
|
||||
// Required if type = default - format 1 ou Null (oui Null et pas NULL).
|
||||
'state_order_cb' => 'Etat_Commande_CB',
|
||||
// Required if type = default - format 1 ou Null (oui Null et pas NULL).
|
||||
'state_order_check' => 'Etat_Commande_Cheque',
|
||||
|
||||
];
|
||||
|
||||
$dom = new DOMDocument('1.0', 'UTF-8');
|
||||
$dom->formatOutput = true;
|
||||
|
||||
$root = $dom->createElement('export_arcadia');
|
||||
$dom->appendChild($root);
|
||||
$order = $root->appendChild($dom->createElement('Commande'));
|
||||
|
||||
$key = array_search('order_num', array_column($fields->root, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$order->appendChild($dom->createElement('Num_Commande'));
|
||||
} else {
|
||||
$order->appendChild($dom->createElement('Num_Commande', $fields->root[$key]->fieldValue));
|
||||
}
|
||||
|
||||
foreach ($fields->root as $value) {
|
||||
// phpcs:ignore PSR2.ControlStructures.ControlStructureSpacing.SpacingAfterOpenBrace
|
||||
if (
|
||||
isset($pivot[$value->fieldName]) && $value->fieldName !== 'state_order_cb' &&
|
||||
$value->fieldName !== 'state_order_check' && $value->fieldName !== 'order_num'
|
||||
) {
|
||||
$order->appendChild($dom->createElement($pivot[$value->fieldName], $value->fieldValue));
|
||||
}
|
||||
}
|
||||
|
||||
if ($type === 'default') {
|
||||
$key = array_search('state_order_cb', array_column($fields->root, 'fieldName'));
|
||||
if ($key) {
|
||||
$order->appendChild($dom->createElement('Etat_Commande_CB', $fields->root[$key]->fieldValue));
|
||||
}
|
||||
|
||||
$key = array_search('state_order_check', array_column($fields->root, 'fieldName'));
|
||||
if ($key) {
|
||||
$order->appendChild($dom->createElement('Etat_Commande_Cheque', $fields->root[$key]->fieldValue));
|
||||
}
|
||||
}
|
||||
|
||||
$order->appendChild($dom->createElement('Email_conso'))
|
||||
->appendChild($dom->createCDATASection("$customer->email"));
|
||||
$order->appendChild($dom->createElement('Civilite'));
|
||||
|
||||
if ($type === 'default') {
|
||||
$order->appendChild($dom->createElement('Nom'))
|
||||
->appendChild($dom->createCDATASection("$shipping->lastname"));
|
||||
$order->appendChild($dom->createElement('Prenom'))
|
||||
->appendChild($dom->createCDATASection("$shipping->firstname"));
|
||||
$order->appendChild($dom->createElement('Adresse'))
|
||||
->appendChild($dom->createCDATASection("$shipping->address"));
|
||||
$order->appendChild($dom->createElement('Adresse_Complementaire'));
|
||||
$order->appendChild($dom->createElement('CP'))
|
||||
->appendChild($dom->createCDATASection("$shipping->postcode"));
|
||||
$order->appendChild($dom->createElement('Ville'))->appendChild($dom->createCDATASection("$shipping->city"));
|
||||
if (isset($shipping->phone) && !empty($shipping->phone)) {
|
||||
$order->appendChild($dom->createElement('Telephone'))
|
||||
->appendChild($dom->createCDATASection("$shipping->phone"));
|
||||
} else {
|
||||
$order->appendChild($dom->createElement('Telephone'));
|
||||
}
|
||||
} else {
|
||||
$order->appendChild($dom->createElement('Nom'))
|
||||
->appendChild($dom->createCDATASection("$customerInfos->lastname"));
|
||||
$order->appendChild($dom->createElement('Prenom'))
|
||||
->appendChild($dom->createCDATASection("$customerInfos->firstname"));
|
||||
$order->appendChild($dom->createElement('Adresse'))
|
||||
->appendChild($dom->createCDATASection("$customerInfos->address"));
|
||||
$order->appendChild($dom->createElement('Adresse_Complementaire'))
|
||||
->appendChild($dom->createCDATASection("$customerInfos->address2"));
|
||||
$order->appendChild($dom->createElement('CP'))
|
||||
->appendChild($dom->createCDATASection("$customerInfos->postcode"));
|
||||
$order->appendChild($dom->createElement('Ville'))
|
||||
->appendChild($dom->createCDATASection("$customerInfos->city"));
|
||||
$order->appendChild($dom->createElement('Telephone'))
|
||||
->appendChild($dom->createCDATASection("$customerInfos->phone"));
|
||||
}//end if
|
||||
|
||||
$orderLine = $order->appendChild($dom->createElement('Ligne_de_Commande'));
|
||||
|
||||
$key = array_search('qty', array_column($fields->orderLine, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$orderLine->appendChild($dom->createElement('Quantite', '1'));
|
||||
}
|
||||
|
||||
$key = array_search('package_unit_weight', array_column($fields->orderLine, 'fieldName'));
|
||||
if ($key === false) {
|
||||
$orderLine->appendChild($dom->createElement('Poids_Unitaire_Colis'));
|
||||
}
|
||||
|
||||
foreach ($fields->orderLine as $value) {
|
||||
// phpcs:ignore PSR2.ControlStructures.ControlStructureSpacing.SpacingAfterOpenBrace
|
||||
if (
|
||||
isset($pivot[$value->fieldName]) &&
|
||||
$value->fieldName !== 'code_on_pack' &&
|
||||
$value->fieldName !== 'code_unique'
|
||||
) {
|
||||
$orderLine->appendChild($dom->createElement($pivot[$value->fieldName], $value->fieldValue));
|
||||
}
|
||||
}
|
||||
|
||||
if ($type === 'game') {
|
||||
$key = array_search('code_on_pack', array_column($fields->orderLine, 'fieldName'));
|
||||
if ($key !== false) {
|
||||
$orderLine->appendChild(
|
||||
$dom->createElement('Code_on_Pack')
|
||||
)->appendChild($dom->createCDATASection($fields->orderLine[$key]->fieldValue));
|
||||
}
|
||||
|
||||
$key = array_search('code_unique', array_column($fields->orderLine, 'fieldName'));
|
||||
if ($key !== false) {
|
||||
$orderLine->appendChild(
|
||||
$dom->createElement('Code_Unique')
|
||||
)->appendChild($dom->createCDATASection($fields->orderLine[$key]->fieldValue));
|
||||
}
|
||||
}
|
||||
|
||||
return $dom->saveXML();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,574 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Enums\Country;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\CustomerResource;
|
||||
use App\Http\Resources\StatusResource;
|
||||
use App\Models\Customer;
|
||||
use App\Models\CustomerInfo;
|
||||
use App\Models\CustomerLogin;
|
||||
use App\Models\CustomerOptInHistory;
|
||||
use App\Models\SingleOptin;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CustomerController extends Controller
|
||||
{
|
||||
/**
|
||||
* Store a newly created resource in storage
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \App\Http\Resources\CustomerResource|\App\Http\Resources\StatusResource
|
||||
*/
|
||||
// phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh, Squiz.Commenting.FunctionComment.Missing
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'email' => 'required|email',
|
||||
'password' => 'required',
|
||||
'firstname' => 'required',
|
||||
'lastname' => 'required',
|
||||
'opt_in' => 'required',
|
||||
'birth_date' => 'date_format:Y-m-d'
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return new StatusResource([
|
||||
'status' => 'KO', 'code' => 102,
|
||||
'message' => 'Error on required fields.', 'errors' => $validator->errors()
|
||||
]);
|
||||
}
|
||||
|
||||
$brandId = $request->brand_id;
|
||||
$email = strtolower(filter_var($request->email, FILTER_SANITIZE_EMAIL));
|
||||
$firstname = filter_var($request->firstname, FILTER_SANITIZE_STRING);
|
||||
$lastname = filter_var($request->lastname, FILTER_SANITIZE_STRING);
|
||||
$optIn = filter_var($request->opt_in, FILTER_SANITIZE_STRING);
|
||||
$hashcode = Str::uuid();
|
||||
|
||||
// Récupère le customer s'il existe déjà.
|
||||
$customer = Customer::where('email', $email)->first();
|
||||
|
||||
// Si le customer n'existe pas déjà.
|
||||
if (!$customer) {
|
||||
$customer = new Customer();
|
||||
$customer->email = $email;
|
||||
$customer->save();
|
||||
$singleOptin = SingleOptin::query()->where([
|
||||
['email', $email], ['brand_id', $brandId]
|
||||
])->first();
|
||||
if ($singleOptin) {
|
||||
$singleOptin->delete();
|
||||
}
|
||||
} else {
|
||||
// Récupère les infos s'ils existent déjà.
|
||||
$CustomerInfo = CustomerInfo::query()->where([
|
||||
['customer_id', $customer->id], ['brand_id', $brandId]
|
||||
])->first();
|
||||
if ($CustomerInfo) {
|
||||
return new StatusResource([
|
||||
'status' => 'KO', 'code' => 103,
|
||||
'message' => 'User already registered on this site.'
|
||||
]);
|
||||
}
|
||||
}//end if
|
||||
|
||||
$customerInfos = new CustomerInfo();
|
||||
$customerInfos->firstname = ucfirst(strtolower($firstname));
|
||||
$customerInfos->lastname = ucfirst(strtolower($lastname));
|
||||
$customerInfos->birth_date = !empty($request->birth_date) ?
|
||||
filter_var($request->birth_date, FILTER_SANITIZE_STRING) : null;
|
||||
$customerInfos->address = !empty($request->address) ?
|
||||
filter_var($request->address, FILTER_SANITIZE_STRING) : null;
|
||||
$customerInfos->address2 = !empty($request->address2) ?
|
||||
filter_var($request->address2, FILTER_SANITIZE_STRING) : null;
|
||||
$customerInfos->phone = !empty($request->phone) ?
|
||||
filter_var($request->phone, FILTER_SANITIZE_STRING) : null;
|
||||
try {
|
||||
$customerInfos->country = Country::make(filter_var($request->country, FILTER_SANITIZE_STRING));
|
||||
} catch (\Exception $e) {
|
||||
$customerInfos->country = Country::france();
|
||||
}
|
||||
$customerInfos->city = !empty($request->city) ?
|
||||
filter_var($request->city, FILTER_SANITIZE_STRING) : null;
|
||||
$customerInfos->postcode = !empty($request->postcode) ?
|
||||
filter_var($request->postcode, FILTER_SANITIZE_STRING) : null;
|
||||
$customerInfos->opt_in = $optIn;
|
||||
$customerInfos->hashcode = $hashcode;
|
||||
$customerInfos->brand_id = $brandId;
|
||||
$customerInfos->customer_id = $customer->id;
|
||||
|
||||
$customer->infos()->save($customerInfos);
|
||||
|
||||
// Création du login pour cet utilisateur sur ce service.
|
||||
$customerLogin = new CustomerLogin();
|
||||
$customerLogin->customer_id = $customer->id;
|
||||
$customerLogin->password = Hash::make(trim($request->password));
|
||||
$customerLogin->last_connection = now();
|
||||
$customerLogin->brand_id = $brandId;
|
||||
$customerLogin->status = 0;
|
||||
|
||||
$customer->logins()->save($customerLogin);
|
||||
|
||||
// Ajout dans la table d'historique des opt-in de la nouvelle valeur.
|
||||
$optInHistory = new CustomerOptInHistory();
|
||||
$optInHistory->customer_id = $customer->id;
|
||||
$optInHistory->brand_id = $brandId;
|
||||
$optInHistory->new_value = $optIn;
|
||||
$optInHistory->save();
|
||||
|
||||
return new CustomerResource($customer, $brandId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $type
|
||||
* @param mixed $value
|
||||
* @return \App\Http\Resources\CustomerResource|\App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function show(Request $request, $type, $value)
|
||||
{
|
||||
$brandId = $request->brand_id;
|
||||
|
||||
if ($type === 'id') {
|
||||
$customer = Customer::find($value);
|
||||
if (!$customer) {
|
||||
return new StatusResource(['status' => 'KO', 'code' => 101, 'message' => 'User not found.']);
|
||||
}
|
||||
} elseif ($type === 'email') {
|
||||
$customer = Customer::where('email', $value)->first();
|
||||
if (!$customer) {
|
||||
return new StatusResource(['status' => 'KO', 'code' => 101, 'message' => 'User not found.']);
|
||||
}
|
||||
|
||||
$CustomerInfo = $customer->infos()->where('brand_id', $brandId)->first();
|
||||
|
||||
if (!$CustomerInfo) {
|
||||
return new StatusResource(['status' => 'KO', 'code' => 101, 'message' => 'User not found.']);
|
||||
}
|
||||
} else {
|
||||
return new StatusResource(['status' => 'KO', 'code' => 101, 'message' => 'User not found.']);
|
||||
}
|
||||
|
||||
return new CustomerResource($customer, $brandId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param integer $id
|
||||
* @return \App\Http\Resources\CustomerResource|\App\Http\Resources\StatusResource
|
||||
*/
|
||||
// phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Squiz.Commenting.FunctionComment.Missing
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'birth_date' => 'date_format:Y-m-d'
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return new StatusResource([
|
||||
'status' => 'KO', 'code' => 104,
|
||||
'message' => 'Error on required fields.', 'errors' => $validator->errors()
|
||||
]);
|
||||
}
|
||||
|
||||
$brandId = $request->brand_id;
|
||||
$customer = Customer::find($id);
|
||||
|
||||
if (!$customer) {
|
||||
return new StatusResource(['status' => 'KO', 'code' => 105, 'message' => 'User not found.']);
|
||||
}
|
||||
|
||||
$CustomerInfo = $customer->infos()->where('brand_id', $brandId)->first();
|
||||
if (!$CustomerInfo) {
|
||||
return new StatusResource(['status' => 'KO', 'code' => 105, 'message' => 'User not found.']);
|
||||
}
|
||||
|
||||
if ($request->has('firstname')) {
|
||||
$CustomerInfo->firstname = filter_var($request->firstname, FILTER_SANITIZE_STRING);
|
||||
}
|
||||
|
||||
if ($request->has('lastname')) {
|
||||
$CustomerInfo->lastname = filter_var($request->lastname, FILTER_SANITIZE_STRING);
|
||||
}
|
||||
|
||||
if ($request->has('birth_date')) {
|
||||
if (!empty($request->birth_date)) {
|
||||
$CustomerInfo->birth_date = filter_var($request->birth_date, FILTER_SANITIZE_STRING);
|
||||
} else {
|
||||
$CustomerInfo->birth_date = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('address')) {
|
||||
if (!empty($request->address)) {
|
||||
$CustomerInfo->address = filter_var($request->address, FILTER_SANITIZE_STRING);
|
||||
} else {
|
||||
$CustomerInfo->address = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('address2')) {
|
||||
if (!empty($request->address2)) {
|
||||
$CustomerInfo->address2 = filter_var($request->address2, FILTER_SANITIZE_STRING);
|
||||
} else {
|
||||
$CustomerInfo->address2 = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('phone')) {
|
||||
if (!empty($request->phone)) {
|
||||
$CustomerInfo->phone = filter_var($request->phone, FILTER_SANITIZE_STRING);
|
||||
} else {
|
||||
$CustomerInfo->phone = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('country')) {
|
||||
try {
|
||||
$CustomerInfo->country = Country::make(filter_var($request->country, FILTER_SANITIZE_STRING));
|
||||
} catch (\Exception $e) {
|
||||
$CustomerInfo->country = Country::france();
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('city')) {
|
||||
if (!empty($request->city)) {
|
||||
$CustomerInfo->city = filter_var($request->city, FILTER_SANITIZE_STRING);
|
||||
} else {
|
||||
$CustomerInfo->city = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('postcode')) {
|
||||
if (!empty($request->postcode)) {
|
||||
$CustomerInfo->postcode = filter_var($request->postcode, FILTER_SANITIZE_STRING);
|
||||
} else {
|
||||
$CustomerInfo->postcode = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('opt_in')) {
|
||||
$optIn = filter_var($request->opt_in, FILTER_SANITIZE_STRING);
|
||||
|
||||
if ($CustomerInfo->opt_in != $optIn) {
|
||||
// Ajout dans la table d'historique des opt-in de la nouvelle valeur.
|
||||
$optInHistory = new CustomerOptInHistory();
|
||||
$optInHistory->customer_id = $customer->id;
|
||||
$optInHistory->brand_id = $brandId;
|
||||
$optInHistory->new_value = $optIn;
|
||||
$optInHistory->save();
|
||||
}
|
||||
|
||||
$CustomerInfo->opt_in = $optIn;
|
||||
}
|
||||
|
||||
$CustomerInfo->save();
|
||||
|
||||
return new CustomerResource($customer, $brandId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the user
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \App\Http\Resources\CustomerResource|\App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function authenticate(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'email' => 'required|email',
|
||||
'password' => 'required',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return new StatusResource([
|
||||
'status' => 'KO', 'code' => 115,
|
||||
'message' => 'Error on required fields.', 'errors' => $validator->errors()
|
||||
]);
|
||||
}
|
||||
|
||||
$brandId = $request->brand_id;
|
||||
$email = filter_var($request->email, FILTER_SANITIZE_EMAIL);
|
||||
$password = trim($request->password);
|
||||
$customer = Customer::where('email', $email)->first();
|
||||
if ($customer) {
|
||||
$login = $customer->logins()->where('brand_id', $brandId)->first();
|
||||
if ($login) {
|
||||
if (Hash::check($password, $login->password)) {
|
||||
if ($login->status === false) {
|
||||
$infos = $customer->infos()->where('brand_id', $brandId)->first();
|
||||
// "Le compte de l'utilisateur n'est pas activé"
|
||||
return new StatusResource(
|
||||
[
|
||||
'status' => 'KO',
|
||||
'code' => 116,
|
||||
'message' => 'Account not activated.',
|
||||
'user' => [
|
||||
'crm_id' => $customer->id,
|
||||
'firstname' => $infos->firstname,
|
||||
'lastname' => $infos->lastname,
|
||||
'email' => $customer->email,
|
||||
'birth_date' => $infos->birth_date,
|
||||
'address' => $infos->address,
|
||||
'address2' => $infos->address2,
|
||||
'phone' => $infos->phone,
|
||||
'country' => $infos->country->label,
|
||||
'city' => $infos->city,
|
||||
'postcode' => $infos->postcode,
|
||||
'opt_in' => $infos->opt_in,
|
||||
'hashcode' => $infos->hashcode,
|
||||
'status' => $login->status,
|
||||
]
|
||||
]
|
||||
);
|
||||
} //end if
|
||||
|
||||
$login->last_connection = now();
|
||||
$customer->logins()->save($login);
|
||||
return new CustomerResource($customer, $brandId);
|
||||
} //end if
|
||||
// "Mot de passe incorrect"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 117, 'message' => 'Authentication failed.']);
|
||||
} else {
|
||||
// "Ce compte n'est pas enregistré pour cette marque"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 118, 'message' => 'User not found.']);
|
||||
} //end if
|
||||
} else {
|
||||
// "Ce compte n'existe pas dans la CRM"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 119, 'message' => 'User not found.']);
|
||||
} //end if
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the password of the user for the brand
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $id
|
||||
* @return \App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function changePassword(Request $request, $id)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'password' => 'required',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return new StatusResource([
|
||||
'status' => 'KO', 'code' => 107,
|
||||
'message' => 'Error on required fields.', 'errors' => $validator->errors()
|
||||
]);
|
||||
}
|
||||
|
||||
$brandId = $request->brand_id;
|
||||
$customer = Customer::find($id);
|
||||
$password = trim($request->password);
|
||||
|
||||
if ($customer) {
|
||||
$customerLogin = $customer->logins()->where('brand_id', $brandId)->first();
|
||||
if ($customerLogin) {
|
||||
// Check if same password.
|
||||
if (Hash::check($password, $customerLogin->password)) {
|
||||
return new StatusResource(['status' => 'KO', 'code' => 123, 'message' => 'Same password.']);
|
||||
}
|
||||
|
||||
$customerLogin->password = Hash::make($password);
|
||||
$customerLogin->save();
|
||||
} else {
|
||||
// "Ce compte n'est pas enregistré pour cette marque"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 108, 'message' => 'User not found.']);
|
||||
}
|
||||
} else {
|
||||
// "Ce compte n'existe pas"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 109, 'message' => 'User not found.']);
|
||||
}
|
||||
return new StatusResource(['status' => 'OK', 'message' => 'Update complete.']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the account of the user
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $id
|
||||
* @return \App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function activateAccount(Request $request, $id)
|
||||
{
|
||||
$brandId = $request->brand_id;
|
||||
|
||||
$customer = Customer::find($id);
|
||||
if ($customer) {
|
||||
$login = $customer->logins()->where('brand_id', $brandId)->first();
|
||||
if ($login) {
|
||||
if ($login->status === false) {
|
||||
$login->status = true;
|
||||
$login->save();
|
||||
// "Le compte a bien été activé"
|
||||
return new StatusResource(['status' => 'OK', 'message' => 'Update complete.']);
|
||||
} else {
|
||||
// "Ce compte est déjà activé"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 110, 'message' => 'User already active.']);
|
||||
}
|
||||
} else {
|
||||
// "Ce compte n'est pas enregistré pour cette marque"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 111, 'message' => 'User not found.']);
|
||||
}
|
||||
} else {
|
||||
// "Cet utilisateur n'existe pas dans la CRM"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 112, 'message' => 'User not found.']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the user account for the brand
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $id
|
||||
*/
|
||||
// phpcs:disable Squiz.PHP.NonExecutableCode.Unreachable, Squiz.Commenting.FunctionComment.Missing
|
||||
public function delete(Request $request, $id)
|
||||
{
|
||||
die("Not implemented yet");
|
||||
// TODO : Gestion avec mesBR.
|
||||
$brandId = $request->brand_id;
|
||||
|
||||
$customer = Customer::find($id);
|
||||
if ($customer) {
|
||||
$customer->infos()->where('brand_id', $brandId)->first()->delete();
|
||||
$customer->logins()->where('brand_id', $brandId)->first()->delete();
|
||||
|
||||
if (count($customer->infos) === 0 && count($customer->logins) === 0) {
|
||||
$customer->optInHistory()->delete();
|
||||
$customer->delete();
|
||||
// Suppression du compte de la CRM terminée.
|
||||
return new StatusResource(['status' => 'OK', 'message' => 'Deletion complete.']);
|
||||
} else {
|
||||
// Suppression des informations du compte pour la marque terminée.
|
||||
return new StatusResource(['status' => 'OK', 'message' => 'Deletion complete.']);
|
||||
}
|
||||
} else {
|
||||
return new StatusResource(['status' => 'KO', 'code' => 106, 'message' => 'User not found.']);
|
||||
}
|
||||
// phpcs:enable Squiz.PHP.NonExecutableCode.Unreachable, Squiz.Commenting.FunctionComment.Missing
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the status of the opt-in for the customer on this brand
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $id
|
||||
* @return \App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function toggleOptin(Request $request, $id)
|
||||
{
|
||||
// TODO : Liaison des opt-in avec MailJet.
|
||||
$brandId = $request->brand_id;
|
||||
|
||||
$customer = Customer::find($id);
|
||||
if ($customer) {
|
||||
$infos = $customer->infos()->where('brand_id', $brandId)->first();
|
||||
if ($infos) {
|
||||
$infos->opt_in = $infos->opt_in === 0 ? 1 : 0;
|
||||
|
||||
// On enregistre l'historique du changement d'optin.
|
||||
$optinHistory = new CustomerOptInHistory();
|
||||
$optinHistory->customer_id = $customer->id;
|
||||
$optinHistory->new_value = $infos->opt_in;
|
||||
$optinHistory->brand_id = $brandId;
|
||||
$optinHistory->save();
|
||||
|
||||
$infos->save();
|
||||
// "Changement effectué"
|
||||
return new StatusResource(['status' => 'OK', 'message' => 'Update complete.']);
|
||||
} else {
|
||||
// "Ce compte n'a pas d'information liés à cette marque"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 113, 'message' => 'User not found.']);
|
||||
}
|
||||
} else {
|
||||
// "Cet utilisateur n'existe pas dans la CRM"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 114, 'message' => 'User not found.']);
|
||||
} //end if
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove opt-in for the customer on this brand
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $hashcode
|
||||
* @return \App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function removeOptin(Request $request, $hashcode)
|
||||
{
|
||||
// TODO : Liaison des opt-in avec MailJet.
|
||||
$brandId = $request->brand_id;
|
||||
|
||||
$infos = CustomerInfo::where([
|
||||
['brand_id', $brandId],
|
||||
['hashcode', $hashcode]
|
||||
])->first();
|
||||
|
||||
if ($infos) {
|
||||
$infos->opt_in = 0;
|
||||
|
||||
// On enregistre l'historique du changement d'optin.
|
||||
$optinHistory = new CustomerOptInHistory();
|
||||
$optinHistory->customer_id = $infos->customer_id;
|
||||
$optinHistory->new_value = 0;
|
||||
$optinHistory->brand_id = $brandId;
|
||||
$optinHistory->save();
|
||||
|
||||
$infos->save();
|
||||
// "Changement effectué"
|
||||
return new StatusResource(['status' => 'OK', 'message' => 'Update complete.']);
|
||||
} else {
|
||||
// "Ce compte n'a pas d'information liés à cette marque"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 122, 'message' => 'User not found.']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return void
|
||||
*/
|
||||
// phpcs:ignore Squiz.PHP.NonExecutableCode.Unreachable, Squiz.Commenting.FunctionComment.Missing
|
||||
public function addSingleOptin(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'email' => 'required|email',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return new StatusResource([
|
||||
'status' => 'KO', 'code' => 120,
|
||||
'message' => 'Error on required fields.', 'errors' => $validator->errors()
|
||||
]);
|
||||
}
|
||||
|
||||
$brandId = $request->brand_id;
|
||||
$email = filter_var($request->email, FILTER_SANITIZE_EMAIL);
|
||||
|
||||
// Check si le customer ou l'optin simple existe avant de l'ajouter en optin simple.
|
||||
if (
|
||||
!SingleOptin::query()->where([['email', $email], ['brand_id', $brandId]])->exists() &&
|
||||
!CustomerInfo::join("customers", "customer_infos.customer_id", "=", "customers.id")->where([
|
||||
['brand_id', $brandId], ['email', $email]
|
||||
])->exists()
|
||||
) {
|
||||
$singleOptin = new SingleOptin();
|
||||
$singleOptin->email = $email;
|
||||
$singleOptin->brand_id = $brandId;
|
||||
$singleOptin->save();
|
||||
} else {
|
||||
// "Cet utilisateur est déjà inscrit à la newsletter pour cette marque"
|
||||
return new StatusResource([
|
||||
'status' => 'KO', 'code' => 121,
|
||||
'message' => 'This user is already subscribed to the newsletter for this brand.'
|
||||
]);
|
||||
}
|
||||
return new StatusResource(['status' => 'OK', 'message' => 'Optin added.']);
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ use Illuminate\Http\JsonResponse;
|
|||
class AnswerController extends Controller
|
||||
{
|
||||
/**
|
||||
* Store the customer answers
|
||||
* Store the customer answers.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\StoreCustomerAnswers $request
|
||||
* @param \App\Models\Service $service
|
||||
|
|
@ -28,7 +28,7 @@ class AnswerController extends Controller
|
|||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
||||
$existingAnswerIds = $customer->getAnswers($service)->pluck('id');
|
||||
$answersID = Answer::whereIn('id', $request->answers)->pluck('id');
|
||||
$answersID = Answer::query()->whereIn('id', $request->answers)->pluck('id');
|
||||
$customer->answers()->sync($answersID->merge($existingAnswerIds));
|
||||
return response()->json();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use Illuminate\Http\JsonResponse;
|
|||
class ApiController extends Controller
|
||||
{
|
||||
/**
|
||||
* Just returns HTTP 200 response
|
||||
* Just returns HTTP 200 response.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,30 +29,30 @@ use Illuminate\Support\Str;
|
|||
class ArcadiaController extends Controller
|
||||
{
|
||||
/**
|
||||
* Send arcadia default mail (reclamations)
|
||||
* Send arcadia default mail (reclamations).
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\SendArchadiaDefaultMailRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function outgoingMailDefault(SendArchadiaDefaultMailRequest $request): JsonResponse
|
||||
{
|
||||
return $this->handleArcadiaMail($request, ArcadiaMailType::default());
|
||||
return $this->handleArcadiaMail($request, ArcadiaMailType::default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send arcadia game mail (games)
|
||||
* Send arcadia game mail (games).
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\SendArchadiaGameMailRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function outgoingMailGame(SendArchadiaGameMailRequest $request): JsonResponse
|
||||
{
|
||||
return $this->handleArcadiaMail($request, ArcadiaMailType::game());
|
||||
return $this->handleArcadiaMail($request, ArcadiaMailType::game);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form xml message and save it in the apropriate storage location
|
||||
* to be picked up by the arcadia job
|
||||
* to be picked up by the arcadia job.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\BaseApiRequest $request
|
||||
* @param \App\Enums\ArcadiaMailType $type
|
||||
|
|
@ -67,14 +67,14 @@ class ArcadiaController extends Controller
|
|||
$xml = 'none';
|
||||
try {
|
||||
$customerInfo = \array_intersect_key($request->all()['deliver'], [
|
||||
'email' => '',
|
||||
'email' => '',
|
||||
'firstname' => '',
|
||||
'lastname' => '',
|
||||
'address' => '',
|
||||
'address2' => '',
|
||||
'city' => '',
|
||||
'postcode' => '',
|
||||
'phone' => ''
|
||||
'lastname' => '',
|
||||
'address' => '',
|
||||
'address2' => '',
|
||||
'city' => '',
|
||||
'postcode' => '',
|
||||
'phone' => ''
|
||||
]);
|
||||
$orderType = ArcadiaOrderType::make(intval($request->state_order));
|
||||
$xml = $this->makeXml($request, $type, $orderType, $customerInfo);
|
||||
|
|
@ -90,7 +90,7 @@ class ArcadiaController extends Controller
|
|||
Storage::disk('arcadia')->put(Str::slug(sprintf(
|
||||
'v2_order_%s_%s_%s%s',
|
||||
$request->order_num,
|
||||
$type->label,
|
||||
$type->label(),
|
||||
date('Ymd_His'),
|
||||
\microtime(true)
|
||||
)) . '.xml', $xml);
|
||||
|
|
@ -109,11 +109,11 @@ class ArcadiaController extends Controller
|
|||
}
|
||||
throw $e;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}//end try
|
||||
} //end try
|
||||
}
|
||||
|
||||
/**
|
||||
* render Arcadia xml for order
|
||||
* Render Arcadia xml for order.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\BaseApiRequest $request
|
||||
* @param \App\Enums\ArcadiaMailType $type
|
||||
|
|
@ -127,12 +127,12 @@ class ArcadiaController extends Controller
|
|||
ArcadiaOrderType $orderType,
|
||||
array $customerInfo
|
||||
): string {
|
||||
$arcadiaMailType = $type->equals(ArcadiaMailType::default()) ?
|
||||
$arcadiaMailType = $type->equals(ArcadiaMailType::default) ?
|
||||
'mail.arcadiaOrders.default' : 'mail.arcadiaOrders.game';
|
||||
return view($arcadiaMailType, [
|
||||
'request' => $request,
|
||||
'type' => $type,
|
||||
'orderType' => $orderType,
|
||||
'request' => $request,
|
||||
'type' => $type,
|
||||
'orderType' => $orderType,
|
||||
'customerInfo' => $customerInfo
|
||||
])->render();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class CustomerController extends Controller
|
|||
$data = (object)$request->validated();
|
||||
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = Customer::where('email', $data->email)->firstOrCreate([
|
||||
$customer = Customer::query()->where('email', $data->email)->firstOrCreate([
|
||||
'email' => $data->email
|
||||
]);
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ class CustomerController extends Controller
|
|||
/** @var \App\Models\CustomerInfo */
|
||||
$customerInfo = $customer->info($service->brand, Customer::FIRST_OR_NEW);
|
||||
if ($customerInfo->exists) {
|
||||
throw new ApiErrorException(ApiError::customerExists());
|
||||
throw new ApiErrorException(ApiError::customerExists);
|
||||
}
|
||||
$customerInfo->fill($request->validated());
|
||||
$customerInfo->brand()->associate($service->brand);
|
||||
|
|
@ -84,7 +84,7 @@ class CustomerController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Renders the specific customer infos
|
||||
* Renders the specific customer infos.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
|
|
@ -99,7 +99,7 @@ class CustomerController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Updates information for a specific customer
|
||||
* Updates information for a specific customer.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\UpdateCustomerRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
|
|
@ -141,7 +141,7 @@ class CustomerController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Deletes customer information for a specific service
|
||||
* Deletes customer information for a specific service.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
|
|
@ -153,7 +153,6 @@ class CustomerController extends Controller
|
|||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
||||
// TODO: Gestion avec mesBR.
|
||||
/** @var \App\Models\CustomerInfo */
|
||||
$customerInfo = $customer->info($service->brand, Customer::FIRST_OR_FAIL);
|
||||
/** @var \App\Models\CustomerLogin */
|
||||
|
|
@ -193,30 +192,30 @@ class CustomerController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Authenticate the user
|
||||
* Authenticate the user.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\AuthenticateRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Resources\Json\JsonResource
|
||||
* @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::authFailed() in case
|
||||
* @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::authFailed in case
|
||||
* of wrong credentials.
|
||||
* @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::customerNotActivated() if
|
||||
* @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::customerNotActivated if
|
||||
* customer account is not activated.
|
||||
*/
|
||||
public function authenticate(AuthenticateRequest $request, Service $service): JsonResource
|
||||
{
|
||||
try {
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = Customer::where('email', $request->email)->firstOrFail();
|
||||
$customer = Customer::query()->where('email', $request->email)->firstOrFail();
|
||||
|
||||
/** @var \App\Models\CustomerLogin $customerLogin */
|
||||
$customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
|
||||
if (!$customerLogin->passwordMatch($request->password)) {
|
||||
throw new ApiErrorException(ApiError::authFailed());
|
||||
throw new ApiErrorException(ApiError::authFailed);
|
||||
}
|
||||
|
||||
if (!$customerLogin->status) {
|
||||
throw new ApiErrorException(ApiError::customerNotActivated());
|
||||
throw new ApiErrorException(ApiError::customerNotActivated);
|
||||
}
|
||||
|
||||
UpdateCustomerLastConnection::dispatch($customer, $customerLogin, now())
|
||||
|
|
@ -224,12 +223,12 @@ class CustomerController extends Controller
|
|||
|
||||
return new CustomerResource($service->brand, $customer);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
throw new ApiErrorException(ApiError::authFailed());
|
||||
throw new ApiErrorException(ApiError::authFailed);
|
||||
} //end try
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the account of the user
|
||||
* Activate the account of the user.
|
||||
*
|
||||
* @param \App\Models\Customer $customer
|
||||
* @param \App\Models\Service $service
|
||||
|
|
@ -238,7 +237,7 @@ class CustomerController extends Controller
|
|||
* if customer account is already active.
|
||||
* @throws \App\Exceptions\Api\V2\CrmException If saving the customer to DB failed.
|
||||
*/
|
||||
public function activateAccount(Customer $customer, Service $service)
|
||||
public function activateAccount(Customer $customer, Service $service): JsonResponse
|
||||
{
|
||||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
|
@ -247,7 +246,7 @@ class CustomerController extends Controller
|
|||
$login = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
|
||||
|
||||
if ($login->status) {
|
||||
throw new ApiErrorException(ApiError::customerAlreadyActive());
|
||||
throw new ApiErrorException(ApiError::customerAlreadyActive);
|
||||
}
|
||||
|
||||
$login->status = true;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use App\Models\SingleOptin;
|
|||
class OptinController extends Controller
|
||||
{
|
||||
/**
|
||||
* Creates a new Single optin or destroys it if exists
|
||||
* Creates a new Single optin or destroys it if exists.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\SingleOptinRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
|
|
@ -29,7 +29,7 @@ class OptinController extends Controller
|
|||
public function optin(SingleOptinRequest $request, Service $service): JsonResponse
|
||||
{
|
||||
if (CustomerInfo::getFromEmail($service->brand, $request->email)->exists()) {
|
||||
throw new ApiErrorException(ApiError::singleOptinCustomerExists());
|
||||
throw new ApiErrorException(ApiError::singleOptinCustomerExists);
|
||||
}
|
||||
|
||||
/** @var \App\Models\SingleOptin */
|
||||
|
|
@ -48,14 +48,14 @@ class OptinController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a new Single optin or destroys it if exists using hashcode
|
||||
* Creates a new Single optin or destroys it if exists using hashcode.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\SingleOptinRemoveWithHashcodeRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \App\Exceptions\Api\V2\CrmException If the single optin could not be removed.
|
||||
*/
|
||||
public function optoutWithHashcode(SingleOptinRemoveWithHashcodeRequest $request, Service $service)
|
||||
public function optoutWithHashcode(SingleOptinRemoveWithHashcodeRequest $request, Service $service): JsonResponse
|
||||
{
|
||||
/** @var \App\Models\SingleOptin */
|
||||
$singleOptin = SingleOptin::query()->where('hashcode', $request->hashcode)
|
||||
|
|
@ -73,7 +73,7 @@ class OptinController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Changes the optin state
|
||||
* Changes the optin state.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Http\Requests\Api\V2\BaseApiRequest $request
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@ class QuestionController extends Controller
|
|||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
||||
$questions = Question::whereHas('brand', function ($q) use ($service) {
|
||||
$questions = Question::query()->whereHas('brand', function ($q) use ($service) {
|
||||
$q->where('id', $service->brand->id);
|
||||
})->whereDoesntHave('answers', function ($q) use ($customer) {
|
||||
$q->whereIn('id', Answer::whereHas('customers', function ($q) use ($customer) {
|
||||
$q->whereIn('id', Answer::query()->whereHas('customers', function ($q) use ($customer) {
|
||||
$q->where('id', $customer->id);
|
||||
})->pluck('id'));
|
||||
})->with('answers')->get();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use Illuminate\Support\Collection;
|
|||
class StatsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get specific brand statistics
|
||||
* Get specific brand statistics.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\GetBrandStatsRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
|
|
@ -26,14 +26,14 @@ class StatsController extends Controller
|
|||
*/
|
||||
public function brandStats(GetBrandStatsRequest $request, Service $service): ResourceCollection
|
||||
{
|
||||
$stats = BrandStat::whereDate('created_at', '>=', $request->start)
|
||||
$stats = BrandStat::query()->whereDate('created_at', '>=', $request->start)
|
||||
->whereDate('created_at', '<=', $request->end)
|
||||
->whereBrandId($service->brand->id)->get();
|
||||
return new BrandStatsResource($stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get statistics for a specific question
|
||||
* Get statistics for a specific question.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V2\GetQuestionStatsRequest $request
|
||||
* @param \App\Models\Question $question
|
||||
|
|
@ -55,7 +55,7 @@ class StatsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Total réponses par dates
|
||||
* Total réponses par dates.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $answers
|
||||
* @param \Illuminate\Support\Carbon $start
|
||||
|
|
@ -65,13 +65,13 @@ class StatsController extends Controller
|
|||
private function answersByDays(Collection $answers, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
// * Totalize by date all answers.
|
||||
$answersByDays = CustomerAnswer::whereDate('created_at', '>=', $start)
|
||||
$answersByDays = CustomerAnswer::query()->whereDate('created_at', '>=', $start)
|
||||
->whereDate('created_at', '<=', $end)
|
||||
->whereIn('answer_id', $answers->pluck('id'))
|
||||
->get()->map(function ($custAnswer) {
|
||||
return [
|
||||
'answer_id' => $custAnswer->answer_id,
|
||||
'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
|
||||
'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
|
||||
];
|
||||
})->groupBy(['created_at', 'answer_id'])->map(function ($day) {
|
||||
return $day->map(function ($custAnswers) {
|
||||
|
|
|
|||
35
app/Http/Controllers/Api/V4/AnswerController.php
Normal file
35
app/Http/Controllers/Api/V4/AnswerController.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V4;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Api\V4\StoreCustomerAnswers;
|
||||
use App\Models\Answer;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class AnswerController extends Controller
|
||||
{
|
||||
/**
|
||||
* Store the customer answers.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\StoreCustomerAnswers $request
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function storeCustomerAnswers(
|
||||
StoreCustomerAnswers $request,
|
||||
Service $service,
|
||||
Customer $customer
|
||||
): JsonResponse {
|
||||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
||||
$existingAnswerIds = $customer->getAnswers($service)->pluck('id');
|
||||
$answersID = Answer::query()->whereIn('id', $request->answers)->pluck('id');
|
||||
$customer->answers()->sync($answersID->merge($existingAnswerIds));
|
||||
return response()->json();
|
||||
}
|
||||
}
|
||||
19
app/Http/Controllers/Api/V4/ApiController.php
Normal file
19
app/Http/Controllers/Api/V4/ApiController.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V4;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class ApiController extends Controller
|
||||
{
|
||||
/**
|
||||
* Just returns HTTP 200 response.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function ping(): JsonResponse
|
||||
{
|
||||
return response()->json();
|
||||
}
|
||||
}
|
||||
139
app/Http/Controllers/Api/V4/ArcadiaController.php
Normal file
139
app/Http/Controllers/Api/V4/ArcadiaController.php
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V4;
|
||||
|
||||
use App\Enums\ArcadiaMailType;
|
||||
use App\Enums\ArcadiaOrderType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Api\V4\BaseApiRequest;
|
||||
use App\Http\Requests\Api\V4\SendArchadiaDefaultMailRequest;
|
||||
use App\Http\Requests\Api\V4\SendArchadiaGameMailRequest;
|
||||
use App\Mail\CourrierArcadiaError;
|
||||
use DOMDocument;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* ! Ici c'est du sale à cause d'arcadia
|
||||
* Ils ont fait le choix de rajouter une fonctionnalité
|
||||
* sur une methode existante en rajoutant des conditions
|
||||
* sales. Ils ont donc une seule méthode pour envoyer plusieurs
|
||||
* types de réclas avec des champs différents...
|
||||
*
|
||||
* Donc une séparation est faite sur les endpoints CRM et dans le client
|
||||
* pour éviter une confusion de nos utilisateurs
|
||||
*/
|
||||
class ArcadiaController extends Controller
|
||||
{
|
||||
/**
|
||||
* Send arcadia default mail (reclamations).
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\SendArchadiaDefaultMailRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function outgoingMailDefault(SendArchadiaDefaultMailRequest $request): JsonResponse
|
||||
{
|
||||
return $this->handleArcadiaMail($request, ArcadiaMailType::default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send arcadia game mail (games).
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\SendArchadiaGameMailRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function outgoingMailGame(SendArchadiaGameMailRequest $request): JsonResponse
|
||||
{
|
||||
return $this->handleArcadiaMail($request, ArcadiaMailType::game);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form xml message and save it in the apropriate storage location
|
||||
* to be picked up by the arcadia job.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\BaseApiRequest $request
|
||||
* @param \App\Enums\ArcadiaMailType $type
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \Exception If an error occurs while generating and saving the xml file.
|
||||
*/
|
||||
private function handleArcadiaMail(BaseApiRequest $request, ArcadiaMailType $type): JsonResponse
|
||||
{
|
||||
$request = $request->merge([
|
||||
'order_num' => str_pad(\intval($request->order_num), 9, '0', STR_PAD_LEFT)
|
||||
]);
|
||||
$xml = 'none';
|
||||
try {
|
||||
$customerInfo = \array_intersect_key($request->all()['deliver'], [
|
||||
'email' => '',
|
||||
'firstname' => '',
|
||||
'lastname' => '',
|
||||
'address' => '',
|
||||
'address2' => '',
|
||||
'city' => '',
|
||||
'postcode' => '',
|
||||
'phone' => ''
|
||||
]);
|
||||
$orderType = ArcadiaOrderType::make(intval($request->state_order));
|
||||
$xml = $this->makeXml($request, $type, $orderType, $customerInfo);
|
||||
|
||||
// * Format xml.
|
||||
$doc = new DOMDocument('1.0', 'utf-8');
|
||||
$doc->xmlStandalone = true;
|
||||
$doc->preserveWhiteSpace = false;
|
||||
$doc->formatOutput = true;
|
||||
$doc->loadXML($xml);
|
||||
$xml = $doc->saveXML();
|
||||
|
||||
Storage::disk('arcadia')->put(Str::slug(sprintf(
|
||||
'v4_order_%s_%s_%s%s',
|
||||
$request->order_num,
|
||||
$type->label(),
|
||||
date('Ymd_His'),
|
||||
\microtime(true)
|
||||
)) . '.xml', $xml);
|
||||
return response()->json();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (\Exception $e) {
|
||||
Log::critical("ARCADIA XML CREATION FAILED FOR $request->order_num : " . $e->getMessage());
|
||||
if (!config('app.debug')) {
|
||||
dispatch(function () use ($xml, $e, $request) {
|
||||
Mail::to(config('mail.MAIL_ADMIN'))->send(new CourrierArcadiaError(
|
||||
"ARCADIA XML CREATION FAILED FOR $request->order_num",
|
||||
"Une erreur est survenue lors de la création du fichier XML : " . $e->getMessage(),
|
||||
$xml ?: ''
|
||||
));
|
||||
})->afterResponse();
|
||||
}
|
||||
throw $e;
|
||||
// @codeCoverageIgnoreEnd
|
||||
} //end try
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Arcadia xml for order.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\BaseApiRequest $request
|
||||
* @param \App\Enums\ArcadiaMailType $type
|
||||
* @param \App\Enums\ArcadiaOrderType $orderType
|
||||
* @param array $customerInfo
|
||||
* @return string
|
||||
*/
|
||||
private function makeXml(
|
||||
BaseApiRequest $request,
|
||||
ArcadiaMailType $type,
|
||||
ArcadiaOrderType $orderType,
|
||||
array $customerInfo
|
||||
): string {
|
||||
$arcadiaMailType = $type->equals(ArcadiaMailType::default) ?
|
||||
'mail.arcadiaOrders.default' : 'mail.arcadiaOrders.game';
|
||||
return view($arcadiaMailType, [
|
||||
'request' => $request,
|
||||
'type' => $type,
|
||||
'orderType' => $orderType,
|
||||
'customerInfo' => $customerInfo
|
||||
])->render();
|
||||
}
|
||||
}
|
||||
260
app/Http/Controllers/Api/V4/CustomerController.php
Normal file
260
app/Http/Controllers/Api/V4/CustomerController.php
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V4;
|
||||
|
||||
use App\Enums\ApiError;
|
||||
use App\Exceptions\Api\V4\ApiErrorException;
|
||||
use App\Exceptions\Api\V4\CrmException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Api\V4\AuthenticateRequest;
|
||||
use App\Http\Requests\Api\V4\StoreCustomerRequest;
|
||||
use App\Http\Requests\Api\V4\UpdateCustomerRequest;
|
||||
use App\Http\Resources\Api\V4\CustomerResource;
|
||||
use App\Jobs\UpdateCustomerLastConnection;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Service;
|
||||
use App\Models\SingleOptin;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CustomerController extends Controller
|
||||
{
|
||||
/**
|
||||
* Creates a new customer for the specified service.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\StoreCustomerRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Resources\Json\JsonResource
|
||||
* @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::customerExists if
|
||||
* the customer with this email already exists.
|
||||
* @throws \App\Exceptions\Api\V4\CrmException If saving the customer to DB failed.
|
||||
*/
|
||||
public function store(StoreCustomerRequest $request, Service $service): JsonResource
|
||||
{
|
||||
$data = (object)$request->validated();
|
||||
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = Customer::query()->where('email', $data->email)->firstOrCreate([
|
||||
'email' => $data->email
|
||||
]);
|
||||
|
||||
DB::transaction(function () use (&$customer, $data, $request, $service) {
|
||||
|
||||
$saved = $customer->save();
|
||||
$customer->setOptIn($service->brand, $data->opt_in);
|
||||
|
||||
// * Delete Single optin if exists.
|
||||
/** @var \App\Models\SingleOptin|null $singleOptin */
|
||||
$singleOptin = SingleOptin::query()->where('email', $data->email)
|
||||
->whereHas('brand', function (Builder $q) use ($service) {
|
||||
$q->where('id', $service->brand->id);
|
||||
})->first();
|
||||
if ($singleOptin) {
|
||||
$saved = $singleOptin->delete() && $saved;
|
||||
}
|
||||
|
||||
/** @var \App\Models\CustomerInfo */
|
||||
$customerInfo = $customer->info($service->brand, Customer::FIRST_OR_NEW);
|
||||
if ($customerInfo->exists) {
|
||||
throw new ApiErrorException(ApiError::customerExists);
|
||||
}
|
||||
$customerInfo->fill($request->validated());
|
||||
$customerInfo->brand()->associate($service->brand);
|
||||
$customerInfo->customer()->associate($customer);
|
||||
$saved = $customerInfo->save() && $saved;
|
||||
|
||||
/** @var \App\Models\CustomerLogin */
|
||||
$customerLogin = $customer->login($service->brand, Customer::FIRST_OR_NEW);
|
||||
$customerLogin->fill($request->validated());
|
||||
$customerLogin->brand()->associate($service->brand);
|
||||
$customerLogin->customer()->associate($customer);
|
||||
$saved = $customerLogin->save() && $saved;
|
||||
|
||||
if (!$saved) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new CrmException('Api failed to store customer.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
});
|
||||
|
||||
return new CustomerResource($service->brand, $customer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the specific customer infos.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\Resources\Json\JsonResource
|
||||
*/
|
||||
public function show(Service $service, Customer $customer): JsonResource
|
||||
{
|
||||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
||||
return new CustomerResource($service->brand, $customer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates information for a specific customer.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\UpdateCustomerRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\Resources\Json\JsonResource
|
||||
* @throws \App\Exceptions\Api\V4\CrmException If saving the customer to DB failed.
|
||||
*/
|
||||
public function update(UpdateCustomerRequest $request, Service $service, Customer $customer): JsonResource
|
||||
{
|
||||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
||||
DB::transaction(function () use ($request, $customer, $service) {
|
||||
// To correct with create.
|
||||
$customer->fill($request->validated());
|
||||
$saved = $customer->save();
|
||||
if ($request->has('opt_in')) {
|
||||
$customer->setOptIn($service->brand, $request->opt_in);
|
||||
}
|
||||
|
||||
/** @var \App\Models\CustomerInfo */
|
||||
$customerInfo = $customer->info($service->brand, Customer::FIRST_OR_FAIL);
|
||||
$customerInfo->fill($request->validated());
|
||||
$saved = $customerInfo->save() && $saved;
|
||||
|
||||
/** @var \App\Models\CustomerLogin */
|
||||
$customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
|
||||
$customerLogin->fill($request->validated());
|
||||
$saved = $customerLogin->save() && $saved;
|
||||
|
||||
if (!$saved) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new CrmException('Api failed to update customer.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
});
|
||||
|
||||
return new CustomerResource($service->brand, $customer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes customer information for a specific service.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \App\Exceptions\Api\V4\CrmException If removing the customer off the DB failed.
|
||||
*/
|
||||
public function destroy(Service $service, Customer $customer): JsonResponse
|
||||
{
|
||||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
||||
/** @var \App\Models\CustomerInfo */
|
||||
$customerInfo = $customer->info($service->brand, Customer::FIRST_OR_FAIL);
|
||||
/** @var \App\Models\CustomerLogin */
|
||||
$customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
|
||||
|
||||
DB::transaction(function () use ($service, $customer, $customerLogin, $customerInfo) {
|
||||
if (
|
||||
$customerInfo->delete() === false ||
|
||||
$customerLogin->delete() === false
|
||||
) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new CrmException('Api failed to delete customer.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
};
|
||||
|
||||
$customer->optInHistory()->whereHas('brand', function ($q) use ($service) {
|
||||
$q->where('id', $service->brand_id);
|
||||
})->delete();
|
||||
|
||||
// * Force loading real relation counts.
|
||||
$customer->unsetRelation('logins');
|
||||
$customer->unsetRelation('infos');
|
||||
$logins = $customer->logins()->count();
|
||||
$infos = $customer->infos()->count();
|
||||
|
||||
// If customer is not associated with any brand then delete.
|
||||
if (!$logins and !$infos) {
|
||||
if ($customer->delete() === false) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new CrmException('Api failed to update customer.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return response()->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the user.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\AuthenticateRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Resources\Json\JsonResource
|
||||
* @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::authFailed in case
|
||||
* of wrong credentials.
|
||||
* @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::customerNotActivated if
|
||||
* customer account is not activated.
|
||||
*/
|
||||
public function authenticate(AuthenticateRequest $request, Service $service): JsonResource
|
||||
{
|
||||
try {
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = Customer::query()->where('email', $request->email)->firstOrFail();
|
||||
|
||||
/** @var \App\Models\CustomerLogin $customerLogin */
|
||||
$customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
|
||||
if (!$customerLogin->passwordMatch($request->password)) {
|
||||
throw new ApiErrorException(ApiError::authFailed);
|
||||
}
|
||||
|
||||
if (!$customerLogin->status) {
|
||||
throw new ApiErrorException(ApiError::customerNotActivated);
|
||||
}
|
||||
|
||||
UpdateCustomerLastConnection::dispatch($customer, $customerLogin, now())
|
||||
->onConnection('database')->afterResponse();
|
||||
|
||||
return new CustomerResource($service->brand, $customer);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
throw new ApiErrorException(ApiError::authFailed);
|
||||
} //end try
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the account of the user.
|
||||
*
|
||||
* @param \App\Models\Customer $customer
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::customerAlreadyActive
|
||||
* if customer account is already active.
|
||||
* @throws \App\Exceptions\Api\V4\CrmException If saving the customer to DB failed.
|
||||
*/
|
||||
public function activateAccount(Customer $customer, Service $service): JsonResponse
|
||||
{
|
||||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
||||
/** @var \App\Models\CustomerLogin $login */
|
||||
$login = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
|
||||
|
||||
if ($login->status) {
|
||||
throw new ApiErrorException(ApiError::customerAlreadyActive);
|
||||
}
|
||||
|
||||
$login->status = true;
|
||||
if (!$login->save()) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new CrmException('Failed to save login');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
return response()->json();
|
||||
}
|
||||
}
|
||||
93
app/Http/Controllers/Api/V4/OptinController.php
Normal file
93
app/Http/Controllers/Api/V4/OptinController.php
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V4;
|
||||
|
||||
use App\Enums\ApiError;
|
||||
use App\Exceptions\Api\V4\ApiErrorException;
|
||||
use App\Exceptions\Api\V4\CrmException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Api\V4\BaseApiRequest;
|
||||
use App\Http\Requests\Api\V4\SingleOptinRequest;
|
||||
use App\Http\Requests\Api\V4\SingleOptinRemoveWithHashcodeRequest;
|
||||
use App\Models\CustomerInfo;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use App\Models\SingleOptin;
|
||||
|
||||
class OptinController extends Controller
|
||||
{
|
||||
/**
|
||||
* Creates a new Single optin or destroys it if exists.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\SingleOptinRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::singleOptinCustomerExists
|
||||
* if this email already has a full account.
|
||||
* @throws \App\Exceptions\Api\V4\CrmException If the single optin could not be added or removed.
|
||||
*/
|
||||
public function optin(SingleOptinRequest $request, Service $service): JsonResponse
|
||||
{
|
||||
if (CustomerInfo::getFromEmail($service->brand, $request->email)->exists()) {
|
||||
throw new ApiErrorException(ApiError::singleOptinCustomerExists);
|
||||
}
|
||||
|
||||
/** @var \App\Models\SingleOptin */
|
||||
$singleOptin = SingleOptin::query()->where('email', $request->email)
|
||||
->whereHas('brand', function ($q) use ($service) {
|
||||
$q->where('id', $service->brand->id);
|
||||
})->firstOrNew();
|
||||
|
||||
if (!$this->changeOptin($service, $request, \boolval($request->opt_in), $singleOptin)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new CrmException('Api failed to update single optin.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return response()->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Single optin or destroys it if exists using hashcode.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\SingleOptinRemoveWithHashcodeRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \App\Exceptions\Api\V4\CrmException If the single optin could not be removed.
|
||||
*/
|
||||
public function optoutWithHashcode(SingleOptinRemoveWithHashcodeRequest $request, Service $service): JsonResponse
|
||||
{
|
||||
/** @var \App\Models\SingleOptin */
|
||||
$singleOptin = SingleOptin::query()->where('hashcode', $request->hashcode)
|
||||
->whereHas('brand', function ($q) use ($service) {
|
||||
$q->whereId($service->brand->id);
|
||||
})->firstOrFail();
|
||||
|
||||
if ($singleOptin and !$this->changeOptin($service, $request, \boolval($request->opt_in), $singleOptin)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new CrmException('Api failed to update single optin.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return response()->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the optin state.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Http\Requests\Api\V4\BaseApiRequest $request
|
||||
* @param boolean $optin
|
||||
* @param \App\Models\SingleOptin $singleOptin
|
||||
* @return boolean Returns false in case of failure.
|
||||
*/
|
||||
private function changeOptin(Service $service, BaseApiRequest $request, bool $optin, SingleOptin $singleOptin): bool
|
||||
{
|
||||
if ($optin) {
|
||||
$singleOptin->fill($request->validated());
|
||||
$singleOptin->brand()->associate($service->brand);
|
||||
return $singleOptin->save();
|
||||
}
|
||||
return $singleOptin->delete() !== false;
|
||||
}
|
||||
}
|
||||
64
app/Http/Controllers/Api/V4/QuestionController.php
Normal file
64
app/Http/Controllers/Api/V4/QuestionController.php
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V4;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\Api\V4\QuestionsResource;
|
||||
use App\Models\Answer;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Question;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class QuestionController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns all service questions.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Resources\Json\ResourceCollection
|
||||
*/
|
||||
public function index(Service $service): ResourceCollection
|
||||
{
|
||||
return new QuestionsResource($service->brand->questions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all service questions with user answers for all of them.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\Resources\Json\ResourceCollection
|
||||
*/
|
||||
public function indexWithResponse(Service $service, Customer $customer): ResourceCollection
|
||||
{
|
||||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
||||
$customerAnswers = $customer->getAnswers($service);
|
||||
return new QuestionsResource($service->brand->questions, $customerAnswers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all service questions that was not answered by a user.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\Resources\Json\JsonResource
|
||||
*/
|
||||
public function unAnsweredBy(Service $service, Customer $customer): JsonResource
|
||||
{
|
||||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('customerBelongsToService', $customer);
|
||||
|
||||
$questions = Question::query()->whereHas('brand', function ($q) use ($service) {
|
||||
$q->where('id', $service->brand->id);
|
||||
})->whereDoesntHave('answers', function ($q) use ($customer) {
|
||||
$q->whereIn('id', Answer::query()->whereHas('customers', function ($q) use ($customer) {
|
||||
$q->where('id', $customer->id);
|
||||
})->pluck('id'));
|
||||
})->with('answers')->get();
|
||||
return new QuestionsResource($questions);
|
||||
}
|
||||
}
|
||||
109
app/Http/Controllers/Api/V4/StatsController.php
Normal file
109
app/Http/Controllers/Api/V4/StatsController.php
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V4;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Api\V4\GetBrandStatsRequest;
|
||||
use App\Http\Requests\Api\V4\GetQuestionStatsRequest;
|
||||
use App\Http\Resources\Api\V4\BrandStatsResource;
|
||||
use App\Http\Resources\Api\V4\QuestionStatsResource;
|
||||
use App\Models\BrandStat;
|
||||
use App\Models\CustomerAnswer;
|
||||
use App\Models\Question;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class StatsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get specific brand statistics.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\GetBrandStatsRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Resources\Json\ResourceCollection
|
||||
*/
|
||||
public function brandStats(GetBrandStatsRequest $request, Service $service): ResourceCollection
|
||||
{
|
||||
$stats = BrandStat::query()->whereDate('created_at', '>=', $request->start)
|
||||
->whereDate('created_at', '<=', $request->end)
|
||||
->whereBrandId($service->brand->id)->get();
|
||||
return new BrandStatsResource($stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get statistics for a specific question.
|
||||
*
|
||||
* @param \App\Http\Requests\Api\V4\GetQuestionStatsRequest $request
|
||||
* @param \App\Models\Question $question
|
||||
* @return \App\Http\Resources\Api\V4\QuestionStatsResource
|
||||
*/
|
||||
public function questionStats(GetQuestionStatsRequest $request, Question $question): QuestionStatsResource
|
||||
{
|
||||
// * Make sure we are accessing a customer that belongs to our service.
|
||||
$this->authorize('questionBelongsToService', $question);
|
||||
|
||||
$answers = $question->answers;
|
||||
$start = Carbon::parse($request->start);
|
||||
$end = Carbon::parse($request->end);
|
||||
|
||||
return new QuestionStatsResource(
|
||||
$this->answersByDays($answers, $start, $end),
|
||||
$question
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Total réponses par dates.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $answers
|
||||
* @param \Illuminate\Support\Carbon $start
|
||||
* @param \Illuminate\Support\Carbon $end
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function answersByDays(Collection $answers, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
// * Totalize by date all answers.
|
||||
$answersByDays = CustomerAnswer::query()->whereDate('created_at', '>=', $start)
|
||||
->whereDate('created_at', '<=', $end)
|
||||
->whereIn('answer_id', $answers->pluck('id'))
|
||||
->get()->map(function ($custAnswer) {
|
||||
return [
|
||||
'answer_id' => $custAnswer->answer_id,
|
||||
'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
|
||||
];
|
||||
})->groupBy(['created_at', 'answer_id'])->map(function ($day) {
|
||||
return $day->map(function ($custAnswers) {
|
||||
return $custAnswers->count();
|
||||
});
|
||||
});
|
||||
|
||||
do {
|
||||
$currentDate = $start->isoFormat('YYYY-MM-DD');
|
||||
/** @var \Illuminate\Support\Collection $answersByDays */
|
||||
if (!$answersByDays->has($currentDate)) {
|
||||
$answersByDays->put(
|
||||
$currentDate,
|
||||
$answers->mapWithKeys(function ($answer) {
|
||||
return [$answer->id => 0];
|
||||
})
|
||||
);
|
||||
} else {
|
||||
$curentAnswers = $answersByDays->pull($currentDate);
|
||||
$answersByDays->put(
|
||||
$currentDate,
|
||||
$answers->mapWithKeys(function ($answer) use ($curentAnswers) {
|
||||
return [$answer->id =>
|
||||
$curentAnswers->has($answer->id) ?
|
||||
$curentAnswers->get($answer->id) : 0];
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
$start = $start->addDay();
|
||||
} while ($start->lessThanOrEqualTo($end));
|
||||
|
||||
return $answersByDays;
|
||||
}
|
||||
}
|
||||
71
app/Http/Controllers/Bo/ActivityLogsController.php
Normal file
71
app/Http/Controllers/Bo/ActivityLogsController.php
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\ActivityLog;
|
||||
use App\Traits\Controllers\ChangesModelOrder;
|
||||
use App\Traits\Controllers\UpdateModelPublished;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ActivityLogsController extends Controller
|
||||
{
|
||||
use ChangesModelOrder;
|
||||
use UpdateModelPublished;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$this->authorize('isConceptor');
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = ActivityLog::query()->with('user');
|
||||
|
||||
/** @var string $search Search field */
|
||||
$search = $request->search;
|
||||
if ($search) {
|
||||
$this->searchQuery(
|
||||
$query,
|
||||
$search,
|
||||
null,
|
||||
'model_class',
|
||||
);
|
||||
}
|
||||
$searchFields = \implode(', ', [
|
||||
trans('validation.custom.target'),
|
||||
]);
|
||||
|
||||
/** Sort columns with a query */
|
||||
$this->sortQuery($query);
|
||||
|
||||
/** Custom pagination */
|
||||
$activitylogModels = $this->paginate($query);
|
||||
|
||||
return view('bo.pages.activity_logs.index', compact('activitylogModels', 'search', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\ActivityLog $activity_log
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(ActivityLog $activity_log): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$this->authorize('isConceptor');
|
||||
$targetModelClass = $activity_log->model_class;
|
||||
$targetModel = $activity_log->model_class::where(
|
||||
(new $targetModelClass())->getRouteKeyName(),
|
||||
$activity_log->model_id
|
||||
)->first();
|
||||
|
||||
return view('bo.pages.activity_logs.show', [
|
||||
'activitylogModel' => $activity_log,
|
||||
'targetModel' => $targetModel,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Answers\StoreAnswerRequest;
|
||||
use App\Http\Requests\Answers\UpdateAnswerRequest;
|
||||
use App\Http\Requests\Bo\Answers\StoreAnswerRequest;
|
||||
use App\Http\Requests\Bo\Answers\UpdateAnswerRequest;
|
||||
use App\Models\Answer;
|
||||
use App\Models\Question;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AnswerController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \App\Models\Question $questionModel */
|
||||
$questionModel = $request->question;
|
||||
|
|
@ -42,9 +39,9 @@ class AnswerController extends Controller
|
|||
$this->sortQuery($answers);
|
||||
$searchFields = trans('Réponse');
|
||||
|
||||
$answerModels = $answers->paginate(12);
|
||||
$answerModels = $this->paginate($answers);
|
||||
|
||||
return view('answers.index', compact('answerModels', 'questionModel', 'searchFields'));
|
||||
return view('bo.pages.answers.index', compact('answerModels', 'questionModel', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -52,14 +49,14 @@ class AnswerController extends Controller
|
|||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \App\Models\Answer $answer
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create(Request $request, Answer $answer)
|
||||
public function create(Request $request, Answer $answer): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \App\Models\Question $questionModel */
|
||||
$questionModel = $request->question;
|
||||
|
||||
return view('answers.create', [
|
||||
return view('bo.pages.answers.create', [
|
||||
'answerModel' => $answer,
|
||||
'questionModel' => $questionModel
|
||||
]);
|
||||
|
|
@ -68,17 +65,17 @@ class AnswerController extends Controller
|
|||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Answers\StoreAnswerRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \App\Http\Requests\Bo\Answers\StoreAnswerRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreAnswerRequest $request)
|
||||
public function store(StoreAnswerRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$answer = new Answer();
|
||||
$answer->fill($request->validated());
|
||||
if ($answer->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('answers.edit', $answer)
|
||||
->route('bo.answers.edit', $answer)
|
||||
->with('success', trans(
|
||||
':model a été créé.',
|
||||
['model' => Str::singular(trans('models.classes.answers'))]
|
||||
|
|
@ -98,11 +95,11 @@ class AnswerController extends Controller
|
|||
*
|
||||
* @param \App\Models\Question $question
|
||||
* @param \App\Models\Answer $answers
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Question $question, Answer $answers)
|
||||
public function edit(Question $question, Answer $answers): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('answers.edit', [
|
||||
return view('bo.pages.answers.edit', [
|
||||
'answerModel' => $answers,
|
||||
'questionModel' => $question
|
||||
]);
|
||||
|
|
@ -111,18 +108,21 @@ class AnswerController extends Controller
|
|||
/**
|
||||
* Update a spacific resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Answers\UpdateAnswerRequest $request
|
||||
* @param \App\Models\Question $question
|
||||
* @param \App\Models\Answer $answer
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \App\Http\Requests\Bo\Answers\UpdateAnswerRequest $request
|
||||
* @param \App\Models\Question $question
|
||||
* @param \App\Models\Answer $answer
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateAnswerRequest $request, Question $question, Answer $answer)
|
||||
{
|
||||
public function update(
|
||||
UpdateAnswerRequest $request,
|
||||
Question $question,
|
||||
Answer $answer
|
||||
): \Illuminate\Http\RedirectResponse {
|
||||
return DB::transaction(function () use ($request, $question, $answer) {
|
||||
$answer->fill($request->validated());
|
||||
if ($answer->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('questions.answers.edit', ['question' => $question, 'answer' => $answer])
|
||||
->route('bo.questions.answers.edit', ['question' => $question, 'answer' => $answer])
|
||||
->with('success', trans(
|
||||
':model a été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.answers'))]
|
||||
|
|
@ -147,7 +147,7 @@ class AnswerController extends Controller
|
|||
public function destroy(Question $question, Answer $answer): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($answer->deleteOrFail()) {
|
||||
return redirect()->route('questions.answers.index', $question)
|
||||
return redirect()->route('bo.questions.answers.index', $question)
|
||||
->with('success', trans(
|
||||
':model a été supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.answers'))]
|
||||
72
app/Http/Controllers/Bo/Auth/LoginController.php
Normal file
72
app/Http/Controllers/Bo/Auth/LoginController.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
use AuthenticatesUsers;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest:backend')->except('logout');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guard to be used during authentication.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
protected function guard(): StatefulGuard
|
||||
{
|
||||
return Auth::guard('backend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application's login form.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function showLoginForm(): View
|
||||
{
|
||||
return view('bo.auth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Where to redirect users after login.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function redirectTo(): string
|
||||
{
|
||||
return response()->redirectToIntended()->getTargetUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to log the user into the application.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return boolean
|
||||
*/
|
||||
protected function attemptLogin(Request $request)
|
||||
{
|
||||
$credentials = $this->credentials($request);
|
||||
// * Attempt login only using published users.
|
||||
$credentials['published'] = true;
|
||||
return $this->guard()->attempt(
|
||||
$credentials,
|
||||
$request->boolean('remember')
|
||||
);
|
||||
}
|
||||
}
|
||||
33
app/Http/Controllers/Bo/Auth/ResetPasswordController.php
Normal file
33
app/Http/Controllers/Bo/Auth/ResetPasswordController.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
use ResetsPasswords;
|
||||
|
||||
/**
|
||||
* Get the guard to be used during authentication.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
protected function guard(): StatefulGuard
|
||||
{
|
||||
return Auth::guard('backend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Where to redirect users after login.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function redirectTo(): string
|
||||
{
|
||||
return \route('bo.login');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Brands\StoreBrandRequest;
|
||||
use App\Http\Requests\Brands\UpdateBrandRequest;
|
||||
use App\Http\Requests\Bo\Brands\StoreBrandRequest;
|
||||
use App\Http\Requests\Bo\Brands\UpdateBrandRequest;
|
||||
use App\Models\Brand;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class BrandController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = Brand::query();
|
||||
|
|
@ -43,20 +40,20 @@ class BrandController extends Controller
|
|||
$q->where('opt_in', true);
|
||||
}]);
|
||||
|
||||
$brandModels = $query->paginate(12);
|
||||
$brandModels = $this->paginate($query);
|
||||
|
||||
return view('brands.index', compact('brandModels', 'searchFields'));
|
||||
return view('bo.pages.brands.index', compact('brandModels', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Models\Brand $brands
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create(Brand $brands)
|
||||
public function create(Brand $brands): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('brands.create', [
|
||||
return view('bo.pages.brands.create', [
|
||||
'brandModel' => $brands
|
||||
]);
|
||||
}
|
||||
|
|
@ -64,17 +61,17 @@ class BrandController extends Controller
|
|||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Brands\StoreBrandRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \App\Http\Requests\Brands\Bo\StoreBrandRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreBrandRequest $request)
|
||||
public function store(StoreBrandRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$brand = new Brand();
|
||||
$brand->fill($request->validated());
|
||||
if ($brand->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('brands.edit', $brand)
|
||||
->route('bo.brands.edit', $brand)
|
||||
->with('success', trans(
|
||||
':model a été créé.',
|
||||
['model' => Str::singular(trans('models.classes.brands'))]
|
||||
|
|
@ -93,11 +90,11 @@ class BrandController extends Controller
|
|||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Brand $brands
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Brand $brands)
|
||||
public function edit(Brand $brands): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('brands.edit', [
|
||||
return view('bo.pages.brands.edit', [
|
||||
'brandModel' => $brands
|
||||
]);
|
||||
}
|
||||
|
|
@ -105,17 +102,17 @@ class BrandController extends Controller
|
|||
/**
|
||||
* Update a spacific resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Brands\UpdateBrandRequest $request
|
||||
* @param \App\Models\Brand $brand
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \App\Http\Requests\Brands\Bo\UpdateBrandRequest $request
|
||||
* @param \App\Models\Brand $brand
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateBrandRequest $request, Brand $brand)
|
||||
public function update(UpdateBrandRequest $request, Brand $brand): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $brand) {
|
||||
$brand->fill($request->validated());
|
||||
if ($brand->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('brands.edit', $brand)
|
||||
->route('bo.brands.edit', $brand)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.brands'))]
|
||||
|
|
@ -133,12 +130,12 @@ class BrandController extends Controller
|
|||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function jsonPaginate()
|
||||
public function jsonPaginate(): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
return DB::transaction(function () {
|
||||
/** @var \App\Models\Tag */
|
||||
/** @var \App\Models\Brand */
|
||||
$brandModels = Brand::paginate(12);
|
||||
return \response()->json($brandModels ?? 500);
|
||||
});
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Enums\CustomerExportType;
|
||||
use App\Http\Requests\CustomerExport;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\CustomerExport;
|
||||
use App\Models\Brand;
|
||||
use App\Models\Customer;
|
||||
use App\Models\CustomerInfo;
|
||||
|
|
@ -20,34 +21,29 @@ use Illuminate\Support\Str;
|
|||
use League\Csv\Writer;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CustomerController extends Controller
|
||||
{
|
||||
/**
|
||||
* View all customers
|
||||
* View all customers.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$modelTable = (new Customer())->getTable();
|
||||
$modelClass = Customer::class;
|
||||
$brands = Brand::select('id', 'name')->get();
|
||||
$brands = Brand::query()->select('id', 'name')->get();
|
||||
$columns = ['customer_infos.lastname', 'customer_infos.firstname'];
|
||||
|
||||
// * Jointure pour pouvoir trier les colonnes.
|
||||
/** @var \Illuminate\Database\Eloquent\Builder */
|
||||
$query = CustomerInfo::join('customer_logins', function (JoinClause $join) {
|
||||
$query = CustomerInfo::query()->join('customer_logins', function (JoinClause $join) {
|
||||
$join->on('customer_logins.brand_id', '=', 'customer_infos.brand_id')
|
||||
->on('customer_logins.customer_id', '=', 'customer_infos.customer_id');
|
||||
})
|
||||
->join('customers', function (JoinClause $join) {
|
||||
->on('customer_logins.customer_id', '=', 'customer_infos.customer_id');
|
||||
})->join('customers', function (JoinClause $join) {
|
||||
$join->on('customers.id', '=', 'customer_infos.customer_id');
|
||||
})
|
||||
->join('brands', function (JoinClause $join) {
|
||||
})->join('brands', function (JoinClause $join) {
|
||||
$join->on('brands.id', '=', 'customer_infos.brand_id');
|
||||
});
|
||||
|
||||
|
|
@ -89,15 +85,15 @@ class CustomerController extends Controller
|
|||
Session::has("crud.$modelTable.sort_col") and
|
||||
Session::has("crud.$modelTable.sort_way") and
|
||||
(Schema::hasColumn($modelTable, Session::get("crud.$modelTable.sort_col")) or
|
||||
in_array(Session::get("crud.$modelTable.sort_col"), [
|
||||
'brands.name',
|
||||
'customers.email',
|
||||
'customer_infos.firstname',
|
||||
'customer_infos.lastname',
|
||||
'customer_infos.opt_in',
|
||||
'customer_logins.last_connection',
|
||||
'customer_logins.status'
|
||||
]))
|
||||
in_array(Session::get("crud.$modelTable.sort_col"), [
|
||||
'brands.name',
|
||||
'customers.email',
|
||||
'customer_infos.firstname',
|
||||
'customer_infos.lastname',
|
||||
'customer_infos.opt_in',
|
||||
'customer_logins.last_connection',
|
||||
'customer_logins.status'
|
||||
]))
|
||||
) {
|
||||
$query = $query->orderBy(
|
||||
Session::get("crud.$modelTable.sort_col"),
|
||||
|
|
@ -107,10 +103,12 @@ class CustomerController extends Controller
|
|||
|
||||
$searchFields = trans('Email, Prénom, Nom');
|
||||
|
||||
/** @var \Illuminate\Pagination\AbstractPaginator */
|
||||
$customerModels = $query->paginate(50);
|
||||
$query->with(['customer', 'brand']);
|
||||
|
||||
return view('customers.index', compact(
|
||||
/** @var \Illuminate\Pagination\AbstractPaginator */
|
||||
$customerModels = $this->paginate($query);
|
||||
|
||||
return view('bo.pages.customers.index', compact(
|
||||
'modelClass',
|
||||
'modelTable',
|
||||
'customerModels',
|
||||
|
|
@ -120,36 +118,35 @@ class CustomerController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Show a specific custmer
|
||||
* Show a specific custmer.
|
||||
*
|
||||
* @param \App\Models\Customer $customer
|
||||
* @param \App\Models\Brand $brand
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(Customer $customer, Brand $brand)
|
||||
public function show(Customer $customer, Brand $brand): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$customerInfos = CustomerInfo::where('customer_id', $customer->id)
|
||||
$customerInfos = CustomerInfo::query()->where('customer_id', $customer->id)
|
||||
->where('brand_id', $brand->id)->firstOrFail();
|
||||
$customerLogin = CustomerLogin::where('customer_id', $customer->id)
|
||||
$customerLogin = CustomerLogin::query()->where('customer_id', $customer->id)
|
||||
->where('brand_id', $brand->id)->first();
|
||||
|
||||
return view('customers.show', compact(
|
||||
return view('bo.pages.customers.show', compact(
|
||||
'customerInfos',
|
||||
'customerLogin'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a specific customer info
|
||||
* Delete a specific customer info.
|
||||
*
|
||||
* @param \App\Models\Customer $customer
|
||||
* @param \App\Models\Brand $brand
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function delete(Customer $customer, Brand $brand)
|
||||
public function delete(Customer $customer, Brand $brand): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
try {
|
||||
// TODO: Gestion avec mesBR.
|
||||
/** @var \App\Models\CustomerInfo */
|
||||
$customerInfo = $customer->info($brand, Customer::FIRST_OR_FAIL);
|
||||
/** @var \App\Models\CustomerLogin */
|
||||
|
|
@ -184,34 +181,34 @@ class CustomerController extends Controller
|
|||
}
|
||||
});
|
||||
} catch (\ErrorException $e) {
|
||||
return redirect()->route('customers.index')
|
||||
->with('error', trans('Le compte n\'a pas pu être supprimé.'));
|
||||
return redirect()->route('bo.customers.index')
|
||||
->with('error', trans('Le compte n\'a pas pu être supprimé.'));
|
||||
} //end try
|
||||
|
||||
return redirect()->route('customers.index')->with('warning', trans('Compte supprimé.'));
|
||||
return redirect()->route('bo.customers.index')->with('warning', trans('Compte supprimé.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show export the customers form
|
||||
* Show export the customers form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function export()
|
||||
public function export(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$brands = Brand::all();
|
||||
return view('customers.export', compact(
|
||||
return view('bo.pages.customers.export', compact(
|
||||
'brands'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports customers following the requested export type
|
||||
* Exports customers following the requested export type.
|
||||
*
|
||||
* @param \App\Http\Requests\CustomerExport $request
|
||||
* @param \App\Http\Requests\Bo\CustomerExport $request
|
||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
* @throws \Exception If the request export type in not handled.
|
||||
*/
|
||||
public function exportSubmit(CustomerExport $request)
|
||||
public function exportSubmit(CustomerExport $request): \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
{
|
||||
$pagination = 2000;
|
||||
$header = '"lastname";"firstname";"email";"hashcode"';
|
||||
|
|
@ -233,19 +230,19 @@ class CustomerController extends Controller
|
|||
sprintf(
|
||||
'attachment; filename="Export pour newsletter %s %s.csv"',
|
||||
Carbon::now()->isoFormat('DD-MM-YYYY_HH-mm'),
|
||||
Str::slug($exportType)
|
||||
Str::slug($exportType->label())
|
||||
)
|
||||
);
|
||||
|
||||
switch ($exportType) {
|
||||
case CustomerExportType::both():
|
||||
case CustomerExportType::both:
|
||||
$continue = true;
|
||||
// ! Continue
|
||||
case CustomerExportType::customer():
|
||||
case CustomerExportType::customer:
|
||||
$page = 1;
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $req */
|
||||
$req = CustomerInfo::where('brand_id', $request->brand)
|
||||
->where('opt_in', true);
|
||||
$req = CustomerInfo::query()->where('brand_id', $request->brand)
|
||||
->where('opt_in', true);
|
||||
$total = $req->count();
|
||||
$pages = \ceil($total / $pagination);
|
||||
do {
|
||||
|
|
@ -271,7 +268,7 @@ class CustomerController extends Controller
|
|||
break;
|
||||
}
|
||||
// ! Continue
|
||||
case CustomerExportType::singleOptin():
|
||||
case CustomerExportType::singleOptin:
|
||||
SingleOptin::query()->whereHas('brand', function (Builder $q) use ($request) {
|
||||
$q->where('id', $request->brand);
|
||||
})->get()->map(function (SingleOptin $singleOptin) use ($w) {
|
||||
|
|
@ -284,7 +281,7 @@ class CustomerController extends Controller
|
|||
});
|
||||
break;
|
||||
default:
|
||||
throw new \Exception(sprintf('Unhandled CustomerExportType %s', $exportType->label));
|
||||
throw new \Exception(sprintf('Unhandled CustomerExportType %s', $exportType->label()));
|
||||
} //end switch
|
||||
|
||||
/*
|
||||
19
app/Http/Controllers/Bo/DashboardController.php
Normal file
19
app/Http/Controllers/Bo/DashboardController.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
* Dashboard Page
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return view('bo.pages.dashboard');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\QuestionExport;
|
||||
use App\Http\Requests\Questions\StoreQuestionRequest;
|
||||
use App\Http\Requests\Questions\UpdateQuestionRequest;
|
||||
use App\Http\Requests\Bo\QuestionExport;
|
||||
use App\Http\Requests\Bo\Questions\StoreQuestionRequest;
|
||||
use App\Http\Requests\Bo\Questions\UpdateQuestionRequest;
|
||||
use App\Models\Brand;
|
||||
use App\Models\Question;
|
||||
use Carbon\Carbon;
|
||||
|
|
@ -15,24 +15,21 @@ use Illuminate\Support\Str;
|
|||
use League\Csv\Writer;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class QuestionController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = Question::query();
|
||||
|
||||
if ($request->brand) {
|
||||
$query = $query->where('brand_id', '=', request()->brand);
|
||||
$query = $query->where('brand_id', '=', $request->brand);
|
||||
}
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
|
|
@ -46,23 +43,25 @@ class QuestionController extends Controller
|
|||
$this->sortQuery($query);
|
||||
$searchFields = trans('Question');
|
||||
|
||||
/** @var \Illuminate\Pagination\AbstractPaginator */
|
||||
$questionModels = $query->paginate(12);
|
||||
$query->with(['brand', 'answers']);
|
||||
|
||||
return view('questions.index', compact('questionModels', 'searchFields'));
|
||||
/** @var \Illuminate\Pagination\AbstractPaginator */
|
||||
$questionModels = $this->paginate($query);
|
||||
|
||||
return view('bo.pages.questions.index', compact('questionModels', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Models\Question $question
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create(Question $question)
|
||||
public function create(Question $question): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$brandModels = Brand::get();
|
||||
$brandModels = Brand::all();
|
||||
|
||||
return view('questions.create', [
|
||||
return view('bo.pages.questions.create', [
|
||||
'questionModel' => $question,
|
||||
'brandModels' => $brandModels
|
||||
]);
|
||||
|
|
@ -72,16 +71,16 @@ class QuestionController extends Controller
|
|||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Questions\StoreQuestionRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreQuestionRequest $request)
|
||||
public function store(StoreQuestionRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$question = new Question();
|
||||
$question->fill($request->validated());
|
||||
if ($question->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('questions.edit', $question)
|
||||
->route('bo.questions.edit', $question)
|
||||
->with('success', trans(
|
||||
':model a été créé.',
|
||||
['model' => Str::singular(trans('models.classes.questions'))]
|
||||
|
|
@ -100,13 +99,14 @@ class QuestionController extends Controller
|
|||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Question $question
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Question $question)
|
||||
public function edit(Question $question): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$brandModels = Brand::get();
|
||||
$brandModels = Brand::all();
|
||||
$question->load('brand');
|
||||
|
||||
return view('questions.edit', [
|
||||
return view('bo.pages.questions.edit', [
|
||||
'questionModel' => $question,
|
||||
'brandModels' => $brandModels
|
||||
]);
|
||||
|
|
@ -117,15 +117,15 @@ class QuestionController extends Controller
|
|||
*
|
||||
* @param \App\Http\Requests\Questions\UpdateQuestionRequest $request
|
||||
* @param \App\Models\Question $question
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateQuestionRequest $request, Question $question)
|
||||
public function update(UpdateQuestionRequest $request, Question $question): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $question) {
|
||||
$question->fill($request->validated());
|
||||
if ($question->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('questions.edit', $question)
|
||||
->route('bo.questions.edit', $question)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.questions'))]
|
||||
|
|
@ -144,11 +144,11 @@ class QuestionController extends Controller
|
|||
* Show the specified resource.
|
||||
*
|
||||
* @param \App\Models\Question $question
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(Question $question)
|
||||
public function show(Question $question): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('questions.show', [
|
||||
return view('bo.pages.questions.show', [
|
||||
'questionModel' => $question
|
||||
]);
|
||||
}
|
||||
|
|
@ -162,7 +162,7 @@ class QuestionController extends Controller
|
|||
public function destroy(Question $question): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($question->deleteOrFail()) {
|
||||
return redirect()->route('questions.index')
|
||||
return redirect()->route('bo.questions.index')
|
||||
->with('success', trans(
|
||||
':model a été supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.questions'))]
|
||||
|
|
@ -178,12 +178,12 @@ class QuestionController extends Controller
|
|||
/**
|
||||
* Shows the question export form
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function export()
|
||||
public function export(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$brands = Brand::all();
|
||||
return view('questions.export', compact('brands'));
|
||||
return view('bo.pages.questions.export', compact('brands'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -192,10 +192,11 @@ class QuestionController extends Controller
|
|||
* @param \App\Http\Requests\QuestionExport $request
|
||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
*/
|
||||
public function exportSubmit(QuestionExport $request)
|
||||
public function exportSubmit(QuestionExport $request): \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
{
|
||||
$results = [];
|
||||
$brand = Brand::findOrFail($request->brand);
|
||||
$results = [];
|
||||
/** @var \App\Models\Brand $brand */
|
||||
$brand = Brand::query()->where('id', $request->brand)->firstOrFail();
|
||||
$questions = $brand->questions->load('answers');
|
||||
|
||||
foreach ($questions as $question) {
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Requests\GenerateServiceToken;
|
||||
use App\Http\Requests\Services\StoreServiceRequest;
|
||||
use App\Http\Requests\Services\UpdateServiceRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\GenerateServiceToken;
|
||||
use App\Http\Requests\Bo\Services\StoreServiceRequest;
|
||||
use App\Http\Requests\Bo\Services\UpdateServiceRequest;
|
||||
use App\Mail\ServiceCredentialRenewed;
|
||||
use App\Models\Brand;
|
||||
use App\Models\Service;
|
||||
|
|
@ -14,24 +15,21 @@ use Illuminate\Support\Facades\Hash;
|
|||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ServiceController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = Service::query();
|
||||
|
||||
if ($request->brand) {
|
||||
$query = $query->where('brand_id', '=', request()->brand);
|
||||
$query = $query->where('brand_id', '=', $request->brand);
|
||||
}
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
|
|
@ -45,22 +43,24 @@ class ServiceController extends Controller
|
|||
$this->sortQuery($query);
|
||||
$searchFields = trans('Nom');
|
||||
|
||||
$serviceModels = $query->paginate(12);
|
||||
$query->with(['brand']);
|
||||
|
||||
return view('services.index', compact('serviceModels', 'searchFields'));
|
||||
$serviceModels = $this->paginate($query);
|
||||
|
||||
return view('bo.pages.services.index', compact('serviceModels', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create(Service $service)
|
||||
public function create(Service $service): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$brandModels = Brand::get();
|
||||
$brandModels = Brand::all();
|
||||
|
||||
return view('services.create', [
|
||||
return view('bo.pages.services.create', [
|
||||
'serviceModel' => $service,
|
||||
'brandModels' => $brandModels
|
||||
]);
|
||||
|
|
@ -69,10 +69,10 @@ class ServiceController extends Controller
|
|||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Services\StoreServiceRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \App\Http\Requests\Bo\Services\StoreServiceRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreServiceRequest $request)
|
||||
public function store(StoreServiceRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$service = new Service();
|
||||
|
|
@ -81,7 +81,7 @@ class ServiceController extends Controller
|
|||
$this->generateServicePassword($service);
|
||||
if ($service->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('services.edit', $service)
|
||||
->route('bo.services.edit', $service)
|
||||
->with('success', trans(
|
||||
':model a été créé.',
|
||||
['model' => Str::singular(trans('models.classes.services'))]
|
||||
|
|
@ -100,13 +100,13 @@ class ServiceController extends Controller
|
|||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Service $service)
|
||||
public function edit(Service $service): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$brandModels = Brand::get();
|
||||
$brandModels = Brand::all();
|
||||
|
||||
return view('services.edit', [
|
||||
return view('bo.pages.services.edit', [
|
||||
'serviceModel' => $service,
|
||||
'brandModels' => $brandModels
|
||||
]);
|
||||
|
|
@ -115,17 +115,17 @@ class ServiceController extends Controller
|
|||
/**
|
||||
* Update a spacific resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Services\UpdateServiceRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \App\Http\Requests\Services\Bo\UpdateServiceRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateServiceRequest $request, Service $service)
|
||||
public function update(UpdateServiceRequest $request, Service $service): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $service) {
|
||||
$service->fill($request->validated());
|
||||
if ($service->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('services.edit', $service)
|
||||
->route('bo.services.edit', $service)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.services'))]
|
||||
|
|
@ -144,11 +144,11 @@ class ServiceController extends Controller
|
|||
* Show the specified resource.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(Service $service)
|
||||
public function show(Service $service): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('services.show', [
|
||||
return view('bo.pages.services.show', [
|
||||
'serviceModel' => $service
|
||||
]);
|
||||
}
|
||||
|
|
@ -162,7 +162,7 @@ class ServiceController extends Controller
|
|||
public function destroy(Service $service): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($service->deleteOrFail()) {
|
||||
return redirect()->route('services.index')
|
||||
return redirect()->route('bo.services.index')
|
||||
->with('success', trans(
|
||||
':model a été supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.services'))]
|
||||
|
|
@ -176,17 +176,19 @@ class ServiceController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Regen service credentials
|
||||
* Regen service credentials.
|
||||
*
|
||||
* @param \App\Http\Requests\GenerateServiceToken $request
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Http\Requests\Bo\GenerateServiceToken $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed, Squiz.Commenting.FunctionComment.Missing
|
||||
public function generateServicePassword(Service $service, GenerateServiceToken $request = null)
|
||||
{
|
||||
public function generateServicePassword(
|
||||
Service $service,
|
||||
GenerateServiceToken $request = null
|
||||
): \Illuminate\Http\RedirectResponse {
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
$user = auth('backend')->user();
|
||||
|
||||
// * Special Condition for migration from v2 to v3.
|
||||
$service->bearer_token = !Hash::needsRehash($service->bearer_token) ?
|
||||
|
|
@ -1,31 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\SingleOptin;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class SingleOptinController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = SingleOptin::query();
|
||||
|
||||
if ($request->brand) {
|
||||
$query = $query->whereHas('brand', function (Builder $q) {
|
||||
$q->where('id', request()->brand);
|
||||
$query = $query->whereHas('brand', function (Builder $q) use ($request) {
|
||||
$q->where('id', $request->brand);
|
||||
});
|
||||
}
|
||||
if ($request->search) {
|
||||
|
|
@ -40,10 +38,12 @@ class SingleOptinController extends Controller
|
|||
$this->sortQuery($query);
|
||||
$searchFields = trans('E-mail');
|
||||
|
||||
/** @var \Illuminate\Pagination\AbstractPaginator */
|
||||
$singleoptinModels = $query->paginate(12);
|
||||
$query->with(['brand']);
|
||||
|
||||
return view('singleoptins.index', compact('singleoptinModels', 'searchFields'));
|
||||
/** @var \Illuminate\Pagination\AbstractPaginator */
|
||||
$singleoptinModels = $this->paginate($query);
|
||||
|
||||
return view('bo.pages.singleoptins.index', compact('singleoptinModels', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -55,7 +55,7 @@ class SingleOptinController extends Controller
|
|||
public function destroy(SingleOptin $singleoptin): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($singleoptin->deleteOrFail()) {
|
||||
return redirect()->route('single_optins.index')
|
||||
return redirect()->route('bo.single_optins.index')
|
||||
->with('success', trans(
|
||||
':model a été supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.singleoptins'))]
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Requests\StatsByBrandRequest;
|
||||
use App\Http\Requests\StatsByQuestionRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\StatsByBrandRequest;
|
||||
use App\Http\Requests\Bo\StatsByQuestionRequest;
|
||||
use App\Models\Brand;
|
||||
use App\Models\BrandStat;
|
||||
use App\Models\CustomerAnswer;
|
||||
|
|
@ -13,38 +14,35 @@ use Illuminate\Support\Collection;
|
|||
use Illuminate\Support\Facades\Schema;
|
||||
use League\Csv\Writer;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class StatsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Shows stats by brand
|
||||
* Shows stats by brand.
|
||||
*
|
||||
* @param \App\Http\Requests\StatsByBrandRequest $request
|
||||
* @param \App\Http\Requests\Bo\StatsByBrandRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function viewStatsByBrand(StatsByBrandRequest $request)
|
||||
{
|
||||
$stats = null;
|
||||
if ($request->post()) {
|
||||
$stats = BrandStat::whereDate('created_at', '>=', $request->start)
|
||||
$stats = BrandStat::query()->whereDate('created_at', '>=', $request->start)
|
||||
->whereDate('created_at', '<=', $request->end)
|
||||
->whereBrandId($request->brand)->get();
|
||||
}
|
||||
return view('stats.view-stats-by-brands', \compact('stats'));
|
||||
return view('bo.pages.stats.view-stats-by-brands', \compact('stats'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports stats by brand as a csv file
|
||||
* Exports stats by brand as a csv file.
|
||||
*
|
||||
* @param \App\Http\Requests\StatsByBrandRequest $request
|
||||
* @param \App\Http\Requests\Bo\StatsByBrandRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function exportByBrandCsv(StatsByBrandRequest $request)
|
||||
public function exportByBrandCsv(StatsByBrandRequest $request): \Illuminate\Http\Response
|
||||
{
|
||||
$brand = Brand::findOrFail($request->brand);
|
||||
$stats = BrandStat::with('brand')->whereDate('created_at', '>=', $request->start)
|
||||
$brand = Brand::query()->findOrFail($request->brand);
|
||||
$stats = BrandStat::query()->with('brand')->whereDate('created_at', '>=', $request->start)
|
||||
->whereDate('created_at', '<=', $request->end)
|
||||
->whereBrandId($request->brand)->get();
|
||||
|
||||
|
|
@ -80,18 +78,18 @@ class StatsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Views stats for a specific question
|
||||
* Views stats for a specific question.
|
||||
*
|
||||
* @param \App\Http\Requests\StatsByQuestionRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \App\Http\Requests\Bo\StatsByQuestionRequest $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function viewByQuestion(StatsByQuestionRequest $request)
|
||||
public function viewByQuestion(StatsByQuestionRequest $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$question = null;
|
||||
$answers = null;
|
||||
$answersByDays = null;
|
||||
if ($request->post()) {
|
||||
$question = Question::findOrFail($request->question);
|
||||
$question = Question::query()->findOrFail($request->question);
|
||||
$answers = $question->answers;
|
||||
$start = Carbon::parse($request->start);
|
||||
$end = Carbon::parse($request->end);
|
||||
|
|
@ -99,18 +97,18 @@ class StatsController extends Controller
|
|||
$answersByDays = $this->answersByDays($answers, $start, $end);
|
||||
}
|
||||
|
||||
return view('stats.view-stats-by-questions', \compact('question', 'answers', 'answersByDays'));
|
||||
return view('bo.pages.stats.view-stats-by-questions', \compact('question', 'answers', 'answersByDays'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports stats for a specific question as csv
|
||||
* Exports stats for a specific question as csv.
|
||||
*
|
||||
* @param \App\Http\Requests\StatsByQuestionRequest $request
|
||||
* @param \App\Http\Requests\Bo\StatsByQuestionRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function exportByQuestionCsv(StatsByQuestionRequest $request)
|
||||
public function exportByQuestionCsv(StatsByQuestionRequest $request): \Illuminate\Http\Response
|
||||
{
|
||||
$question = Question::findOrFail($request->question);
|
||||
$question = Question::query()->findOrFail($request->question);
|
||||
$answers = $question->answers;
|
||||
$start = Carbon::parse($request->start);
|
||||
$end = Carbon::parse($request->end);
|
||||
|
|
@ -144,7 +142,7 @@ class StatsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Makes a collection of total users answers by day
|
||||
* Makes a collection of total users answers by day.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $answers A collection of Answer.
|
||||
* @param \Illuminate\Support\Carbon $start The wanted start period.
|
||||
|
|
@ -152,16 +150,16 @@ class StatsController extends Controller
|
|||
* @return \Illuminate\Support\Collection A collection with date as Y_m_d index
|
||||
* with array of answers and their total.
|
||||
*/
|
||||
private function answersByDays(Collection $answers, Carbon $start, Carbon $end): Collection
|
||||
private function answersByDays(Collection $answers, Carbon $start, Carbon $end): \Illuminate\Support\Collection
|
||||
{
|
||||
// * Totalize by date all answers.
|
||||
$answersByDays = CustomerAnswer::whereDate('created_at', '>=', $start)
|
||||
$answersByDays = CustomerAnswer::query()->whereDate('created_at', '>=', $start)
|
||||
->whereDate('created_at', '<=', $end)
|
||||
->whereIn('answer_id', $answers->pluck('id'))
|
||||
->get()->map(function ($custAnswer) {
|
||||
return [
|
||||
'answer_id' => $custAnswer->answer_id,
|
||||
'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
|
||||
'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
|
||||
];
|
||||
})->groupBy(['created_at', 'answer_id'])->map(function ($day) {
|
||||
return $day->map(function ($custAnswers) {
|
||||
169
app/Http/Controllers/Bo/UsersController.php
Normal file
169
app/Http/Controllers/Bo/UsersController.php
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Users\StoreUserRequest;
|
||||
use App\Http\Requests\Bo\Users\UpdateUserRequest;
|
||||
use App\Models\User;
|
||||
use App\Traits\Controllers\UpdateModelPublished;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UsersController extends Controller
|
||||
{
|
||||
use UpdateModelPublished;
|
||||
|
||||
/**
|
||||
* Create the controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->authorizeResource(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $userModels */
|
||||
$userModels = User::query();
|
||||
|
||||
/** @var string $search Search field */
|
||||
$search = $request->search;
|
||||
if ($search) {
|
||||
$this->searchQuery(
|
||||
$userModels,
|
||||
$search,
|
||||
null,
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'role',
|
||||
);
|
||||
}
|
||||
$searchFields = \implode(', ', [
|
||||
trans('validation.attributes.first_name'),
|
||||
trans('validation.attributes.last_name'),
|
||||
trans('validation.attributes.email'),
|
||||
trans('validation.attributes.role'),
|
||||
]);
|
||||
|
||||
/** Sort columns with a query */
|
||||
$this->sortQuery($userModels);
|
||||
|
||||
/** Custom pagination */
|
||||
$userModels = $this->paginate($userModels);
|
||||
|
||||
return view('bo.pages.users.index', compact('userModels', 'search', 'searchFields'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create(User $user): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.users.create', ['userModel' => $user]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Users\StoreUserRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreUserRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$user = new User();
|
||||
$user->fill($request->validated());
|
||||
|
||||
if ($user->saveOrFail()) {
|
||||
return redirect()->route('bo.users.edit', $user)
|
||||
->with('success', __('crud.messages.has_been_created', [
|
||||
'model' => Str::ucfirst(__('models.classes.user'))
|
||||
]));
|
||||
}
|
||||
return redirect()->back()
|
||||
->with('error', __('crud.messages.cannot_be_created', [
|
||||
'model' => Str::ucfirst(__('models.classes.user'))
|
||||
]));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\User $user
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(User $user): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.users.edit', ['userModel' => $user]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Users\UpdateUserRequest $request
|
||||
* @param \App\Models\User $user
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateUserRequest $request, User $user): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $user) {
|
||||
$user->fill($request->validated());
|
||||
|
||||
if ($user->saveOrFail()) {
|
||||
return redirect()->route('bo.users.edit', $user)
|
||||
->with('success', __('crud.messages.has_been_updated', [
|
||||
'model' => Str::ucfirst(__('models.classes.user'))
|
||||
]));
|
||||
}
|
||||
return redirect()->route('bo.users.edit', $user)
|
||||
->with('error', __('crud.messages.cannot_be_updated', [
|
||||
'model' => Str::ucfirst(__('models.classes.user'))
|
||||
]));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(User $user): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($user->deleteOrFail()) {
|
||||
return redirect()->route('bo.users.index')
|
||||
->with('success', __('crud.messages.has_been_deleted', [
|
||||
'model' => Str::ucfirst(__('models.classes.user'))
|
||||
]));
|
||||
}
|
||||
return redirect()->back()
|
||||
->with('error', __('crud.messages.cannot_be_deleted', [
|
||||
'model' => Str::ucfirst(__('models.classes.user'))
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate the specified resource.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function duplicate(User $user): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return $this->create($user->replicate());
|
||||
}
|
||||
}
|
||||
|
|
@ -2,21 +2,22 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\Pagination\ItemsPerPaginationEnum;
|
||||
use App\Enums\Theme\BootstrapThemeEnum;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
use DispatchesJobs;
|
||||
use ValidatesRequests;
|
||||
|
||||
/**
|
||||
|
|
@ -36,7 +37,7 @@ class Controller extends BaseController
|
|||
string $search,
|
||||
callable $searchQuery = null,
|
||||
string ...$fields
|
||||
): Builder {
|
||||
): \Illuminate\Database\Eloquent\Builder {
|
||||
if (count($fields)) {
|
||||
// Search using words.
|
||||
$words = explode(' ', $search);
|
||||
|
|
@ -65,36 +66,85 @@ class Controller extends BaseController
|
|||
* @param array $fields
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
private function searchOnFields(Builder $query, string $search, array $fields): Builder
|
||||
{
|
||||
private function searchOnFields(
|
||||
Builder $query,
|
||||
string $search,
|
||||
array $fields
|
||||
): \Illuminate\Database\Eloquent\Builder {
|
||||
$table = $query->getModel()->getTable();
|
||||
foreach ($fields as $f) {
|
||||
$f = str_replace('?', '\?', $f);
|
||||
if (is_array($f)) {
|
||||
foreach ($fields as $field) {
|
||||
$field = str_replace('?', '\?', $field);
|
||||
if (is_array($field)) {
|
||||
$query->orWhereRaw(
|
||||
sprintf("UPPER(CONCAT(%s)) LIKE UPPER(?)", collect($f)->map(function ($q) use ($table) {
|
||||
sprintf("UPPER(CONCAT(%s)) LIKE UPPER(?)", collect($field)->map(function ($q) use ($table) {
|
||||
return "`$table`.`$q`";
|
||||
})->implode(', \' \', ')),
|
||||
['%' . filter_var($search, FILTER_SANITIZE_STRING) . '%']
|
||||
);
|
||||
} else {
|
||||
$query->orWhereRaw(
|
||||
"UPPER(`$table`.`$f`) LIKE UPPER(?)",
|
||||
['%' . filter_var($search, FILTER_SANITIZE_STRING) . '%']
|
||||
['%' . htmlspecialchars($search) . '%']
|
||||
);
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
// Get models woth enum's label.
|
||||
if (is_array($this->getSearchValue($query, $search, $field))) {
|
||||
foreach ($this->getSearchValue($query, $search, $field) as $array) {
|
||||
$query->orWhereRaw(
|
||||
"UPPER(`$table`.`$field`) LIKE UPPER(?)",
|
||||
['%' . htmlspecialchars($array->value) . '%']
|
||||
);
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
// Get models with relation's name/label.
|
||||
if (Str::endsWith($field, '_id') && $query->getModel()->has(Str::remove('_id', $field))) {
|
||||
$query->orWhereHas(Str::remove('_id', $field), function ($queryRelation) use ($field, $search) {
|
||||
if (Schema::hasColumn(Str::remove('_id', $field) . 's', 'name')) {
|
||||
$queryRelation->where('name', 'like', '%' . $search . '%');
|
||||
} elseif (Schema::hasColumn(Str::remove('_id', $field) . 's', 'label')) {
|
||||
$queryRelation->where('label', 'like', '%' . $search . '%');
|
||||
}
|
||||
});
|
||||
return $query;
|
||||
}
|
||||
$query->orWhereRaw(
|
||||
"UPPER(`$table`.`$field`) LIKE UPPER(?)",
|
||||
['%' . htmlspecialchars($this->getSearchValue($query, $search, $field)) . '%']
|
||||
);
|
||||
} //end foreach
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort columns with a query
|
||||
* Get the search value (on string or Enum).
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string $search
|
||||
* @param string $field
|
||||
* @return string|array
|
||||
*/
|
||||
protected function getSearchValue(Builder $query, string $search, string $field): string|array
|
||||
{
|
||||
if (
|
||||
count($query->getModel()->getCasts()) and // Check if the model has casts.
|
||||
isset($query->getModel()->getCasts()[$field]) and // Check if there is cast about specific field.
|
||||
enum_exists($query->getModel()->getCasts()[$field]) // Check if the cast is an enum.
|
||||
) {
|
||||
$cases = collect($query->getModel()->getCasts()[$field]::toArray());
|
||||
$enum = $cases->filter(function ($item) use ($search) {
|
||||
return preg_match('/' . Str::lower($search) . '/', Str::lower($item->label));
|
||||
});
|
||||
return $enum->toArray();
|
||||
} else {
|
||||
return $search;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort columns with a query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param array $ignore
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function sortQuery(Builder $query, array $ignore = []): Builder
|
||||
protected function sortQuery(Builder $query, array $ignore = []): \Illuminate\Database\Eloquent\Builder
|
||||
{
|
||||
$rName = request()->route()->getName();
|
||||
$table = $query->getModel()->getTable();
|
||||
|
|
@ -122,7 +172,60 @@ class Controller extends BaseController
|
|||
$query = $query->orderBy('order', 'ASC');
|
||||
Session::put("$rName.sort_col", 'order');
|
||||
Session::put("$rName.sort_way", 'asc');
|
||||
} elseif (Schema::hasColumn($table, 'updated_at')) {
|
||||
$query = $query->orderBy('updated_at', 'DESC');
|
||||
Session::put("$rName.sort_col", 'updated_at');
|
||||
Session::put("$rName.sort_way", 'desc');
|
||||
} elseif (Schema::hasColumn($table, 'created_at')) {
|
||||
$query = $query->orderBy('created_at', 'DESC');
|
||||
Session::put("$rName.sort_col", 'created_at');
|
||||
Session::put("$rName.sort_way", 'desc');
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize pagination with cache or config (default).
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \App\Enums\Pagination\ItemsPerPaginationEnum|null $pagination
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
protected function paginate(
|
||||
Builder $query,
|
||||
ItemsPerPaginationEnum $pagination = null
|
||||
): \Illuminate\Contracts\Pagination\LengthAwarePaginator {
|
||||
$currentRoutePath = Str::slug(request()->route()->getName());
|
||||
$cacheKey = "pagination.{$currentRoutePath}";
|
||||
$pagination = $pagination ?? ItemsPerPaginationEnum::twelve;
|
||||
$pagination = ToolboxHelper::getValidatedEnum(
|
||||
Cache::get($cacheKey, $pagination->value()),
|
||||
'pagination',
|
||||
'\App\Enums\Pagination\ItemsPerPaginationEnum',
|
||||
);
|
||||
if (Cache::get($cacheKey) !== $pagination) {
|
||||
Cache::put($cacheKey, $pagination);
|
||||
}
|
||||
$query = $query->paginate($pagination);
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bootstrap theme or light (default).
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
protected function setTheme(Request $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$theme = ToolboxHelper::getValidatedEnum(
|
||||
$request->theme ?: Cache::get('theme', BootstrapThemeEnum::light->value()),
|
||||
'theme',
|
||||
'\App\Http\Controllers\BootstrapThemeEnum',
|
||||
);
|
||||
if (Cache::get("theme") !== $theme) {
|
||||
Cache::put("theme", $theme);
|
||||
}
|
||||
return redirect()->back()->with('success', __('crud.messages.theme_updated'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class LoginController extends Controller
|
||||
{
|
||||
/**
|
||||
* Shows the login view
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function authenticate(Request $request)
|
||||
{
|
||||
if (
|
||||
Auth::attempt(
|
||||
["email" => $request->email, "password" => $request->password],
|
||||
$request->remember !== null ? true : false
|
||||
)
|
||||
) {
|
||||
return redirect()->route('customers.index');
|
||||
} else {
|
||||
return back()->withInput($request->except("password"))
|
||||
->withErrors("Les identifiants entrés sont incorrects, veuillez réessayer.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
Auth::logout();
|
||||
return redirect()->route('login');
|
||||
}
|
||||
}
|
||||
|
|
@ -14,12 +14,13 @@ class Kernel extends HttpKernel
|
|||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
\App\Http\Middleware\TrustHosts::class,
|
||||
\App\Http\Middleware\TrustProxies::class,
|
||||
\Fruitcake\Cors\HandleCors::class,
|
||||
\Illuminate\Http\Middleware\HandleCors::class,
|
||||
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
\App\Http\Middleware\XssSanitizer::class
|
||||
\App\Http\Middleware\HtmlSanitizer::class
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -40,7 +41,7 @@ class Kernel extends HttpKernel
|
|||
],
|
||||
|
||||
'api' => [
|
||||
'throttle:api',
|
||||
\Illuminate\Routing\Middleware\ThrottleRequests::class . ':api',
|
||||
\App\Http\Middleware\JsonOnly::class,
|
||||
\App\Http\Middleware\ApiResponse::class,
|
||||
\App\Http\Middleware\ApiCheckTimeStamps::class,
|
||||
|
|
@ -58,13 +59,14 @@ class Kernel extends HttpKernel
|
|||
protected $routeMiddleware = [
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||
'check-brand' => \App\Http\Middleware\CheckBrand::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'signed' => \App\Http\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Enums\ApiError;
|
||||
use App\Exceptions\Api\V2\ApiErrorException;
|
||||
use App\Exceptions\Api\V4\ApiErrorException;
|
||||
use App\Lib\Helper;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
|
@ -21,21 +21,21 @@ class ApiCheckTimeStamps
|
|||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
* @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::wrongTimeStamp
|
||||
* @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::wrongTimeStamp
|
||||
* if timestamp has an incorrect
|
||||
* format or is timed out.
|
||||
*/
|
||||
public function handle(Request $request, \Closure $next)
|
||||
public function handle(Request $request, \Closure $next): mixed
|
||||
{
|
||||
if (Helper::isRequestForApiV2($request)) {
|
||||
if (Helper::isRequestForApiV2($request) || Helper::isRequestForApiV4($request)) {
|
||||
if (!\is_string($request->timestamp) or !Carbon::hasFormat($request->timestamp, 'Y-m-d H:i:s')) {
|
||||
throw new ApiErrorException(ApiError::wrongTimeStamp());
|
||||
throw new ApiErrorException(ApiError::wrongTimeStamp);
|
||||
}
|
||||
if (
|
||||
Carbon::parse($request->timestamp, 'utc')
|
||||
->isBefore(Carbon::now('UTC')->subSeconds(config('api.timestampTimeout', 10)))
|
||||
) {
|
||||
throw new ApiErrorException(ApiError::wrongTimeStamp());
|
||||
throw new ApiErrorException(ApiError::wrongTimeStamp);
|
||||
}
|
||||
}
|
||||
return $next($request);
|
||||
|
|
|
|||
|
|
@ -4,12 +4,11 @@ namespace App\Http\Middleware;
|
|||
|
||||
use App\Enums\ApiStatus;
|
||||
use App\Http\Resources\Api\V2\ApiResponse as V2ApiResponse;
|
||||
use App\Http\Resources\Api\V4\ApiResponse as V4ApiResponse;
|
||||
use App\Lib\Helper;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ApiResponse
|
||||
{
|
||||
|
|
@ -21,7 +20,7 @@ class ApiResponse
|
|||
* @return mixed
|
||||
* @throws \ErrorException If the received response is not a JsonResponse.
|
||||
*/
|
||||
public function handle(Request $request, \Closure $next)
|
||||
public function handle(Request $request, \Closure $next): mixed
|
||||
{
|
||||
/** @var \Illuminate\Http\JsonResponse $response */
|
||||
$response = $next($request);
|
||||
|
|
@ -35,19 +34,6 @@ class ApiResponse
|
|||
// Set no cache header.
|
||||
$response->header('Cache-Control', 'No-Store');
|
||||
|
||||
if (Helper::isRequestForApiV1($request)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
try {
|
||||
$bearerToken = Helper::getBearerTokenFromRequest($request) ?? $request->api_token ?? '';
|
||||
$service = Service::getFromBearerToken($bearerToken);
|
||||
$service->incrementStat();
|
||||
} catch (ModelNotFoundException $e) {
|
||||
Log::error(sprintf('Could not increment stats %s', $e->getMessage()));
|
||||
}
|
||||
return $response;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/** @var \App\Models\Service|null */
|
||||
if (\optional($service = app(Service::class))->id) {
|
||||
$service->incrementStat();
|
||||
|
|
@ -56,18 +42,24 @@ class ApiResponse
|
|||
/** @var object $data */
|
||||
$data = $response->getData();
|
||||
|
||||
// If reponse is already a V2ApiResponse then just return it. This happens if error handler comes to action.
|
||||
/** Check if it's V2 or V4 response. */
|
||||
if (
|
||||
gettype($data) === "object" and
|
||||
isset($data->status) and
|
||||
isset($data->data) and
|
||||
isset($data->version) and
|
||||
in_array($data->status, [ApiStatus::OK()->value, ApiStatus::KO()->value])
|
||||
in_array($data->status, [ApiStatus::OK->value(), ApiStatus::KO->value()])
|
||||
) {
|
||||
/** Return direct ApiResponse */
|
||||
return $response;
|
||||
}
|
||||
|
||||
/** @var \App\Enums\ApiStatus $status */
|
||||
$status = intval($response->getStatusCode() / 100) == 2 ? ApiStatus::OK() : ApiStatus::KO();
|
||||
return $response->setData(new V2ApiResponse((object)$response->getData(), $status));
|
||||
$status = intval($response->getStatusCode() / 100) == 2 ? ApiStatus::OK : ApiStatus::KO;
|
||||
|
||||
if (Helper::isRequestForApiV2($request)) {
|
||||
return $response->setData(new V2ApiResponse((object)$data, $status));
|
||||
}
|
||||
|
||||
return $response->setData(new V4ApiResponse((object)$data, $status));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,57 +2,38 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Lib\Helper;
|
||||
use App\Models\Service;
|
||||
use Closure;
|
||||
use Illuminate\Auth\Middleware\Authenticate as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
/**
|
||||
* Updated for ApiV2
|
||||
*/
|
||||
class Authenticate extends Middleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param mixed $request
|
||||
* @param \Closure $next
|
||||
* @param mixed ...$guards
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Auth\AuthenticationException If authentification fails.
|
||||
*/
|
||||
public function handle($request, Closure $next, ...$guards)
|
||||
{
|
||||
if (Helper::isRequestForApiV1($request)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
// Use patched v1 Auth mecanism (without bearer reimplementation).
|
||||
$bearerToken = Helper::getBearerTokenFromRequest($request) ?? $request->api_token ?? '';
|
||||
$service = Service::getFromBearerToken($bearerToken);
|
||||
$request->request->add(['brand_id' => $service->brand->id]);
|
||||
$response = $next($request);
|
||||
// @codeCoverageIgnoreEnd
|
||||
} else {
|
||||
// Use Laravel auth check mecanism.
|
||||
$response = \call_user_func_array(
|
||||
[$this, 'parent::' . __FUNCTION__],
|
||||
array_merge([$request, $next], $guards)
|
||||
);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
/**
|
||||
* Get the path the user should be redirected to when they are not authenticated.
|
||||
*
|
||||
* @param mixed $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string|null
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function redirectTo($request)
|
||||
protected function redirectTo(Request $request): ?string
|
||||
{
|
||||
if (! $request->expectsJson()) {
|
||||
$logins = [
|
||||
'backend' => route('bo.login')
|
||||
];
|
||||
if (!$request->expectsJson()) {
|
||||
// * Notify must login
|
||||
Session::flash('warning', trans('Veuillez vous connecter pour continuer'));
|
||||
|
||||
foreach ($request->route()->gatherMiddleware() as $middleware) {
|
||||
if (\is_string($middleware) and strpos($middleware, 'auth:') !== false) {
|
||||
$route = $logins[str_replace('auth:', '', $middleware)] ?? null;
|
||||
if ($route) {
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
}
|
||||
return route('login');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Lib\Helper;
|
||||
use App\Models\Service;
|
||||
use Closure;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CheckBrand
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$apiToken = Helper::getBearerTokenFromRequest($request) ?? $request->api_token ?? '';
|
||||
|
||||
if ($apiToken === null) {
|
||||
abort(401, 'Le token d\'authentification est incorrect ' . \json_encode($request->all()));
|
||||
}
|
||||
|
||||
try {
|
||||
$brand = Service::getFromBearerToken($apiToken)->brand;
|
||||
$request->request->add(['brand_id' => $brand->id]);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
abort(401, 'Le token d\'authentification est incorrect ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
61
app/Http/Middleware/HtmlSanitizer.php
Normal file
61
app/Http/Middleware/HtmlSanitizer.php
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class HtmlSanitizer
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|array ...$params
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function handle(Request $request, \Closure $next, string|array ...$params): Response
|
||||
{
|
||||
$inputs = $request->all();
|
||||
/** @var callable|null */
|
||||
$cleanInput = null;
|
||||
$cleanInput = function (
|
||||
null|string|array &$input,
|
||||
string $name,
|
||||
?string $rootName = null
|
||||
) use (
|
||||
$params,
|
||||
&$cleanInput
|
||||
): void {
|
||||
// * Nested element array
|
||||
if (is_array($input)) {
|
||||
array_walk_recursive($input, $cleanInput, $name);
|
||||
}
|
||||
if (!is_string($input)) {
|
||||
return;
|
||||
}
|
||||
if (in_array($name, $params) or in_array($rootName ?? $name, $params)) {
|
||||
// ? Is a json input ?
|
||||
if ($isJson = \json_decode($input, true) and is_array($isJson)) {
|
||||
// ! Decode each json field recursive.
|
||||
\array_walk_recursive($isJson, function (string|array &$item) {
|
||||
if (\is_string($item)) {
|
||||
$item = clean($item);
|
||||
$item = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($item);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$input = clean($input);
|
||||
$input = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($input);
|
||||
}
|
||||
} else {
|
||||
$input = strip_tags($input);
|
||||
}
|
||||
};
|
||||
\array_walk($inputs, $cleanInput);
|
||||
$request->merge($inputs);
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Lib\Helper;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class JsonOnly
|
||||
|
|
@ -14,11 +13,9 @@ class JsonOnly
|
|||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, \Closure $next)
|
||||
public function handle(Request $request, \Closure $next): mixed
|
||||
{
|
||||
// TODO remove condition v1 check when dropped.
|
||||
if (
|
||||
!Helper::isRequestForApiV1($request) and
|
||||
(!$request->isJson() or
|
||||
!$request->expectsJson() or
|
||||
is_null(json_decode($request->getContent())))
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class PreventRequestsDuringMaintenance extends Middleware
|
|||
/**
|
||||
* The URIs that should be reachable while maintenance mode is enabled.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,31 +2,39 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class RedirectIfAuthenticated
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null ...$guards
|
||||
* @return mixed
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
* @param string|null ...$guards
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @throws \RuntimeException If guard is unhandled.
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, ...$guards)
|
||||
public function handle(Request $request, \Closure $next, ...$guards): Response
|
||||
{
|
||||
// phpcs:enable phpcs:disable
|
||||
$guards = empty($guards) ? [null] : $guards;
|
||||
|
||||
foreach ($guards as $guard) {
|
||||
if (Auth::guard($guard)->check()) {
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
if (auth($guard)->check()) {
|
||||
switch ($guard) {
|
||||
case 'frontend':
|
||||
return \redirect()->route('fo.homepage');
|
||||
case 'backend':
|
||||
if (!$request->routeIs('bo.*')) {
|
||||
continue;
|
||||
}
|
||||
return \redirect()->route('bo.dashboard');
|
||||
default:
|
||||
throw new \RuntimeException("Unhandled guard `{$guard}` .");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use Closure;
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\Facades\Vite;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class SecureHeaders
|
||||
|
|
@ -33,9 +34,10 @@ class SecureHeaders
|
|||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
// phpcs:enable
|
||||
View::share('nonce', $nonce = \uniqid());
|
||||
View::share('nonce', $nonce = Vite::useCspNonce());
|
||||
// * For VueJS dev tool to execute
|
||||
$jsDev = config('app.debug') ? "'unsafe-eval' 'unsafe-inline'" : "'nonce-{$nonce}' 'strict-dynamic'";
|
||||
$scheme = config('app.env') === 'local' ? 'http' : 'https';
|
||||
$reportUri = Route::has('cspReportUri') ?
|
||||
\sprintf(' report-uri %s ;', \parse_url(route('cspReportUri'), \PHP_URL_PATH)) : '';
|
||||
$this->removeUnwantedHeaders($this->unwantedHeaderList);
|
||||
|
|
@ -46,11 +48,12 @@ class SecureHeaders
|
|||
$response->headers->set('X-Frame-Options', 'SAMEORIGIN');
|
||||
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains;');
|
||||
$cspPolicies = [
|
||||
"default-src 'none';",
|
||||
"manifest-src 'self';",
|
||||
"connect-src 'self' blob:;",
|
||||
"img-src * data: blob:;",
|
||||
"font-src 'self' data: https://fonts.gstatic.com;",
|
||||
"style-src 'self' 'unsafe-inline';",
|
||||
"style-src 'self' 'unsafe-inline' " . \implode(' ', []) . ';',
|
||||
"script-src 'self' {$jsDev} " . \implode(' ', [
|
||||
'https: blob:',
|
||||
]) . ';'
|
||||
|
|
@ -70,7 +73,7 @@ class SecureHeaders
|
|||
* @param array $headerList
|
||||
* @return void
|
||||
*/
|
||||
private function removeUnwantedHeaders(array $headerList)
|
||||
private function removeUnwantedHeaders(array $headerList): void
|
||||
{
|
||||
foreach ($headerList as $header) {
|
||||
header_remove($header);
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ class TrimStrings extends Middleware
|
|||
/**
|
||||
* The names of the attributes that should not be trimmed.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [
|
||||
'current_password',
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -4,15 +4,12 @@ namespace App\Http\Middleware;
|
|||
|
||||
use Illuminate\Http\Middleware\TrustHosts as Middleware;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class TrustHosts extends Middleware
|
||||
{
|
||||
/**
|
||||
* Get the host patterns that should be trusted.
|
||||
*
|
||||
* @return array
|
||||
* @return array<int, string|null>
|
||||
*/
|
||||
public function hosts()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Fideloper\Proxy\TrustProxies as Middleware;
|
||||
use Illuminate\Http\Middleware\TrustProxies as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TrustProxies extends Middleware
|
||||
|
|
@ -10,7 +10,7 @@ class TrustProxies extends Middleware
|
|||
/**
|
||||
* The trusted proxies for this application.
|
||||
*
|
||||
* @var array|string|null
|
||||
* @var array<int, string>|string|null
|
||||
*/
|
||||
protected $proxies;
|
||||
|
||||
|
|
@ -19,9 +19,10 @@ class TrustProxies extends Middleware
|
|||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $headers = Request::HEADER_X_FORWARDED_FOR |
|
||||
Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PORT |
|
||||
Request::HEADER_X_FORWARDED_PROTO |
|
||||
Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||
protected $headers =
|
||||
Request::HEADER_X_FORWARDED_FOR |
|
||||
Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PORT |
|
||||
Request::HEADER_X_FORWARDED_PROTO |
|
||||
Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||
}
|
||||
|
|
|
|||
15
app/Http/Middleware/ValidateSignature.php
Normal file
15
app/Http/Middleware/ValidateSignature.php
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
|
||||
|
||||
class ValidateSignature extends Middleware
|
||||
{
|
||||
/**
|
||||
* The names of the query string parameters that should be ignored.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [];
|
||||
}
|
||||
|
|
@ -9,7 +9,9 @@ class VerifyCsrfToken extends Middleware
|
|||
/**
|
||||
* The URIs that should be excluded from CSRF verification.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [];
|
||||
protected $except = [
|
||||
'/csp-report'
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class XssSanitizer
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param mixed $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$input = $request->all();
|
||||
array_walk_recursive($input, function (&$input) {
|
||||
$input = strip_tags($input);
|
||||
});
|
||||
$request->merge($input);
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace App\Http\Requests\Api\V2;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AuthenticateRequest extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
|
|
@ -9,7 +12,7 @@ class AuthenticateRequest extends BaseApiRequest
|
|||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -22,7 +25,7 @@ class AuthenticateRequest extends BaseApiRequest
|
|||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email:rfc',
|
||||
'email' => 'required|email:rfc',
|
||||
'password' => 'required'
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,24 +11,28 @@ use ArondeParon\RequestSanitizer\Sanitizers\TrimDuplicateSpaces;
|
|||
use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
abstract class BaseApiRequest extends FormRequest
|
||||
{
|
||||
use SanitizesInputs;
|
||||
|
||||
/**
|
||||
* Using these sanitizers before proceeding the request
|
||||
* Using these sanitizers before proceeding the request.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sanitizers = [
|
||||
'firstname' => [Trim::class, TrimDuplicateSpaces::class, Capitalize::class],
|
||||
'lastname' => [Trim::class, TrimDuplicateSpaces::class, Capitalize::class],
|
||||
'address' => [Trim::class, TrimDuplicateSpaces::class],
|
||||
'address2' => [Trim::class, TrimDuplicateSpaces::class],
|
||||
'city' => [Trim::class, TrimDuplicateSpaces::class],
|
||||
'password' => Trim::class,
|
||||
'phone' => [Trim::class, RemoveSpaces::class],
|
||||
'email' => [Lowercase::class, Trim::class, RemoveSpaces::class],
|
||||
'postcode' => [RemoveNonNumeric::class, Trim::class]
|
||||
'lastname' => [Trim::class, TrimDuplicateSpaces::class, Capitalize::class],
|
||||
'address' => [Trim::class, TrimDuplicateSpaces::class],
|
||||
'address2' => [Trim::class, TrimDuplicateSpaces::class],
|
||||
'city' => [Trim::class, TrimDuplicateSpaces::class],
|
||||
'password' => Trim::class,
|
||||
'phone' => [Trim::class, RemoveSpaces::class],
|
||||
'email' => [Lowercase::class, Trim::class, RemoveSpaces::class],
|
||||
'postcode' => [RemoveNonNumeric::class, Trim::class]
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -36,9 +40,9 @@ abstract class BaseApiRequest extends FormRequest
|
|||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->check();
|
||||
return auth('api')->check();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ use App\Http\Requests\Api\V2\BaseApiRequest;
|
|||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class GetBrandStatsRequest extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
|
|
@ -34,7 +37,7 @@ class GetBrandStatsRequest extends BaseApiRequest
|
|||
}
|
||||
return [
|
||||
'start' => 'required|date|date_format:Y-m-d',
|
||||
'end' => 'required|date|date_format:Y-m-d|after_or_equal:start',
|
||||
'end' => 'required|date|date_format:Y-m-d|after_or_equal:start',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ use Exception;
|
|||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class GetQuestionStatsRequest extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
|
|
@ -35,7 +38,7 @@ class GetQuestionStatsRequest extends BaseApiRequest
|
|||
}
|
||||
return [
|
||||
'start' => 'required|date|date_format:Y-m-d',
|
||||
'end' => 'required|date|date_format:Y-m-d|after_or_equal:start',
|
||||
'end' => 'required|date|date_format:Y-m-d|after_or_equal:start',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,31 +7,35 @@ use App\Http\Sanitizers\RemoveSpaces;
|
|||
use ArondeParon\RequestSanitizer\Sanitizers\RemoveNonNumeric;
|
||||
use ArondeParon\RequestSanitizer\Sanitizers\Trim;
|
||||
use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
|
||||
use Kwaadpepper\Enum\Rules\EnumIsValidRule;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class SendArchadiaDefaultMailRequest extends BaseApiRequest
|
||||
{
|
||||
use SanitizesInputs;
|
||||
|
||||
/**
|
||||
* Using these sanitizers before proceeding the request
|
||||
* Using these sanitizers before proceeding the request.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sanitizers = [
|
||||
'label_type_support' => Trim::class,
|
||||
'operation' => Trim::class,
|
||||
'order_date' => Trim::class,
|
||||
'order_num' => RemoveNonNumeric::class,
|
||||
'label_type_support' => Trim::class,
|
||||
'operation' => Trim::class,
|
||||
'order_date' => Trim::class,
|
||||
'order_num' => RemoveNonNumeric::class,
|
||||
'package_unit_weight' => RemoveNonNumeric::class,
|
||||
'support_code' => Trim::class,
|
||||
'deliver.firstname' => Trim::class,
|
||||
'deliver.lastname' => Trim::class,
|
||||
'deliver.email' => Trim::class,
|
||||
'deliver.address' => Trim::class,
|
||||
'deliver.address2' => Trim::class,
|
||||
'deliver.city' => Trim::class,
|
||||
'deliver.postcode' => Trim::class,
|
||||
'deliver.phone' => [Trim::class, RemoveSpaces::class]
|
||||
'support_code' => Trim::class,
|
||||
'deliver.firstname' => Trim::class,
|
||||
'deliver.lastname' => Trim::class,
|
||||
'deliver.email' => Trim::class,
|
||||
'deliver.address' => Trim::class,
|
||||
'deliver.address2' => Trim::class,
|
||||
'deliver.city' => Trim::class,
|
||||
'deliver.postcode' => Trim::class,
|
||||
'deliver.phone' => [Trim::class, RemoveSpaces::class]
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -42,67 +46,67 @@ class SendArchadiaDefaultMailRequest extends BaseApiRequest
|
|||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'label_type_support' => 'required|string',
|
||||
'operation' => 'required|int',
|
||||
'order_date' => 'required|date',
|
||||
'order_num' => 'required|numeric',
|
||||
'label_type_support' => 'required|string',
|
||||
'operation' => 'required|int',
|
||||
'order_date' => 'required|date',
|
||||
'order_num' => 'required|numeric',
|
||||
'package_unit_weight' => 'required|integer',
|
||||
'state_order' => [
|
||||
'state_order' => [
|
||||
'required',
|
||||
new EnumIsValidRule(ArcadiaOrderType::class)
|
||||
new Enum(ArcadiaOrderType::class)
|
||||
],
|
||||
'support_code' => 'required|int',
|
||||
'deliver' => 'required|array',
|
||||
'deliver.firstname' => 'required|string|min:1|max:255',
|
||||
'deliver.lastname' => 'required|string|min:1|max:255',
|
||||
'deliver.email' => 'required|email:rfc,dns,spoof,filter|max:255',
|
||||
'deliver.address' => 'required|string|min:2|max:255',
|
||||
'deliver.address2' => 'sometimes|string|min:2|max:255',
|
||||
'deliver.city' => 'required|string|min:2|max:255',
|
||||
'deliver.postcode' => 'required|string|postal_code:FR|max:255',
|
||||
'deliver.phone' => 'present|string|nullable|phone:FR|max:255',
|
||||
'support_code' => 'required|int',
|
||||
'deliver' => 'required|array',
|
||||
'deliver.firstname' => 'required|string|min:1|max:255',
|
||||
'deliver.lastname' => 'required|string|min:1|max:255',
|
||||
'deliver.email' => 'required|email:rfc,dns,spoof,filter|max:255',
|
||||
'deliver.address' => 'required|string|min:2|max:255',
|
||||
'deliver.address2' => 'sometimes|string|min:2|max:255',
|
||||
'deliver.city' => 'required|string|min:2|max:255',
|
||||
'deliver.postcode' => 'required|string|postal_code:FR|max:255',
|
||||
'deliver.phone' => 'present|string|nullable|phone:FR|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributes
|
||||
* Attributes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes()
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'label_type_support' => trans('label type support'),
|
||||
'operation' => trans('code opération'),
|
||||
'order_date' => trans('date de la commande'),
|
||||
'order_num' => trans('numero de commande'),
|
||||
'label_type_support' => trans('label type support'),
|
||||
'operation' => trans('code opération'),
|
||||
'order_date' => trans('date de la commande'),
|
||||
'order_num' => trans('numero de commande'),
|
||||
'package_unit_weight' => trans('poids unitaire du paquet'),
|
||||
'state_order' => trans('type de commande arcadia'),
|
||||
'support_code' => trans('code de support'),
|
||||
'deliver' => trans('coordonées de livraison'),
|
||||
'deliver.civility' => trans('civilitée dans coordonées de livraison'),
|
||||
'deliver.firstname' => trans('prénom dans coordonées de livraison'),
|
||||
'deliver.lastname' => trans('nom dans coordonées de livraison'),
|
||||
'deliver.address' => trans('adresse dans coordonées de livraison'),
|
||||
'deliver.postcode' => trans('code postal dans coordonées de livraison'),
|
||||
'deliver.phone' => trans('téléphone dans coordonées de livraison'),
|
||||
'deliver.city' => trans('ville dans coordonées de livraison'),
|
||||
'deliver.email' => trans('e-mail dans coordonées de livraison'),
|
||||
'state_order' => trans('type de commande arcadia'),
|
||||
'support_code' => trans('code de support'),
|
||||
'deliver' => trans('coordonées de livraison'),
|
||||
'deliver.civility' => trans('civilitée dans coordonées de livraison'),
|
||||
'deliver.firstname' => trans('prénom dans coordonées de livraison'),
|
||||
'deliver.lastname' => trans('nom dans coordonées de livraison'),
|
||||
'deliver.address' => trans('adresse dans coordonées de livraison'),
|
||||
'deliver.postcode' => trans('code postal dans coordonées de livraison'),
|
||||
'deliver.phone' => trans('téléphone dans coordonées de livraison'),
|
||||
'deliver.city' => trans('ville dans coordonées de livraison'),
|
||||
'deliver.email' => trans('e-mail dans coordonées de livraison'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Messages
|
||||
* Messages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function messages()
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'deliver.phone.phone' => trans('Le champ :attribute est invalide, il accepte les numéros des pays suivants: France.'),
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'deliver.postcode.postal_code' => trans('Le champ :attribute accepte les codes postaux des pays suivants :countries comme par exemple :examples.'),
|
||||
'deliver.phone.phone' => trans('Le champ :attribute est invalide, il accepte les numéros
|
||||
des pays suivants: France.'),
|
||||
'deliver.postcode.postal_code' => trans('Le champ :attribute accepte les codes postaux des pays
|
||||
suivants :countries comme par exemple :examples.'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,30 +6,34 @@ use App\Http\Sanitizers\RemoveSpaces;
|
|||
use ArondeParon\RequestSanitizer\Sanitizers\Trim;
|
||||
use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class SendArchadiaGameMailRequest extends BaseApiRequest
|
||||
{
|
||||
use SanitizesInputs;
|
||||
|
||||
/**
|
||||
* Using these sanitizers before proceeding the request
|
||||
* Using these sanitizers before proceeding the request.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sanitizers = [
|
||||
'code_on_pack' => Trim::class,
|
||||
'code_unique' => Trim::class,
|
||||
'code_on_pack' => Trim::class,
|
||||
'code_unique' => Trim::class,
|
||||
'label_type_support' => Trim::class,
|
||||
'operation' => Trim::class,
|
||||
'order_date' => Trim::class,
|
||||
'support_code' => Trim::class,
|
||||
'type' => Trim::class,
|
||||
'deliver.firstname' => Trim::class,
|
||||
'deliver.lastname' => Trim::class,
|
||||
'deliver.email' => Trim::class,
|
||||
'deliver.address' => Trim::class,
|
||||
'deliver.address2' => Trim::class,
|
||||
'deliver.city' => Trim::class,
|
||||
'deliver.postcode' => Trim::class,
|
||||
'deliver.phone' => [Trim::class, RemoveSpaces::class]
|
||||
'operation' => Trim::class,
|
||||
'order_date' => Trim::class,
|
||||
'support_code' => Trim::class,
|
||||
'type' => Trim::class,
|
||||
'deliver.firstname' => Trim::class,
|
||||
'deliver.lastname' => Trim::class,
|
||||
'deliver.email' => Trim::class,
|
||||
'deliver.address' => Trim::class,
|
||||
'deliver.address2' => Trim::class,
|
||||
'deliver.city' => Trim::class,
|
||||
'deliver.postcode' => Trim::class,
|
||||
'deliver.phone' => [Trim::class, RemoveSpaces::class]
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -40,62 +44,62 @@ class SendArchadiaGameMailRequest extends BaseApiRequest
|
|||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'code_on_pack' => 'sometimes|string|max:50',
|
||||
'code_unique' => 'required|string',
|
||||
'code_on_pack' => 'sometimes|string|max:50',
|
||||
'code_unique' => 'required|string',
|
||||
'label_type_support' => 'required|string',
|
||||
'operation' => 'required|int',
|
||||
'order_date' => 'required|date',
|
||||
'support_code' => 'required|int',
|
||||
'deliver' => 'required|array',
|
||||
'deliver.firstname' => 'required|string|min:1|max:255',
|
||||
'deliver.lastname' => 'required|string|min:1|max:255',
|
||||
'deliver.email' => 'required|email:rfc,dns,spoof,filter|max:255',
|
||||
'deliver.address' => 'required|string|min:2|max:255',
|
||||
'deliver.address2' => 'sometimes|string|min:2|max:255',
|
||||
'deliver.city' => 'required|string|min:2|max:255',
|
||||
'deliver.postcode' => 'required|string|postal_code:FR|max:255',
|
||||
'deliver.phone' => 'present|string|nullable|phone:FR|max:255',
|
||||
'operation' => 'required|int',
|
||||
'order_date' => 'required|date',
|
||||
'support_code' => 'required|int',
|
||||
'deliver' => 'required|array',
|
||||
'deliver.firstname' => 'required|string|min:1|max:255',
|
||||
'deliver.lastname' => 'required|string|min:1|max:255',
|
||||
'deliver.email' => 'required|email:rfc,dns,spoof,filter|max:255',
|
||||
'deliver.address' => 'required|string|min:2|max:255',
|
||||
'deliver.address2' => 'sometimes|string|min:2|max:255',
|
||||
'deliver.city' => 'required|string|min:2|max:255',
|
||||
'deliver.postcode' => 'required|string|postal_code:FR|max:255',
|
||||
'deliver.phone' => 'present|string|nullable|phone:FR|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributes
|
||||
* Attributes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes()
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'code_on_pack' => trans('code ean emballage'),
|
||||
'code_unique' => trans('code unique'),
|
||||
'code_on_pack' => trans('code ean emballage'),
|
||||
'code_unique' => trans('code unique'),
|
||||
'label_type_support' => trans('label type support'),
|
||||
'operation' => trans('code opération'),
|
||||
'order_date' => trans('date de la commande'),
|
||||
'support_code' => trans('code de support'),
|
||||
'deliver' => trans('coordonées de livraison'),
|
||||
'deliver.civility' => trans('civilitée dans coordonées de livraison'),
|
||||
'deliver.firstname' => trans('prénom dans coordonées de livraison'),
|
||||
'deliver.lastname' => trans('nom dans coordonées de livraison'),
|
||||
'deliver.address' => trans('adresse dans coordonées de livraison'),
|
||||
'deliver.postcode' => trans('code postal dans coordonées de livraison'),
|
||||
'deliver.phone' => trans('téléphone dans coordonées de livraison'),
|
||||
'deliver.city' => trans('ville dans coordonées de livraison'),
|
||||
'deliver.email' => trans('e-mail dans coordonées de livraison'),
|
||||
'operation' => trans('code opération'),
|
||||
'order_date' => trans('date de la commande'),
|
||||
'support_code' => trans('code de support'),
|
||||
'deliver' => trans('coordonées de livraison'),
|
||||
'deliver.civility' => trans('civilitée dans coordonées de livraison'),
|
||||
'deliver.firstname' => trans('prénom dans coordonées de livraison'),
|
||||
'deliver.lastname' => trans('nom dans coordonées de livraison'),
|
||||
'deliver.address' => trans('adresse dans coordonées de livraison'),
|
||||
'deliver.postcode' => trans('code postal dans coordonées de livraison'),
|
||||
'deliver.phone' => trans('téléphone dans coordonées de livraison'),
|
||||
'deliver.city' => trans('ville dans coordonées de livraison'),
|
||||
'deliver.email' => trans('e-mail dans coordonées de livraison'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Messages
|
||||
* Messages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function messages()
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'deliver.phone.phone' => trans('Le champ :attribute est invalide, il accepte les numéros des pays suivants: France.'),
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'deliver.postcode.postal_code' => trans('Le champ :attribute accepte les codes postaux des pays suivants :countries comme par exemple :examples.'),
|
||||
'deliver.phone.phone' => trans('Le champ :attribute est invalide, il accepte
|
||||
les numéros des pays suivants: France.'),
|
||||
'deliver.postcode.postal_code' => trans('Le champ :attribute accepte les codes postaux
|
||||
des pays suivants :countries comme par exemple :examples.'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace App\Http\Requests\Api\V2;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class SingleOptinRemoveWithHashcodeRequest extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace App\Http\Requests\Api\V2;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class SingleOptinRequest extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
|
|
@ -12,7 +15,7 @@ class SingleOptinRequest extends BaseApiRequest
|
|||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email:rfc,dns,spoof,filter',
|
||||
'email' => 'required|email:rfc,dns,spoof,filter',
|
||||
'opt_in' => 'required|boolean'
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ namespace App\Http\Requests\Api\V2;
|
|||
|
||||
use App\Models\Answer;
|
||||
use App\Models\Question;
|
||||
use App\Models\Service;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class StoreCustomerAnswers extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
|
|
@ -15,13 +19,13 @@ class StoreCustomerAnswers extends BaseApiRequest
|
|||
public function rules(): array
|
||||
{
|
||||
// * Resolve Service.
|
||||
$service = app()->make(\App\Models\Service::class);
|
||||
$service = app()->make(Service::class);
|
||||
$brandId = $service->brand->id;
|
||||
$question = Question::findOrFail($this->question);
|
||||
$question = Question::query()->findOrFail($this->question);
|
||||
$questionTableName = (new Question())->getTable();
|
||||
$answerTableName = (new Answer())->getTable();
|
||||
return [
|
||||
'question' => [
|
||||
'question' => [
|
||||
'required',
|
||||
"exists:$questionTableName,id",
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
|
|
@ -31,13 +35,13 @@ class StoreCustomerAnswers extends BaseApiRequest
|
|||
}
|
||||
}
|
||||
],
|
||||
'answers' => 'required|array',
|
||||
'answers' => 'required|array',
|
||||
'answers.*' => [
|
||||
'int',
|
||||
'distinct',
|
||||
"exists:$answerTableName,id",
|
||||
function ($attribute, $value, $fail) use ($question) {
|
||||
if (Answer::findOrFail($value)->question->id !== $question->id) {
|
||||
if (Answer::query()->findOrFail($value)->question->id !== $question->id) {
|
||||
$fail("$attribute does not belong to question $question->id");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,12 @@
|
|||
namespace App\Http\Requests\Api\V2;
|
||||
|
||||
use App\Enums\Country;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
use Kwaadpepper\Enum\Rules\EnumIsValidRule;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class StoreCustomerRequest extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
|
|
@ -15,6 +18,21 @@ class StoreCustomerRequest extends BaseApiRequest
|
|||
*/
|
||||
protected $currentCountry = null;
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
try {
|
||||
$this->currentCountry = Country::make(\intval($this->country));
|
||||
} catch (\TypeError | \BadMethodCallException $e) {
|
||||
$this->currentCountry = null;
|
||||
}
|
||||
parent::prepareForValidation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
|
|
@ -22,11 +40,13 @@ class StoreCustomerRequest extends BaseApiRequest
|
|||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$countryList = ($this->currentCountry && $this->currentCountry->get('iso')) ?
|
||||
$this->currentCountry->get('iso') : implode(',', Country::getValidIsoAplha2Codes());
|
||||
return [
|
||||
'firstname' => 'required|string|min:1|max:255',
|
||||
'lastname' => 'required|string|min:1|max:255',
|
||||
'email' => 'required|email:rfc,dns,spoof,filter|max:255',
|
||||
'password' => [
|
||||
'firstname' => 'required|string|min:1|max:255',
|
||||
'lastname' => 'required|string|min:1|max:255',
|
||||
'email' => 'required|email:rfc,dns,spoof,filter|max:255',
|
||||
'password' => [
|
||||
'required',
|
||||
'max:255',
|
||||
Password::min(8)
|
||||
|
|
@ -37,59 +57,42 @@ class StoreCustomerRequest extends BaseApiRequest
|
|||
->uncompromised()
|
||||
],
|
||||
'birth_date' => 'required|date_format:Y-m-d|max:255',
|
||||
'address' => 'sometimes|required_with:address2|string|max:255',
|
||||
'address2' => 'sometimes|string|max:255',
|
||||
'phone' => ['sometimes', 'string', 'phone:' . ($this->currentCountry ?
|
||||
$this->currentCountry->iso : implode(',', Country::getValidIsoAplha2Codes()))],
|
||||
'country' => [
|
||||
'address' => 'sometimes|required_with:address2|string|max:255',
|
||||
'address2' => 'sometimes|string|max:255',
|
||||
'phone' => ['sometimes', 'string', "phone:{$countryList}"],
|
||||
'country' => [
|
||||
'sometimes',
|
||||
'numeric',
|
||||
new EnumIsValidRule(Country::class),
|
||||
new Enum(Country::class),
|
||||
sprintf(
|
||||
'in:%s',
|
||||
implode(',', Country::getValidCountries())
|
||||
implode(',', Country::getValidCountriesValues())
|
||||
)
|
||||
],
|
||||
'city' => 'sometimes|string|min:2|max:255',
|
||||
'postcode' => ['sometimes', 'string', 'postal_code:' . ($this->currentCountry ?
|
||||
$this->currentCountry->iso : implode(',', Country::getValidIsoAplha2Codes()))],
|
||||
'opt_in' => 'required|boolean',
|
||||
'city' => 'sometimes|string|min:2|max:255',
|
||||
'postcode' => ['sometimes', 'string', "postal_code:{$countryList}"],
|
||||
'opt_in' => 'required|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
try {
|
||||
if (is_array($this->country)) {
|
||||
$this->currentCountry = Country::make(\intval($this->country));
|
||||
}
|
||||
} catch (\TypeError | \BadMethodCallException $e) {
|
||||
$this->currentCountry = null;
|
||||
}
|
||||
parent::prepareForValidation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Messages
|
||||
* Messages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function messages()
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'phone.phone' => trans('Le champ :attribute est invalide, il accepte les numéros des pays suivants :countries.', [
|
||||
'countries' => implode(',', Country::getValidCountriesLabel())
|
||||
]),
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'country.in' => trans('Le champ :attribute est invalide, il accepte les pays suivants :countries.', [
|
||||
'countries' => implode(',', Country::getValidCountriesLabel())
|
||||
])
|
||||
'phone.phone' => trans(
|
||||
'Le champ :attribute est invalide, il accepte les numéros des pays
|
||||
suivants :countries.',
|
||||
['countries' => implode(',', Country::getValidCountriesLabel())]
|
||||
),
|
||||
'country.in' => trans(
|
||||
'Le champ :attribute est invalide, il accepte les pays suivants
|
||||
:countries.',
|
||||
['countries' => implode(',', Country::getValidCountriesLabel())]
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,12 @@
|
|||
namespace App\Http\Requests\Api\V2;
|
||||
|
||||
use App\Enums\Country;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
use Kwaadpepper\Enum\Rules\EnumIsValidRule;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class UpdateCustomerRequest extends StoreCustomerRequest
|
||||
{
|
||||
/**
|
||||
|
|
@ -27,10 +30,10 @@ class UpdateCustomerRequest extends StoreCustomerRequest
|
|||
})->implode(',');
|
||||
};
|
||||
return [
|
||||
'firstname' => [$atLeast('firstname'), 'string', 'min:1', 'max:255'],
|
||||
'lastname' => [$atLeast('lastname'), 'string', 'min:1', 'max:255'],
|
||||
'email' => [$atLeast('email'), 'email:rfc,dns,spoof,filter', 'max:255'],
|
||||
'password' => [
|
||||
'firstname' => [$atLeast('firstname'), 'string', 'min:1', 'max:255'],
|
||||
'lastname' => [$atLeast('lastname'), 'string', 'min:1', 'max:255'],
|
||||
'email' => [$atLeast('email'), 'email:rfc,dns,spoof,filter', 'max:255'],
|
||||
'password' => [
|
||||
$atLeast('password'), 'max:255', Password::min(8)
|
||||
->mixedCase()
|
||||
->letters()
|
||||
|
|
@ -39,23 +42,27 @@ class UpdateCustomerRequest extends StoreCustomerRequest
|
|||
->uncompromised()
|
||||
],
|
||||
'birth_date' => [$atLeast('birth_date'), 'date_format:Y-m-d', 'max:255'],
|
||||
'address' => [$atLeast('address'), 'required_with:address2', 'string', 'max:255'],
|
||||
'address2' => ['sometimes', 'string', 'max:255'],
|
||||
'phone' => [$atLeast('phone'), 'string', 'phone:' . ($this->currentCountry ?
|
||||
$this->currentCountry->iso : implode(',', Country::getValidIsoAplha2Codes())), 'max:255'],
|
||||
'country' => [
|
||||
'address' => [$atLeast('address'), 'required_with:address2', 'string', 'max:255'],
|
||||
'address2' => ['sometimes', 'string', 'max:255'],
|
||||
'phone' => [$atLeast('phone'), 'string', 'phone:' . (
|
||||
($this->currentCountry && $this->currentCountry->get('iso')) ?
|
||||
$this->currentCountry->get('iso') : implode(',', Country::getValidIsoAplha2Codes())
|
||||
), 'max:255'],
|
||||
'country' => [
|
||||
$atLeast('country'),
|
||||
'numeric',
|
||||
new EnumIsValidRule(Country::class),
|
||||
new Enum(Country::class),
|
||||
sprintf(
|
||||
'in:%s',
|
||||
implode(',', Country::getValidCountries())
|
||||
implode(',', Country::getValidCountriesValues())
|
||||
)
|
||||
],
|
||||
'city' => [$atLeast('city'), 'string', 'min:2', 'max:255'],
|
||||
'postcode' => [$atLeast('postcode'), 'string', 'postal_code:' . ($this->currentCountry ?
|
||||
$this->currentCountry->iso : implode(',', Country::getValidIsoAplha2Codes())), 'max:255'],
|
||||
'opt_in' => [$atLeast('opt_in'), 'boolean'],
|
||||
'city' => [$atLeast('city'), 'string', 'min:2', 'max:255'],
|
||||
'postcode' => [$atLeast('postcode'), 'string', 'postal_code:' . (
|
||||
($this->currentCountry && $this->currentCountry->get('iso')) ?
|
||||
$this->currentCountry->get('iso') : implode(',', Country::getValidIsoAplha2Codes())
|
||||
), 'max:255'],
|
||||
'opt_in' => [$atLeast('opt_in'), 'boolean'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
29
app/Http/Requests/Api/V4/AuthenticateRequest.php
Normal file
29
app/Http/Requests/Api/V4/AuthenticateRequest.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Api\V4;
|
||||
|
||||
class AuthenticateRequest extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email:rfc',
|
||||
'password' => 'required'
|
||||
];
|
||||
}
|
||||
}
|
||||
51
app/Http/Requests/Api/V4/BaseApiRequest.php
Normal file
51
app/Http/Requests/Api/V4/BaseApiRequest.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Api\V4;
|
||||
|
||||
use App\Http\Sanitizers\RemoveSpaces;
|
||||
use ArondeParon\RequestSanitizer\Sanitizers\Capitalize;
|
||||
use ArondeParon\RequestSanitizer\Sanitizers\Lowercase;
|
||||
use ArondeParon\RequestSanitizer\Sanitizers\RemoveNonNumeric;
|
||||
use ArondeParon\RequestSanitizer\Sanitizers\Trim;
|
||||
use ArondeParon\RequestSanitizer\Sanitizers\TrimDuplicateSpaces;
|
||||
use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
abstract class BaseApiRequest extends FormRequest
|
||||
{
|
||||
use SanitizesInputs;
|
||||
|
||||
/**
|
||||
* Using these sanitizers before proceeding the request.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sanitizers = [
|
||||
'firstname' => [Trim::class, TrimDuplicateSpaces::class, Capitalize::class],
|
||||
'lastname' => [Trim::class, TrimDuplicateSpaces::class, Capitalize::class],
|
||||
'address' => [Trim::class, TrimDuplicateSpaces::class],
|
||||
'address2' => [Trim::class, TrimDuplicateSpaces::class],
|
||||
'city' => [Trim::class, TrimDuplicateSpaces::class],
|
||||
'password' => Trim::class,
|
||||
'phone' => [Trim::class, RemoveSpaces::class],
|
||||
'email' => [Lowercase::class, Trim::class, RemoveSpaces::class],
|
||||
'postcode' => [RemoveNonNumeric::class, Trim::class]
|
||||
];
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth('api')->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function rules(): array;
|
||||
}
|
||||
40
app/Http/Requests/Api/V4/GetBrandStatsRequest.php
Normal file
40
app/Http/Requests/Api/V4/GetBrandStatsRequest.php
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Api\V4;
|
||||
|
||||
use App\Http\Requests\Api\V4\BaseApiRequest;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class GetBrandStatsRequest extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
* @throws \Illuminate\Validation\ValidationException If given dates are unparsable of
|
||||
* period is bigger than 3 months.
|
||||
* @throws \Exception If carbon date processing failed.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
try {
|
||||
if (Carbon::parse($this->end)->floatDiffInMonths(Carbon::parse($this->start)) > 3) {
|
||||
throw ValidationException::withMessages([
|
||||
'Vous devez sélectionner une période de maximum 3 mois'
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
if (\get_class($e) !== ValidationException::class) {
|
||||
throw ValidationException::withMessages([
|
||||
'Les dates séléectionnées ne sembles pas être valides'
|
||||
]);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
return [
|
||||
'start' => 'required|date|date_format:Y-m-d',
|
||||
'end' => 'required|date|date_format:Y-m-d|after_or_equal:start',
|
||||
];
|
||||
}
|
||||
}
|
||||
40
app/Http/Requests/Api/V4/GetQuestionStatsRequest.php
Normal file
40
app/Http/Requests/Api/V4/GetQuestionStatsRequest.php
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Api\V4;
|
||||
|
||||
use App\Http\Requests\Api\V4\BaseApiRequest;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class GetQuestionStatsRequest extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
* @throws \Illuminate\Validation\ValidationException If given dates are unparsable of
|
||||
* period is bigger than 3 months.
|
||||
* @throws \Exception If carbon date processing failed.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
try {
|
||||
if (Carbon::parse($this->end)->floatDiffInMonths(Carbon::parse($this->start)) > 3) {
|
||||
throw ValidationException::withMessages([
|
||||
'Vous devez sélectionner une période de maximum 3 mois'
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
if (\get_class($e) !== ValidationException::class) {
|
||||
throw ValidationException::withMessages([
|
||||
'Les dates sélectionnées ne sembles pas être valides'
|
||||
]);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
return [
|
||||
'start' => 'required|date|date_format:Y-m-d',
|
||||
'end' => 'required|date|date_format:Y-m-d|after_or_equal:start',
|
||||
];
|
||||
}
|
||||
}
|
||||
109
app/Http/Requests/Api/V4/SendArchadiaDefaultMailRequest.php
Normal file
109
app/Http/Requests/Api/V4/SendArchadiaDefaultMailRequest.php
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Api\V4;
|
||||
|
||||
use App\Enums\ArcadiaOrderType;
|
||||
use App\Http\Sanitizers\RemoveSpaces;
|
||||
use ArondeParon\RequestSanitizer\Sanitizers\RemoveNonNumeric;
|
||||
use ArondeParon\RequestSanitizer\Sanitizers\Trim;
|
||||
use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
|
||||
class SendArchadiaDefaultMailRequest extends BaseApiRequest
|
||||
{
|
||||
use SanitizesInputs;
|
||||
|
||||
/**
|
||||
* Using these sanitizers before proceeding the request.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sanitizers = [
|
||||
'label_type_support' => Trim::class,
|
||||
'operation' => Trim::class,
|
||||
'order_date' => Trim::class,
|
||||
'order_num' => RemoveNonNumeric::class,
|
||||
'package_unit_weight' => RemoveNonNumeric::class,
|
||||
'support_code' => Trim::class,
|
||||
'deliver.firstname' => Trim::class,
|
||||
'deliver.lastname' => Trim::class,
|
||||
'deliver.email' => Trim::class,
|
||||
'deliver.address' => Trim::class,
|
||||
'deliver.address2' => Trim::class,
|
||||
'deliver.city' => Trim::class,
|
||||
'deliver.postcode' => Trim::class,
|
||||
'deliver.phone' => [Trim::class, RemoveSpaces::class]
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'label_type_support' => 'required|string',
|
||||
'operation' => 'required|int',
|
||||
'order_date' => 'required|date',
|
||||
'order_num' => 'required|numeric',
|
||||
'package_unit_weight' => 'required|integer',
|
||||
'state_order' => [
|
||||
'required',
|
||||
new Enum(ArcadiaOrderType::class)
|
||||
],
|
||||
'support_code' => 'required|int',
|
||||
'deliver' => 'required|array',
|
||||
'deliver.firstname' => 'required|string|min:1|max:255',
|
||||
'deliver.lastname' => 'required|string|min:1|max:255',
|
||||
'deliver.email' => 'required|email:rfc,dns,spoof,filter|max:255',
|
||||
'deliver.address' => 'required|string|min:2|max:255',
|
||||
'deliver.address2' => 'sometimes|string|min:2|max:255',
|
||||
'deliver.city' => 'required|string|min:2|max:255',
|
||||
'deliver.postcode' => 'required|string|postal_code:FR|max:255',
|
||||
'deliver.phone' => 'present|string|nullable|phone:FR|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'label_type_support' => trans('label type support'),
|
||||
'operation' => trans('code opération'),
|
||||
'order_date' => trans('date de la commande'),
|
||||
'order_num' => trans('numero de commande'),
|
||||
'package_unit_weight' => trans('poids unitaire du paquet'),
|
||||
'state_order' => trans('type de commande arcadia'),
|
||||
'support_code' => trans('code de support'),
|
||||
'deliver' => trans('coordonées de livraison'),
|
||||
'deliver.civility' => trans('civilitée dans coordonées de livraison'),
|
||||
'deliver.firstname' => trans('prénom dans coordonées de livraison'),
|
||||
'deliver.lastname' => trans('nom dans coordonées de livraison'),
|
||||
'deliver.address' => trans('adresse dans coordonées de livraison'),
|
||||
'deliver.postcode' => trans('code postal dans coordonées de livraison'),
|
||||
'deliver.phone' => trans('téléphone dans coordonées de livraison'),
|
||||
'deliver.city' => trans('ville dans coordonées de livraison'),
|
||||
'deliver.email' => trans('e-mail dans coordonées de livraison'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Messages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'deliver.phone.phone' => trans('Le champ :attribute est invalide, il accepte les numéros
|
||||
des pays suivants: France.'),
|
||||
'deliver.postcode.postal_code' => trans('Le champ :attribute accepte les codes postaux des pays
|
||||
suivants :countries comme par exemple :examples.'),
|
||||
];
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue