Merge branch 'trunk'
This commit is contained in:
commit
1974969ccc
403 changed files with 24883 additions and 12117 deletions
5
.browserslistrc
Normal file
5
.browserslistrc
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Browsers that we support
|
||||
|
||||
last 3 version
|
||||
> 0.3%
|
||||
not dead # no browsers without security updates
|
||||
2
.dockerignore
Normal file
2
.dockerignore
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
.git
|
||||
*.md
|
||||
|
|
@ -13,3 +13,9 @@ trim_trailing_whitespace = false
|
|||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[*.vue]
|
||||
indent_size = 2
|
||||
|
||||
[docker-compose.yml]
|
||||
indent_size = 4
|
||||
|
|
|
|||
41
.eslintrc.json
Normal file
41
.eslintrc.json
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:vue/vue3-strongly-recommended",
|
||||
"@vue/eslint-config-typescript"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.vue"],
|
||||
"rules": {
|
||||
"no-undef": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.vue"],
|
||||
"rules": {
|
||||
"indent": "off"
|
||||
}
|
||||
}
|
||||
],
|
||||
"parser": "vue-eslint-parser",
|
||||
"parserOptions": {
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["vue", "@typescript-eslint"],
|
||||
"ignorePatterns": ["webpack.mix.js", "**/vendor/*.js", "**/vendor/**/*.js"],
|
||||
"rules": {
|
||||
"indent": ["error", 4, { "SwitchCase": 1 }],
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"quotes": ["error", "double"],
|
||||
"semi": ["error", "always"],
|
||||
"vue/script-indent": ["error", 2, { "baseIndent": 0, "switchCase": 1 }],
|
||||
"vue/one-component-per-file": "off"
|
||||
}
|
||||
}
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1,6 +1,11 @@
|
|||
/node_modules
|
||||
/public/hot
|
||||
/public/storage
|
||||
/public/build
|
||||
/public/medias
|
||||
/public/uploads
|
||||
/public/cache
|
||||
/public/sitemap.xml
|
||||
/storage/*.key
|
||||
/vendor
|
||||
.vscode/
|
||||
|
|
@ -18,3 +23,4 @@ MIG/errors_sql.txt
|
|||
public/js
|
||||
public/css
|
||||
public/assets
|
||||
auth.json
|
||||
|
|
|
|||
19
.gitlab-ci.yml
Normal file
19
.gitlab-ci.yml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
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'
|
||||
|
||||
stages:
|
||||
- lint
|
||||
- security
|
||||
- build
|
||||
- test
|
||||
4
.gitmodules
vendored
4
.gitmodules
vendored
|
|
@ -1,3 +1,3 @@
|
|||
[submodule "clients/V2"]
|
||||
path = clients/V2
|
||||
url = https://voight001.lesidc.com/crm-client
|
||||
path = clients/V2
|
||||
url = git@lab.s-web.fr:ldc-web/projets/crm-client.git
|
||||
|
|
|
|||
43
.stylelintrc.json
Normal file
43
.stylelintrc.json
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"extends": [
|
||||
"stylelint-config-prettier",
|
||||
"stylelint-config-standard-scss",
|
||||
"stylelint-config-sass-guidelines",
|
||||
"stylelint-config-idiomatic-order"
|
||||
],
|
||||
"plugins": ["stylelint-scss"],
|
||||
"files": ["**/*.css", "**/*.scss"],
|
||||
"ignoreFiles": [
|
||||
"**/vendor/*.css",
|
||||
"**/vendor/**/*.css",
|
||||
"**/vendor/*.scss",
|
||||
"**/vendor/**/*.scss",
|
||||
"**/vendor/*.sass",
|
||||
"**/vendor/**/*.sass",
|
||||
"**/vendor/*.less",
|
||||
"**/vendor/**/*.less"
|
||||
],
|
||||
"customSyntax": "postcss-scss",
|
||||
"rules": {
|
||||
"indentation": 4,
|
||||
"string-quotes": "double",
|
||||
"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,
|
||||
"scss/double-slash-comment-empty-line-before": [
|
||||
"always",
|
||||
{
|
||||
"ignore": [
|
||||
"between-comments",
|
||||
"stylelint-commands",
|
||||
"inside-block"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
26
.vscode/settings.json
vendored
Normal file
26
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
{
|
||||
"phpcs.executablePath": "vendor/bin/phpcs",
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.activeBackground": "#8dc952",
|
||||
"activityBar.activeBorder": "#3d7fc2",
|
||||
"activityBar.background": "#8dc952",
|
||||
"activityBar.foreground": "#15202b",
|
||||
"activityBar.inactiveForeground": "#15202b99",
|
||||
"activityBarBadge.background": "#3d7fc2",
|
||||
"activityBarBadge.foreground": "#e7e7e7",
|
||||
"sash.hoverBorder": "#8dc952",
|
||||
"statusBar.background": "#73b137",
|
||||
"statusBar.foreground": "#15202b",
|
||||
"statusBarItem.hoverBackground": "#5a8a2b",
|
||||
"statusBarItem.remoteBackground": "#73b137",
|
||||
"statusBarItem.remoteForeground": "#15202b",
|
||||
"titleBar.activeBackground": "#73b137",
|
||||
"titleBar.activeForeground": "#15202b",
|
||||
"titleBar.inactiveBackground": "#73b13799",
|
||||
"titleBar.inactiveForeground": "#15202b99",
|
||||
"commandCenter.border": "#15202b99"
|
||||
},
|
||||
"peacock.remoteColor": "#73b137",
|
||||
"intelephense.environment.phpVersion": "7.4"
|
||||
}
|
||||
7
Dockerfile
Normal file
7
Dockerfile
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-7.3: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
|
||||
102
app/Console/Commands/CreateAdmin.php
Normal file
102
app/Console/Commands/CreateAdmin.php
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class UserCreate extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'user:create';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$firstname = $this->ask('What is the firstname?');
|
||||
$lastname = $this->ask('What is the lastname?');
|
||||
$email = $this->ask('What is the email?');
|
||||
$pwd = $this->secret('What is the password?');
|
||||
|
||||
$user = new User();
|
||||
$user->firstname = $firstname;
|
||||
$user->lastname = $lastname;
|
||||
$user->email = $email;
|
||||
$user->password = Hash::make($pwd);
|
||||
$user->save();
|
||||
|
||||
$this->info('User created.');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,6 @@ use Illuminate\Http\Request;
|
|||
use Illuminate\Validation\ValidationException;
|
||||
use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
|
|
@ -56,7 +55,7 @@ class Handler extends ExceptionHandler
|
|||
* @param \Throwable $e
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function render($request, Throwable $e)
|
||||
public function render($request, \Throwable $e)
|
||||
{
|
||||
if (Helper::isRequestForApiV2($request) and $request->isJson()) {
|
||||
return $this->handleApiV2Exception($request, $e);
|
||||
|
|
@ -142,7 +141,7 @@ class Handler extends ExceptionHandler
|
|||
// phpcs:ignore Squiz.PHP.DiscouragedFunctions.Found
|
||||
print_r((string)$e);
|
||||
}
|
||||
return $this->getReponse($request, 500, $e->getCode(), $e->getMessage());
|
||||
return $this->getReponse($request, 500, \intval($e->getCode()), $e->getMessage());
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,72 +3,160 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Answers\StoreAnswerRequest;
|
||||
use App\Http\Requests\Answers\UpdateAnswerRequest;
|
||||
use App\Models\Answer;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
|
||||
use Kwaadpepper\CrudPolicies\Traits\CrudController;
|
||||
use App\Models\Question;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AnswerController extends Controller
|
||||
{
|
||||
use CrudController {
|
||||
index as crudIndex;
|
||||
}
|
||||
|
||||
/** @var Log */
|
||||
public static $modelClass = Answer::class;
|
||||
|
||||
/**
|
||||
* The Bo app layout
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $layout = 'layouts.app';
|
||||
|
||||
/**
|
||||
* Event index crud-policies
|
||||
*
|
||||
* @param Builder $query
|
||||
* @return Builder
|
||||
*/
|
||||
public function indexQuery(Builder $query): Builder
|
||||
{
|
||||
$parent = request()->question;
|
||||
if ($parent) {
|
||||
$query->whereHas('question', function ($q) use ($parent) {
|
||||
return $q->whereId($parent->id);
|
||||
});
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload crud-policies index
|
||||
*
|
||||
* @param CrudIndexRequest $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(CrudIndexRequest $request)
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\View\View */
|
||||
$view = $this->crudIndex($request);
|
||||
if ($request->ajax()) {
|
||||
return $view;
|
||||
/** @var \App\Models\Question $questionModel */
|
||||
$questionModel = $request->question;
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $answers */
|
||||
$answers = Answer::query()->where('question_id', $questionModel->id);
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$answers,
|
||||
$request->search,
|
||||
null,
|
||||
'answer',
|
||||
);
|
||||
}
|
||||
return view('answer.index', $view->getData());
|
||||
|
||||
$this->sortQuery($answers);
|
||||
$searchFields = trans('Réponse');
|
||||
|
||||
$answerModels = $answers->paginate(12);
|
||||
|
||||
return view('answers.index', compact('answerModels', 'questionModel', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Before store model middleware
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param Answer $answer
|
||||
* @return void
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \App\Models\Answer $answer
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function storeModel(Answer &$answer)
|
||||
public function create(Request $request, Answer $answer)
|
||||
{
|
||||
// * Save relation on create
|
||||
$answer->question()->associate(request()->question);
|
||||
/** @var \App\Models\Question $questionModel */
|
||||
$questionModel = $request->question;
|
||||
|
||||
return view('answers.create', [
|
||||
'answerModel' => $answer,
|
||||
'questionModel' => $questionModel
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Answers\StoreAnswerRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreAnswerRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$answer = new Answer();
|
||||
$answer->fill($request->validated());
|
||||
if ($answer->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('answers.edit', $answer)
|
||||
->with('success', trans(
|
||||
':model a été créé.',
|
||||
['model' => Str::singular(trans('models.classes.answers'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été créé.',
|
||||
['model' => Str::singular(trans('models.classes.answers'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Question $question
|
||||
* @param \App\Models\Answer $answers
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Question $question, Answer $answers)
|
||||
{
|
||||
return view('answers.edit', [
|
||||
'answerModel' => $answers,
|
||||
'questionModel' => $question
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public function update(UpdateAnswerRequest $request, Question $question, Answer $answer)
|
||||
{
|
||||
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])
|
||||
->with('success', trans(
|
||||
':model a été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.answers'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.answers'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Question $question
|
||||
* @param \App\Models\Answer $answer
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(Question $question, Answer $answer): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($answer->deleteOrFail()) {
|
||||
return redirect()->route('questions.answers.index', $question)
|
||||
->with('success', trans(
|
||||
':model a été supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.answers'))]
|
||||
));
|
||||
}
|
||||
return redirect()->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas pu être supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.answers'))]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ use Illuminate\Support\Facades\Validator;
|
|||
class ArcadiaController extends Controller
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return StatusResource
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function outgoingMail(Request $request)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ class CustomerController extends Controller
|
|||
{
|
||||
/**
|
||||
* Store a newly created resource in storage
|
||||
* @param Request $request
|
||||
* @return CustomerResource|StatusResource
|
||||
* @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)
|
||||
|
|
@ -60,41 +60,45 @@ class CustomerController extends Controller
|
|||
$customer = new Customer();
|
||||
$customer->email = $email;
|
||||
$customer->save();
|
||||
$singleOptin = SingleOptin::where([['email', $email], ['brand_id', $brandId]])->first();
|
||||
$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::where([['customer_id', $customer->id], ['brand_id', $brandId]])->first();
|
||||
$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;
|
||||
filter_var($request->birth_date, FILTER_SANITIZE_STRING) : null;
|
||||
$customerInfos->address = !empty($request->address) ?
|
||||
filter_var($request->address, FILTER_SANITIZE_STRING) : null;
|
||||
filter_var($request->address, FILTER_SANITIZE_STRING) : null;
|
||||
$customerInfos->address2 = !empty($request->address2) ?
|
||||
filter_var($request->address2, FILTER_SANITIZE_STRING) : null;
|
||||
filter_var($request->address2, FILTER_SANITIZE_STRING) : null;
|
||||
$customerInfos->phone = !empty($request->phone) ?
|
||||
filter_var($request->phone, FILTER_SANITIZE_STRING) : null;
|
||||
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;
|
||||
filter_var($request->city, FILTER_SANITIZE_STRING) : null;
|
||||
$customerInfos->postcode = !empty($request->postcode) ?
|
||||
filter_var($request->postcode, FILTER_SANITIZE_STRING) : null;
|
||||
filter_var($request->postcode, FILTER_SANITIZE_STRING) : null;
|
||||
$customerInfos->opt_in = $optIn;
|
||||
$customerInfos->hashcode = $hashcode;
|
||||
$customerInfos->brand_id = $brandId;
|
||||
|
|
@ -125,10 +129,10 @@ class CustomerController extends Controller
|
|||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Illuminate\Http\Request $request
|
||||
* @param mixed $type
|
||||
* @param mixed $value
|
||||
* @return CustomerResource | StatusResource
|
||||
* @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)
|
||||
{
|
||||
|
|
@ -161,8 +165,8 @@ class CustomerController extends Controller
|
|||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return CustomerResource|StatusResource
|
||||
* @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)
|
||||
|
|
@ -276,8 +280,8 @@ class CustomerController extends Controller
|
|||
|
||||
/**
|
||||
* Authenticate the user
|
||||
* @param Request $request
|
||||
* @return CustomerResource|StatusResource
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \App\Http\Resources\CustomerResource|\App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function authenticate(Request $request)
|
||||
{
|
||||
|
|
@ -327,29 +331,29 @@ class CustomerController extends Controller
|
|||
]
|
||||
]
|
||||
);
|
||||
}//end if
|
||||
} //end if
|
||||
|
||||
$login->last_connection = now();
|
||||
$customer->logins()->save($login);
|
||||
return new CustomerResource($customer, $brandId);
|
||||
}//end if
|
||||
} //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
|
||||
} //end if
|
||||
} else {
|
||||
// "Ce compte n'existe pas dans la CRM"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 119, 'message' => 'User not found.']);
|
||||
}//end if
|
||||
} //end if
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the password of the user for the brand
|
||||
* @param Request $request
|
||||
* @param mixed $id
|
||||
* @return StatusResource
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $id
|
||||
* @return \App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function changePassword(Request $request, $id)
|
||||
{
|
||||
|
|
@ -391,9 +395,9 @@ class CustomerController extends Controller
|
|||
|
||||
/**
|
||||
* Activate the account of the user
|
||||
* @param Request $request
|
||||
* @param mixed $id
|
||||
* @return StatusResource
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $id
|
||||
* @return \App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function activateAccount(Request $request, $id)
|
||||
{
|
||||
|
|
@ -424,8 +428,8 @@ class CustomerController extends Controller
|
|||
|
||||
/**
|
||||
* Delete the user account for the brand
|
||||
* @param Request $request
|
||||
* @param mixed $id
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $id
|
||||
*/
|
||||
// phpcs:disable Squiz.PHP.NonExecutableCode.Unreachable, Squiz.Commenting.FunctionComment.Missing
|
||||
public function delete(Request $request, $id)
|
||||
|
|
@ -456,9 +460,9 @@ class CustomerController extends Controller
|
|||
|
||||
/**
|
||||
* Change the status of the opt-in for the customer on this brand
|
||||
* @param Request $request
|
||||
* @param mixed $id
|
||||
* @return StatusResource
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $id
|
||||
* @return \App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function toggleOptin(Request $request, $id)
|
||||
{
|
||||
|
|
@ -488,14 +492,14 @@ class CustomerController extends Controller
|
|||
} else {
|
||||
// "Cet utilisateur n'existe pas dans la CRM"
|
||||
return new StatusResource(['status' => 'KO', 'code' => 114, 'message' => 'User not found.']);
|
||||
}//end if
|
||||
} //end if
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove opt-in for the customer on this brand
|
||||
* @param Request $request
|
||||
* @param mixed $hashcode
|
||||
* @return StatusResource
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $hashcode
|
||||
* @return \App\Http\Resources\StatusResource
|
||||
*/
|
||||
public function removeOptin(Request $request, $hashcode)
|
||||
{
|
||||
|
|
@ -527,7 +531,7 @@ class CustomerController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return void
|
||||
*/
|
||||
// phpcs:ignore Squiz.PHP.NonExecutableCode.Unreachable, Squiz.Commenting.FunctionComment.Missing
|
||||
|
|
@ -549,7 +553,7 @@ class CustomerController extends Controller
|
|||
|
||||
// Check si le customer ou l'optin simple existe avant de l'ajouter en optin simple.
|
||||
if (
|
||||
!SingleOptin::where([['email', $email], ['brand_id', $brandId]])->exists() &&
|
||||
!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()
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ class AnswerController extends Controller
|
|||
/**
|
||||
* Store the customer answers
|
||||
*
|
||||
* @param StoreCustomerAnswers $request
|
||||
* @param Service $service
|
||||
* @param Customer $customer
|
||||
* @return JsonResponse
|
||||
* @param \App\Http\Requests\Api\V2\StoreCustomerAnswers $request
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function storeCustomerAnswers(
|
||||
StoreCustomerAnswers $request,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class ApiController extends Controller
|
|||
/**
|
||||
* Just returns HTTP 200 response
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function ping(): JsonResponse
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ class ArcadiaController extends Controller
|
|||
/**
|
||||
* Send arcadia default mail (reclamations)
|
||||
*
|
||||
* @param SendArchadiaDefaultMailRequest $request
|
||||
* @return JsonResponse
|
||||
* @param \App\Http\Requests\Api\V2\SendArchadiaDefaultMailRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function outgoingMailDefault(SendArchadiaDefaultMailRequest $request): JsonResponse
|
||||
{
|
||||
|
|
@ -42,8 +42,8 @@ class ArcadiaController extends Controller
|
|||
/**
|
||||
* Send arcadia game mail (games)
|
||||
*
|
||||
* @param SendArchadiaGameMailRequest $request
|
||||
* @return JsonResponse
|
||||
* @param \App\Http\Requests\Api\V2\SendArchadiaGameMailRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function outgoingMailGame(SendArchadiaGameMailRequest $request): JsonResponse
|
||||
{
|
||||
|
|
@ -54,9 +54,9 @@ class ArcadiaController extends Controller
|
|||
* Form xml message and save it in the apropriate storage location
|
||||
* to be picked up by the arcadia job
|
||||
*
|
||||
* @param BaseApiRequest $request
|
||||
* @param ArcadiaMailType $type
|
||||
* @return JsonResponse
|
||||
* @param \App\Http\Requests\Api\V2\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
|
||||
|
|
@ -115,10 +115,10 @@ class ArcadiaController extends Controller
|
|||
/**
|
||||
* render Arcadia xml for order
|
||||
*
|
||||
* @param BaseApiRequest $request
|
||||
* @param ArcadiaMailType $type
|
||||
* @param ArcadiaOrderType $orderType
|
||||
* @param array $customerInfo
|
||||
* @param \App\Http\Requests\Api\V2\BaseApiRequest $request
|
||||
* @param \App\Enums\ArcadiaMailType $type
|
||||
* @param \App\Enums\ArcadiaOrderType $orderType
|
||||
* @param array $customerInfo
|
||||
* @return string
|
||||
*/
|
||||
private function makeXml(
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ 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;
|
||||
|
|
@ -24,11 +25,12 @@ class CustomerController extends Controller
|
|||
/**
|
||||
* Creates a new customer for the specified service.
|
||||
*
|
||||
* @param StoreCustomerRequest $request
|
||||
* @param Service $service
|
||||
* @return JsonResource
|
||||
* @throws ApiErrorException With ApiError::customerExists if the customer with this email already exists.
|
||||
* @throws CrmException If saving the customer to DB failed.
|
||||
* @param \App\Http\Requests\Api\V2\StoreCustomerRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Resources\Json\JsonResource
|
||||
* @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::customerExists if
|
||||
* the customer with this email already exists.
|
||||
* @throws \App\Exceptions\Api\V2\CrmException If saving the customer to DB failed.
|
||||
*/
|
||||
public function store(StoreCustomerRequest $request, Service $service): JsonResource
|
||||
{
|
||||
|
|
@ -46,8 +48,10 @@ class CustomerController extends Controller
|
|||
|
||||
// * Delete Single optin if exists.
|
||||
/** @var \App\Models\SingleOptin|null $singleOptin */
|
||||
$singleOptin = SingleOptin::where('email', $data->email)
|
||||
->where('brand_id', $service->brand->id)->first();
|
||||
$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;
|
||||
}
|
||||
|
|
@ -82,9 +86,9 @@ class CustomerController extends Controller
|
|||
/**
|
||||
* Renders the specific customer infos
|
||||
*
|
||||
* @param Service $service
|
||||
* @param Customer $customer
|
||||
* @return JsonResource
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\Resources\Json\JsonResource
|
||||
*/
|
||||
public function show(Service $service, Customer $customer): JsonResource
|
||||
{
|
||||
|
|
@ -97,11 +101,11 @@ class CustomerController extends Controller
|
|||
/**
|
||||
* Updates information for a specific customer
|
||||
*
|
||||
* @param UpdateCustomerRequest $request
|
||||
* @param Service $service
|
||||
* @param Customer $customer
|
||||
* @return JsonResource
|
||||
* @throws CrmException If saving the customer to DB failed.
|
||||
* @param \App\Http\Requests\Api\V2\UpdateCustomerRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\Resources\Json\JsonResource
|
||||
* @throws \App\Exceptions\Api\V2\CrmException If saving the customer to DB failed.
|
||||
*/
|
||||
public function update(UpdateCustomerRequest $request, Service $service, Customer $customer): JsonResource
|
||||
{
|
||||
|
|
@ -139,10 +143,10 @@ class CustomerController extends Controller
|
|||
/**
|
||||
* Deletes customer information for a specific service
|
||||
*
|
||||
* @param Service $service
|
||||
* @param Customer $customer
|
||||
* @return JsonResponse
|
||||
* @throws CrmException If removing the customer off the DB failed.
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \App\Exceptions\Api\V2\CrmException If removing the customer off the DB failed.
|
||||
*/
|
||||
public function destroy(Service $service, Customer $customer): JsonResponse
|
||||
{
|
||||
|
|
@ -190,11 +194,14 @@ class CustomerController extends Controller
|
|||
|
||||
/**
|
||||
* Authenticate the user
|
||||
* @param AuthenticateRequest $request
|
||||
* @param Service $service
|
||||
* @return JsonResource
|
||||
* @throws ApiErrorException With ApiError::authFailed() in case of wrong credentials.
|
||||
* @throws ApiErrorException With ApiError::customerNotActivated() if customer account is not activated.
|
||||
*
|
||||
* @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
|
||||
* of wrong credentials.
|
||||
* @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::customerNotActivated() if
|
||||
* customer account is not activated.
|
||||
*/
|
||||
public function authenticate(AuthenticateRequest $request, Service $service): JsonResource
|
||||
{
|
||||
|
|
@ -218,16 +225,18 @@ class CustomerController extends Controller
|
|||
return new CustomerResource($service->brand, $customer);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
throw new ApiErrorException(ApiError::authFailed());
|
||||
}//end try
|
||||
} //end try
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the account of the user
|
||||
* @param Customer $customer
|
||||
* @param Service $service
|
||||
*
|
||||
* @param \App\Models\Customer $customer
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws ApiErrorException With ApiError::customerAlreadyActive if customer account is already active.
|
||||
* @throws CrmException If saving the customer to DB failed.
|
||||
* @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::customerAlreadyActive
|
||||
* 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,9 +6,12 @@ use App\Enums\ApiError;
|
|||
use App\Exceptions\Api\V2\ApiErrorException;
|
||||
use App\Exceptions\Api\V2\CrmException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Api\V2\BaseApiRequest;
|
||||
use App\Http\Requests\Api\V2\SingleOptinRequest;
|
||||
use App\Http\Requests\Api\V2\SingleOptinRemoveWithHashcodeRequest;
|
||||
use App\Models\CustomerInfo;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use App\Models\SingleOptin;
|
||||
|
||||
class OptinController extends Controller
|
||||
|
|
@ -16,33 +19,26 @@ class OptinController extends Controller
|
|||
/**
|
||||
* Creates a new Single optin or destroys it if exists
|
||||
*
|
||||
* @param SingleOptinRequest $request
|
||||
* @param Service $service
|
||||
* @return JsonResponse
|
||||
* @throws ApiErrorException With ApiError::singleOptinCustomerExists if this email already has a full account.
|
||||
* @throws CrmException If the single optin could not be added or removed.
|
||||
* @param \App\Http\Requests\Api\V2\SingleOptinRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::singleOptinCustomerExists
|
||||
* if this email already has a full account.
|
||||
* @throws \App\Exceptions\Api\V2\CrmException If the single optin could not be added or removed.
|
||||
*/
|
||||
public function optin(SingleOptinRequest $request, Service $service)
|
||||
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::where('email', $request->email)
|
||||
->whereHas('brand', function ($q) use ($service) {
|
||||
$q->whereId($service->brand->id);
|
||||
})->firstOrNew();
|
||||
$singleOptin = SingleOptin::query()->where('email', $request->email)
|
||||
->whereHas('brand', function ($q) use ($service) {
|
||||
$q->where('id', $service->brand->id);
|
||||
})->firstOrNew();
|
||||
|
||||
if ($request->opt_in) {
|
||||
$singleOptin->fill($request->validated());
|
||||
$singleOptin->brand()->associate($service->brand);
|
||||
$success = $singleOptin->save();
|
||||
} else {
|
||||
$success = $singleOptin->delete() !== false;
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
if (!$this->changeOptin($service, $request, \boolval($request->opt_in), $singleOptin)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new CrmException('Api failed to update single optin.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
|
@ -50,4 +46,48 @@ class OptinController extends Controller
|
|||
|
||||
return response()->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
/** @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\V2\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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ class QuestionController extends Controller
|
|||
/**
|
||||
* Returns all service questions.
|
||||
*
|
||||
* @param Service $service
|
||||
* @return JsonResource
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Resources\Json\ResourceCollection
|
||||
*/
|
||||
public function index(Service $service): ResourceCollection
|
||||
{
|
||||
|
|
@ -27,9 +27,9 @@ class QuestionController extends Controller
|
|||
/**
|
||||
* Returns all service questions with user answers for all of them.
|
||||
*
|
||||
* @param Service $service
|
||||
* @param Customer $customer
|
||||
* @return JsonResource
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\Resources\Json\ResourceCollection
|
||||
*/
|
||||
public function indexWithResponse(Service $service, Customer $customer): ResourceCollection
|
||||
{
|
||||
|
|
@ -43,9 +43,9 @@ class QuestionController extends Controller
|
|||
/**
|
||||
* Returns all service questions that was not answered by a user.
|
||||
*
|
||||
* @param Service $service
|
||||
* @param Customer $customer
|
||||
* @return JsonResource
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return \Illuminate\Http\Resources\Json\JsonResource
|
||||
*/
|
||||
public function unAnsweredBy(Service $service, Customer $customer): JsonResource
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ class StatsController extends Controller
|
|||
/**
|
||||
* Get specific brand statistics
|
||||
*
|
||||
* @param GetBrandStatsRequest $request
|
||||
* @param Service $service
|
||||
* @return ResourceCollection
|
||||
* @param \App\Http\Requests\Api\V2\GetBrandStatsRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Resources\Json\ResourceCollection
|
||||
*/
|
||||
public function brandStats(GetBrandStatsRequest $request, Service $service): ResourceCollection
|
||||
{
|
||||
|
|
@ -35,9 +35,9 @@ class StatsController extends Controller
|
|||
/**
|
||||
* Get statistics for a specific question
|
||||
*
|
||||
* @param GetQuestionStatsRequest $request
|
||||
* @param Question $question
|
||||
* @return QuestionStatsResource
|
||||
* @param \App\Http\Requests\Api\V2\GetQuestionStatsRequest $request
|
||||
* @param \App\Models\Question $question
|
||||
* @return \App\Http\Resources\Api\V2\QuestionStatsResource
|
||||
*/
|
||||
public function questionStats(GetQuestionStatsRequest $request, Question $question): QuestionStatsResource
|
||||
{
|
||||
|
|
@ -57,10 +57,10 @@ class StatsController extends Controller
|
|||
/**
|
||||
* Total réponses par dates
|
||||
*
|
||||
* @param Collection $answers
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @return Collection
|
||||
* @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
|
||||
{
|
||||
|
|
@ -71,7 +71,7 @@ class StatsController extends Controller
|
|||
->get()->map(function ($custAnswer) {
|
||||
return [
|
||||
'answer_id' => $custAnswer->answer_id,
|
||||
'created_at' => $custAnswer->created_at->format('Y-m-d'),
|
||||
'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
|
||||
];
|
||||
})->groupBy(['created_at', 'answer_id'])->map(function ($day) {
|
||||
return $day->map(function ($custAnswers) {
|
||||
|
|
@ -80,7 +80,7 @@ class StatsController extends Controller
|
|||
});
|
||||
|
||||
do {
|
||||
$currentDate = $start->format('Y-m-d');
|
||||
$currentDate = $start->isoFormat('YYYY-MM-DD');
|
||||
/** @var \Illuminate\Support\Collection $answersByDays */
|
||||
if (!$answersByDays->has($currentDate)) {
|
||||
$answersByDays->put(
|
||||
|
|
|
|||
|
|
@ -3,42 +3,144 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Brands\StoreBrandRequest;
|
||||
use App\Http\Requests\Brands\UpdateBrandRequest;
|
||||
use App\Models\Brand;
|
||||
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
|
||||
use Kwaadpepper\CrudPolicies\Traits\CrudController;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class BrandController extends Controller
|
||||
{
|
||||
use CrudController {
|
||||
index as crudIndex;
|
||||
}
|
||||
|
||||
/** @var Brand */
|
||||
public static $modelClass = Brand::class;
|
||||
|
||||
/**
|
||||
* The Bo app layout
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $layout = 'layouts.app';
|
||||
|
||||
/**
|
||||
* Overload crud-policies index
|
||||
*
|
||||
* @param CrudIndexRequest $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(CrudIndexRequest $request)
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\View\View */
|
||||
$view = $this->crudIndex($request);
|
||||
if ($request->ajax()) {
|
||||
return $view;
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = Brand::query();
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$query,
|
||||
$request->search,
|
||||
null,
|
||||
'name',
|
||||
);
|
||||
}
|
||||
return view('brand.index', $view->getData());
|
||||
|
||||
$this->sortQuery($query);
|
||||
$searchFields = trans('Nom');
|
||||
|
||||
$query->withCount(['customerInfos', 'customerInfos as customer_infos_optin_count' => function (Builder $q) {
|
||||
$q->where('opt_in', true);
|
||||
}]);
|
||||
|
||||
$brandModels = $query->paginate(12);
|
||||
|
||||
return view('brands.index', compact('brandModels', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Models\Brand $brands
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create(Brand $brands)
|
||||
{
|
||||
return view('brands.create', [
|
||||
'brandModel' => $brands
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Brands\StoreBrandRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreBrandRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$brand = new Brand();
|
||||
$brand->fill($request->validated());
|
||||
if ($brand->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('brands.edit', $brand)
|
||||
->with('success', trans(
|
||||
':model a été créé.',
|
||||
['model' => Str::singular(trans('models.classes.brands'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été créé.',
|
||||
['model' => Str::singular(trans('models.classes.brands'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Brand $brands
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Brand $brands)
|
||||
{
|
||||
return view('brands.edit', [
|
||||
'brandModel' => $brands
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a spacific resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Brands\UpdateBrandRequest $request
|
||||
* @param \App\Models\Brand $brand
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateBrandRequest $request, Brand $brand)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $brand) {
|
||||
$brand->fill($request->validated());
|
||||
if ($brand->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('brands.edit', $brand)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.brands'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.brands'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function jsonPaginate()
|
||||
{
|
||||
return DB::transaction(function () {
|
||||
/** @var \App\Models\Tag */
|
||||
$brandModels = Brand::paginate(12);
|
||||
return \response()->json($brandModels ?? 500);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
|
|
@ -15,4 +18,111 @@ class Controller extends BaseController
|
|||
use AuthorizesRequests;
|
||||
use DispatchesJobs;
|
||||
use ValidatesRequests;
|
||||
|
||||
/**
|
||||
* Build Search query on specified fields
|
||||
* splitting search into words or using whole sentence
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query The eloquent query builder.
|
||||
* @param string $search The query string.
|
||||
* @param callable $searchQuery The query string.
|
||||
* @param string ...$fields Either a simple array or a string
|
||||
* in case of a string the two fields
|
||||
* would be concatenate to make the search.
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function searchQuery(
|
||||
Builder $query,
|
||||
string $search,
|
||||
callable $searchQuery = null,
|
||||
string ...$fields
|
||||
): Builder {
|
||||
if (count($fields)) {
|
||||
// Search using words.
|
||||
$words = explode(' ', $search);
|
||||
$query->where(function ($query) use ($searchQuery, $words, $search, $fields) {
|
||||
foreach ($words as $word) {
|
||||
if (!strlen($word)) {
|
||||
continue;
|
||||
}
|
||||
$this->searchOnFields($query, $word, $fields);
|
||||
} //end foreach
|
||||
// Search whole using whole sentence.
|
||||
$this->searchOnFields($query, $search, $fields);
|
||||
if ($searchQuery) {
|
||||
$searchQuery($query);
|
||||
}
|
||||
});
|
||||
} //end if
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build query search on all fields
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string $search
|
||||
* @param array $fields
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
private function searchOnFields(Builder $query, string $search, array $fields): Builder
|
||||
{
|
||||
$table = $query->getModel()->getTable();
|
||||
foreach ($fields as $f) {
|
||||
$f = str_replace('?', '\?', $f);
|
||||
if (is_array($f)) {
|
||||
$query->orWhereRaw(
|
||||
sprintf("UPPER(CONCAT(%s)) LIKE UPPER(?)", collect($f)->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) . '%']
|
||||
);
|
||||
}
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
$rName = request()->route()->getName();
|
||||
$table = $query->getModel()->getTable();
|
||||
if (request()->sort_col) {
|
||||
Session::put("$rName.sort_col", request()->sort_col);
|
||||
Session::put("$rName.sorted", true);
|
||||
}
|
||||
if (request()->sort_way) {
|
||||
Session::put("$rName.sort_way", request()->sort_way);
|
||||
Session::put("$rName.sorted", true);
|
||||
}
|
||||
if (request()->rst) {
|
||||
Session::remove("$rName.sorted");
|
||||
Session::remove("$rName.sort_col");
|
||||
Session::remove("$rName.sort_way");
|
||||
}
|
||||
if (request()->sort_col and request()->sort_way and Schema::hasColumn($table, request()->sort_col)) {
|
||||
if (
|
||||
!isset($ignore) or
|
||||
(isset($ignore) and !in_array(request()->sort_col, $ignore))
|
||||
) {
|
||||
$query = $query->orderBy(\sprintf("$table.%s", request()->sort_col), request()->sort_way);
|
||||
}
|
||||
} elseif (Schema::hasColumn($table, 'order')) {
|
||||
$query = $query->orderBy('order', 'ASC');
|
||||
Session::put("$rName.sort_col", 'order');
|
||||
Session::put("$rName.sort_way", 'asc');
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ use App\Models\Customer;
|
|||
use App\Models\CustomerInfo;
|
||||
use App\Models\CustomerLogin;
|
||||
use App\Models\SingleOptin;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\Str;
|
||||
use League\Csv\Writer;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
|
@ -25,21 +25,10 @@ use Symfony\Component\HttpFoundation\StreamedResponse;
|
|||
*/
|
||||
class CustomerController extends Controller
|
||||
{
|
||||
/**
|
||||
* View share crud policies modelClass
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware(function ($request, $next) {
|
||||
View::share('modelClass', Customer::class);
|
||||
return $next($request);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* View all customers
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
|
|
@ -69,7 +58,6 @@ class CustomerController extends Controller
|
|||
Session::remove("crud.$modelTable.sort_col");
|
||||
}
|
||||
|
||||
|
||||
if (request()->brand or Session::has("crud.$modelTable.brand")) {
|
||||
$brand = $request->brand ?? Session::get("crud.$modelTable.brand");
|
||||
Session::put("crud.$modelTable.brand", $brand);
|
||||
|
|
@ -117,22 +105,25 @@ class CustomerController extends Controller
|
|||
);
|
||||
}
|
||||
|
||||
/** @var \Illuminate\Pagination\AbstractPaginator */
|
||||
$customers = $query->paginate(config('crud.paginate', 50));
|
||||
$searchFields = trans('Email, Prénom, Nom');
|
||||
|
||||
return view('customer.index', compact(
|
||||
/** @var \Illuminate\Pagination\AbstractPaginator */
|
||||
$customerModels = $query->paginate(50);
|
||||
|
||||
return view('customers.index', compact(
|
||||
'modelClass',
|
||||
'modelTable',
|
||||
'customers',
|
||||
'brands'
|
||||
'customerModels',
|
||||
'brands',
|
||||
'searchFields'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a specific custmer
|
||||
*
|
||||
* @param Customer $customer
|
||||
* @param Brand $brand
|
||||
* @param \App\Models\Customer $customer
|
||||
* @param \App\Models\Brand $brand
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Customer $customer, Brand $brand)
|
||||
|
|
@ -142,7 +133,7 @@ class CustomerController extends Controller
|
|||
$customerLogin = CustomerLogin::where('customer_id', $customer->id)
|
||||
->where('brand_id', $brand->id)->first();
|
||||
|
||||
return view('customer.show', compact(
|
||||
return view('customers.show', compact(
|
||||
'customerInfos',
|
||||
'customerLogin'
|
||||
));
|
||||
|
|
@ -151,8 +142,8 @@ class CustomerController extends Controller
|
|||
/**
|
||||
* Delete a specific customer info
|
||||
*
|
||||
* @param Customer $customer
|
||||
* @param Brand $brand
|
||||
* @param \App\Models\Customer $customer
|
||||
* @param \App\Models\Brand $brand
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function delete(Customer $customer, Brand $brand)
|
||||
|
|
@ -194,7 +185,7 @@ class CustomerController extends Controller
|
|||
});
|
||||
} catch (\ErrorException $e) {
|
||||
return redirect()->route('customers.index')
|
||||
->with('error', trans('Le compte n\'as pas pu être supprimé.'));
|
||||
->with('error', trans('Le compte n\'a pas pu être supprimé.'));
|
||||
} //end try
|
||||
|
||||
return redirect()->route('customers.index')->with('warning', trans('Compte supprimé.'));
|
||||
|
|
@ -208,7 +199,7 @@ class CustomerController extends Controller
|
|||
public function export()
|
||||
{
|
||||
$brands = Brand::all();
|
||||
return view('customer.export', compact(
|
||||
return view('customers.export', compact(
|
||||
'brands'
|
||||
));
|
||||
}
|
||||
|
|
@ -216,7 +207,7 @@ class CustomerController extends Controller
|
|||
/**
|
||||
* Exports customers following the requested export type
|
||||
*
|
||||
* @param CustomerExport $request
|
||||
* @param \App\Http\Requests\CustomerExport $request
|
||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
* @throws \Exception If the request export type in not handled.
|
||||
*/
|
||||
|
|
@ -241,7 +232,7 @@ class CustomerController extends Controller
|
|||
'Content-Disposition',
|
||||
sprintf(
|
||||
'attachment; filename="Export pour newsletter %s %s.csv"',
|
||||
Carbon::now()->format('d-m-Y_H-i'),
|
||||
Carbon::now()->isoFormat('DD-MM-YYYY_HH-mm'),
|
||||
Str::slug($exportType)
|
||||
)
|
||||
);
|
||||
|
|
@ -281,15 +272,16 @@ class CustomerController extends Controller
|
|||
}
|
||||
// ! Continue
|
||||
case CustomerExportType::singleOptin():
|
||||
SingleOptin::where('brand_id', $request->brand)->get()
|
||||
->map(function (SingleOptin $singleOptin) use ($w) {
|
||||
$w->insertOne([
|
||||
'lastname' => '',
|
||||
'firstname' => '',
|
||||
'email' => $singleOptin->email,
|
||||
'hashcode' => ''
|
||||
]);
|
||||
});
|
||||
SingleOptin::query()->whereHas('brand', function (Builder $q) use ($request) {
|
||||
$q->where('id', $request->brand);
|
||||
})->get()->map(function (SingleOptin $singleOptin) use ($w) {
|
||||
$w->insertOne([
|
||||
'lastname' => '',
|
||||
'firstname' => '',
|
||||
'email' => $singleOptin->email,
|
||||
'hashcode' => $singleOptin->hashcode
|
||||
]);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new \Exception(sprintf('Unhandled CustomerExportType %s', $exportType->label));
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class LoginController extends Controller
|
|||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function authenticate(Request $request)
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ namespace App\Http\Controllers;
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\QuestionExport;
|
||||
use App\Http\Requests\Questions\StoreQuestionRequest;
|
||||
use App\Http\Requests\Questions\UpdateQuestionRequest;
|
||||
use App\Models\Brand;
|
||||
use App\Models\Question;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
|
||||
use Kwaadpepper\CrudPolicies\Traits\CrudController;
|
||||
use League\Csv\Writer;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
|
|
@ -20,48 +20,159 @@ use Symfony\Component\HttpFoundation\StreamedResponse;
|
|||
*/
|
||||
class QuestionController extends Controller
|
||||
{
|
||||
use CrudController {
|
||||
index as crudIndex;
|
||||
}
|
||||
|
||||
/** @var Question */
|
||||
public static $modelClass = Question::class;
|
||||
|
||||
/**
|
||||
* The Bo app layout
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $layout = 'layouts.app';
|
||||
|
||||
/**
|
||||
* Event index crud-policies
|
||||
*
|
||||
* @param Builder $query
|
||||
* @return Builder
|
||||
*/
|
||||
public function indexQuery(Builder $query): Builder
|
||||
{
|
||||
if (request()->brand) {
|
||||
$query = $query->where('brand_id', '=', request()->brand);
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload crud-policies index
|
||||
*
|
||||
* @param CrudIndexRequest $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(CrudIndexRequest $request)
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\View\View */
|
||||
$view = $this->crudIndex($request);
|
||||
if ($request->ajax()) {
|
||||
return $view;
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = Question::query();
|
||||
|
||||
if ($request->brand) {
|
||||
$query = $query->where('brand_id', '=', request()->brand);
|
||||
}
|
||||
return view('question.index', $view->getData());
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$query,
|
||||
$request->search,
|
||||
null,
|
||||
'question',
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($query);
|
||||
$searchFields = trans('Question');
|
||||
|
||||
/** @var \Illuminate\Pagination\AbstractPaginator */
|
||||
$questionModels = $query->paginate(12);
|
||||
|
||||
return view('questions.index', compact('questionModels', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Models\Question $question
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create(Question $question)
|
||||
{
|
||||
$brandModels = Brand::get();
|
||||
|
||||
return view('questions.create', [
|
||||
'questionModel' => $question,
|
||||
'brandModels' => $brandModels
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Questions\StoreQuestionRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreQuestionRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$question = new Question();
|
||||
$question->fill($request->validated());
|
||||
if ($question->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('questions.edit', $question)
|
||||
->with('success', trans(
|
||||
':model a été créé.',
|
||||
['model' => Str::singular(trans('models.classes.questions'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été créé.',
|
||||
['model' => Str::singular(trans('models.classes.questions'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Question $question
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Question $question)
|
||||
{
|
||||
$brandModels = Brand::get();
|
||||
|
||||
return view('questions.edit', [
|
||||
'questionModel' => $question,
|
||||
'brandModels' => $brandModels
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a spacific resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Questions\UpdateQuestionRequest $request
|
||||
* @param \App\Models\Question $question
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateQuestionRequest $request, Question $question)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $question) {
|
||||
$question->fill($request->validated());
|
||||
if ($question->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('questions.edit', $question)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.questions'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.questions'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
*
|
||||
* @param \App\Models\Question $question
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Question $question)
|
||||
{
|
||||
return view('questions.show', [
|
||||
'questionModel' => $question
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Question $question
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(Question $question): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($question->deleteOrFail()) {
|
||||
return redirect()->route('questions.index')
|
||||
->with('success', trans(
|
||||
':model a été supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.questions'))]
|
||||
));
|
||||
}
|
||||
return redirect()->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas pu être supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.questions'))]
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -72,13 +183,13 @@ class QuestionController extends Controller
|
|||
public function export()
|
||||
{
|
||||
$brands = Brand::all();
|
||||
return view('question.export', compact('brands'));
|
||||
return view('questions.export', compact('brands'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports questions as csv the requested export type
|
||||
*
|
||||
* @param QuestionExport $request
|
||||
* @param \App\Http\Requests\QuestionExport $request
|
||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
*/
|
||||
public function exportSubmit(QuestionExport $request)
|
||||
|
|
@ -122,7 +233,7 @@ class QuestionController extends Controller
|
|||
'Content-Disposition',
|
||||
sprintf(
|
||||
'attachment; filename="Export pour newsletter %s %s.csv"',
|
||||
Carbon::now()->format('d-m-Y_H-i'),
|
||||
Carbon::now()->isoFormat('DD-MM-YYYY_HH-mm'),
|
||||
Str::slug($brand->name)
|
||||
)
|
||||
);
|
||||
|
|
@ -137,6 +248,13 @@ class QuestionController extends Controller
|
|||
$w->insertOne([]);
|
||||
}
|
||||
|
||||
// * Push empty line if nothing to export
|
||||
if (empty($results)) {
|
||||
$w->insertOne([
|
||||
'Aucune question pour cette marque'
|
||||
]);
|
||||
}
|
||||
|
||||
/*
|
||||
We create a callable to output the CSV in chunk
|
||||
with Symfony StreamResponse you can flush the body content if necessary
|
||||
|
|
|
|||
|
|
@ -3,57 +3,187 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\GenerateServiceToken;
|
||||
use App\Http\Requests\Services\StoreServiceRequest;
|
||||
use App\Http\Requests\Services\UpdateServiceRequest;
|
||||
use App\Mail\ServiceCredentialRenewed;
|
||||
use App\Models\Brand;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
|
||||
use Kwaadpepper\CrudPolicies\Traits\CrudController;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ServiceController extends Controller
|
||||
{
|
||||
use CrudController {
|
||||
index as crudIndex;
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = Service::query();
|
||||
|
||||
if ($request->brand) {
|
||||
$query = $query->where('brand_id', '=', request()->brand);
|
||||
}
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$query,
|
||||
$request->search,
|
||||
null,
|
||||
'name',
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($query);
|
||||
$searchFields = trans('Nom');
|
||||
|
||||
$serviceModels = $query->paginate(12);
|
||||
|
||||
return view('services.index', compact('serviceModels', 'searchFields'));
|
||||
}
|
||||
|
||||
/** @var Service */
|
||||
public static $modelClass = Service::class;
|
||||
|
||||
/**
|
||||
* The Bo app layout
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @var string
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public static $layout = 'layouts.app';
|
||||
|
||||
/**
|
||||
* Overload crud-policies index
|
||||
*
|
||||
* @param CrudIndexRequest $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(CrudIndexRequest $request)
|
||||
public function create(Service $service)
|
||||
{
|
||||
/** @var \Illuminate\View\View */
|
||||
$view = $this->crudIndex($request);
|
||||
if ($request->ajax()) {
|
||||
return $view;
|
||||
$brandModels = Brand::get();
|
||||
|
||||
return view('services.create', [
|
||||
'serviceModel' => $service,
|
||||
'brandModels' => $brandModels
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Services\StoreServiceRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreServiceRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$service = new Service();
|
||||
$service->fill($request->validated());
|
||||
$service->generateBearerToken();
|
||||
$this->generateServicePassword($service);
|
||||
if ($service->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('services.edit', $service)
|
||||
->with('success', trans(
|
||||
':model a été créé.',
|
||||
['model' => Str::singular(trans('models.classes.services'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été créé.',
|
||||
['model' => Str::singular(trans('models.classes.services'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Service $service)
|
||||
{
|
||||
$brandModels = Brand::get();
|
||||
|
||||
return view('services.edit', [
|
||||
'serviceModel' => $service,
|
||||
'brandModels' => $brandModels
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a spacific resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Services\UpdateServiceRequest $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateServiceRequest $request, Service $service)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $service) {
|
||||
$service->fill($request->validated());
|
||||
if ($service->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('services.edit', $service)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.services'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été mis à jour.',
|
||||
['model' => Str::singular(trans('models.classes.services'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Service $service)
|
||||
{
|
||||
return view('services.show', [
|
||||
'serviceModel' => $service
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(Service $service): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if ($service->deleteOrFail()) {
|
||||
return redirect()->route('services.index')
|
||||
->with('success', trans(
|
||||
':model a été supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.services'))]
|
||||
));
|
||||
}
|
||||
return view('service.index', $view->getData());
|
||||
return redirect()->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas pu être supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.services'))]
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Regen service credentials
|
||||
*
|
||||
* @param GenerateServiceToken $request
|
||||
* @param Service $service
|
||||
* @param \App\Http\Requests\GenerateServiceToken $request
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed, Squiz.Commenting.FunctionComment.Missing
|
||||
public function generateServicePassword(GenerateServiceToken $request, Service $service)
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed, Squiz.Commenting.FunctionComment.Missing
|
||||
public function generateServicePassword(Service $service, GenerateServiceToken $request = null)
|
||||
{
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
|
|
|||
|
|
@ -4,55 +4,67 @@ namespace App\Http\Controllers;
|
|||
|
||||
use App\Models\SingleOptin;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
|
||||
use Kwaadpepper\CrudPolicies\Traits\CrudController;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class SingleOptinController extends Controller
|
||||
{
|
||||
use CrudController {
|
||||
index as crudIndex;
|
||||
}
|
||||
|
||||
/** @var SingleOptin */
|
||||
public static $modelClass = SingleOptin::class;
|
||||
|
||||
/**
|
||||
* The Bo app layout
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @var string
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public static $layout = 'layouts.app';
|
||||
|
||||
/**
|
||||
* Event index crud-policies
|
||||
*
|
||||
* @param Builder $query
|
||||
* @return Builder
|
||||
*/
|
||||
public function indexQuery(Builder $query): Builder
|
||||
public function index(Request $request)
|
||||
{
|
||||
if (request()->brand) {
|
||||
$query = $query->where('brand_id', request()->brand);
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = SingleOptin::query();
|
||||
|
||||
if ($request->brand) {
|
||||
$query = $query->whereHas('brand', function (Builder $q) {
|
||||
$q->where('id', request()->brand);
|
||||
});
|
||||
}
|
||||
return $query;
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$query,
|
||||
$request->search,
|
||||
null,
|
||||
'email',
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($query);
|
||||
$searchFields = trans('E-mail');
|
||||
|
||||
/** @var \Illuminate\Pagination\AbstractPaginator */
|
||||
$singleoptinModels = $query->paginate(12);
|
||||
|
||||
return view('singleoptins.index', compact('singleoptinModels', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload crud-policies index
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param CrudIndexRequest $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
* @param \App\Models\SingleOptin $singleoptin
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function index(CrudIndexRequest $request)
|
||||
public function destroy(SingleOptin $singleoptin): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
/** @var \Illuminate\View\View */
|
||||
$view = $this->crudIndex($request);
|
||||
if ($request->ajax()) {
|
||||
return $view;
|
||||
if ($singleoptin->deleteOrFail()) {
|
||||
return redirect()->route('single_optins.index')
|
||||
->with('success', trans(
|
||||
':model a été supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.singleoptins'))]
|
||||
));
|
||||
}
|
||||
return view('single_optin.index', $view->getData());
|
||||
return redirect()->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas pu être supprimé.',
|
||||
['model' => Str::singular(trans('models.classes.singleoptins'))]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class StatsController extends Controller
|
|||
/**
|
||||
* Shows stats by brand
|
||||
*
|
||||
* @param StatsByBrandRequest $request
|
||||
* @param \App\Http\Requests\StatsByBrandRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function viewStatsByBrand(StatsByBrandRequest $request)
|
||||
|
|
@ -38,7 +38,7 @@ class StatsController extends Controller
|
|||
/**
|
||||
* Exports stats by brand as a csv file
|
||||
*
|
||||
* @param StatsByBrandRequest $request
|
||||
* @param \App\Http\Requests\StatsByBrandRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function exportByBrandCsv(StatsByBrandRequest $request)
|
||||
|
|
@ -62,7 +62,7 @@ class StatsController extends Controller
|
|||
|
||||
foreach ($stats as $stat) {
|
||||
$cols = [
|
||||
$stat->created_at->format('Y-m-d'),
|
||||
$stat->created_at->isoFormat('YYYY-MM-DD'),
|
||||
$stat->brand->name
|
||||
];
|
||||
foreach ($columns as $colname) {
|
||||
|
|
@ -82,7 +82,7 @@ class StatsController extends Controller
|
|||
/**
|
||||
* Views stats for a specific question
|
||||
*
|
||||
* @param StatsByQuestionRequest $request
|
||||
* @param \App\Http\Requests\StatsByQuestionRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function viewByQuestion(StatsByQuestionRequest $request)
|
||||
|
|
@ -105,7 +105,7 @@ class StatsController extends Controller
|
|||
/**
|
||||
* Exports stats for a specific question as csv
|
||||
*
|
||||
* @param StatsByQuestionRequest $request
|
||||
* @param \App\Http\Requests\StatsByQuestionRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function exportByQuestionCsv(StatsByQuestionRequest $request)
|
||||
|
|
@ -146,10 +146,11 @@ class StatsController extends Controller
|
|||
/**
|
||||
* Makes a collection of total users answers by day
|
||||
*
|
||||
* @param Collection $answers A collection of Answer.
|
||||
* @param Carbon $start The wanted start period.
|
||||
* @param Carbon $end The wanted end period.
|
||||
* @return Collection A collection with date as Y_m_d index with array of answers and their total.
|
||||
* @param \Illuminate\Support\Collection $answers A collection of Answer.
|
||||
* @param \Illuminate\Support\Carbon $start The wanted start period.
|
||||
* @param \Illuminate\Support\Carbon $end The wanted end period.
|
||||
* @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
|
||||
{
|
||||
|
|
@ -160,7 +161,7 @@ class StatsController extends Controller
|
|||
->get()->map(function ($custAnswer) {
|
||||
return [
|
||||
'answer_id' => $custAnswer->answer_id,
|
||||
'created_at' => $custAnswer->created_at->format('Y-m-d'),
|
||||
'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
|
||||
];
|
||||
})->groupBy(['created_at', 'answer_id'])->map(function ($day) {
|
||||
return $day->map(function ($custAnswers) {
|
||||
|
|
@ -169,7 +170,7 @@ class StatsController extends Controller
|
|||
});
|
||||
|
||||
do {
|
||||
$currentDate = $start->format('Y-m-d');
|
||||
$currentDate = $start->isoFormat('YYYY-MM-DD');
|
||||
/** @var \Illuminate\Support\Collection $answersByDays */
|
||||
if (!$answersByDays->has($currentDate)) {
|
||||
$answersByDays->put(
|
||||
|
|
@ -185,7 +186,7 @@ class StatsController extends Controller
|
|||
$answers->mapWithKeys(function ($answer) use ($curentAnswers) {
|
||||
return [$answer->answer =>
|
||||
$curentAnswers->has($answer->id) ?
|
||||
$curentAnswers->get($answer->id) : 0];
|
||||
$curentAnswers->get($answer->id) : 0];
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class Kernel extends HttpKernel
|
|||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\App\Http\Middleware\SecureHeaders::class
|
||||
],
|
||||
|
||||
'api' => [
|
||||
|
|
|
|||
|
|
@ -18,10 +18,12 @@ class ApiCheckTimeStamps
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
* @throws ApiErrorException With ApiError::wrongTimeStamp if timestamp has an incorrect format or is timed out.
|
||||
* @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::wrongTimeStamp
|
||||
* if timestamp has an incorrect
|
||||
* format or is timed out.
|
||||
*/
|
||||
public function handle(Request $request, \Closure $next)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ class Authenticate extends Middleware
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param mixed $request
|
||||
* @param \Closure $next
|
||||
* @param mixed ...$guards
|
||||
* @param mixed $request
|
||||
* @param \Closure $next
|
||||
* @param mixed ...$guards
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Auth\AuthenticationException If authentification fails.
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ class CheckBrand
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
|
|
|
|||
79
app/Http/Middleware/SecureHeaders.php
Normal file
79
app/Http/Middleware/SecureHeaders.php
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class SecureHeaders
|
||||
{
|
||||
/**
|
||||
* Enumerate headers which you do not want in your application's responses.
|
||||
* Great starting point would be to go check out @Scott_Helme's:
|
||||
* https://securityheaders.com/
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $unwantedHeaderList = [
|
||||
'X-Powered-By',
|
||||
'Server',
|
||||
];
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
// phpcs:enable
|
||||
View::share('nonce', $nonce = \uniqid());
|
||||
// * For VueJS dev tool to execute
|
||||
$jsDev = config('app.debug') ? "'unsafe-eval' 'unsafe-inline'" : "'nonce-{$nonce}' 'strict-dynamic'";
|
||||
$reportUri = Route::has('cspReportUri') ?
|
||||
\sprintf(' report-uri %s ;', \parse_url(route('cspReportUri'), \PHP_URL_PATH)) : '';
|
||||
$this->removeUnwantedHeaders($this->unwantedHeaderList);
|
||||
$response = $next($request);
|
||||
$response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade');
|
||||
$response->headers->set('X-Content-Type-Options', 'nosniff');
|
||||
$response->headers->set('X-XSS-Protection', '1; mode=block');
|
||||
$response->headers->set('X-Frame-Options', 'SAMEORIGIN');
|
||||
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains;');
|
||||
$cspPolicies = [
|
||||
"manifest-src 'self';",
|
||||
"connect-src 'self' blob:;",
|
||||
"img-src * data: blob:;",
|
||||
"font-src 'self' data: https://fonts.gstatic.com;",
|
||||
"style-src 'self' 'unsafe-inline';",
|
||||
"script-src 'self' {$jsDev} " . \implode(' ', [
|
||||
'https: blob:',
|
||||
]) . ';'
|
||||
];
|
||||
|
||||
$response->headers->set(
|
||||
'Content-Security-Policy',
|
||||
implode(' ', $cspPolicies) . $reportUri
|
||||
);
|
||||
$response->headers->set('Feature-Policy', 'fullscreen \'self\';');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove unwanted headers
|
||||
*
|
||||
* @param array $headerList
|
||||
* @return void
|
||||
*/
|
||||
private function removeUnwantedHeaders(array $headerList)
|
||||
{
|
||||
foreach ($headerList as $header) {
|
||||
header_remove($header);
|
||||
}
|
||||
}
|
||||
}
|
||||
42
app/Http/Requests/Answers/StoreAnswerRequest.php
Normal file
42
app/Http/Requests/Answers/StoreAnswerRequest.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Answers;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreAnswerRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'answer' => 'required|string|min:1|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'answer' => trans('Réponse à une question'),
|
||||
];
|
||||
}
|
||||
}
|
||||
7
app/Http/Requests/Answers/UpdateAnswerRequest.php
Normal file
7
app/Http/Requests/Answers/UpdateAnswerRequest.php
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Answers;
|
||||
|
||||
class UpdateAnswerRequest extends StoreAnswerRequest
|
||||
{
|
||||
}
|
||||
|
|
@ -12,13 +12,14 @@ class GetBrandStatsRequest extends BaseApiRequest
|
|||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
* @throws ValidationException If given dates are unparsable of period is bigger than 3 months.
|
||||
* @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)->diffInMonths(Carbon::parse($this->start)->addDay()) >= 3) {
|
||||
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'
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -13,13 +13,14 @@ class GetQuestionStatsRequest extends BaseApiRequest
|
|||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
* @throws ValidationException If given dates are unparsable of period is bigger than 3 months.
|
||||
* @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)->diffInMonths(Carbon::parse($this->start)->addDay()) >= 3) {
|
||||
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'
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Api\V2;
|
||||
|
||||
class SingleOptinRemoveWithHashcodeRequest extends BaseApiRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'hashcode' => 'required|string|size:36'
|
||||
];
|
||||
}
|
||||
}
|
||||
42
app/Http/Requests/Brands/StoreBrandRequest.php
Normal file
42
app/Http/Requests/Brands/StoreBrandRequest.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Brands;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreBrandRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|min:5|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'name' => trans('Nom de la marque'),
|
||||
];
|
||||
}
|
||||
}
|
||||
7
app/Http/Requests/Brands/UpdateBrandRequest.php
Normal file
7
app/Http/Requests/Brands/UpdateBrandRequest.php
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Brands;
|
||||
|
||||
class UpdateBrandRequest extends StoreBrandRequest
|
||||
{
|
||||
}
|
||||
48
app/Http/Requests/Questions/StoreQuestionRequest.php
Normal file
48
app/Http/Requests/Questions/StoreQuestionRequest.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Questions;
|
||||
|
||||
use App\Enums\QuestionType;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Kwaadpepper\Enum\Rules\EnumIsValidRule;
|
||||
|
||||
class StoreQuestionRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'question' => 'required|string|min:10|max:255',
|
||||
'type' => ['required', new EnumIsValidRule(QuestionType::class)],
|
||||
'brand_id' => 'required|integer|min:0|exists:brands,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'question' => trans('Texte de la question'),
|
||||
'type' => trans('Type de question'),
|
||||
'brand_id' => trans('Id de la marque'),
|
||||
];
|
||||
}
|
||||
}
|
||||
7
app/Http/Requests/Questions/UpdateQuestionRequest.php
Normal file
7
app/Http/Requests/Questions/UpdateQuestionRequest.php
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Questions;
|
||||
|
||||
class UpdateQuestionRequest extends StoreQuestionRequest
|
||||
{
|
||||
}
|
||||
44
app/Http/Requests/Services/StoreServiceRequest.php
Normal file
44
app/Http/Requests/Services/StoreServiceRequest.php
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Services;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreServiceRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|min:5|max:255',
|
||||
'brand_id' => 'required|integer|min:0|exists:brands,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'name' => trans('Nom du service'),
|
||||
'brand_id' => trans('Id de la marque'),
|
||||
];
|
||||
}
|
||||
}
|
||||
7
app/Http/Requests/Services/UpdateServiceRequest.php
Normal file
7
app/Http/Requests/Services/UpdateServiceRequest.php
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Services;
|
||||
|
||||
class UpdateServiceRequest extends StoreServiceRequest
|
||||
{
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ class StatsByBrandRequest extends FormRequest
|
|||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
* @throws ValidationException If given dates are unparsable of period is bigger than 1 year.
|
||||
* @throws \Illuminate\Validation\ValidationException If given dates are unparsable of period is bigger than 1 year.
|
||||
* @throws \Exception If carbon date processing failed.
|
||||
*/
|
||||
public function rules()
|
||||
|
|
@ -51,7 +51,7 @@ class StatsByBrandRequest extends FormRequest
|
|||
'start' => 'required|date|date_format:Y-m-d',
|
||||
'end' => 'required|date|date_format:Y-m-d|after_or_equal:start',
|
||||
];
|
||||
}//end if
|
||||
} //end if
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ class StatsByQuestionRequest extends FormRequest
|
|||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
* @throws ValidationException If given dates are unparsable of period is bigger than 1 year.
|
||||
* @throws \Illuminate\Validation\ValidationException If given dates are unparsable of period
|
||||
* is bigger than 1 year.
|
||||
* @throws \Exception If carbon date processing failed.
|
||||
*/
|
||||
public function rules()
|
||||
|
|
@ -51,7 +52,7 @@ class StatsByQuestionRequest extends FormRequest
|
|||
'start' => 'required|date|date_format:Y-m-d',
|
||||
'end' => 'required|date|date_format:Y-m-d|after_or_equal:start',
|
||||
];
|
||||
}//end if
|
||||
} //end if
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@ use stdClass;
|
|||
|
||||
class ApiResponse extends JsonResource
|
||||
{
|
||||
/** @var stdClass */
|
||||
/** @var \stdClass */
|
||||
protected $data;
|
||||
|
||||
/** @var \App\Enums\ApiStatus */
|
||||
protected $status;
|
||||
|
||||
/**
|
||||
* @param stdClass $data
|
||||
* @param ApiStatus $status
|
||||
* @param \stdClass $data
|
||||
* @param \App\Enums\ApiStatus $status
|
||||
*/
|
||||
public function __construct(stdClass $data = null, ApiStatus $status)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class BrandStatsResource extends JsonResourceCollection
|
|||
return [
|
||||
'stats' => $this->collection->map(function (BrandStat $brandStat) {
|
||||
return [
|
||||
'date' => $brandStat->created_at->format('Y-m-d'),
|
||||
'date' => $brandStat->created_at->isoFormat('YYYY-MM-DD'),
|
||||
'active' => $brandStat->active,
|
||||
'inactive' => $brandStat->inactive,
|
||||
'old_accounts' => $brandStat->old_accounts,
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ class CustomerResource extends JsonResource
|
|||
/**
|
||||
* CustomerResource
|
||||
*
|
||||
* @param Brand $brand
|
||||
* @param Customer $customer
|
||||
* @param \App\Models\Brand $brand
|
||||
* @param \App\Models\Customer $customer
|
||||
*/
|
||||
public function __construct(Brand $brand, Customer $customer)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class SetServiceStats implements ShouldQueue
|
|||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param Service $service
|
||||
* @param \App\Models\Service $service
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Service $service)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use App\Models\CustomerLogin;
|
|||
use App\Models\SingleOptin;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
|
|
@ -41,7 +42,7 @@ class StatJob implements ShouldQueue
|
|||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param Brand $brand
|
||||
* @param \App\Models\Brand $brand
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Brand $brand)
|
||||
|
|
@ -57,17 +58,29 @@ class StatJob implements ShouldQueue
|
|||
public function handle()
|
||||
{
|
||||
$stats = new BrandStat([
|
||||
'active' => CustomerLogin::whereBrandId($this->brand->id)
|
||||
->whereDate('last_connection', '<', Carbon::now()->subMonths(6))->count(),
|
||||
'inactive' => CustomerLogin::whereBrandId($this->brand->id)
|
||||
'active' => CustomerLogin::query()->whereHas('brand', function (Builder $q) {
|
||||
$q->where('id', $this->brand->id);
|
||||
})->whereDate('last_connection', '<', Carbon::now()->subMonths(6))->count(),
|
||||
'inactive' => CustomerLogin::query()->whereHas('brand', function (Builder $q) {
|
||||
$q->where('id', $this->brand->id);
|
||||
})
|
||||
->whereDate('last_connection', '>', Carbon::now()->subMonths(6))->count(),
|
||||
'new_accounts' => CustomerLogin::whereBrandId($this->brand->id)
|
||||
'new_accounts' => CustomerLogin::query()->whereHas('brand', function (Builder $q) {
|
||||
$q->where('id', $this->brand->id);
|
||||
})
|
||||
->whereDate('created_at', '<', Carbon::now()->subMonths(6))->count(),
|
||||
'old_accounts' => CustomerLogin::whereBrandId($this->brand->id)
|
||||
'old_accounts' => CustomerLogin::query()->whereHas('brand', function (Builder $q) {
|
||||
$q->where('id', $this->brand->id);
|
||||
})
|
||||
->whereDate('created_at', '>', Carbon::now()->subMonths(6))->count(),
|
||||
'total_accounts' => CustomerLogin::whereBrandId($this->brand->id)->count(),
|
||||
'total_opt_in' => CustomerInfo::whereBrandId($this->brand->id)
|
||||
->whereOptIn(true)->count() + SingleOptin::whereBrandId($this->brand->id)->count()
|
||||
'total_accounts' => CustomerLogin::query()->whereHas('brand', function (Builder $q) {
|
||||
$q->where('id', $this->brand->id);
|
||||
})->count(),
|
||||
'total_opt_in' => CustomerInfo::query()->whereHas('brand', function (Builder $q) {
|
||||
$q->where('id', $this->brand->id);
|
||||
})->whereOptIn(true)->count() + SingleOptin::query()->whereHas('brand', function (Builder $q) {
|
||||
$q->where('id', $this->brand->id);
|
||||
})->count()
|
||||
]);
|
||||
$stats->brand()->associate($this->brand);
|
||||
$stats->saveOrFail();
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ class UpdateCustomerLastConnection implements ShouldQueue
|
|||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param Customer $customer
|
||||
* @param CustomerLogin $customerLogin
|
||||
* @param Carbon $date
|
||||
* @param \App\Models\Customer $customer
|
||||
* @param \App\Models\CustomerLogin $customerLogin
|
||||
* @param \Illuminate\Support\Carbon $date
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class Helper
|
|||
/**
|
||||
* Tells if the request is within apiV2 routes
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isRequestForApiV2(Request $request)
|
||||
|
|
@ -38,7 +38,7 @@ class Helper
|
|||
/**
|
||||
* Tells if the request is within apiV1 routes
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isRequestForApiV1(Request $request): bool
|
||||
|
|
@ -52,7 +52,7 @@ class Helper
|
|||
/**
|
||||
* Try to get current route name
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getRouteName(Request $request)
|
||||
|
|
@ -63,7 +63,7 @@ class Helper
|
|||
/**
|
||||
* Get the bearer token from request
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getBearerTokenFromRequest(Request $request): ?string
|
||||
|
|
@ -84,7 +84,7 @@ class Helper
|
|||
/**
|
||||
* Try to get current route prefix
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getRoutePrefix(Request $request)
|
||||
|
|
@ -96,7 +96,7 @@ class Helper
|
|||
/**
|
||||
* Try to get route from request
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Routing\Route|null
|
||||
*/
|
||||
public static function getRoute(Request $request)
|
||||
|
|
@ -125,7 +125,7 @@ class Helper
|
|||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return string request signature
|
||||
* @throws CrmException If an error occurs.
|
||||
* @throws \App\Exceptions\Api\V2\CrmException If an error occurs.
|
||||
*/
|
||||
public static function signRequest(string $secret, string $uri, string $method, array $parameters): string
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use App\Models\CustomerLogin;
|
|||
use App\Models\SingleOptin;
|
||||
use Carbon\Exceptions\InvalidFormatException;
|
||||
use Database\migrations\LeGaulois2016Migration;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
|
@ -21,14 +22,17 @@ use Illuminate\Support\Str;
|
|||
*/
|
||||
class MigrateOldData extends LeGaulois2016Migration
|
||||
{
|
||||
/** @var Brand */
|
||||
/** @var \App\Models\Brand */
|
||||
private $brand;
|
||||
|
||||
/** @var string */
|
||||
private $table;
|
||||
|
||||
/**
|
||||
* runMigration
|
||||
*
|
||||
* @param Brand $brand
|
||||
* @param string $table
|
||||
* @param \App\Models\Brand $brand
|
||||
* @param string $table
|
||||
* @return void
|
||||
*/
|
||||
public function runMigration(Brand $brand, string $table)
|
||||
|
|
@ -82,8 +86,10 @@ class MigrateOldData extends LeGaulois2016Migration
|
|||
|
||||
// * Just save Single optin.
|
||||
if (empty($first_name) && empty($last_name)) {
|
||||
$sglOptin = SingleOptin::where('email', strtolower($email))
|
||||
->where('brand_id', $this->brand->id)->firstOrNew();
|
||||
$sglOptin = SingleOptin::query()->where('email', strtolower($email))
|
||||
->whereHas('brand', function (Builder $q) {
|
||||
$q->where('id', $this->brand->id);
|
||||
})->firstOrNew();
|
||||
$sglOptin->email = strtolower($email);
|
||||
$sglOptin->brand_id = $this->brand->id;
|
||||
$sglOptin->save();
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ class ServiceCredentialRenewed extends Mailable
|
|||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param Service $service
|
||||
* @param User $user
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\User $user
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Service $service, User $user)
|
||||
|
|
|
|||
|
|
@ -4,21 +4,10 @@ namespace App\Models;
|
|||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
|
||||
use Kwaadpepper\CrudPolicies\Enums\CrudType;
|
||||
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
|
||||
|
||||
class Answer extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use IsCrudModel;
|
||||
|
||||
/** @var string */
|
||||
protected $crudLabelColumn = 'answer';
|
||||
|
||||
/** @var string */
|
||||
protected $crudValueColumn = 'id';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
@ -29,32 +18,6 @@ class Answer extends Model
|
|||
'answer'
|
||||
];
|
||||
|
||||
/**
|
||||
* Answer
|
||||
*
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
self::$editableProperties = [
|
||||
'answer' => [
|
||||
'label' => Str::ucfirst(trans('models.common.answer')),
|
||||
'type' => CrudType::string(),
|
||||
'validate' => [
|
||||
'min:1',
|
||||
'max:255'
|
||||
],
|
||||
'actions' => [
|
||||
CrudAction::viewAny(),
|
||||
CrudAction::view(),
|
||||
CrudAction::create(),
|
||||
CrudAction::update()
|
||||
]
|
||||
]
|
||||
];
|
||||
parent::__construct($attributes);
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,24 +4,13 @@ namespace App\Models;
|
|||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
|
||||
use Kwaadpepper\CrudPolicies\Enums\CrudType;
|
||||
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
|
||||
use Rennokki\QueryCache\Traits\QueryCacheable;
|
||||
|
||||
class Brand extends Model
|
||||
{
|
||||
use IsCrudModel;
|
||||
use HasFactory;
|
||||
use QueryCacheable;
|
||||
|
||||
/** @var string */
|
||||
protected $crudLabelColumn = 'name';
|
||||
|
||||
/** @var string */
|
||||
protected $crudValueColumn = 'id';
|
||||
|
||||
/**
|
||||
* The timeout cache for this model
|
||||
*
|
||||
|
|
@ -47,22 +36,6 @@ class Brand extends Model
|
|||
{
|
||||
$this->cacheFor = config('api.servicesDBCache') * 60;
|
||||
|
||||
self::$editableProperties = [
|
||||
'name' => [
|
||||
'label' => Str::ucfirst(trans('models.common.name')),
|
||||
'type' => CrudType::string(),
|
||||
'validate' => [
|
||||
'min:5',
|
||||
'max:255'
|
||||
],
|
||||
'actions' => [
|
||||
CrudAction::viewAny(),
|
||||
CrudAction::view(),
|
||||
CrudAction::create(),
|
||||
CrudAction::update()
|
||||
]
|
||||
]
|
||||
];
|
||||
parent::__construct($attributes);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class BrandStat extends Model
|
||||
{
|
||||
|
|
@ -41,9 +40,9 @@ class BrandStat extends Model
|
|||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (BrandStat $stat) {
|
||||
if (!$stat->created_at) {
|
||||
$stat->created_at = Carbon::now();
|
||||
static::creating(function (self $model) {
|
||||
if (!$model->created_at) {
|
||||
$model->created_at = now();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class Customer extends Model
|
|||
/**
|
||||
* Customer Brand belongsToMany relation
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\belongsToMany
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function brands()
|
||||
{
|
||||
|
|
@ -84,8 +84,8 @@ class Customer extends Model
|
|||
* or create a New one if $firstOrNewOrFail is 1
|
||||
* throw model not found exception if firstOrNewOrFail = 2
|
||||
*
|
||||
* @param Brand $brand
|
||||
* @param integer $firstOrNewOrFail
|
||||
* @param \App\Models\Brand $brand
|
||||
* @param integer $firstOrNewOrFail
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function info(Brand $brand, int $firstOrNewOrFail = self::FIRST_OR_NULL): ?CustomerInfo
|
||||
|
|
@ -98,10 +98,10 @@ class Customer extends Model
|
|||
}
|
||||
}
|
||||
}
|
||||
$query = CustomerInfo::whereHas('brand', function (Builder $query) use ($brand) {
|
||||
$query->where('id', $brand->id);
|
||||
})->whereHas('customer', function (Builder $query) {
|
||||
$query->where('id', $this->id);
|
||||
$query = CustomerInfo::query()->whereHas('brand', function (Builder $q) use ($brand) {
|
||||
$q->where('id', $brand->id);
|
||||
})->whereHas('customer', function (Builder $q) {
|
||||
$q->where('id', $this->id);
|
||||
});
|
||||
if ($firstOrNewOrFail === self::FIRST_OR_NEW) {
|
||||
return $query->firstOrNew();
|
||||
|
|
@ -117,8 +117,8 @@ class Customer extends Model
|
|||
* or create a New one if $firstOrNewOrFail is 1
|
||||
* throw model not found exception if firstOrNewOrFail = 2
|
||||
*
|
||||
* @param Brand $brand
|
||||
* @param integer $firstOrNewOrFail
|
||||
* @param \App\Models\Brand $brand
|
||||
* @param integer $firstOrNewOrFail
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function login(Brand $brand, int $firstOrNewOrFail = self::FIRST_OR_NULL): ?CustomerLogin
|
||||
|
|
@ -131,10 +131,10 @@ class Customer extends Model
|
|||
}
|
||||
}
|
||||
}
|
||||
$query = CustomerLogin::whereHas('brand', function (Builder $query) use ($brand) {
|
||||
$query->where('id', $brand->id);
|
||||
})->whereHas('customer', function (Builder $query) use ($brand) {
|
||||
$query->where('id', $this->id);
|
||||
$query = CustomerLogin::query()->whereHas('brand', function (Builder $q) use ($brand) {
|
||||
$q->where('id', $brand->id);
|
||||
})->whereHas('customer', function (Builder $q) {
|
||||
$q->where('id', $this->id);
|
||||
});
|
||||
if ($firstOrNewOrFail === self::FIRST_OR_NEW) {
|
||||
return $query->firstOrNew();
|
||||
|
|
@ -148,8 +148,8 @@ class Customer extends Model
|
|||
/**
|
||||
* Load login and info for this customer and this specific brand.
|
||||
*
|
||||
* @param Brand $brand
|
||||
* @param boolean $orFail
|
||||
* @param \App\Models\Brand $brand
|
||||
* @param boolean $orFail
|
||||
* @return self
|
||||
* @throws ModelNotFoundException If no login or info was found for the brand.
|
||||
*/
|
||||
|
|
@ -175,8 +175,8 @@ class Customer extends Model
|
|||
/**
|
||||
* Set this customer as optin
|
||||
*
|
||||
* @param Brand $brand
|
||||
* @param boolean $optIn
|
||||
* @param \App\Models\Brand $brand
|
||||
* @param boolean $optIn
|
||||
* @return void
|
||||
* @throws \Throwable If customer history update failed.
|
||||
*/
|
||||
|
|
@ -196,16 +196,16 @@ class Customer extends Model
|
|||
* Get All answers given by this customer
|
||||
* for a specific service
|
||||
*
|
||||
* @param Service $service
|
||||
* @return Collection
|
||||
* @param \App\Models\Service $service
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getAnswers(Service $service): Collection
|
||||
{
|
||||
return Answer::whereHas('customers', function ($q) {
|
||||
$q->whereId($this->id);
|
||||
})->whereHas('question', function ($q) use ($service) {
|
||||
$q->whereHas('brand', function ($q) use ($service) {
|
||||
$q->whereId($service->brand->id);
|
||||
return Answer::query()->whereHas('customers', function (Builder $q) {
|
||||
$q->where('id', $this->id);
|
||||
})->whereHas('question', function (Builder $q) use ($service) {
|
||||
$q->whereHas('brand', function (Builder $q) use ($service) {
|
||||
$q->where('id', $service->brand->id);
|
||||
});
|
||||
})->get();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Enums\Country;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
|
@ -56,14 +57,14 @@ class CustomerInfo extends Model
|
|||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (CustomerInfo $customerInfo) {
|
||||
$customerInfo->hashcode = Str::uuid();
|
||||
static::creating(function (self $model) {
|
||||
$model->hashcode = Str::uuid();
|
||||
});
|
||||
static::deleting(function (CustomerInfo $customerInfo) {
|
||||
CustomerOptInHistory::whereHas('customer', function ($q) use ($customerInfo) {
|
||||
$q->whereId($customerInfo->customer->id);
|
||||
})->whereHas('brand', function ($q) use ($customerInfo) {
|
||||
$q->whereId($customerInfo->brand->id);
|
||||
static::deleting(function (self $model) {
|
||||
CustomerOptInHistory::query()->whereHas('customer', function (Builder $q) use ($model) {
|
||||
$q->where('id', $model->customer->id);
|
||||
})->whereHas('brand', function (Builder $q) use ($model) {
|
||||
$q->where('id', $model->brand->id);
|
||||
})->delete();
|
||||
});
|
||||
}
|
||||
|
|
@ -105,16 +106,30 @@ class CustomerInfo extends Model
|
|||
/**
|
||||
* Get customer info from email
|
||||
*
|
||||
* @param Brand $brand
|
||||
* @param string $email
|
||||
* @param \App\Models\Brand $brand
|
||||
* @param string $email
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public static function getFromEmail(Brand $brand, string $email)
|
||||
{
|
||||
return CustomerInfo::whereHas('brand', function ($q) use ($brand) {
|
||||
return CustomerInfo::query()->whereHas('brand', function (Builder $q) use ($brand) {
|
||||
$q->where('id', $brand->id);
|
||||
})->whereHas('customer', function ($q) use ($email) {
|
||||
})->whereHas('customer', function (Builder $q) use ($email) {
|
||||
$q->where('email', $email);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customer info from hashcode
|
||||
*
|
||||
* @param \App\Models\Brand $brand
|
||||
* @param string $hashcode
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public static function getFromHashcode(Brand $brand, string $hashcode)
|
||||
{
|
||||
return CustomerInfo::query()->whereHas('brand', function (Builder $q) use ($brand) {
|
||||
$q->where('id', $brand->id);
|
||||
})->where('hashcode', $hashcode);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,14 +44,14 @@ class CustomerLogin extends Model
|
|||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($customerLogin) {
|
||||
if (Hash::needsRehash($customerLogin->password)) {
|
||||
$customerLogin->password = Hash::make(trim($customerLogin->password));
|
||||
static::creating(function (self $model) {
|
||||
if (Hash::needsRehash($model->password)) {
|
||||
$model->password = Hash::make(trim($model->password));
|
||||
}
|
||||
});
|
||||
static::updating(function ($customerLogin) {
|
||||
if (Hash::needsRehash($customerLogin->password)) {
|
||||
$customerLogin->password = Hash::make(trim($customerLogin->password));
|
||||
static::updating(function (self $model) {
|
||||
if (Hash::needsRehash($model->password)) {
|
||||
$model->password = Hash::make(trim($model->password));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,23 +5,12 @@ namespace App\Models;
|
|||
use App\Enums\QuestionType;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
|
||||
use Kwaadpepper\CrudPolicies\Enums\CrudType;
|
||||
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
|
||||
use Kwaadpepper\Enum\Traits\CastsEnums;
|
||||
|
||||
class Question extends Model
|
||||
{
|
||||
use CastsEnums;
|
||||
use HasFactory;
|
||||
use IsCrudModel;
|
||||
|
||||
/** @var string */
|
||||
protected $crudLabelColumn = 'question';
|
||||
|
||||
/** @var string */
|
||||
protected $crudValueColumn = 'id';
|
||||
|
||||
/**
|
||||
* Map attribute names to enum classes.
|
||||
|
|
@ -39,69 +28,10 @@ class Question extends Model
|
|||
*/
|
||||
protected $fillable = [
|
||||
'question',
|
||||
'type'
|
||||
'type',
|
||||
'brand_id'
|
||||
];
|
||||
|
||||
/**
|
||||
* Question
|
||||
*
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
self::$editableProperties = [
|
||||
'question' => [
|
||||
'label' => Str::ucfirst(trans('models.common.question')),
|
||||
'type' => CrudType::string(),
|
||||
'validate' => [
|
||||
'min:10',
|
||||
'max:255'
|
||||
],
|
||||
'actions' => [
|
||||
CrudAction::viewAny(),
|
||||
CrudAction::view(),
|
||||
CrudAction::create(),
|
||||
CrudAction::update()
|
||||
]
|
||||
],
|
||||
'type' => [
|
||||
'label' => Str::ucfirst(trans('models.common.type')),
|
||||
'type' => CrudType::enum(),
|
||||
'enum' => QuestionType::class,
|
||||
'actions' => [
|
||||
CrudAction::view(),
|
||||
CrudAction::create(),
|
||||
CrudAction::update(),
|
||||
]
|
||||
],
|
||||
'brand_id' => [
|
||||
'label' => Str::ucfirst(trans('models.classes.brand')),
|
||||
'type' => CrudType::belongsTo(),
|
||||
'belongsTo' => Brand::class,
|
||||
'actions' => [
|
||||
CrudAction::viewAny(),
|
||||
CrudAction::view(),
|
||||
CrudAction::create(),
|
||||
CrudAction::update(),
|
||||
]
|
||||
],
|
||||
'answers' => [
|
||||
'label' => Str::ucfirst(Str::plural(trans('models.classes.answers'))),
|
||||
'type' => CrudType::hasMany(),
|
||||
'hasMany' => Answer::class,
|
||||
'hasManyLabel' => 'answer',
|
||||
'readonly' => true,
|
||||
'actions' => [
|
||||
CrudAction::viewAny(),
|
||||
CrudAction::view(),
|
||||
CrudAction::create(),
|
||||
CrudAction::update(),
|
||||
]
|
||||
]
|
||||
];
|
||||
parent::__construct($attributes);
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -11,24 +11,14 @@ use Illuminate\Http\Request;
|
|||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
|
||||
use Kwaadpepper\CrudPolicies\Enums\CrudType;
|
||||
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
|
||||
use Rennokki\QueryCache\Traits\QueryCacheable;
|
||||
use RuntimeException;
|
||||
|
||||
class Service extends Model
|
||||
{
|
||||
use IsCrudModel;
|
||||
use HasFactory;
|
||||
use QueryCacheable;
|
||||
|
||||
/** @var string */
|
||||
protected $crudLabelColumn = 'name';
|
||||
|
||||
/** @var string */
|
||||
protected $crudValueColumn = 'id';
|
||||
|
||||
/**
|
||||
* The timeout cache for this model
|
||||
*
|
||||
|
|
@ -52,36 +42,8 @@ class Service extends Model
|
|||
*/
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
$this->cacheFor = config('api.servicesDBCache') * 60;
|
||||
|
||||
self::$editableProperties = [
|
||||
'name' => [
|
||||
'label' => Str::ucfirst(trans('models.common.name')),
|
||||
'type' => CrudType::string(),
|
||||
'validate' => [
|
||||
'min:5',
|
||||
'max:255'
|
||||
],
|
||||
'actions' => [
|
||||
CrudAction::viewAny(),
|
||||
CrudAction::view(),
|
||||
CrudAction::create(),
|
||||
CrudAction::update()
|
||||
]
|
||||
],
|
||||
'brand_id' => [
|
||||
'label' => Str::ucfirst(trans('models.classes.brand')),
|
||||
'type' => CrudType::belongsTo(),
|
||||
'belongsTo' => Brand::class,
|
||||
'actions' => [
|
||||
CrudAction::viewAny(),
|
||||
CrudAction::view(),
|
||||
CrudAction::create(),
|
||||
CrudAction::update()
|
||||
]
|
||||
],
|
||||
];
|
||||
parent::__construct($attributes);
|
||||
$this->cacheFor = config('api.servicesDBCache') * 60;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -106,9 +68,9 @@ class Service extends Model
|
|||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $service) {
|
||||
$service->generateBearerToken();
|
||||
$service->generateBearerPassword();
|
||||
static::creating(function (self $model) {
|
||||
$model->generateBearerToken();
|
||||
$model->generateBearerPassword();
|
||||
});
|
||||
static::created(function () {
|
||||
// * Flush Eloquent cache.
|
||||
|
|
|
|||
|
|
@ -5,20 +5,31 @@ namespace App\Models;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
|
||||
use Kwaadpepper\CrudPolicies\Enums\CrudType;
|
||||
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
|
||||
|
||||
class SingleOptin extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use IsCrudModel;
|
||||
|
||||
/** @var string */
|
||||
protected $crudLabelColumn = 'email';
|
||||
/**
|
||||
* The primary key for the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'hashcode';
|
||||
|
||||
/** @var string */
|
||||
protected $crudValueColumn = 'id';
|
||||
/**
|
||||
* The "type" of the primary key ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $keyType = 'uuid';
|
||||
|
||||
/**
|
||||
* Indicates if the IDs are auto-incrementing.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $incrementing = false;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
@ -30,60 +41,15 @@ class SingleOptin extends Model
|
|||
];
|
||||
|
||||
/**
|
||||
* SingleOptin
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $attributes = [])
|
||||
protected static function booted()
|
||||
{
|
||||
self::$editableProperties = [
|
||||
'email' => [
|
||||
'label' => Str::ucfirst(trans('models.common.email')),
|
||||
'type' => CrudType::email(),
|
||||
'validate' => [
|
||||
'required',
|
||||
'email:rfc,dns',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
$q = static::query();
|
||||
if (request()->user) {
|
||||
$q = $q->where('id', '!=', $this->id);
|
||||
}
|
||||
if ($q->where('email', $value)->exists()) {
|
||||
$fail(__(':attribute est déjà utilisé', [
|
||||
'attribute' => $attribute
|
||||
]));
|
||||
}
|
||||
}
|
||||
],
|
||||
'actions' => [
|
||||
CrudAction::viewAny(),
|
||||
CrudAction::view(),
|
||||
CrudAction::create(),
|
||||
CrudAction::update()
|
||||
]
|
||||
],
|
||||
'brand_id' => [
|
||||
'label' => Str::ucfirst(trans('models.classes.brand')),
|
||||
'type' => CrudType::belongsTo(),
|
||||
'belongsTo' => Brand::class,
|
||||
'actions' => [
|
||||
CrudAction::viewAny(),
|
||||
CrudAction::view()
|
||||
]
|
||||
],
|
||||
'created_at' => [
|
||||
'label' => Str::ucfirst(trans('models.common.optinDate')),
|
||||
'type' => CrudType::string(),
|
||||
'readonly' => true,
|
||||
'actions' => [
|
||||
CrudAction::viewAny(),
|
||||
CrudAction::view(),
|
||||
CrudAction::update()
|
||||
]
|
||||
],
|
||||
];
|
||||
parent::__construct($attributes);
|
||||
static::creating(function (self $model) {
|
||||
$model->hashcode = Str::uuid();
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ namespace App\Models;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
|
|
@ -17,7 +19,8 @@ class User extends Authenticatable
|
|||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'lastname',
|
||||
'firstname',
|
||||
'email',
|
||||
'password',
|
||||
];
|
||||
|
|
@ -40,4 +43,26 @@ class User extends Authenticatable
|
|||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
// * EVENT CLOSURES.
|
||||
static::creating(function (self $model) {
|
||||
if (Hash::needsRehash($model->password)) {
|
||||
$model->password = Hash::make($model->password);
|
||||
}
|
||||
$model->remember_token = Str::random(10);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
if (Hash::needsRehash($model->password)) {
|
||||
$model->password = Hash::make($model->password);
|
||||
}
|
||||
$model->remember_token = Str::random(10);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,31 +3,58 @@
|
|||
namespace App\Policies;
|
||||
|
||||
use App\Policies\Rules\UserStaticRules as USR;
|
||||
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AnswerPolicy extends RootPolicy
|
||||
class AnswerPolicy
|
||||
{
|
||||
/**
|
||||
* Init policies on call
|
||||
* View an Answer.
|
||||
*
|
||||
* @return void
|
||||
* @return boolean
|
||||
*/
|
||||
public function setPolicies()
|
||||
public function view(): bool
|
||||
{
|
||||
/**
|
||||
* This first rule to return true in a policy action authorises the action
|
||||
*/
|
||||
$this->policies = [
|
||||
'answer' => [
|
||||
'viewAny' => USR::make('everyOne'),
|
||||
'view' => USR::make('noOne'),
|
||||
'update' => USR::make('everyOne'),
|
||||
'create' => USR::make('everyOne'),
|
||||
'delete' => USR::make('everyOne')
|
||||
]
|
||||
];
|
||||
return USR::noOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* viewAny an Answer.
|
||||
* @return boolean
|
||||
*/
|
||||
public function viewAny(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an Answer.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function create(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an Answer.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an Answer.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,31 +3,58 @@
|
|||
namespace App\Policies;
|
||||
|
||||
use App\Policies\Rules\UserStaticRules as USR;
|
||||
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class BrandPolicy extends RootPolicy
|
||||
class BrandPolicy
|
||||
{
|
||||
/**
|
||||
* Init policies on call
|
||||
* View a Brand.
|
||||
*
|
||||
* @return void
|
||||
* @return boolean
|
||||
*/
|
||||
public function setPolicies()
|
||||
public function view(): bool
|
||||
{
|
||||
/**
|
||||
* This first rule to return true in a policy action authorises the action
|
||||
*/
|
||||
$this->policies = [
|
||||
'brand' => [
|
||||
'viewAny' => USR::make('everyOne'),
|
||||
'view' => USR::make('noOne'),
|
||||
'update' => USR::make('everyOne'),
|
||||
'create' => USR::make('everyOne'),
|
||||
'delete' => USR::make('noOne')
|
||||
]
|
||||
];
|
||||
return USR::noOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* viewAny a Brand.
|
||||
* @return boolean
|
||||
*/
|
||||
public function viewAny(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Brand.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function create(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a Brand.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Brand.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete(): bool
|
||||
{
|
||||
return USR::noOne();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,43 +4,71 @@ namespace App\Policies;
|
|||
|
||||
use App\Models\Customer;
|
||||
use App\Models\Service;
|
||||
use App\Policies\Rules\UserStaticRules as USR;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
|
||||
use App\Policies\Rules\UserStaticRules as USR;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CustomerPolicy extends RootPolicy
|
||||
class CustomerPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Init policies on call
|
||||
* View a Customer.
|
||||
*
|
||||
* @return void
|
||||
* @return boolean
|
||||
*/
|
||||
public function setPolicies()
|
||||
public function view(): bool
|
||||
{
|
||||
/**
|
||||
* This first rule to return true in a policy action authorises the action
|
||||
*/
|
||||
$this->policies = [
|
||||
'customer' => [
|
||||
'viewAny' => USR::make('everyOne'),
|
||||
'view' => USR::make('everyOne'),
|
||||
'create' => USR::make('noOne'),
|
||||
'update' => USR::make('noOne'),
|
||||
'delete' => USR::make('everyOne')
|
||||
]
|
||||
];
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* View any a Customer.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function viewAny(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Customer.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function create(): bool
|
||||
{
|
||||
return USR::noOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a Customer.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(): bool
|
||||
{
|
||||
return USR::noOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Customer.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the customer belongs to the service
|
||||
*
|
||||
* @param Service $service
|
||||
* @param Customer $customer
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Customer $customer
|
||||
* @return boolean
|
||||
*/
|
||||
public function customerBelongsToService(Service $service, Customer $customer)
|
||||
|
|
|
|||
|
|
@ -5,39 +5,66 @@ namespace App\Policies;
|
|||
use App\Models\Question;
|
||||
use App\Models\Service;
|
||||
use App\Policies\Rules\UserStaticRules as USR;
|
||||
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class QuestionPolicy extends RootPolicy
|
||||
class QuestionPolicy
|
||||
{
|
||||
/**
|
||||
* Init policies on call
|
||||
* View a Question.
|
||||
*
|
||||
* @return void
|
||||
* @return boolean
|
||||
*/
|
||||
public function setPolicies()
|
||||
public function view(): bool
|
||||
{
|
||||
/**
|
||||
* This first rule to return true in a policy action authorises the action
|
||||
*/
|
||||
$this->policies = [
|
||||
'question' => [
|
||||
'viewAny' => USR::make('everyOne'),
|
||||
'view' => USR::make('everyOne'),
|
||||
'update' => USR::make('everyOne'),
|
||||
'create' => USR::make('everyOne'),
|
||||
'delete' => USR::make('everyOne')
|
||||
]
|
||||
];
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* viewAny a Question.
|
||||
* @return boolean
|
||||
*/
|
||||
public function viewAny(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Question.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function create(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a Question.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Question.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the question belongs to the service
|
||||
*
|
||||
* @param Service $service
|
||||
* @param Question $question
|
||||
* @param \App\Models\Service $service
|
||||
* @param \App\Models\Question $question
|
||||
* @return boolean
|
||||
*/
|
||||
public function questionBelongsToService(Service $service, Question $question)
|
||||
|
|
|
|||
|
|
@ -2,21 +2,19 @@
|
|||
|
||||
namespace App\Policies\Rules;
|
||||
|
||||
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
|
||||
|
||||
/**
|
||||
* Userlevel Policiy Static Rules
|
||||
* ! Rules has to return boolean value
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
abstract class UserStaticRules extends StaticRules
|
||||
abstract class UserStaticRules
|
||||
{
|
||||
/**
|
||||
* Allow everyone
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function everyOne(): bool
|
||||
public static function everyOne(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -25,7 +23,7 @@ abstract class UserStaticRules extends StaticRules
|
|||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function noOne(): bool
|
||||
public static function noOne(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,31 +3,59 @@
|
|||
namespace App\Policies;
|
||||
|
||||
use App\Policies\Rules\UserStaticRules as USR;
|
||||
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ServicePolicy extends RootPolicy
|
||||
class ServicePolicy
|
||||
{
|
||||
/**
|
||||
* Init policies on call
|
||||
* View an Answer.
|
||||
*
|
||||
* @return void
|
||||
* @return boolean
|
||||
*/
|
||||
public function setPolicies()
|
||||
public function view(): bool
|
||||
{
|
||||
/**
|
||||
* This first rule to return true in a policy action authorises the action
|
||||
*/
|
||||
$this->policies = [
|
||||
'service' => [
|
||||
'viewAny' => USR::make('everyOne'),
|
||||
'view' => USR::make('everyOne'),
|
||||
'update' => USR::make('everyOne'),
|
||||
'create' => USR::make('everyOne'),
|
||||
'delete' => USR::make('noOne')
|
||||
]
|
||||
];
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* viewAny an Service.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function viewAny(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an Service.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function create(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an Service.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an Service.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete(): bool
|
||||
{
|
||||
return USR::noOne();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,31 +3,58 @@
|
|||
namespace App\Policies;
|
||||
|
||||
use App\Policies\Rules\UserStaticRules as USR;
|
||||
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class SingleOptinPolicy extends RootPolicy
|
||||
class SingleOptinPolicy
|
||||
{
|
||||
/**
|
||||
* Init policies on call
|
||||
* View an Answer.
|
||||
*
|
||||
* @return void
|
||||
* @return boolean
|
||||
*/
|
||||
public function setPolicies()
|
||||
public function view(): bool
|
||||
{
|
||||
/**
|
||||
* This first rule to return true in a policy action authorises the action
|
||||
*/
|
||||
$this->policies = [
|
||||
'singleoptin' => [
|
||||
'viewAny' => USR::make('everyOne'),
|
||||
'view' => USR::make('noOne'),
|
||||
'create' => USR::make('noOne'),
|
||||
'update' => USR::make('noOne'),
|
||||
'delete' => USR::make('everyOne')
|
||||
]
|
||||
];
|
||||
return USR::noOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* viewAny an Answer.
|
||||
* @return boolean
|
||||
*/
|
||||
public function viewAny(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an Answer.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function create(): bool
|
||||
{
|
||||
return USR::noOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an Answer.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(): bool
|
||||
{
|
||||
return USR::noOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an Answer.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete(): bool
|
||||
{
|
||||
return USR::everyOne();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,10 @@ namespace App\Providers;
|
|||
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
/**
|
||||
|
|
@ -36,14 +32,11 @@ class AppServiceProvider extends ServiceProvider
|
|||
JsonResource::withoutWrapping();
|
||||
|
||||
// * LOCAL HTTPS FIX.
|
||||
if (!in_array(config('app.env'), ['local', 'testing'])) {
|
||||
URL::forceScheme('https');
|
||||
}
|
||||
URL::forceScheme('https');
|
||||
|
||||
// * HA PROXY FIX.
|
||||
App::singleton('clientIp', function () {
|
||||
if (
|
||||
config('app.env') === 'local'
|
||||
) {
|
||||
if (config('app.env') === 'local') {
|
||||
return request()->getClientIp();
|
||||
} else {
|
||||
return request()->server('HTTP_X_FORWARDED_FOR') ??
|
||||
|
|
@ -57,16 +50,5 @@ class AppServiceProvider extends ServiceProvider
|
|||
\strtoupper(config('app.locale'))
|
||||
));
|
||||
Carbon::setLocale(config('app.locale'));
|
||||
// * FORCE BOOTSTRAP PAGINATOR.
|
||||
if (!app()->runningInConsole()) {
|
||||
Paginator::useBootstrap();
|
||||
}
|
||||
|
||||
$appInfos = Cache::remember('composer', 360, function () {
|
||||
return json_decode(File::get(\app_path('../composer.json')));
|
||||
});
|
||||
View::share('name', $appInfos->name);
|
||||
View::share('version', $appInfos->version);
|
||||
View::share('license', $appInfos->license);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function boot()
|
||||
{
|
||||
// Register policies.
|
||||
$this->registerPolicies();
|
||||
|
||||
Auth::viaRequest('api-hmac', function (Request $request) {
|
||||
|
|
|
|||
77
app/Providers/TranslationServiceProvider.php
Normal file
77
app/Providers/TranslationServiceProvider.php
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class TranslationServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap the application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
foreach ($this->collectLocalesStrings() as $locale) {
|
||||
// * Suported locales
|
||||
Cache::rememberForever(sprintf('translations.%s', $locale), function () use ($locale) {
|
||||
$translations = [
|
||||
'php' => $this->phpTranslations($locale),
|
||||
'json' => $this->jsonTranslations($locale),
|
||||
];
|
||||
return $translations;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather provided langs checking from files
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function collectLocalesStrings(): Collection
|
||||
{
|
||||
return collect(File::allFiles(resource_path('lang/')))->flatMap(function ($file) {
|
||||
if ($file->getRelativePath()) {
|
||||
return [$file->getRelativePath() => ''];
|
||||
}
|
||||
})->keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather all php translations
|
||||
*
|
||||
* @param string $locale
|
||||
* @return array
|
||||
*/
|
||||
private function phpTranslations(string $locale): array
|
||||
{
|
||||
$path = resource_path("lang/$locale");
|
||||
|
||||
return collect(File::allFiles($path))->flatMap(function ($file) use ($locale) {
|
||||
$translation = $file->getBasename('.php');
|
||||
return [$translation => trans($translation, [], $locale)];
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather json translations
|
||||
*
|
||||
* @param string $locale
|
||||
* @return array
|
||||
*/
|
||||
private function jsonTranslations(string $locale): array
|
||||
{
|
||||
$path = resource_path("lang/$locale.json");
|
||||
|
||||
if (is_string($path) && is_readable($path)) {
|
||||
return json_decode(file_get_contents($path), true) ?? [];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
32
app/Providers/ViewServiceProvider.php
Normal file
32
app/Providers/ViewServiceProvider.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ViewServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
// * Set default view of the paginator.
|
||||
Paginator::defaultView('modules.pagination');
|
||||
|
||||
// * Shares this data with all views.
|
||||
// Get data from composer.json.
|
||||
$appInfos = Cache::remember('composer', 360, function () {
|
||||
return json_decode(File::get(\app_path('../composer.json')));
|
||||
});
|
||||
View::share('name', $appInfos->name);
|
||||
View::share('version', $appInfos->version);
|
||||
View::share('license', $appInfos->license);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 41e2fff7f76107859805cd4a138b80a575f9f72c
|
||||
Subproject commit b15e9bcb59f4680a736e34dabdb059682fc7b8bc
|
||||
|
|
@ -40,9 +40,9 @@ use Exception;
|
|||
*/
|
||||
class WPCrm extends ApiV1
|
||||
{
|
||||
|
||||
/** @var LDCCRM\WPCrm $sessionKey */
|
||||
private static $sessionKey = 'LDC_CRM_USER';
|
||||
|
||||
/** @var DCCRM\WPCrm $sessionDestroyed */
|
||||
private static $sessionDestroyed = false;
|
||||
|
||||
/**
|
||||
|
|
@ -63,8 +63,8 @@ class WPCrm extends ApiV1
|
|||
* Try to login with CRM API
|
||||
* return api response code if an error occurs
|
||||
*
|
||||
* @param string $email The customer email
|
||||
* @param string $password The customer password
|
||||
* @param string $email The customer email.
|
||||
* @param string $password The customer password.
|
||||
*
|
||||
* @return \LDCCRM\WPCrmUser|int
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ use JsonSerializable;
|
|||
*/
|
||||
class WPCrmUser implements JsonSerializable
|
||||
{
|
||||
|
||||
/**
|
||||
* The CRM ID
|
||||
*
|
||||
|
|
@ -61,9 +60,9 @@ class WPCrmUser implements JsonSerializable
|
|||
/**
|
||||
* WPCrmUser construct
|
||||
*
|
||||
* @param int $crm_id The crm id
|
||||
* @param string $hashcode The customer hashcode (UUID)
|
||||
* @param string $email The customer email
|
||||
* @param integer $crm_id The crm id.
|
||||
* @param string $hashcode The customer hashcode (UUID).
|
||||
* @param string $email The customer email.
|
||||
*/
|
||||
public function __construct($crm_id, $hashcode, $email)
|
||||
{
|
||||
|
|
@ -75,9 +74,9 @@ class WPCrmUser implements JsonSerializable
|
|||
/**
|
||||
* Magic getter
|
||||
*
|
||||
* @param string $prop The prop to get
|
||||
* @param string $prop The prop to get.
|
||||
*
|
||||
* @return int|string
|
||||
* @return integer|string
|
||||
*/
|
||||
public function __get($prop)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,24 +1,8 @@
|
|||
{
|
||||
"name": "ldc/ldccrmv2",
|
||||
"type": "project",
|
||||
"version": "3.0.5",
|
||||
"version": "3.0.6",
|
||||
"description": "LDC CRM V2 - revamped",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Romain Bonhomme",
|
||||
"email": "romain.bonhomme@ldc.fr"
|
||||
},
|
||||
{
|
||||
"name": "Vincent Bridier",
|
||||
"email": "vicent.bridier@ldc.fr",
|
||||
"homepage": "https://bridier.me"
|
||||
},
|
||||
{
|
||||
"name": "Jérémy Munsch",
|
||||
"email": "jeremy.munsch@ldc.fr",
|
||||
"homepage": "https://jeremydev.ovh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7",
|
||||
|
|
@ -27,11 +11,11 @@
|
|||
"ext-json": "*",
|
||||
"arondeparon/laravel-request-sanitizer": "^3.1",
|
||||
"axlon/laravel-postal-code-validation": "^3.2",
|
||||
"diglactic/laravel-breadcrumbs": "^8.1",
|
||||
"doctrine/dbal": "^3.0",
|
||||
"fideloper/proxy": "^4.4",
|
||||
"fruitcake/laravel-cors": "^2.0",
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
"kwaadpepper/crud-policies": "^0.3.5",
|
||||
"kwaadpepper/enum": "^2.1",
|
||||
"kwaadpepper/exception-handler": "^0.0.6",
|
||||
"laravel-lang/lang": "~7.0",
|
||||
|
|
@ -105,7 +89,7 @@
|
|||
"runtestmigration": "@php artisan migrate:fresh --env=testing --seed",
|
||||
"runtest": "@php artisan test --no-coverage --testsuite CRM,Client",
|
||||
"runtestWithCoverage": "@php artisan test --testsuite CRM,Client",
|
||||
"runserve": "@php artisan serve --host=127.0.0.1 --port=8888 --env=testing&",
|
||||
"runserve": "@php artisan serve -q --host=127.0.0.1 --port=8888 --env=testing&",
|
||||
"killserve": "kill $(ps -f | grep '[1]27.0.0.1:8888' | awk '{print $2}')",
|
||||
"post-autoload-dump": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||
|
|
|
|||
406
composer.lock
generated
406
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "754ae14d2b3a505a0f58f377d93fc1b9",
|
||||
"content-hash": "ceff538e9083e5fcfd91d183dcd2677b",
|
||||
"packages": [
|
||||
{
|
||||
"name": "arondeparon/laravel-request-sanitizer",
|
||||
|
|
@ -253,6 +253,77 @@
|
|||
],
|
||||
"time": "2021-08-15T20:50:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "diglactic/laravel-breadcrumbs",
|
||||
"version": "v8.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/diglactic/laravel-breadcrumbs.git",
|
||||
"reference": "f72a78eb3e26aea507d7888a65f15e5790864e21"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/diglactic/laravel-breadcrumbs/zipball/f72a78eb3e26aea507d7888a65f15e5790864e21",
|
||||
"reference": "f72a78eb3e26aea507d7888a65f15e5790864e21",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"facade/ignition-contracts": "^1.0",
|
||||
"laravel/framework": "^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0",
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"davejamesmiller/laravel-breadcrumbs": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0",
|
||||
"php-coveralls/php-coveralls": "^2.4",
|
||||
"phpunit/phpunit": "^8.5 || ^9.5",
|
||||
"spatie/phpunit-snapshot-assertions": "^2.2 || ^4.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Diglactic\\Breadcrumbs\\ServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Breadcrumbs": "Diglactic\\Breadcrumbs\\Breadcrumbs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Diglactic\\Breadcrumbs\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sheng Slogar",
|
||||
"email": "sheng@diglactic.com",
|
||||
"role": "Maintainer"
|
||||
},
|
||||
{
|
||||
"name": "Dave James Miller",
|
||||
"email": "dave@davejamesmiller.com",
|
||||
"role": "Original Creator"
|
||||
}
|
||||
],
|
||||
"description": "A simple Laravel-style way to create breadcrumbs.",
|
||||
"homepage": "https://github.com/diglactic/laravel-breadcrumbs",
|
||||
"keywords": [
|
||||
"laravel"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/diglactic/laravel-breadcrumbs/issues",
|
||||
"source": "https://github.com/diglactic/laravel-breadcrumbs/tree/v8.1.1"
|
||||
},
|
||||
"time": "2023-04-17T23:24:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/cache",
|
||||
"version": "2.2.0",
|
||||
|
|
@ -887,125 +958,6 @@
|
|||
],
|
||||
"time": "2020-12-29T14:50:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ezyang/htmlpurifier",
|
||||
"version": "v4.13.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ezyang/htmlpurifier.git",
|
||||
"reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
|
||||
"reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"library/HTMLPurifier.composer.php"
|
||||
],
|
||||
"psr-0": {
|
||||
"HTMLPurifier": "library/"
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/library/HTMLPurifier/Language/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Edward Z. Yang",
|
||||
"email": "admin@htmlpurifier.org",
|
||||
"homepage": "http://ezyang.com"
|
||||
}
|
||||
],
|
||||
"description": "Standards compliant HTML filter written in PHP",
|
||||
"homepage": "http://htmlpurifier.org/",
|
||||
"keywords": [
|
||||
"html"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ezyang/htmlpurifier/issues",
|
||||
"source": "https://github.com/ezyang/htmlpurifier/tree/master"
|
||||
},
|
||||
"time": "2020-06-29T00:56:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "facade/flare-client-php",
|
||||
"version": "1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/facade/flare-client-php.git",
|
||||
"reference": "213fa2c69e120bca4c51ba3e82ed1834ef3f41b8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/facade/flare-client-php/zipball/213fa2c69e120bca4c51ba3e82ed1834ef3f41b8",
|
||||
"reference": "213fa2c69e120bca4c51ba3e82ed1834ef3f41b8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"facade/ignition-contracts": "~1.0",
|
||||
"illuminate/pipeline": "^5.5|^6.0|^7.0|^8.0",
|
||||
"php": "^7.1|^8.0",
|
||||
"symfony/http-foundation": "^3.3|^4.1|^5.0",
|
||||
"symfony/mime": "^3.4|^4.0|^5.1",
|
||||
"symfony/var-dumper": "^3.4|^4.0|^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.14",
|
||||
"phpunit/phpunit": "^7.5",
|
||||
"spatie/phpunit-snapshot-assertions": "^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Facade\\FlareClient\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Send PHP errors to Flare",
|
||||
"homepage": "https://github.com/facade/flare-client-php",
|
||||
"keywords": [
|
||||
"exception",
|
||||
"facade",
|
||||
"flare",
|
||||
"reporting"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/facade/flare-client-php/issues",
|
||||
"source": "https://github.com/facade/flare-client-php/tree/1.10.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/spatie",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-09T11:23:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "facade/ignition-contracts",
|
||||
"version": "1.0.2",
|
||||
|
|
@ -1708,72 +1660,6 @@
|
|||
],
|
||||
"time": "2022-06-20T21:43:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kwaadpepper/crud-policies",
|
||||
"version": "0.3.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Kwaadpepper/crud-policies.git",
|
||||
"reference": "205b8a16c99c362fc78422eeb31c0ba618a3d351"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Kwaadpepper/crud-policies/zipball/205b8a16c99c362fc78422eeb31c0ba618a3d351",
|
||||
"reference": "205b8a16c99c362fc78422eeb31c0ba618a3d351",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/dbal": "^3.1",
|
||||
"facade/flare-client-php": "^1.8",
|
||||
"illuminate/support": "~8",
|
||||
"kwaadpepper/enum": "^2.0",
|
||||
"laravel/framework": "~8",
|
||||
"mews/purifier": "^3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^6.13",
|
||||
"phpunit/phpunit": "~9.0",
|
||||
"slevomat/coding-standard": "^7.0",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Kwaadpepper\\CrudPolicies\\Providers\\CrudPoliciesServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Kwaadpepper\\CrudPolicies\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jérémy Munsch",
|
||||
"email": "github@jeremydev.ovh",
|
||||
"homepage": "https://jeremydev.ovh"
|
||||
}
|
||||
],
|
||||
"description": "Makes CRUD easy, make policies easy and everyone happy",
|
||||
"homepage": "https://github.com/kwaadpepper/crud-policies",
|
||||
"keywords": [
|
||||
"Scafolding",
|
||||
"crud",
|
||||
"laravel",
|
||||
"policies"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Kwaadpepper/crud-policies/issues",
|
||||
"source": "https://github.com/Kwaadpepper/crud-policies/tree/0.3.6"
|
||||
},
|
||||
"time": "2022-05-04T13:19:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kwaadpepper/enum",
|
||||
"version": "2.1.4",
|
||||
|
|
@ -2624,87 +2510,6 @@
|
|||
],
|
||||
"time": "2022-04-17T13:12:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mews/purifier",
|
||||
"version": "3.3.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mewebstudio/Purifier.git",
|
||||
"reference": "164b420c4a80d2d0a89c1023f0aa9b3c0e3d6dc5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mewebstudio/Purifier/zipball/164b420c4a80d2d0a89c1023f0aa9b3c0e3d6dc5",
|
||||
"reference": "164b420c4a80d2d0a89c1023f0aa9b3c0e3d6dc5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ezyang/htmlpurifier": "4.13.*",
|
||||
"illuminate/config": "^5.8|^6.0|^7.0|^8.0|^9.0",
|
||||
"illuminate/filesystem": "^5.8|^6.0|^7.0|^8.0|^9.0",
|
||||
"illuminate/support": "^5.8|^6.0|^7.0|^8.0|^9.0",
|
||||
"php": "^7.2|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"graham-campbell/testbench": "^3.2|^5.5.1",
|
||||
"mockery/mockery": "^1.3.3",
|
||||
"phpunit/phpunit": "^8.0|^9.0"
|
||||
},
|
||||
"suggest": {
|
||||
"laravel/framework": "To test the Laravel bindings",
|
||||
"laravel/lumen-framework": "To test the Lumen bindings"
|
||||
},
|
||||
"type": "package",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Mews\\Purifier\\PurifierServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Purifier": "Mews\\Purifier\\Facades\\Purifier"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Mews\\Purifier\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Muharrem ERİN",
|
||||
"email": "me@mewebstudio.com",
|
||||
"homepage": "https://github.com/mewebstudio",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Laravel 5/6/7 HtmlPurifier Package",
|
||||
"homepage": "https://github.com/mewebstudio/purifier",
|
||||
"keywords": [
|
||||
"Purifier",
|
||||
"htmlpurifier",
|
||||
"laravel5 HtmlPurifier",
|
||||
"laravel5 Purifier",
|
||||
"laravel5 Security",
|
||||
"laravel6 HtmlPurifier",
|
||||
"laravel6 Purifier",
|
||||
"laravel6 Security",
|
||||
"security",
|
||||
"xss"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/mewebstudio/Purifier/issues",
|
||||
"source": "https://github.com/mewebstudio/Purifier/tree/3.3.8"
|
||||
},
|
||||
"time": "2022-07-20T12:14:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "2.8.0",
|
||||
|
|
@ -6792,6 +6597,71 @@
|
|||
],
|
||||
"time": "2022-03-03T08:28:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "facade/flare-client-php",
|
||||
"version": "1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/facade/flare-client-php.git",
|
||||
"reference": "213fa2c69e120bca4c51ba3e82ed1834ef3f41b8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/facade/flare-client-php/zipball/213fa2c69e120bca4c51ba3e82ed1834ef3f41b8",
|
||||
"reference": "213fa2c69e120bca4c51ba3e82ed1834ef3f41b8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"facade/ignition-contracts": "~1.0",
|
||||
"illuminate/pipeline": "^5.5|^6.0|^7.0|^8.0",
|
||||
"php": "^7.1|^8.0",
|
||||
"symfony/http-foundation": "^3.3|^4.1|^5.0",
|
||||
"symfony/mime": "^3.4|^4.0|^5.1",
|
||||
"symfony/var-dumper": "^3.4|^4.0|^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.14",
|
||||
"phpunit/phpunit": "^7.5",
|
||||
"spatie/phpunit-snapshot-assertions": "^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Facade\\FlareClient\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Send PHP errors to Flare",
|
||||
"homepage": "https://github.com/facade/flare-client-php",
|
||||
"keywords": [
|
||||
"exception",
|
||||
"facade",
|
||||
"flare",
|
||||
"reporting"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/facade/flare-client-php/issues",
|
||||
"source": "https://github.com/facade/flare-client-php/tree/1.10.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/spatie",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-08-09T11:23:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "facade/ignition",
|
||||
"version": "2.17.6",
|
||||
|
|
@ -9179,5 +9049,5 @@
|
|||
"platform-overrides": {
|
||||
"php": "7.3.26"
|
||||
},
|
||||
"plugin-api-version": "2.2.0"
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,7 +175,8 @@ return [
|
|||
App\Providers\AuthServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
|
||||
App\Providers\TranslationServiceProvider::class,
|
||||
App\Providers\ViewServiceProvider::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|
|
@ -228,14 +229,5 @@ return [
|
|||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||
'View' => Illuminate\Support\Facades\View::class,
|
||||
'Carbon' => Illuminate\Support\Carbon::class,
|
||||
'ArcadiaMailType' => App\Enums\ArcadiaMailType::class,
|
||||
'ArcadiaOrderType' => App\Enums\ArcadiaOrderType::class,
|
||||
'CustomerExportType' => App\Enums\CustomerExportType::class,
|
||||
'Brand' => App\Models\Brand::class,
|
||||
'Customer' => App\Models\Customer::class,
|
||||
'Question' => App\Models\Question::class,
|
||||
'Answer' => App\Models\Answer::class,
|
||||
'BrandController' => App\Http\Controllers\BrandController::class,
|
||||
],
|
||||
|
||||
];
|
||||
|
|
|
|||
77
config/breadcrumbs.php
Normal file
77
config/breadcrumbs.php
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| View Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Choose a view to display when Breadcrumbs::render() is called.
|
||||
| Built in templates are:
|
||||
|
|
||||
| - 'breadcrumbs::bootstrap5' - Bootstrap 5
|
||||
| - 'breadcrumbs::bootstrap4' - Bootstrap 4
|
||||
| - 'breadcrumbs::bulma' - Bulma
|
||||
| - 'breadcrumbs::foundation6' - Foundation 6
|
||||
| - 'breadcrumbs::json-ld' - JSON-LD Structured Data
|
||||
| - 'breadcrumbs::materialize' - Materialize
|
||||
| - 'breadcrumbs::tailwind' - Tailwind CSS
|
||||
| - 'breadcrumbs::uikit' - UIkit
|
||||
|
|
||||
| Or a custom view, e.g. '_partials/breadcrumbs'.
|
||||
|
|
||||
*/
|
||||
|
||||
'view' => 'breadcrumbs/layout',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Breadcrumbs File(s)
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The file(s) where breadcrumbs are defined. e.g.
|
||||
|
|
||||
| - base_path('routes/breadcrumbs.php')
|
||||
| - glob(base_path('breadcrumbs/*.php'))
|
||||
|
|
||||
*/
|
||||
|
||||
'files' => [
|
||||
base_path('routes/breadcrumbs.php'),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Exceptions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Determine when to throw an exception.
|
||||
|
|
||||
*/
|
||||
|
||||
// * When route-bound breadcrumbs are used but the current route doesn't have a name (UnnamedRouteException)
|
||||
'unnamed-route-exception' => true,
|
||||
|
||||
// * When route-bound breadcrumbs are used and the matching breadcrumb doesn't exist (InvalidBreadcrumbException)
|
||||
'missing-route-bound-breadcrumb-exception' => true,
|
||||
|
||||
// * When a named breadcrumb is used but doesn't exist (InvalidBreadcrumbException)
|
||||
'invalid-named-breadcrumb-exception' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Classes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Subclass the default classes for more advanced customisations.
|
||||
|
|
||||
*/
|
||||
|
||||
// * Manager
|
||||
'manager-class' => Diglactic\Breadcrumbs\Manager::class,
|
||||
|
||||
// * Generator
|
||||
'generator-class' => Diglactic\Breadcrumbs\Generator::class,
|
||||
|
||||
];
|
||||
|
|
@ -31,7 +31,7 @@ class RepairStatsJobs extends Migration
|
|||
$ref->setAccessible(true);
|
||||
$service = $ref->getValue(unserialize($payload->data->command));
|
||||
|
||||
$date = Carbon::parse($job->created_at)->format('Y-m-d');
|
||||
$date = Carbon::parse($job->created_at)->isoFormat('YYYY-MM-DD');
|
||||
|
||||
$serviceStat = ServiceStat::whereDate('date', $date)
|
||||
->where('service_id', $service->id)->where('brand_id', $service->brand->id)
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@ class ParseCountryOnCustomerInfos extends Migration
|
|||
$perPage = 10000;
|
||||
$currentPage = 0;
|
||||
$totalPages = ceil(CustomerInfo::query()->count() / $perPage);
|
||||
dump("items per page $perPage");
|
||||
for ($currentPage; $currentPage <= $totalPages; $currentPage++) {
|
||||
dump("page $currentPage");
|
||||
DB::transaction(function () use ($currentPage, $perPage) {
|
||||
collect(CustomerInfo::query()
|
||||
->simplePaginate($perPage, ['*'], 'page', $currentPage)->items())
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CascadeDeleteQuestionAnswers extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
// * Add cascade delete
|
||||
Schema::table('answers', function (Blueprint $table) {
|
||||
$table->dropForeign(['question_id']);
|
||||
$table->foreign('question_id')->references('id')->on('questions')->cascadeOnDelete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
// * Undo cascade delete (restrict as default)
|
||||
Schema::table('answers', function (Blueprint $table) {
|
||||
$table->dropForeign(['question_id']);
|
||||
$table->foreign('question_id')->references('id')->on('questions');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CascadeDeleteCustomerAnswer extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
// * Add cascade delete
|
||||
Schema::table('customer_answer', function (Blueprint $table) {
|
||||
$table->dropForeign(['answer_id']);
|
||||
$table->foreign('answer_id')->references('id')->on('answers')->cascadeOnDelete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
// * Undo cascade delete (restrict as default)
|
||||
Schema::table('customer_answer', function (Blueprint $table) {
|
||||
$table->dropForeign(['answer_id']);
|
||||
$table->foreign('answer_id')->references('id')->on('answers');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class AddChangeSingleOptinToUseHashcode extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('single_optins', function (Blueprint $table) {
|
||||
$table->uuid('hashcode')->comment('Single optin hashcode')->after('id');
|
||||
});
|
||||
DB::transaction(function () {
|
||||
DB::table('single_optins')->get()->each(function (object $single_optin) {
|
||||
DB::table('single_optins')->where('id', $single_optin->id)->update([
|
||||
'hashcode' => Str::uuid()
|
||||
]);
|
||||
});
|
||||
});
|
||||
Schema::table('single_optins', function (Blueprint $table) {
|
||||
$table->uuid('hashcode')->comment('Single optin hashcode')->after('id')
|
||||
->unique()->change();
|
||||
$table->dropColumn('id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('single_optins', function (Blueprint $table) {
|
||||
$table->id()->after('hashcode');
|
||||
});
|
||||
Schema::table('single_optins', function (Blueprint $table) {
|
||||
$table->dropColumn('hashcode');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class EnhanceCustomerInfosHashcode extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('customer_infos', function (Blueprint $table) {
|
||||
$table->uuid('hashcode')
|
||||
->comment('Customer hashcode relative for a specific brand')->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
// * No need to undo that.
|
||||
}
|
||||
}
|
||||
12841
package-lock.json
generated
12841
package-lock.json
generated
File diff suppressed because it is too large
Load diff
44
package.json
44
package.json
|
|
@ -7,23 +7,59 @@
|
|||
"watch-poll": "mix watch -- --watch-options-poll=1000",
|
||||
"hot": "mix watch --hot",
|
||||
"prod": "npm run production",
|
||||
"production": "mix --production"
|
||||
"production": "mix --production",
|
||||
"eslint": "node ./node_modules/.bin/eslint -c .eslintrc.json ./resources",
|
||||
"eslint-ci": "node ./node_modules/.bin/eslint -c .eslintrc.json ./resources -f junit",
|
||||
"stylelint": "npx stylelint '**/*.scss'",
|
||||
"stylelint-ci": "npx stylelint '**/*.scss' -f json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.4.0",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.4.0",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.4.0",
|
||||
"@rushstack/eslint-patch": "^1.3.1",
|
||||
"@types/bootstrap": "^5.2.6",
|
||||
"@types/vue-select": "^3.16.2",
|
||||
"@types/webpack-env": "^1.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.9",
|
||||
"@typescript-eslint/parser": "^5.59.9",
|
||||
"@vue/eslint-config-typescript": "^11.0.3",
|
||||
"axios": "^0.21",
|
||||
"bootstrap": "^5.3.0",
|
||||
"chart.js": "^3.6.0",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"eslint": "^8.42.0",
|
||||
"eslint-plugin-vue": "^9.14.1",
|
||||
"eslint-webpack-plugin": "^4.0.1",
|
||||
"laravel-mix": "^6.0.6",
|
||||
"laravel-mix-clean": "^0.1.0",
|
||||
"laravel-mix-eslint": "^0.2.0",
|
||||
"laravel-mix-polyfill": "^3.0.0",
|
||||
"laravel-mix-stylelint": "^1.0.0",
|
||||
"moment": "^2.29.1",
|
||||
"postcss": "^8.1.14",
|
||||
"postcss-discard-comments": "^4.0.2",
|
||||
"prettier": "^2.8.8",
|
||||
"print-js": "^1.6.0",
|
||||
"resolve-url-loader": "^3.1.3",
|
||||
"sass": "^1.32.11",
|
||||
"sass-loader": "^11.0.1",
|
||||
"slugify": "^1.6.6",
|
||||
"stylelint": "^14.11.0",
|
||||
"stylelint-config-idiomatic-order": "^8.1.0",
|
||||
"stylelint-config-prettier": "^9.0.5",
|
||||
"stylelint-config-sass-guidelines": "^9.0.1",
|
||||
"stylelint-config-standard-scss": "^6.1.0",
|
||||
"stylelint-webpack-plugin": "^4.1.1",
|
||||
"sweetalert2": "^11.7.12",
|
||||
"swiper": "^6.6.1",
|
||||
"vue": "^2.6.12",
|
||||
"vue-loader": "^15.9.6",
|
||||
"vue-template-compiler": "^2.6.12"
|
||||
"ts-loader": "^9.4.3",
|
||||
"typescript": "^4.8.2",
|
||||
"typescript-eslint": "^0.0.1-alpha.0",
|
||||
"vue": "^3.2.38",
|
||||
"vue-eslint-parser": "^9.1.0",
|
||||
"vue-loader": "^16.8.3",
|
||||
"vue-select": "^4.0.0-beta.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"/js/preload-back.js": "/js/preload-back.js",
|
||||
"/css/preload-back.css": "/css/preload-back.css"
|
||||
}
|
||||
6
resources/js/back.js
vendored
6
resources/js/back.js
vendored
|
|
@ -1,6 +0,0 @@
|
|||
require('./bootstrap');
|
||||
|
||||
require('./pages/customer.delete')
|
||||
require('./pages/service.index')
|
||||
require('./pages/single_optin.index')
|
||||
require('./pages/statsExport')
|
||||
28
resources/js/bootstrap.js
vendored
28
resources/js/bootstrap.js
vendored
|
|
@ -1,28 +0,0 @@
|
|||
window._ = require('lodash');
|
||||
|
||||
/**
|
||||
* We'll load the axios HTTP library which allows us to easily issue requests
|
||||
* to our Laravel back-end. This library automatically handles sending the
|
||||
* CSRF token as a header based on the value of the "XSRF" token cookie.
|
||||
*/
|
||||
|
||||
window.axios = require('axios');
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
/**
|
||||
* Echo exposes an expressive API for subscribing to channels and listening
|
||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
||||
* allows your team to easily build robust real-time web applications.
|
||||
*/
|
||||
|
||||
// import Echo from 'laravel-echo';
|
||||
|
||||
// window.Pusher = require('pusher-js');
|
||||
|
||||
// window.Echo = new Echo({
|
||||
// broadcaster: 'pusher',
|
||||
// key: process.env.MIX_PUSHER_APP_KEY,
|
||||
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
|
||||
// forceTLS: true
|
||||
// });
|
||||
34
resources/js/pages/customer.delete.js
vendored
34
resources/js/pages/customer.delete.js
vendored
|
|
@ -1,34 +0,0 @@
|
|||
let customerDelete = document.getElementById('customerDelete');
|
||||
|
||||
if (customerDelete) {
|
||||
customerDelete.addEventListener('submit', (e) => {
|
||||
let self = e.target
|
||||
e.preventDefault()
|
||||
Swal.fire({
|
||||
title: 'Supprimer ce client pour cette marque ?',
|
||||
text: 'Attention cette action est irréversible, si le client n\'appartient plus à aucune marque il sera complètement retiré des bases',
|
||||
icon: 'warning',
|
||||
confirmButtonText: 'Je comprends le danger et suis conscient de ce que je fait',
|
||||
showCancelButton: true,
|
||||
cancelButtonText: 'Annuler',
|
||||
confirmButtonColor: '#dc3545'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
Swal.fire({
|
||||
title: 'Attention au conséquences',
|
||||
html: 'La supression de ce compte dans la crm n\'entrainera pas ça supression dans MESBR ni dans le front cache DB (pour les sites WPCRM). <br><h3><b>Une fois le compte supprimé je ne pourrai plus récupérer le hashcode nécessaire pour effectuer ces opérations.</b></h3>',
|
||||
icon: 'info',
|
||||
confirmButtonText: 'Je comprends le danger et suis conscient que celà aura des conséquences',
|
||||
showCancelButton: true,
|
||||
cancelButtonText: 'Annuler',
|
||||
confirmButtonColor: '#dc3545'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
self.submit()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
36
resources/js/pages/service.index.js
vendored
36
resources/js/pages/service.index.js
vendored
|
|
@ -1,36 +0,0 @@
|
|||
let genForms = document.getElementsByClassName('genToken');
|
||||
|
||||
if (genForms.length) {
|
||||
for (let form of genForms) {
|
||||
form.addEventListener('submit', (e) => {
|
||||
let self = e.target
|
||||
e.preventDefault()
|
||||
Swal.fire({
|
||||
title: 'Regénérer un token ?',
|
||||
text: 'Attention la regeneration empêchera le service de fonctionner tant que son token n\'aura pas été mis à jour',
|
||||
icon: 'warning',
|
||||
confirmButtonText: 'Je comprends le danger et suis conscient de ce que je fait',
|
||||
showCancelButton: true,
|
||||
cancelButtonText: 'Annuler',
|
||||
confirmButtonColor: '#dc3545'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
Swal.fire({
|
||||
title: 'Vous allez régénérer un token de service en production',
|
||||
html: '<h3><b>Je suis conscient que celà va avoir des implications et qu\'il me faudra mettre à jour le bearer token du service concerné dans son envirronement actuel</b></h3>',
|
||||
icon: 'info',
|
||||
confirmButtonText: 'Oui, feu patate !!',
|
||||
showCancelButton: true,
|
||||
cancelButtonText: 'Annuler',
|
||||
confirmButtonColor: '#dc3545'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
self.submit()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
11
resources/js/pages/single_optin.index.js
vendored
11
resources/js/pages/single_optin.index.js
vendored
|
|
@ -1,11 +0,0 @@
|
|||
let brandSelect = document.getElementById('brandSelect');
|
||||
if (brandSelect) {
|
||||
brandSelect.addEventListener('change', function (e) {
|
||||
if (brandSelect.value !== '0') {
|
||||
const url = new URL(location.href);
|
||||
url.searchParams.set('brand', brandSelect.value);
|
||||
url.searchParams.delete('rst');
|
||||
location.assign(url.search);
|
||||
}
|
||||
});
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue