From 29e5728220bc75d07764d4f7b9ea7cdf99ab6ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 22 Oct 2026 15:57:30 +0200 Subject: [PATCH 1/8] chore: git ignore tests coverage --- .gitignore | 1 + tests/coverage/_css/bootstrap.min.css | 7 - tests/coverage/_css/custom.css | 0 tests/coverage/_css/nv.d3.min.css | 1 - tests/coverage/_css/octicons.css | 5 - tests/coverage/_css/style.css | 158 -- tests/coverage/_icons/file-code.svg | 1 - tests/coverage/_icons/file-directory.svg | 1 - tests/coverage/_js/bootstrap.min.js | 7 - tests/coverage/_js/d3.min.js | 5 - tests/coverage/_js/file.js | 62 - tests/coverage/_js/jquery.min.js | 2 - tests/coverage/_js/nv.d3.min.js | 8 - tests/coverage/_js/popper.min.js | 5 - .../app/Console/Commands/CreateAdmin.php.html | 345 ---- .../DeleteUnconfirmedCustomers.php.html | 187 --- .../Console/Commands/GenerateClient.php.html | 417 ----- .../Commands/LdcWebStatusChecker.php.html | 194 --- .../Console/Commands/MigrateCrmUsers.php.html | 187 --- .../Console/Commands/StartStatJobs.php.html | 152 -- .../app/Console/Commands/TestMail.php.html | 190 --- .../app/Console/Commands/UserCreate.php.html | 496 ------ .../app/Console/Commands/dashboard.html | 301 ---- .../coverage/app/Console/Commands/index.html | 214 --- tests/coverage/app/Console/Kernel.php.html | 210 --- tests/coverage/app/Console/dashboard.html | 300 ---- tests/coverage/app/Console/index.html | 148 -- .../ActivityLogsEventEnum.php.html | 201 --- .../app/Enums/ActivityLogs/dashboard.html | 288 ---- .../app/Enums/ActivityLogs/index.html | 121 -- tests/coverage/app/Enums/ApiError.php.html | 132 -- tests/coverage/app/Enums/ApiStatus.php.html | 101 -- .../app/Enums/ArcadiaMailType.php.html | 101 -- .../app/Enums/ArcadiaOrderType.php.html | 101 -- tests/coverage/app/Enums/Country.php.html | 875 ---------- .../app/Enums/CustomerExportType.php.html | 111 -- .../ItemsPerPaginationEnum.php.html | 105 -- .../app/Enums/Pagination/dashboard.html | 286 ---- .../coverage/app/Enums/Pagination/index.html | 91 - .../coverage/app/Enums/QuestionType.php.html | 102 -- .../Enums/Theme/BootstrapThemeEnum.php.html | 110 -- tests/coverage/app/Enums/Theme/dashboard.html | 286 ---- tests/coverage/app/Enums/Theme/index.html | 91 - .../app/Enums/Users/RoleEnum.php.html | 112 -- tests/coverage/app/Enums/Users/dashboard.html | 286 ---- tests/coverage/app/Enums/Users/index.html | 91 - tests/coverage/app/Enums/dashboard.html | 289 ---- tests/coverage/app/Enums/index.html | 265 --- .../AbortRowImportException.php.html | 115 -- .../Api/V2/ApiErrorException.php.html | 316 ---- .../Exceptions/Api/V2/CrmException.php.html | 184 --- .../app/Exceptions/Api/V2/dashboard.html | 290 ---- .../coverage/app/Exceptions/Api/V2/index.html | 150 -- .../Api/V4/ApiErrorException.php.html | 314 ---- .../Exceptions/Api/V4/CrmException.php.html | 184 --- .../app/Exceptions/Api/V4/dashboard.html | 290 ---- .../coverage/app/Exceptions/Api/V4/index.html | 150 -- .../app/Exceptions/Api/dashboard.html | 292 ---- tests/coverage/app/Exceptions/Api/index.html | 149 -- .../coverage/app/Exceptions/Handler.php.html | 412 ----- tests/coverage/app/Exceptions/dashboard.html | 297 ---- tests/coverage/app/Exceptions/index.html | 161 -- .../Controllers/AnswerController.php.html | 427 ----- .../Api/V2/AnswerController.php.html | 192 --- .../Controllers/Api/V2/ApiController.php.html | 176 -- .../Api/V2/ArcadiaController.php.html | 362 ---- .../Api/V2/CustomerController.php.html | 528 ------ .../Api/V2/OptinController.php.html | 294 ---- .../Api/V2/QuestionController.php.html | 265 --- .../Api/V2/StatsController.php.html | 310 ---- .../Http/Controllers/Api/V2/dashboard.html | 288 ---- .../app/Http/Controllers/Api/V2/index.html | 291 ---- .../Api/V4/AnswerController.php.html | 192 --- .../Controllers/Api/V4/ApiController.php.html | 176 -- .../Api/V4/ArcadiaController.php.html | 362 ---- .../Api/V4/CustomerController.php.html | 528 ------ .../Api/V4/OptinController.php.html | 294 ---- .../Api/V4/QuestionController.php.html | 265 --- .../Api/V4/StatsController.php.html | 310 ---- .../Http/Controllers/Api/V4/dashboard.html | 288 ---- .../app/Http/Controllers/Api/V4/index.html | 291 ---- .../app/Http/Controllers/Api/dashboard.html | 287 ---- .../app/Http/Controllers/Api/index.html | 150 -- .../Bo/ActivityLogsController.php.html | 249 --- .../Controllers/Bo/AnswerController.php.html | 428 ----- .../Bo/Auth/LoginController.php.html | 317 ---- .../Bo/Auth/ResetPasswordController.php.html | 212 --- .../Http/Controllers/Bo/Auth/dashboard.html | 297 ---- .../app/Http/Controllers/Bo/Auth/index.html | 151 -- .../Controllers/Bo/BrandController.php.html | 409 ----- .../Bo/CustomerController.php.html | 551 ------- .../Bo/DashboardController.php.html | 175 -- .../Bo/QuestionController.php.html | 610 ------- .../Controllers/Bo/ServiceController.php.html | 514 ------ .../Bo/SingleOptinController.php.html | 248 --- .../Controllers/Bo/StatsController.php.html | 441 ----- .../Controllers/Bo/UsersController.php.html | 479 ------ .../app/Http/Controllers/Bo/dashboard.html | 399 ----- .../app/Http/Controllers/Bo/index.html | 402 ----- .../Http/Controllers/BrandController.php.html | 408 ----- .../app/Http/Controllers/Controller.php.html | 496 ------ .../Controllers/CustomerController.php.html | 547 ------ .../Http/Controllers/LoginController.php.html | 250 --- .../Controllers/QuestionController.php.html | 606 ------- .../Controllers/ServiceController.php.html | 510 ------ .../SingleOptinController.php.html | 244 --- .../Http/Controllers/StatsController.php.html | 439 ----- .../app/Http/Controllers/dashboard.html | 412 ----- .../coverage/app/Http/Controllers/index.html | 177 -- tests/coverage/app/Http/Kernel.php.html | 174 -- .../Middleware/ApiCheckTimeStamps.php.html | 198 --- .../app/Http/Middleware/ApiResponse.php.html | 220 --- .../app/Http/Middleware/Authenticate.php.html | 194 --- .../Http/Middleware/EncryptCookies.php.html | 118 -- .../Http/Middleware/HtmlSanitizer.php.html | 216 --- .../app/Http/Middleware/JsonOnly.php.html | 183 --- .../PreventRequestsDuringMaintenance.php.html | 118 -- .../RedirectIfAuthenticated.php.html | 198 --- .../Http/Middleware/SecureHeaders.php.html | 259 --- .../app/Http/Middleware/TrimStrings.php.html | 122 -- .../app/Http/Middleware/TrustHosts.php.html | 175 -- .../app/Http/Middleware/TrustProxies.php.html | 131 -- .../Middleware/ValidateSignature.php.html | 118 -- .../Http/Middleware/VerifyCsrfToken.php.html | 120 -- .../app/Http/Middleware/XssSanitizer.php.html | 180 -- .../app/Http/Middleware/dashboard.html | 306 ---- tests/coverage/app/Http/Middleware/index.html | 395 ----- .../Answers/StoreAnswerRequest.php.html | 242 --- .../Answers/UpdateAnswerRequest.php.html | 111 -- .../app/Http/Requests/Answers/dashboard.html | 291 ---- .../app/Http/Requests/Answers/index.html | 135 -- .../Api/V2/AuthenticateRequest.php.html | 161 -- .../Requests/Api/V2/BaseApiRequest.php.html | 183 --- .../Api/V2/GetBrandStatsRequest.php.html | 160 -- .../Api/V2/GetQuestionStatsRequest.php.html | 161 -- .../SendArchadiaDefaultMailRequest.php.html | 253 --- .../V2/SendArchadiaGameMailRequest.php.html | 246 --- ...gleOptinRemoveWithHashcodeRequest.php.html | 138 -- .../Api/V2/SingleOptinRequest.php.html | 139 -- .../Api/V2/StoreCustomerAnswers.php.html | 168 -- .../Api/V2/StoreCustomerRequest.php.html | 239 --- .../Api/V2/UpdateCustomerRequest.php.html | 185 --- .../app/Http/Requests/Api/V2/dashboard.html | 288 ---- .../app/Http/Requests/Api/V2/index.html | 223 --- .../Api/V4/AuthenticateRequest.php.html | 208 --- .../Requests/Api/V4/BaseApiRequest.php.html | 220 --- .../Api/V4/GetBrandStatsRequest.php.html | 197 --- .../Api/V4/GetQuestionStatsRequest.php.html | 197 --- .../SendArchadiaDefaultMailRequest.php.html | 310 ---- .../V4/SendArchadiaGameMailRequest.php.html | 303 ---- ...gleOptinRemoveWithHashcodeRequest.php.html | 175 -- .../Api/V4/SingleOptinRequest.php.html | 176 -- .../Api/V4/StoreCustomerAnswers.php.html | 205 --- .../Api/V4/StoreCustomerRequest.php.html | 296 ---- .../Api/V4/UpdateCustomerRequest.php.html | 222 --- .../app/Http/Requests/Api/V4/dashboard.html | 290 ---- .../app/Http/Requests/Api/V4/index.html | 403 ----- .../app/Http/Requests/Api/dashboard.html | 289 ---- .../coverage/app/Http/Requests/Api/index.html | 135 -- .../Bo/Answers/StoreAnswerRequest.php.html | 243 --- .../Bo/Answers/UpdateAnswerRequest.php.html | 112 -- .../Http/Requests/Bo/Answers/dashboard.html | 292 ---- .../app/Http/Requests/Bo/Answers/index.html | 136 -- .../Bo/Brands/StoreBrandRequest.php.html | 243 --- .../Bo/Brands/UpdateBrandRequest.php.html | 112 -- .../Http/Requests/Bo/Brands/dashboard.html | 292 ---- .../app/Http/Requests/Bo/Brands/index.html | 136 -- .../Http/Requests/Bo/CustomerExport.php.html | 219 --- .../Requests/Bo/GenerateServiceToken.php.html | 206 --- .../Requests/Bo/ManageBrandRequest.php.html | 228 --- .../Requests/Bo/ManageServiceRequest.php.html | 229 --- .../Http/Requests/Bo/QuestionExport.php.html | 208 --- .../Questions/StoreQuestionRequest.php.html | 283 ---- .../Questions/UpdateQuestionRequest.php.html | 112 -- .../Http/Requests/Bo/Questions/dashboard.html | 293 ---- .../app/Http/Requests/Bo/Questions/index.html | 136 -- .../Bo/Services/StoreServiceRequest.php.html | 279 ---- .../Bo/Services/UpdateServiceRequest.php.html | 112 -- .../Http/Requests/Bo/Services/dashboard.html | 293 ---- .../app/Http/Requests/Bo/Services/index.html | 136 -- .../Requests/Bo/StatsByBrandRequest.php.html | 232 --- .../Bo/StatsByQuestionRequest.php.html | 232 --- .../Bo/UpdateChangeOrderRequest.php.html | 242 --- .../Bo/UpdateMiniCrudRequest.php.html | 473 ------ .../Bo/Users/StoreUserRequest.php.html | 297 ---- .../Bo/Users/UpdateUserRequest.php.html | 227 --- .../app/Http/Requests/Bo/Users/dashboard.html | 300 ---- .../app/Http/Requests/Bo/Users/index.html | 151 -- .../app/Http/Requests/Bo/dashboard.html | 364 ---- .../coverage/app/Http/Requests/Bo/index.html | 486 ------ .../Brands/StoreBrandRequest.php.html | 242 --- .../Brands/UpdateBrandRequest.php.html | 111 -- .../app/Http/Requests/Brands/dashboard.html | 291 ---- .../app/Http/Requests/Brands/index.html | 135 -- .../app/Http/Requests/CustomerExport.php.html | 218 --- .../Requests/GenerateServiceToken.php.html | 205 --- .../Http/Requests/ManageBrandRequest.php.html | 227 --- .../Requests/ManageServiceRequest.php.html | 228 --- .../app/Http/Requests/QuestionExport.php.html | 207 --- .../Questions/StoreQuestionRequest.php.html | 248 --- .../Questions/UpdateQuestionRequest.php.html | 111 -- .../Http/Requests/Questions/dashboard.html | 291 ---- .../app/Http/Requests/Questions/index.html | 135 -- .../Services/StoreServiceRequest.php.html | 244 --- .../Services/UpdateServiceRequest.php.html | 111 -- .../app/Http/Requests/Services/dashboard.html | 291 ---- .../app/Http/Requests/Services/index.html | 135 -- .../Requests/StatsByBrandRequest.php.html | 231 --- .../Requests/StatsByQuestionRequest.php.html | 231 --- .../coverage/app/Http/Requests/dashboard.html | 365 ---- tests/coverage/app/Http/Requests/index.html | 149 -- .../Resources/Api/V2/AnswersResource.php.html | 185 --- .../Resources/Api/V2/ApiResponse.php.html | 223 --- .../Api/V2/BrandStatsResource.php.html | 192 --- .../Api/V2/CustomerResource.php.html | 302 ---- .../Api/V2/QuestionStatsResource.php.html | 222 --- .../Api/V2/QuestionsResource.php.html | 237 --- .../app/Http/Resources/Api/V2/dashboard.html | 288 ---- .../app/Http/Resources/Api/V2/index.html | 263 --- .../Resources/Api/V4/AnswersResource.php.html | 185 --- .../Resources/Api/V4/ApiResponse.php.html | 223 --- .../Api/V4/BrandStatsResource.php.html | 192 --- .../Api/V4/CustomerResource.php.html | 302 ---- .../Api/V4/QuestionStatsResource.php.html | 222 --- .../Api/V4/QuestionsResource.php.html | 237 --- .../app/Http/Resources/Api/V4/dashboard.html | 288 ---- .../app/Http/Resources/Api/V4/index.html | 263 --- .../app/Http/Resources/Api/dashboard.html | 287 ---- .../app/Http/Resources/Api/index.html | 150 -- .../Http/Resources/CustomerResource.php.html | 234 --- .../Http/Resources/StatusResource.php.html | 112 -- .../app/Http/Resources/dashboard.html | 289 ---- tests/coverage/app/Http/Resources/index.html | 162 -- .../app/Http/Sanitizers/RemoveSpaces.php.html | 174 -- .../app/Http/Sanitizers/dashboard.html | 286 ---- tests/coverage/app/Http/Sanitizers/index.html | 121 -- tests/coverage/app/Http/dashboard.html | 513 ------ tests/coverage/app/Http/index.html | 245 --- .../app/Jobs/SetServiceStats.php.html | 299 ---- .../coverage/app/Jobs/StartStatJobs.php.html | 184 --- tests/coverage/app/Jobs/StatJob.php.html | 294 ---- .../UpdateCustomerLastConnection.php.html | 236 --- tests/coverage/app/Jobs/dashboard.html | 293 ---- tests/coverage/app/Jobs/index.html | 204 --- tests/coverage/app/Lib/Helper.php.html | 458 ------ .../app/Lib/Helpers/ExceptionsHelper.php.html | 379 ----- .../app/Lib/Helpers/ToolboxHelper.php.html | 1069 ------------ tests/coverage/app/Lib/Helpers/dashboard.html | 321 ---- tests/coverage/app/Lib/Helpers/index.html | 134 -- .../coverage/app/Lib/MigrateOldData.php.html | 401 ----- tests/coverage/app/Lib/dashboard.html | 322 ---- tests/coverage/app/Lib/index.html | 161 -- .../app/Mail/CourrierArcadiaError.php.html | 237 --- .../Mail/ServiceCredentialRenewed.php.html | 231 --- tests/coverage/app/Mail/dashboard.html | 291 ---- tests/coverage/app/Mail/index.html | 148 -- .../coverage/app/Models/ActivityLog.php.html | 331 ---- tests/coverage/app/Models/Answer.php.html | 229 --- tests/coverage/app/Models/Brand.php.html | 522 ------ tests/coverage/app/Models/BrandStat.php.html | 252 --- tests/coverage/app/Models/Customer.php.html | 582 ------- .../app/Models/CustomerAnswer.php.html | 247 --- .../coverage/app/Models/CustomerInfo.php.html | 410 ----- .../app/Models/CustomerLogin.php.html | 327 ---- .../app/Models/CustomerOptInHistory.php.html | 236 --- tests/coverage/app/Models/Question.php.html | 243 --- tests/coverage/app/Models/Service.php.html | 609 ------- .../coverage/app/Models/ServiceStat.php.html | 248 --- .../coverage/app/Models/SingleOptin.php.html | 251 --- tests/coverage/app/Models/User.php.html | 327 ---- tests/coverage/app/Models/dashboard.html | 322 ---- tests/coverage/app/Models/index.html | 484 ------ .../app/Observers/ModelObserver.php.html | 274 --- tests/coverage/app/Observers/dashboard.html | 290 ---- tests/coverage/app/Observers/index.html | 120 -- .../app/Policies/AnswerPolicy.php.html | 300 ---- .../app/Policies/BrandPolicy.php.html | 300 ---- .../app/Policies/CustomerPolicy.php.html | 339 ---- .../app/Policies/QuestionPolicy.php.html | 336 ---- .../Policies/Rules/UserStaticRules.php.html | 186 --- .../app/Policies/Rules/dashboard.html | 286 ---- tests/coverage/app/Policies/Rules/index.html | 91 - .../app/Policies/ServicePolicy.php.html | 300 ---- .../app/Policies/SingleOptinPolicy.php.html | 300 ---- .../coverage/app/Policies/UserPolicy.php.html | 459 ------ tests/coverage/app/Policies/dashboard.html | 339 ---- tests/coverage/app/Policies/index.html | 301 ---- .../app/Providers/AppServiceProvider.php.html | 204 --- .../Providers/AuthServiceProvider.php.html | 238 --- .../Providers/EventServiceProvider.php.html | 185 --- .../Providers/RouteServiceProvider.php.html | 356 ---- .../TranslationServiceProvider.php.html | 298 ---- .../Providers/ViewServiceProvider.php.html | 195 --- tests/coverage/app/Providers/dashboard.html | 301 ---- tests/coverage/app/Providers/index.html | 260 --- .../Controllers/ChangesModelOrder.php.html | 212 --- .../Controllers/UpdateModelPublished.php.html | 181 -- .../app/Traits/Controllers/dashboard.html | 292 ---- .../app/Traits/Controllers/index.html | 149 -- .../app/Traits/Enums/BaseEnum.php.html | 720 -------- .../coverage/app/Traits/Enums/dashboard.html | 301 ---- tests/coverage/app/Traits/Enums/index.html | 121 -- .../app/Traits/Models/ActivityLog.php.html | 178 -- .../Models/IsCachedAsCollection.php.html | 390 ----- .../app/Traits/Models/MiniCrudModel.php.html | 511 ------ .../coverage/app/Traits/Models/dashboard.html | 314 ---- tests/coverage/app/Traits/Models/index.html | 177 -- tests/coverage/app/Traits/dashboard.html | 334 ---- tests/coverage/app/Traits/index.html | 176 -- tests/coverage/app/dashboard.html | 755 --------- tests/coverage/app/index.html | 427 ----- tests/coverage/client/dashboard.html | 438 ----- tests/coverage/client/index.html | 119 -- tests/coverage/client/src/CrmApiV4.php.html | 430 ----- .../client/src/Enums/ApiError.php.html | 133 -- .../client/src/Enums/ApiStatus.php.html | 102 -- .../client/src/Enums/ArcadiaMailType.php.html | 102 -- .../src/Enums/ArcadiaOrderType.php.html | 102 -- .../client/src/Enums/Country.php.html | 792 --------- .../client/src/Enums/HttpMethods.php.html | 104 -- .../client/src/Enums/LogLevel.php.html | 108 -- .../client/src/Enums/QuestionType.php.html | 103 -- .../coverage/client/src/Enums/dashboard.html | 286 ---- tests/coverage/client/src/Enums/index.html | 182 -- .../src/Exceptions/AccessError.php.html | 178 -- .../src/Exceptions/ApiErrorException.php.html | 313 ---- .../src/Exceptions/CrmException.php.html | 182 -- .../SkipValidationException.php.html | 116 -- .../Exceptions/ValidationException.php.html | 181 -- .../WpCrmInvalidJsonUserInfo.php.html | 181 -- .../client/src/Exceptions/dashboard.html | 293 ---- .../coverage/client/src/Exceptions/index.html | 246 --- .../client/src/Models/Answer.php.html | 334 ---- .../src/Models/ArcadiaMailDefault.php.html | 703 -------- .../src/Models/ArcadiaMailGame.php.html | 601 ------- .../client/src/Models/ClientModel.php.html | 747 --------- .../client/src/Models/Customer.php.html | 1099 ------------- .../client/src/Models/Question.php.html | 641 -------- .../client/src/Models/SingleOptin.php.html | 251 --- .../coverage/client/src/Models/Stats.php.html | 264 --- .../coverage/client/src/Models/dashboard.html | 323 ---- tests/coverage/client/src/Models/index.html | 317 ---- .../client/src/Traits/BaseEnum.php.html | 720 -------- .../coverage/client/src/Traits/dashboard.html | 302 ---- tests/coverage/client/src/Traits/index.html | 121 -- .../src/Transport/ApiInterface.php.html | 540 ------ .../client/src/Transport/Request.php.html | 494 ------ .../client/src/Transport/Response.php.html | 430 ----- .../client/src/Transport/dashboard.html | 304 ---- .../coverage/client/src/Transport/index.html | 177 -- tests/coverage/client/src/Utils.php.html | 1462 ----------------- .../client/src/WordPress/WPCrm.php.html | 1330 --------------- .../client/src/WordPress/WPCrmAnswer.php.html | 203 --- .../src/WordPress/WPCrmQuestion.php.html | 288 ---- .../client/src/WordPress/WPCrmUser.php.html | 608 ------- .../client/src/WordPress/dashboard.html | 351 ---- .../coverage/client/src/WordPress/index.html | 205 --- tests/coverage/client/src/dashboard.html | 439 ----- tests/coverage/client/src/index.html | 301 ---- tests/coverage/dashboard.html | 908 ---------- tests/coverage/index.html | 146 -- 361 files changed, 1 insertion(+), 97858 deletions(-) delete mode 100644 tests/coverage/_css/bootstrap.min.css delete mode 100644 tests/coverage/_css/custom.css delete mode 100644 tests/coverage/_css/nv.d3.min.css delete mode 100644 tests/coverage/_css/octicons.css delete mode 100644 tests/coverage/_css/style.css delete mode 100644 tests/coverage/_icons/file-code.svg delete mode 100644 tests/coverage/_icons/file-directory.svg delete mode 100644 tests/coverage/_js/bootstrap.min.js delete mode 100644 tests/coverage/_js/d3.min.js delete mode 100644 tests/coverage/_js/file.js delete mode 100644 tests/coverage/_js/jquery.min.js delete mode 100644 tests/coverage/_js/nv.d3.min.js delete mode 100644 tests/coverage/_js/popper.min.js delete mode 100644 tests/coverage/app/Console/Commands/CreateAdmin.php.html delete mode 100644 tests/coverage/app/Console/Commands/DeleteUnconfirmedCustomers.php.html delete mode 100644 tests/coverage/app/Console/Commands/GenerateClient.php.html delete mode 100644 tests/coverage/app/Console/Commands/LdcWebStatusChecker.php.html delete mode 100644 tests/coverage/app/Console/Commands/MigrateCrmUsers.php.html delete mode 100644 tests/coverage/app/Console/Commands/StartStatJobs.php.html delete mode 100644 tests/coverage/app/Console/Commands/TestMail.php.html delete mode 100644 tests/coverage/app/Console/Commands/UserCreate.php.html delete mode 100644 tests/coverage/app/Console/Commands/dashboard.html delete mode 100644 tests/coverage/app/Console/Commands/index.html delete mode 100644 tests/coverage/app/Console/Kernel.php.html delete mode 100644 tests/coverage/app/Console/dashboard.html delete mode 100644 tests/coverage/app/Console/index.html delete mode 100644 tests/coverage/app/Enums/ActivityLogs/ActivityLogsEventEnum.php.html delete mode 100644 tests/coverage/app/Enums/ActivityLogs/dashboard.html delete mode 100644 tests/coverage/app/Enums/ActivityLogs/index.html delete mode 100644 tests/coverage/app/Enums/ApiError.php.html delete mode 100644 tests/coverage/app/Enums/ApiStatus.php.html delete mode 100644 tests/coverage/app/Enums/ArcadiaMailType.php.html delete mode 100644 tests/coverage/app/Enums/ArcadiaOrderType.php.html delete mode 100644 tests/coverage/app/Enums/Country.php.html delete mode 100644 tests/coverage/app/Enums/CustomerExportType.php.html delete mode 100644 tests/coverage/app/Enums/Pagination/ItemsPerPaginationEnum.php.html delete mode 100644 tests/coverage/app/Enums/Pagination/dashboard.html delete mode 100644 tests/coverage/app/Enums/Pagination/index.html delete mode 100644 tests/coverage/app/Enums/QuestionType.php.html delete mode 100644 tests/coverage/app/Enums/Theme/BootstrapThemeEnum.php.html delete mode 100644 tests/coverage/app/Enums/Theme/dashboard.html delete mode 100644 tests/coverage/app/Enums/Theme/index.html delete mode 100644 tests/coverage/app/Enums/Users/RoleEnum.php.html delete mode 100644 tests/coverage/app/Enums/Users/dashboard.html delete mode 100644 tests/coverage/app/Enums/Users/index.html delete mode 100644 tests/coverage/app/Enums/dashboard.html delete mode 100644 tests/coverage/app/Enums/index.html delete mode 100644 tests/coverage/app/Exceptions/AbortRowImportException.php.html delete mode 100644 tests/coverage/app/Exceptions/Api/V2/ApiErrorException.php.html delete mode 100644 tests/coverage/app/Exceptions/Api/V2/CrmException.php.html delete mode 100644 tests/coverage/app/Exceptions/Api/V2/dashboard.html delete mode 100644 tests/coverage/app/Exceptions/Api/V2/index.html delete mode 100644 tests/coverage/app/Exceptions/Api/V4/ApiErrorException.php.html delete mode 100644 tests/coverage/app/Exceptions/Api/V4/CrmException.php.html delete mode 100644 tests/coverage/app/Exceptions/Api/V4/dashboard.html delete mode 100644 tests/coverage/app/Exceptions/Api/V4/index.html delete mode 100644 tests/coverage/app/Exceptions/Api/dashboard.html delete mode 100644 tests/coverage/app/Exceptions/Api/index.html delete mode 100644 tests/coverage/app/Exceptions/Handler.php.html delete mode 100644 tests/coverage/app/Exceptions/dashboard.html delete mode 100644 tests/coverage/app/Exceptions/index.html delete mode 100644 tests/coverage/app/Http/Controllers/AnswerController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V2/AnswerController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V2/ApiController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V2/ArcadiaController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V2/CustomerController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V2/OptinController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V2/QuestionController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V2/StatsController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V2/dashboard.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V2/index.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V4/AnswerController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V4/ApiController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V4/ArcadiaController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V4/CustomerController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V4/OptinController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V4/QuestionController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V4/StatsController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V4/dashboard.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/V4/index.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/dashboard.html delete mode 100644 tests/coverage/app/Http/Controllers/Api/index.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/ActivityLogsController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/AnswerController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/Auth/LoginController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/Auth/ResetPasswordController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/Auth/dashboard.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/Auth/index.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/BrandController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/CustomerController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/DashboardController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/QuestionController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/ServiceController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/SingleOptinController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/StatsController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/UsersController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/dashboard.html delete mode 100644 tests/coverage/app/Http/Controllers/Bo/index.html delete mode 100644 tests/coverage/app/Http/Controllers/BrandController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/Controller.php.html delete mode 100644 tests/coverage/app/Http/Controllers/CustomerController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/LoginController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/QuestionController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/ServiceController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/SingleOptinController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/StatsController.php.html delete mode 100644 tests/coverage/app/Http/Controllers/dashboard.html delete mode 100644 tests/coverage/app/Http/Controllers/index.html delete mode 100644 tests/coverage/app/Http/Kernel.php.html delete mode 100644 tests/coverage/app/Http/Middleware/ApiCheckTimeStamps.php.html delete mode 100644 tests/coverage/app/Http/Middleware/ApiResponse.php.html delete mode 100644 tests/coverage/app/Http/Middleware/Authenticate.php.html delete mode 100644 tests/coverage/app/Http/Middleware/EncryptCookies.php.html delete mode 100644 tests/coverage/app/Http/Middleware/HtmlSanitizer.php.html delete mode 100644 tests/coverage/app/Http/Middleware/JsonOnly.php.html delete mode 100644 tests/coverage/app/Http/Middleware/PreventRequestsDuringMaintenance.php.html delete mode 100644 tests/coverage/app/Http/Middleware/RedirectIfAuthenticated.php.html delete mode 100644 tests/coverage/app/Http/Middleware/SecureHeaders.php.html delete mode 100644 tests/coverage/app/Http/Middleware/TrimStrings.php.html delete mode 100644 tests/coverage/app/Http/Middleware/TrustHosts.php.html delete mode 100644 tests/coverage/app/Http/Middleware/TrustProxies.php.html delete mode 100644 tests/coverage/app/Http/Middleware/ValidateSignature.php.html delete mode 100644 tests/coverage/app/Http/Middleware/VerifyCsrfToken.php.html delete mode 100644 tests/coverage/app/Http/Middleware/XssSanitizer.php.html delete mode 100644 tests/coverage/app/Http/Middleware/dashboard.html delete mode 100644 tests/coverage/app/Http/Middleware/index.html delete mode 100644 tests/coverage/app/Http/Requests/Answers/StoreAnswerRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Answers/UpdateAnswerRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Answers/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Answers/index.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/AuthenticateRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/BaseApiRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/GetBrandStatsRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/GetQuestionStatsRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/SendArchadiaDefaultMailRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/SendArchadiaGameMailRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/SingleOptinRemoveWithHashcodeRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/SingleOptinRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/StoreCustomerAnswers.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/StoreCustomerRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/UpdateCustomerRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V2/index.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/AuthenticateRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/BaseApiRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/GetBrandStatsRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/GetQuestionStatsRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/SendArchadiaDefaultMailRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/SendArchadiaGameMailRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/SingleOptinRemoveWithHashcodeRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/SingleOptinRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/StoreCustomerAnswers.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/StoreCustomerRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/UpdateCustomerRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Api/V4/index.html delete mode 100644 tests/coverage/app/Http/Requests/Api/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Api/index.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Answers/StoreAnswerRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Answers/UpdateAnswerRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Answers/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Answers/index.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Brands/StoreBrandRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Brands/UpdateBrandRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Brands/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Brands/index.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/CustomerExport.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/GenerateServiceToken.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/ManageBrandRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/ManageServiceRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/QuestionExport.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Questions/StoreQuestionRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Questions/UpdateQuestionRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Questions/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Questions/index.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Services/StoreServiceRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Services/UpdateServiceRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Services/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Services/index.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/StatsByBrandRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/StatsByQuestionRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/UpdateChangeOrderRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/UpdateMiniCrudRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Users/StoreUserRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Users/UpdateUserRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Users/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/Users/index.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Bo/index.html delete mode 100644 tests/coverage/app/Http/Requests/Brands/StoreBrandRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Brands/UpdateBrandRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Brands/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Brands/index.html delete mode 100644 tests/coverage/app/Http/Requests/CustomerExport.php.html delete mode 100644 tests/coverage/app/Http/Requests/GenerateServiceToken.php.html delete mode 100644 tests/coverage/app/Http/Requests/ManageBrandRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/ManageServiceRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/QuestionExport.php.html delete mode 100644 tests/coverage/app/Http/Requests/Questions/StoreQuestionRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Questions/UpdateQuestionRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Questions/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Questions/index.html delete mode 100644 tests/coverage/app/Http/Requests/Services/StoreServiceRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Services/UpdateServiceRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/Services/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/Services/index.html delete mode 100644 tests/coverage/app/Http/Requests/StatsByBrandRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/StatsByQuestionRequest.php.html delete mode 100644 tests/coverage/app/Http/Requests/dashboard.html delete mode 100644 tests/coverage/app/Http/Requests/index.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V2/AnswersResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V2/ApiResponse.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V2/BrandStatsResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V2/CustomerResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V2/QuestionStatsResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V2/QuestionsResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V2/dashboard.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V2/index.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V4/AnswersResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V4/ApiResponse.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V4/BrandStatsResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V4/CustomerResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V4/QuestionStatsResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V4/QuestionsResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V4/dashboard.html delete mode 100644 tests/coverage/app/Http/Resources/Api/V4/index.html delete mode 100644 tests/coverage/app/Http/Resources/Api/dashboard.html delete mode 100644 tests/coverage/app/Http/Resources/Api/index.html delete mode 100644 tests/coverage/app/Http/Resources/CustomerResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/StatusResource.php.html delete mode 100644 tests/coverage/app/Http/Resources/dashboard.html delete mode 100644 tests/coverage/app/Http/Resources/index.html delete mode 100644 tests/coverage/app/Http/Sanitizers/RemoveSpaces.php.html delete mode 100644 tests/coverage/app/Http/Sanitizers/dashboard.html delete mode 100644 tests/coverage/app/Http/Sanitizers/index.html delete mode 100644 tests/coverage/app/Http/dashboard.html delete mode 100644 tests/coverage/app/Http/index.html delete mode 100644 tests/coverage/app/Jobs/SetServiceStats.php.html delete mode 100644 tests/coverage/app/Jobs/StartStatJobs.php.html delete mode 100644 tests/coverage/app/Jobs/StatJob.php.html delete mode 100644 tests/coverage/app/Jobs/UpdateCustomerLastConnection.php.html delete mode 100644 tests/coverage/app/Jobs/dashboard.html delete mode 100644 tests/coverage/app/Jobs/index.html delete mode 100644 tests/coverage/app/Lib/Helper.php.html delete mode 100644 tests/coverage/app/Lib/Helpers/ExceptionsHelper.php.html delete mode 100644 tests/coverage/app/Lib/Helpers/ToolboxHelper.php.html delete mode 100644 tests/coverage/app/Lib/Helpers/dashboard.html delete mode 100644 tests/coverage/app/Lib/Helpers/index.html delete mode 100644 tests/coverage/app/Lib/MigrateOldData.php.html delete mode 100644 tests/coverage/app/Lib/dashboard.html delete mode 100644 tests/coverage/app/Lib/index.html delete mode 100644 tests/coverage/app/Mail/CourrierArcadiaError.php.html delete mode 100644 tests/coverage/app/Mail/ServiceCredentialRenewed.php.html delete mode 100644 tests/coverage/app/Mail/dashboard.html delete mode 100644 tests/coverage/app/Mail/index.html delete mode 100644 tests/coverage/app/Models/ActivityLog.php.html delete mode 100644 tests/coverage/app/Models/Answer.php.html delete mode 100644 tests/coverage/app/Models/Brand.php.html delete mode 100644 tests/coverage/app/Models/BrandStat.php.html delete mode 100644 tests/coverage/app/Models/Customer.php.html delete mode 100644 tests/coverage/app/Models/CustomerAnswer.php.html delete mode 100644 tests/coverage/app/Models/CustomerInfo.php.html delete mode 100644 tests/coverage/app/Models/CustomerLogin.php.html delete mode 100644 tests/coverage/app/Models/CustomerOptInHistory.php.html delete mode 100644 tests/coverage/app/Models/Question.php.html delete mode 100644 tests/coverage/app/Models/Service.php.html delete mode 100644 tests/coverage/app/Models/ServiceStat.php.html delete mode 100644 tests/coverage/app/Models/SingleOptin.php.html delete mode 100644 tests/coverage/app/Models/User.php.html delete mode 100644 tests/coverage/app/Models/dashboard.html delete mode 100644 tests/coverage/app/Models/index.html delete mode 100644 tests/coverage/app/Observers/ModelObserver.php.html delete mode 100644 tests/coverage/app/Observers/dashboard.html delete mode 100644 tests/coverage/app/Observers/index.html delete mode 100644 tests/coverage/app/Policies/AnswerPolicy.php.html delete mode 100644 tests/coverage/app/Policies/BrandPolicy.php.html delete mode 100644 tests/coverage/app/Policies/CustomerPolicy.php.html delete mode 100644 tests/coverage/app/Policies/QuestionPolicy.php.html delete mode 100644 tests/coverage/app/Policies/Rules/UserStaticRules.php.html delete mode 100644 tests/coverage/app/Policies/Rules/dashboard.html delete mode 100644 tests/coverage/app/Policies/Rules/index.html delete mode 100644 tests/coverage/app/Policies/ServicePolicy.php.html delete mode 100644 tests/coverage/app/Policies/SingleOptinPolicy.php.html delete mode 100644 tests/coverage/app/Policies/UserPolicy.php.html delete mode 100644 tests/coverage/app/Policies/dashboard.html delete mode 100644 tests/coverage/app/Policies/index.html delete mode 100644 tests/coverage/app/Providers/AppServiceProvider.php.html delete mode 100644 tests/coverage/app/Providers/AuthServiceProvider.php.html delete mode 100644 tests/coverage/app/Providers/EventServiceProvider.php.html delete mode 100644 tests/coverage/app/Providers/RouteServiceProvider.php.html delete mode 100644 tests/coverage/app/Providers/TranslationServiceProvider.php.html delete mode 100644 tests/coverage/app/Providers/ViewServiceProvider.php.html delete mode 100644 tests/coverage/app/Providers/dashboard.html delete mode 100644 tests/coverage/app/Providers/index.html delete mode 100644 tests/coverage/app/Traits/Controllers/ChangesModelOrder.php.html delete mode 100644 tests/coverage/app/Traits/Controllers/UpdateModelPublished.php.html delete mode 100644 tests/coverage/app/Traits/Controllers/dashboard.html delete mode 100644 tests/coverage/app/Traits/Controllers/index.html delete mode 100644 tests/coverage/app/Traits/Enums/BaseEnum.php.html delete mode 100644 tests/coverage/app/Traits/Enums/dashboard.html delete mode 100644 tests/coverage/app/Traits/Enums/index.html delete mode 100644 tests/coverage/app/Traits/Models/ActivityLog.php.html delete mode 100644 tests/coverage/app/Traits/Models/IsCachedAsCollection.php.html delete mode 100644 tests/coverage/app/Traits/Models/MiniCrudModel.php.html delete mode 100644 tests/coverage/app/Traits/Models/dashboard.html delete mode 100644 tests/coverage/app/Traits/Models/index.html delete mode 100644 tests/coverage/app/Traits/dashboard.html delete mode 100644 tests/coverage/app/Traits/index.html delete mode 100644 tests/coverage/app/dashboard.html delete mode 100644 tests/coverage/app/index.html delete mode 100644 tests/coverage/client/dashboard.html delete mode 100644 tests/coverage/client/index.html delete mode 100644 tests/coverage/client/src/CrmApiV4.php.html delete mode 100644 tests/coverage/client/src/Enums/ApiError.php.html delete mode 100644 tests/coverage/client/src/Enums/ApiStatus.php.html delete mode 100644 tests/coverage/client/src/Enums/ArcadiaMailType.php.html delete mode 100644 tests/coverage/client/src/Enums/ArcadiaOrderType.php.html delete mode 100644 tests/coverage/client/src/Enums/Country.php.html delete mode 100644 tests/coverage/client/src/Enums/HttpMethods.php.html delete mode 100644 tests/coverage/client/src/Enums/LogLevel.php.html delete mode 100644 tests/coverage/client/src/Enums/QuestionType.php.html delete mode 100644 tests/coverage/client/src/Enums/dashboard.html delete mode 100644 tests/coverage/client/src/Enums/index.html delete mode 100644 tests/coverage/client/src/Exceptions/AccessError.php.html delete mode 100644 tests/coverage/client/src/Exceptions/ApiErrorException.php.html delete mode 100644 tests/coverage/client/src/Exceptions/CrmException.php.html delete mode 100644 tests/coverage/client/src/Exceptions/SkipValidationException.php.html delete mode 100644 tests/coverage/client/src/Exceptions/ValidationException.php.html delete mode 100644 tests/coverage/client/src/Exceptions/WpCrmInvalidJsonUserInfo.php.html delete mode 100644 tests/coverage/client/src/Exceptions/dashboard.html delete mode 100644 tests/coverage/client/src/Exceptions/index.html delete mode 100644 tests/coverage/client/src/Models/Answer.php.html delete mode 100644 tests/coverage/client/src/Models/ArcadiaMailDefault.php.html delete mode 100644 tests/coverage/client/src/Models/ArcadiaMailGame.php.html delete mode 100644 tests/coverage/client/src/Models/ClientModel.php.html delete mode 100644 tests/coverage/client/src/Models/Customer.php.html delete mode 100644 tests/coverage/client/src/Models/Question.php.html delete mode 100644 tests/coverage/client/src/Models/SingleOptin.php.html delete mode 100644 tests/coverage/client/src/Models/Stats.php.html delete mode 100644 tests/coverage/client/src/Models/dashboard.html delete mode 100644 tests/coverage/client/src/Models/index.html delete mode 100644 tests/coverage/client/src/Traits/BaseEnum.php.html delete mode 100644 tests/coverage/client/src/Traits/dashboard.html delete mode 100644 tests/coverage/client/src/Traits/index.html delete mode 100644 tests/coverage/client/src/Transport/ApiInterface.php.html delete mode 100644 tests/coverage/client/src/Transport/Request.php.html delete mode 100644 tests/coverage/client/src/Transport/Response.php.html delete mode 100644 tests/coverage/client/src/Transport/dashboard.html delete mode 100644 tests/coverage/client/src/Transport/index.html delete mode 100644 tests/coverage/client/src/Utils.php.html delete mode 100644 tests/coverage/client/src/WordPress/WPCrm.php.html delete mode 100644 tests/coverage/client/src/WordPress/WPCrmAnswer.php.html delete mode 100644 tests/coverage/client/src/WordPress/WPCrmQuestion.php.html delete mode 100644 tests/coverage/client/src/WordPress/WPCrmUser.php.html delete mode 100644 tests/coverage/client/src/WordPress/dashboard.html delete mode 100644 tests/coverage/client/src/WordPress/index.html delete mode 100644 tests/coverage/client/src/dashboard.html delete mode 100644 tests/coverage/client/src/index.html delete mode 100644 tests/coverage/dashboard.html delete mode 100644 tests/coverage/index.html diff --git a/.gitignore b/.gitignore index 5a0e861..affaf15 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ yarn-error.log .zshrc .npm/ .composer/ +tests/coverage diff --git a/tests/coverage/_css/bootstrap.min.css b/tests/coverage/_css/bootstrap.min.css deleted file mode 100644 index 83a71b1..0000000 --- a/tests/coverage/_css/bootstrap.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v4.6.2 (https://getbootstrap.com/) - * Copyright 2011-2022 The Bootstrap Authors - * Copyright 2011-2022 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:.875em;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#28a745}.valid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem)!important;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{padding-right:3rem!important;background-position:right 1.5rem center}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem)!important;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem)!important;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{padding-right:3rem!important;background-position:right 1.5rem center}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem)!important;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label::after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label::after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;z-index:1;display:block;min-height:1.5rem;padding-left:1.5rem;-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:1px solid #adb5bd}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;overflow:hidden;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;overflow:hidden;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{background:0 0;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item,.nav-fill>.nav-link{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:50%/100% 100% no-repeat}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;z-index:2;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:1s linear infinite progress-bar-stripes;animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{-ms-flex-preferred-size:350px;flex-basis:350px;max-width:350px;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:50%/100% 100% no-repeat}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;border:.25em solid currentcolor;border-right-color:transparent;border-radius:50%;-webkit-animation:.75s linear infinite spinner-border;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;background-color:currentcolor;border-radius:50%;opacity:0;-webkit-animation:.75s linear infinite spinner-grow;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}} -/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/tests/coverage/_css/custom.css b/tests/coverage/_css/custom.css deleted file mode 100644 index e69de29..0000000 diff --git a/tests/coverage/_css/nv.d3.min.css b/tests/coverage/_css/nv.d3.min.css deleted file mode 100644 index 7a6f7fe..0000000 --- a/tests/coverage/_css/nv.d3.min.css +++ /dev/null @@ -1 +0,0 @@ -.nvd3 .nv-axis{pointer-events:none;opacity:1}.nvd3 .nv-axis path{fill:none;stroke:#000;stroke-opacity:.75;shape-rendering:crispEdges}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{fill:none;stroke:#e5e5e5;shape-rendering:crispEdges}.nvd3 .nv-axis .zero line,.nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-axis.nv-disabled{opacity:0}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:rgba(0,0,0,0)}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect,.nvd3 .nv-discretebar .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:rgba(0,0,0,0)}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover{fill-opacity:1}.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nvd3 .nv-legend .nv-disabled rect{}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-scatter .nv-groups .nv-point.hover,.nvd3 .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none;display:block;width:100%;height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nvd3 text{font:400 12px Arial}.nvd3 .title{font:700 14px Arial}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125;shape-rendering:crispEdges}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4;shape-rendering:crispEdges}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie path{stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{stroke:#fff;stroke-width:1px;stroke-opacity:1}.nvd3.nv-pie .hover path{fill-opacity:.7}.nvd3.nv-pie .nv-label{pointer-events:none}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nv-noninteractive{pointer-events:none}.nv-distx,.nv-disty{pointer-events:none}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;background-color:rgba(255,255,255,1);color:rgba(0,0,0,1);padding:1px;border:1px solid rgba(0,0,0,.2);z-index:10000;display:block;font-family:Arial;font-size:13px;text-align:left;pointer-events:none;white-space:nowrap;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.nvtooltip{background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;-moz-transition:opacity 50ms linear;-webkit-transition:opacity 50ms linear;transition-delay:200ms;-moz-transition-delay:200ms;-webkit-transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{margin:0;padding:4px 14px;line-height:18px;font-weight:400;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);text-align:center;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.nvtooltip p{margin:0;padding:5px 14px;text-align:center}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key{font-weight:400}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{width:8px;height:8px;vertical-align:middle}.nvtooltip table td.legend-color-guide div{width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;display:none}.nvd3 .nv-interactiveGuideLine{pointer-events:none}.nvd3 line.nv-guideline{stroke:#ccc} \ No newline at end of file diff --git a/tests/coverage/_css/octicons.css b/tests/coverage/_css/octicons.css deleted file mode 100644 index 31d9786..0000000 --- a/tests/coverage/_css/octicons.css +++ /dev/null @@ -1,5 +0,0 @@ -.octicon { - display: inline-block; - vertical-align: text-top; - fill: currentColor; -} diff --git a/tests/coverage/_css/style.css b/tests/coverage/_css/style.css deleted file mode 100644 index 4d2766f..0000000 --- a/tests/coverage/_css/style.css +++ /dev/null @@ -1,158 +0,0 @@ -body { - font-family: sans-serif; - font-size: 1em; - font-kerning: normal; - font-variant-ligatures: common-ligatures; - text-rendering: optimizeLegibility; - padding-top: 10px; -} - -.popover { - max-width: none; -} - -.octicon { - margin-right:.25em; - vertical-align: baseline; - width: 0.75em; -} - -.table-bordered>thead>tr>td { - border-bottom-width: 1px; -} - -.table tbody>tr>td, .table thead>tr>td { - padding-top: 3px; - padding-bottom: 3px; -} - -.table-condensed tbody>tr>td { - padding-top: 0; - padding-bottom: 0; -} - -.table .progress { - margin-bottom: inherit; -} - -.table-borderless th, .table-borderless td { - border: 0 !important; -} - -.table tbody tr.covered-by-large-tests, li.covered-by-large-tests, tr.success, td.success, li.success, span.success { - background-color: #dff0d8; -} - -.table tbody tr.covered-by-medium-tests, li.covered-by-medium-tests { - background-color: #c3e3b5; -} - -.table tbody tr.covered-by-small-tests, li.covered-by-small-tests { - background-color: #99cb84; -} - -.table tbody tr.warning, .table tbody td.warning, li.warning, span.warning { - background-color: #fcf8e3; -} - -.table tbody tr.danger, .table tbody td.danger, li.danger, span.danger { - background-color: #f2dede; -} - -.table tbody td.info { - background-color: #d9edf7; -} - -td.big { - vertical-align: middle; - width: 117px; -} - -td.small { -} - -td.codeLine { - font-family: "Source Code Pro", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - white-space: pre-wrap; -} - -td span.comment { - color: #888a85; -} - -td span.default { - color: #2e3436; -} - -td span.html { - color: #888a85; -} - -td span.keyword { - color: #2e3436; - font-weight: bold; -} - -pre span.string { - color: #2e3436; -} - -span.success, span.warning, span.danger { - margin-right: 2px; - padding-left: 10px; - padding-right: 10px; - text-align: center; -} - -#toplink { - position: fixed; - left: 5px; - bottom: 5px; - outline: 0; -} - -svg text { - font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; - color: #666; - fill: #666; -} - -.scrollbox { - height:245px; - overflow-x:hidden; - overflow-y:scroll; -} - -table + .structure-heading { - border-top: 1px solid lightgrey; - padding-top: 0.5em; -} - -.legend { - font-weight: bold; - margin-right: 2px; - padding-left: 10px; - padding-right: 10px; - text-align: center; -} - -.covered-by-small-tests { - background-color: #99cb84; -} - -.covered-by-medium-tests { - background-color: #c3e3b5; -} - -.covered-by-large-tests { - background-color: #dff0d8; -} - -.not-covered { - background-color: #f2dede; -} - -.not-coverable { - background-color: #fcf8e3; -} diff --git a/tests/coverage/_icons/file-code.svg b/tests/coverage/_icons/file-code.svg deleted file mode 100644 index 5b4b199..0000000 --- a/tests/coverage/_icons/file-code.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/tests/coverage/_icons/file-directory.svg b/tests/coverage/_icons/file-directory.svg deleted file mode 100644 index 4bf1f1c..0000000 --- a/tests/coverage/_icons/file-directory.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/tests/coverage/_js/bootstrap.min.js b/tests/coverage/_js/bootstrap.min.js deleted file mode 100644 index 97206dc..0000000 --- a/tests/coverage/_js/bootstrap.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v4.6.2 (https://getbootstrap.com/) - * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap={},t.jQuery,t.Popper)}(this,(function(t,e,n){"use strict";function i(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var o=i(e),a=i(n);function s(t,e){for(var n=0;n=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};d.jQueryDetection(),o.default.fn.emulateTransitionEnd=function(t){var e=this,n=!1;return o.default(this).one(d.TRANSITION_END,(function(){n=!0})),setTimeout((function(){n||d.triggerTransitionEnd(e)}),t),this},o.default.event.special[d.TRANSITION_END]={bindType:f,delegateType:f,handle:function(t){if(o.default(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var c="bs.alert",h=o.default.fn.alert,g=function(){function t(t){this._element=t}var e=t.prototype;return e.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},e.dispose=function(){o.default.removeData(this._element,c),this._element=null},e._getRootElement=function(t){var e=d.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=o.default(t).closest(".alert")[0]),n},e._triggerCloseEvent=function(t){var e=o.default.Event("close.bs.alert");return o.default(t).trigger(e),e},e._removeElement=function(t){var e=this;if(o.default(t).removeClass("show"),o.default(t).hasClass("fade")){var n=d.getTransitionDurationFromElement(t);o.default(t).one(d.TRANSITION_END,(function(n){return e._destroyElement(t,n)})).emulateTransitionEnd(n)}else this._destroyElement(t)},e._destroyElement=function(t){o.default(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(c);i||(i=new t(this),n.data(c,i)),"close"===e&&i[e](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();o.default(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',g._handleDismiss(new g)),o.default.fn.alert=g._jQueryInterface,o.default.fn.alert.Constructor=g,o.default.fn.alert.noConflict=function(){return o.default.fn.alert=h,g._jQueryInterface};var m="bs.button",p=o.default.fn.button,_="active",v='[data-toggle^="button"]',y='input:not([type="hidden"])',b=".btn",E=function(){function t(t){this._element=t,this.shouldAvoidTriggerChange=!1}var e=t.prototype;return e.toggle=function(){var t=!0,e=!0,n=o.default(this._element).closest('[data-toggle="buttons"]')[0];if(n){var i=this._element.querySelector(y);if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains(_))t=!1;else{var a=n.querySelector(".active");a&&o.default(a).removeClass(_)}t&&("checkbox"!==i.type&&"radio"!==i.type||(i.checked=!this._element.classList.contains(_)),this.shouldAvoidTriggerChange||o.default(i).trigger("change")),i.focus(),e=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(_)),t&&o.default(this._element).toggleClass(_))},e.dispose=function(){o.default.removeData(this._element,m),this._element=null},t._jQueryInterface=function(e,n){return this.each((function(){var i=o.default(this),a=i.data(m);a||(a=new t(this),i.data(m,a)),a.shouldAvoidTriggerChange=n,"toggle"===e&&a[e]()}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();o.default(document).on("click.bs.button.data-api",v,(function(t){var e=t.target,n=e;if(o.default(e).hasClass("btn")||(e=o.default(e).closest(b)[0]),!e||e.hasAttribute("disabled")||e.classList.contains("disabled"))t.preventDefault();else{var i=e.querySelector(y);if(i&&(i.hasAttribute("disabled")||i.classList.contains("disabled")))return void t.preventDefault();"INPUT"!==n.tagName&&"LABEL"===e.tagName||E._jQueryInterface.call(o.default(e),"toggle","INPUT"===n.tagName)}})).on("focus.bs.button.data-api blur.bs.button.data-api",v,(function(t){var e=o.default(t.target).closest(b)[0];o.default(e).toggleClass("focus",/^focus(in)?$/.test(t.type))})),o.default(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var e=t.prototype;return e.next=function(){this._isSliding||this._slide(N)},e.nextWhenVisible=function(){var t=o.default(this._element);!document.hidden&&t.is(":visible")&&"hidden"!==t.css("visibility")&&this.next()},e.prev=function(){this._isSliding||this._slide(D)},e.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(d.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},e.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},e.to=function(t){var e=this;this._activeElement=this._element.querySelector(I);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)o.default(this._element).one(A,(function(){return e.to(t)}));else{if(n===t)return this.pause(),void this.cycle();var i=t>n?N:D;this._slide(i,this._items[t])}},e.dispose=function(){o.default(this._element).off(".bs.carousel"),o.default.removeData(this._element,w),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},e._getConfig=function(t){return t=r({},k,t),d.typeCheckConfig(T,t,O),t},e._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},e._addEventListeners=function(){var t=this;this._config.keyboard&&o.default(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&o.default(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},e._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var e=function(e){t._pointerEvent&&j[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},n=function(e){t._pointerEvent&&j[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};o.default(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(o.default(this._element).on("pointerdown.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("pointerup.bs.carousel",(function(t){return n(t)})),this._element.classList.add("pointer-event")):(o.default(this._element).on("touchstart.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("touchmove.bs.carousel",(function(e){return function(e){t.touchDeltaX=e.originalEvent.touches&&e.originalEvent.touches.length>1?0:e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),o.default(this._element).on("touchend.bs.carousel",(function(t){return n(t)})))}},e._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},e._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},e._getItemByDirection=function(t,e){var n=t===N,i=t===D,o=this._getItemIndex(e),a=this._items.length-1;if((i&&0===o||n&&o===a)&&!this._config.wrap)return e;var s=(o+(t===D?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},e._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(this._element.querySelector(I)),a=o.default.Event("slide.bs.carousel",{relatedTarget:t,direction:e,from:i,to:n});return o.default(this._element).trigger(a),a},e._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));o.default(e).removeClass(S);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&o.default(n).addClass(S)}},e._updateInterval=function(){var t=this._activeElement||this._element.querySelector(I);if(t){var e=parseInt(t.getAttribute("data-interval"),10);e?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=e):this._config.interval=this._config.defaultInterval||this._config.interval}},e._slide=function(t,e){var n,i,a,s=this,l=this._element.querySelector(I),r=this._getItemIndex(l),u=e||l&&this._getItemByDirection(t,l),f=this._getItemIndex(u),c=Boolean(this._interval);if(t===N?(n="carousel-item-left",i="carousel-item-next",a="left"):(n="carousel-item-right",i="carousel-item-prev",a="right"),u&&o.default(u).hasClass(S))this._isSliding=!1;else if(!this._triggerSlideEvent(u,a).isDefaultPrevented()&&l&&u){this._isSliding=!0,c&&this.pause(),this._setActiveIndicatorElement(u),this._activeElement=u;var h=o.default.Event(A,{relatedTarget:u,direction:a,from:r,to:f});if(o.default(this._element).hasClass("slide")){o.default(u).addClass(i),d.reflow(u),o.default(l).addClass(n),o.default(u).addClass(n);var g=d.getTransitionDurationFromElement(l);o.default(l).one(d.TRANSITION_END,(function(){o.default(u).removeClass(n+" "+i).addClass(S),o.default(l).removeClass("active "+i+" "+n),s._isSliding=!1,setTimeout((function(){return o.default(s._element).trigger(h)}),0)})).emulateTransitionEnd(g)}else o.default(l).removeClass(S),o.default(u).addClass(S),this._isSliding=!1,o.default(this._element).trigger(h);c&&this.cycle()}},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data(w),i=r({},k,o.default(this).data());"object"==typeof e&&(i=r({},i,e));var a="string"==typeof e?e:i.slide;if(n||(n=new t(this,i),o.default(this).data(w,n)),"number"==typeof e)n.to(e);else if("string"==typeof a){if("undefined"==typeof n[a])throw new TypeError('No method named "'+a+'"');n[a]()}else i.interval&&i.ride&&(n.pause(),n.cycle())}))},t._dataApiClickHandler=function(e){var n=d.getSelectorFromElement(this);if(n){var i=o.default(n)[0];if(i&&o.default(i).hasClass("carousel")){var a=r({},o.default(i).data(),o.default(this).data()),s=this.getAttribute("data-slide-to");s&&(a.interval=!1),t._jQueryInterface.call(o.default(i),a),s&&o.default(i).data(w).to(s),e.preventDefault()}}},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return k}}]),t}();o.default(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",P._dataApiClickHandler),o.default(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),e=0,n=t.length;e0&&(this._selector=s,this._triggerArray.push(a))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var e=t.prototype;return e.toggle=function(){o.default(this._element).hasClass(q)?this.hide():this.show()},e.show=function(){var e,n,i=this;if(!(this._isTransitioning||o.default(this._element).hasClass(q)||(this._parent&&0===(e=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof i._config.parent?t.getAttribute("data-parent")===i._config.parent:t.classList.contains(F)}))).length&&(e=null),e&&(n=o.default(e).not(this._selector).data(R))&&n._isTransitioning))){var a=o.default.Event("show.bs.collapse");if(o.default(this._element).trigger(a),!a.isDefaultPrevented()){e&&(t._jQueryInterface.call(o.default(e).not(this._selector),"hide"),n||o.default(e).data(R,null));var s=this._getDimension();o.default(this._element).removeClass(F).addClass(Q),this._element.style[s]=0,this._triggerArray.length&&o.default(this._triggerArray).removeClass(B).attr("aria-expanded",!0),this.setTransitioning(!0);var l="scroll"+(s[0].toUpperCase()+s.slice(1)),r=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,(function(){o.default(i._element).removeClass(Q).addClass("collapse show"),i._element.style[s]="",i.setTransitioning(!1),o.default(i._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(r),this._element.style[s]=this._element[l]+"px"}}},e.hide=function(){var t=this;if(!this._isTransitioning&&o.default(this._element).hasClass(q)){var e=o.default.Event("hide.bs.collapse");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",d.reflow(this._element),o.default(this._element).addClass(Q).removeClass("collapse show");var i=this._triggerArray.length;if(i>0)for(var a=0;a0},e._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t._config.offset(e.offsets,t._element)),e}:e.offset=this._config.offset,e},e._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),r({},t,this._config.popperConfig)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data(K);if(n||(n=new t(this,"object"==typeof e?e:null),o.default(this).data(K,n)),"string"==typeof e){if("undefined"==typeof n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},t._clearMenus=function(e){if(!e||3!==e.which&&("keyup"!==e.type||9===e.which))for(var n=[].slice.call(document.querySelectorAll(it)),i=0,a=n.length;i0&&s--,40===e.which&&sdocument.documentElement.clientHeight;n||(this._element.style.overflowY="hidden"),this._element.classList.add(ht);var i=d.getTransitionDurationFromElement(this._dialog);o.default(this._element).off(d.TRANSITION_END),o.default(this._element).one(d.TRANSITION_END,(function(){t._element.classList.remove(ht),n||o.default(t._element).one(d.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,i)})).emulateTransitionEnd(i),this._element.focus()}},e._showElement=function(t){var e=this,n=o.default(this._element).hasClass(dt),i=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),o.default(this._dialog).hasClass("modal-dialog-scrollable")&&i?i.scrollTop=0:this._element.scrollTop=0,n&&d.reflow(this._element),o.default(this._element).addClass(ct),this._config.focus&&this._enforceFocus();var a=o.default.Event("shown.bs.modal",{relatedTarget:t}),s=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,o.default(e._element).trigger(a)};if(n){var l=d.getTransitionDurationFromElement(this._dialog);o.default(this._dialog).one(d.TRANSITION_END,s).emulateTransitionEnd(l)}else s()},e._enforceFocus=function(){var t=this;o.default(document).off(pt).on(pt,(function(e){document!==e.target&&t._element!==e.target&&0===o.default(t._element).has(e.target).length&&t._element.focus()}))},e._setEscapeEvent=function(){var t=this;this._isShown?o.default(this._element).on(yt,(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||o.default(this._element).off(yt)},e._setResizeEvent=function(){var t=this;this._isShown?o.default(window).on(_t,(function(e){return t.handleUpdate(e)})):o.default(window).off(_t)},e._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){o.default(document.body).removeClass(ft),t._resetAdjustments(),t._resetScrollbar(),o.default(t._element).trigger(gt)}))},e._removeBackdrop=function(){this._backdrop&&(o.default(this._backdrop).remove(),this._backdrop=null)},e._showBackdrop=function(t){var e=this,n=o.default(this._element).hasClass(dt)?dt:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",n&&this._backdrop.classList.add(n),o.default(this._backdrop).appendTo(document.body),o.default(this._element).on(vt,(function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._triggerBackdropTransition():e.hide())})),n&&d.reflow(this._backdrop),o.default(this._backdrop).addClass(ct),!t)return;if(!n)return void t();var i=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){o.default(this._backdrop).removeClass(ct);var a=function(){e._removeBackdrop(),t&&t()};if(o.default(this._element).hasClass(dt)){var s=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a()}else t&&t()},e._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",customClass:"",sanitize:!0,sanitizeFn:null,whiteList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},Ut={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},Mt={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},Wt=function(){function t(t,e){if("undefined"==typeof a.default)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var e=t.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=o.default(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(o.default(this.getTipElement()).hasClass(Rt))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),o.default.removeData(this.element,this.constructor.DATA_KEY),o.default(this.element).off(this.constructor.EVENT_KEY),o.default(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&o.default(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===o.default(this.element).css("display"))throw new Error("Please use show on visible elements");var e=o.default.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){o.default(this.element).trigger(e);var n=d.findShadowRoot(this.element),i=o.default.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!i)return;var s=this.getTipElement(),l=d.getUID(this.constructor.NAME);s.setAttribute("id",l),this.element.setAttribute("aria-describedby",l),this.setContent(),this.config.animation&&o.default(s).addClass(Lt);var r="function"==typeof this.config.placement?this.config.placement.call(this,s,this.element):this.config.placement,u=this._getAttachment(r);this.addAttachmentClass(u);var f=this._getContainer();o.default(s).data(this.constructor.DATA_KEY,this),o.default.contains(this.element.ownerDocument.documentElement,this.tip)||o.default(s).appendTo(f),o.default(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new a.default(this.element,s,this._getPopperConfig(u)),o.default(s).addClass(Rt),o.default(s).addClass(this.config.customClass),"ontouchstart"in document.documentElement&&o.default(document.body).children().on("mouseover",null,o.default.noop);var c=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,o.default(t.element).trigger(t.constructor.Event.SHOWN),e===qt&&t._leave(null,t)};if(o.default(this.tip).hasClass(Lt)){var h=d.getTransitionDurationFromElement(this.tip);o.default(this.tip).one(d.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},e.hide=function(t){var e=this,n=this.getTipElement(),i=o.default.Event(this.constructor.Event.HIDE),a=function(){e._hoverState!==xt&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),o.default(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(o.default(this.element).trigger(i),!i.isDefaultPrevented()){if(o.default(n).removeClass(Rt),"ontouchstart"in document.documentElement&&o.default(document.body).children().off("mouseover",null,o.default.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,o.default(this.tip).hasClass(Lt)){var s=d.getTransitionDurationFromElement(n);o.default(n).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-tooltip-"+t)},e.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},e.setContent=function(){var t=this.getTipElement();this.setElementContent(o.default(t.querySelectorAll(".tooltip-inner")),this.getTitle()),o.default(t).removeClass("fade show")},e.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=At(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?o.default(e).parent().is(t)||t.empty().append(e):t.text(o.default(e).text())},e.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},e._getPopperConfig=function(t){var e=this;return r({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t.config.offset(e.offsets,t.element)),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:d.isElement(this.config.container)?o.default(this.config.container):o.default(document).find(this.config.container)},e._getAttachment=function(t){return Bt[t.toUpperCase()]},e._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)o.default(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==e){var n=e===Ft?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,i=e===Ft?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;o.default(t.element).on(n,t.config.selector,(function(e){return t._enter(e)})).on(i,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},o.default(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=r({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Qt:Ft]=!0),o.default(e.getTipElement()).hasClass(Rt)||e._hoverState===xt?e._hoverState=xt:(clearTimeout(e._timeout),e._hoverState=xt,e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){e._hoverState===xt&&e.show()}),e.config.delay.show):e.show())},e._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Qt:Ft]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=qt,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){e._hoverState===qt&&e.hide()}),e.config.delay.hide):e.hide())},e._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},e._getConfig=function(t){var e=o.default(this.element).data();return Object.keys(e).forEach((function(t){-1!==Pt.indexOf(t)&&delete e[t]})),"number"==typeof(t=r({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),d.typeCheckConfig(It,t,this.constructor.DefaultType),t.sanitize&&(t.template=At(t.template,t.whiteList,t.sanitizeFn)),t},e._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},e._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(jt);null!==e&&e.length&&t.removeClass(e.join(""))},e._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},e._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(o.default(t).removeClass(Lt),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(kt),a="object"==typeof e&&e;if((i||!/dispose|hide/.test(e))&&(i||(i=new t(this,a),n.data(kt,i)),"string"==typeof e)){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return Ht}},{key:"NAME",get:function(){return It}},{key:"DATA_KEY",get:function(){return kt}},{key:"Event",get:function(){return Mt}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return Ut}}]),t}();o.default.fn.tooltip=Wt._jQueryInterface,o.default.fn.tooltip.Constructor=Wt,o.default.fn.tooltip.noConflict=function(){return o.default.fn.tooltip=Ot,Wt._jQueryInterface};var Vt="bs.popover",zt=o.default.fn.popover,Kt=new RegExp("(^|\\s)bs-popover\\S+","g"),Xt=r({},Wt.Default,{placement:"right",trigger:"click",content:"",template:''}),Yt=r({},Wt.DefaultType,{content:"(string|element|function)"}),$t={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},Jt=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),e.prototype.constructor=e,u(e,n);var a=i.prototype;return a.isWithContent=function(){return this.getTitle()||this._getContent()},a.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-popover-"+t)},a.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},a.setContent=function(){var t=o.default(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(".popover-body"),e),t.removeClass("fade show")},a._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},a._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(Kt);null!==e&&e.length>0&&t.removeClass(e.join(""))},i._jQueryInterface=function(t){return this.each((function(){var e=o.default(this).data(Vt),n="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new i(this,n),o.default(this).data(Vt,e)),"string"==typeof t)){if("undefined"==typeof e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},l(i,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return Xt}},{key:"NAME",get:function(){return"popover"}},{key:"DATA_KEY",get:function(){return Vt}},{key:"Event",get:function(){return $t}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return Yt}}]),i}(Wt);o.default.fn.popover=Jt._jQueryInterface,o.default.fn.popover.Constructor=Jt,o.default.fn.popover.noConflict=function(){return o.default.fn.popover=zt,Jt._jQueryInterface};var Gt="scrollspy",Zt="bs.scrollspy",te=o.default.fn[Gt],ee="active",ne="position",ie=".nav, .list-group",oe={offset:10,method:"auto",target:""},ae={offset:"number",method:"string",target:"(string|element)"},se=function(){function t(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,o.default(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return n._process(t)})),this.refresh(),this._process()}var e=t.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?"offset":ne,n="auto"===this._config.method?e:this._config.method,i=n===ne?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var e,a=d.getSelectorFromElement(t);if(a&&(e=document.querySelector(a)),e){var s=e.getBoundingClientRect();if(s.width||s.height)return[o.default(e)[n]().top+i,a]}return null})).filter(Boolean).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},e.dispose=function(){o.default.removeData(this._element,Zt),o.default(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},e._getConfig=function(t){if("string"!=typeof(t=r({},oe,"object"==typeof t&&t?t:{})).target&&d.isElement(t.target)){var e=o.default(t.target).attr("id");e||(e=d.getUID(Gt),o.default(t.target).attr("id",e)),t.target="#"+e}return d.typeCheckConfig(Gt,t,ae),t},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;)this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t li > .active",ge=function(){function t(t){this._element=t}var e=t.prototype;return e.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&o.default(this._element).hasClass(ue)||o.default(this._element).hasClass("disabled")||this._element.hasAttribute("disabled"))){var e,n,i=o.default(this._element).closest(".nav, .list-group")[0],a=d.getSelectorFromElement(this._element);if(i){var s="UL"===i.nodeName||"OL"===i.nodeName?he:ce;n=(n=o.default.makeArray(o.default(i).find(s)))[n.length-1]}var l=o.default.Event("hide.bs.tab",{relatedTarget:this._element}),r=o.default.Event("show.bs.tab",{relatedTarget:n});if(n&&o.default(n).trigger(l),o.default(this._element).trigger(r),!r.isDefaultPrevented()&&!l.isDefaultPrevented()){a&&(e=document.querySelector(a)),this._activate(this._element,i);var u=function(){var e=o.default.Event("hidden.bs.tab",{relatedTarget:t._element}),i=o.default.Event("shown.bs.tab",{relatedTarget:n});o.default(n).trigger(e),o.default(t._element).trigger(i)};e?this._activate(e,e.parentNode,u):u()}}},e.dispose=function(){o.default.removeData(this._element,le),this._element=null},e._activate=function(t,e,n){var i=this,a=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?o.default(e).children(ce):o.default(e).find(he))[0],s=n&&a&&o.default(a).hasClass(fe),l=function(){return i._transitionComplete(t,a,n)};if(a&&s){var r=d.getTransitionDurationFromElement(a);o.default(a).removeClass(de).one(d.TRANSITION_END,l).emulateTransitionEnd(r)}else l()},e._transitionComplete=function(t,e,n){if(e){o.default(e).removeClass(ue);var i=o.default(e.parentNode).find("> .dropdown-menu .active")[0];i&&o.default(i).removeClass(ue),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}o.default(t).addClass(ue),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),d.reflow(t),t.classList.contains(fe)&&t.classList.add(de);var a=t.parentNode;if(a&&"LI"===a.nodeName&&(a=a.parentNode),a&&o.default(a).hasClass("dropdown-menu")){var s=o.default(t).closest(".dropdown")[0];if(s){var l=[].slice.call(s.querySelectorAll(".dropdown-toggle"));o.default(l).addClass(ue)}t.setAttribute("aria-expanded",!0)}n&&n()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(le);if(i||(i=new t(this),n.data(le,i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();o.default(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),ge._jQueryInterface.call(o.default(this),"show")})),o.default.fn.tab=ge._jQueryInterface,o.default.fn.tab.Constructor=ge,o.default.fn.tab.noConflict=function(){return o.default.fn.tab=re,ge._jQueryInterface};var me="bs.toast",pe=o.default.fn.toast,_e="hide",ve="show",ye="showing",be="click.dismiss.bs.toast",Ee={animation:!0,autohide:!0,delay:500},Te={animation:"boolean",autohide:"boolean",delay:"number"},we=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var e=t.prototype;return e.show=function(){var t=this,e=o.default.Event("show.bs.toast");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var n=function(){t._element.classList.remove(ye),t._element.classList.add(ve),o.default(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove(_e),d.reflow(this._element),this._element.classList.add(ye),this._config.animation){var i=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,n).emulateTransitionEnd(i)}else n()}},e.hide=function(){if(this._element.classList.contains(ve)){var t=o.default.Event("hide.bs.toast");o.default(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},e.dispose=function(){this._clearTimeout(),this._element.classList.contains(ve)&&this._element.classList.remove(ve),o.default(this._element).off(be),o.default.removeData(this._element,me),this._element=null,this._config=null},e._getConfig=function(t){return t=r({},Ee,o.default(this._element).data(),"object"==typeof t&&t?t:{}),d.typeCheckConfig("toast",t,this.constructor.DefaultType),t},e._setListeners=function(){var t=this;o.default(this._element).on(be,'[data-dismiss="toast"]',(function(){return t.hide()}))},e._close=function(){var t=this,e=function(){t._element.classList.add(_e),o.default(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove(ve),this._config.animation){var n=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},e._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(me);if(i||(i=new t(this,"object"==typeof e&&e),n.data(me,i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e](this)}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"DefaultType",get:function(){return Te}},{key:"Default",get:function(){return Ee}}]),t}();o.default.fn.toast=we._jQueryInterface,o.default.fn.toast.Constructor=we,o.default.fn.toast.noConflict=function(){return o.default.fn.toast=pe,we._jQueryInterface},t.Alert=g,t.Button=E,t.Carousel=P,t.Collapse=V,t.Dropdown=lt,t.Modal=Ct,t.Popover=Jt,t.Scrollspy=se,t.Tab=ge,t.Toast=we,t.Tooltip=Wt,t.Util=d,Object.defineProperty(t,"__esModule",{value:!0})})); -//# sourceMappingURL=bootstrap.min.js.map \ No newline at end of file diff --git a/tests/coverage/_js/d3.min.js b/tests/coverage/_js/d3.min.js deleted file mode 100644 index 1664873..0000000 --- a/tests/coverage/_js/d3.min.js +++ /dev/null @@ -1,5 +0,0 @@ -!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function i(n){return!isNaN(n)}function u(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)<0?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)>0?i=u:r=u+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function f(n){return(n+="")===bo||n[0]===_o?_o+n:n}function s(n){return(n+="")[0]===_o?n.slice(1):n}function h(n){return f(n)in this._}function p(n){return(n=f(n))in this._&&delete this._[n]}function g(){var n=[];for(var t in this._)n.push(s(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function y(){this._=Object.create(null)}function m(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=wo.length;r>e;++e){var i=wo[e]+t;if(i in n)return i}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,i=-1,u=r.length;++ie;e++)for(var i,u=n[e],o=0,a=u.length;a>o;o++)(i=u[o])&&t(i,o,e);return n}function Z(n){return ko(n,qo),n}function V(n){var t,e;return function(r,i,u){var o,a=n[u].update,l=a.length;for(u!=e&&(e=u,t=0),i>=t&&(t=i+1);!(o=a[t])&&++t0&&(n=n.slice(0,a));var c=To.get(n);return c&&(n=c,l=B),a?t?i:r:t?b:u}function $(n,t){return function(e){var r=ao.event;ao.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ao.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Do,i="click"+r,u=ao.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ro&&(Ro="onselectstart"in e?!1:x(e.style,"userSelect")),Ro){var o=n(e).style,a=o[Ro];o[Ro]="none"}return function(n){if(u.on(r,null),Ro&&(o[Ro]=a),n){var t=function(){u.on(i,null)};u.on(i,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var i=r.createSVGPoint();if(0>Po){var u=t(n);if(u.scrollX||u.scrollY){r=ao.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Po=!(o.f||o.e),r.remove()}}return Po?(i.x=e.pageX,i.y=e.pageY):(i.x=e.clientX,i.y=e.clientY),i=i.matrixTransform(n.getScreenCTM().inverse()),[i.x,i.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ao.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nn(n){return n>1?0:-1>n?Fo:Math.acos(n)}function tn(n){return n>1?Io:-1>n?-Io:Math.asin(n)}function en(n){return((n=Math.exp(n))-1/n)/2}function rn(n){return((n=Math.exp(n))+1/n)/2}function un(n){return((n=Math.exp(2*n))-1)/(n+1)}function on(n){return(n=Math.sin(n/2))*n}function an(){}function ln(n,t,e){return this instanceof ln?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof ln?new ln(n.h,n.s,n.l):_n(""+n,wn,ln):new ln(n,t,e)}function cn(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?u+(o-u)*n/60:180>n?o:240>n?u+(o-u)*(240-n)/60:u}function i(n){return Math.round(255*r(n))}var u,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,u=2*e-o,new mn(i(n+120),i(n),i(n-120))}function fn(n,t,e){return this instanceof fn?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof fn?new fn(n.h,n.c,n.l):n instanceof hn?gn(n.l,n.a,n.b):gn((n=Sn((n=ao.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new fn(n,t,e)}function sn(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new hn(e,Math.cos(n*=Yo)*t,Math.sin(n)*t)}function hn(n,t,e){return this instanceof hn?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof hn?new hn(n.l,n.a,n.b):n instanceof fn?sn(n.h,n.c,n.l):Sn((n=mn(n)).r,n.g,n.b):new hn(n,t,e)}function pn(n,t,e){var r=(n+16)/116,i=r+t/500,u=r-e/200;return i=vn(i)*na,r=vn(r)*ta,u=vn(u)*ea,new mn(yn(3.2404542*i-1.5371385*r-.4985314*u),yn(-.969266*i+1.8760108*r+.041556*u),yn(.0556434*i-.2040259*r+1.0572252*u))}function gn(n,t,e){return n>0?new fn(Math.atan2(e,t)*Zo,Math.sqrt(t*t+e*e),n):new fn(NaN,NaN,n)}function vn(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function dn(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function yn(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mn(n,t,e){return this instanceof mn?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mn?new mn(n.r,n.g,n.b):_n(""+n,mn,cn):new mn(n,t,e)}function Mn(n){return new mn(n>>16,n>>8&255,255&n)}function xn(n){return Mn(n)+""}function bn(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function _n(n,t,e){var r,i,u,o=0,a=0,l=0;if(r=/([a-z]+)\((.*)\)/.exec(n=n.toLowerCase()))switch(i=r[2].split(","),r[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Nn(i[0]),Nn(i[1]),Nn(i[2]))}return(u=ua.get(n))?t(u.r,u.g,u.b):(null==n||"#"!==n.charAt(0)||isNaN(u=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&u)>>4,o=o>>4|o,a=240&u,a=a>>4|a,l=15&u,l=l<<4|l):7===n.length&&(o=(16711680&u)>>16,a=(65280&u)>>8,l=255&u)),t(o,a,l))}function wn(n,t,e){var r,i,u=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-u,l=(o+u)/2;return a?(i=.5>l?a/(o+u):a/(2-o-u),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=NaN,i=l>0&&1>l?0:r),new ln(r,i,l)}function Sn(n,t,e){n=kn(n),t=kn(t),e=kn(e);var r=dn((.4124564*n+.3575761*t+.1804375*e)/na),i=dn((.2126729*n+.7151522*t+.072175*e)/ta),u=dn((.0193339*n+.119192*t+.9503041*e)/ea);return hn(116*i-16,500*(r-i),200*(i-u))}function kn(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Nn(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function En(n){return"function"==typeof n?n:function(){return n}}function An(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Cn(t,e,n,r)}}function Cn(n,t,e,r){function i(){var n,t=l.status;if(!t&&Ln(l)||t>=200&&300>t||304===t){try{n=e.call(u,l)}catch(r){return void o.error.call(u,r)}o.load.call(u,n)}else o.error.call(u,l)}var u={},o=ao.dispatch("beforesend","progress","load","error"),a={},l=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in l||!/^(http(s)?:)?\/\//.test(n)||(l=new XDomainRequest),"onload"in l?l.onload=l.onerror=i:l.onreadystatechange=function(){l.readyState>3&&i()},l.onprogress=function(n){var t=ao.event;ao.event=n;try{o.progress.call(u,l)}finally{ao.event=t}},u.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",u)},u.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",u):t},u.responseType=function(n){return arguments.length?(c=n,u):c},u.response=function(n){return e=n,u},["get","post"].forEach(function(n){u[n]=function(){return u.send.apply(u,[n].concat(co(arguments)))}}),u.send=function(e,r,i){if(2===arguments.length&&"function"==typeof r&&(i=r,r=null),l.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),l.setRequestHeader)for(var f in a)l.setRequestHeader(f,a[f]);return null!=t&&l.overrideMimeType&&l.overrideMimeType(t),null!=c&&(l.responseType=c),null!=i&&u.on("error",i).on("load",function(n){i(null,n)}),o.beforesend.call(u,l),l.send(null==r?null:r),u},u.abort=function(){return l.abort(),u},ao.rebind(u,o,"on"),null==r?u:u.get(zn(r))}function zn(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Ln(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qn(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var i=e+t,u={c:n,t:i,n:null};return aa?aa.n=u:oa=u,aa=u,la||(ca=clearTimeout(ca),la=1,fa(Tn)),u}function Tn(){var n=Rn(),t=Dn()-n;t>24?(isFinite(t)&&(clearTimeout(ca),ca=setTimeout(Tn,t)),la=0):(la=1,fa(Tn))}function Rn(){for(var n=Date.now(),t=oa;t;)n>=t.t&&t.c(n-t.t)&&(t.c=null),t=t.n;return n}function Dn(){for(var n,t=oa,e=1/0;t;)t.c?(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function jn(n){var t=n.decimal,e=n.thousands,r=n.grouping,i=n.currency,u=r&&e?function(n,t){for(var i=n.length,u=[],o=0,a=r[0],l=0;i>0&&a>0&&(l+a+1>t&&(a=Math.max(1,t-l)),u.push(n.substring(i-=a,i+a)),!((l+=a+1)>t));)a=r[o=(o+1)%r.length];return u.reverse().join(e)}:m;return function(n){var e=ha.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",l=e[4]||"",c=e[5],f=+e[6],s=e[7],h=e[8],p=e[9],g=1,v="",d="",y=!1,m=!0;switch(h&&(h=+h.substring(1)),(c||"0"===r&&"="===o)&&(c=r="0",o="="),p){case"n":s=!0,p="g";break;case"%":g=100,d="%",p="f";break;case"p":g=100,d="%",p="r";break;case"b":case"o":case"x":case"X":"#"===l&&(v="0"+p.toLowerCase());case"c":m=!1;case"d":y=!0,h=0;break;case"s":g=-1,p="r"}"$"===l&&(v=i[0],d=i[1]),"r"!=p||h||(p="g"),null!=h&&("g"==p?h=Math.max(1,Math.min(21,h)):"e"!=p&&"f"!=p||(h=Math.max(0,Math.min(20,h)))),p=pa.get(p)||Fn;var M=c&&s;return function(n){var e=d;if(y&&n%1)return"";var i=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>g){var l=ao.formatPrefix(n,h);n=l.scale(n),e=l.symbol+d}else n*=g;n=p(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=m?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!c&&s&&(x=u(x,1/0));var S=v.length+x.length+b.length+(M?0:i.length),k=f>S?new Array(S=f-S+1).join(r):"";return M&&(x=u(k+x,k.length?f-b.length:1/0)),i+=v,n=x+b,("<"===o?i+n+k:">"===o?k+i+n:"^"===o?k.substring(0,S>>=1)+i+n+k.substring(S):i+(M?n:k+n))+e}}}function Fn(n){return n+""}function Hn(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function On(n,t,e){function r(t){var e=n(t),r=u(e,1);return r-t>t-e?e:r}function i(e){return t(e=n(new va(e-1)),1),e}function u(n,e){return t(n=new va(+n),e),n}function o(n,r,u){var o=i(n),a=[];if(u>1)for(;r>o;)e(o)%u||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{va=Hn;var r=new Hn;return r._=n,o(r,t,e)}finally{va=Date}}n.floor=n,n.round=r,n.ceil=i,n.offset=u,n.range=o;var l=n.utc=In(n);return l.floor=l,l.round=In(r),l.ceil=In(i),l.offset=In(u),l.range=a,n}function In(n){return function(t,e){try{va=Hn;var r=new Hn;return r._=t,n(r,e)._}finally{va=Date}}}function Yn(n){function t(n){function t(t){for(var e,i,u,o=[],a=-1,l=0;++aa;){if(r>=c)return-1;if(i=t.charCodeAt(a++),37===i){if(o=t.charAt(a++),u=C[o in ya?t.charAt(a++):o],!u||(r=u(n,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){N.lastIndex=0;var r=N.exec(t.slice(e));return r?(n.m=E.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,A.c.toString(),t,r)}function l(n,t,r){return e(n,A.x.toString(),t,r)}function c(n,t,r){return e(n,A.X.toString(),t,r)}function f(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var s=n.dateTime,h=n.date,p=n.time,g=n.periods,v=n.days,d=n.shortDays,y=n.months,m=n.shortMonths;t.utc=function(n){function e(n){try{va=Hn;var t=new va;return t._=n,r(t)}finally{va=Date}}var r=t(n);return e.parse=function(n){try{va=Hn;var t=r.parse(n);return t&&t._}finally{va=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ct;var M=ao.map(),x=Vn(v),b=Xn(v),_=Vn(d),w=Xn(d),S=Vn(y),k=Xn(y),N=Vn(m),E=Xn(m);g.forEach(function(n,t){M.set(n.toLowerCase(),t)});var A={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return m[n.getMonth()]},B:function(n){return y[n.getMonth()]},c:t(s),d:function(n,t){return Zn(n.getDate(),t,2)},e:function(n,t){return Zn(n.getDate(),t,2)},H:function(n,t){return Zn(n.getHours(),t,2)},I:function(n,t){return Zn(n.getHours()%12||12,t,2)},j:function(n,t){return Zn(1+ga.dayOfYear(n),t,3)},L:function(n,t){return Zn(n.getMilliseconds(),t,3)},m:function(n,t){return Zn(n.getMonth()+1,t,2)},M:function(n,t){return Zn(n.getMinutes(),t,2)},p:function(n){return g[+(n.getHours()>=12)]},S:function(n,t){return Zn(n.getSeconds(),t,2)},U:function(n,t){return Zn(ga.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Zn(ga.mondayOfYear(n),t,2)},x:t(h),X:t(p),y:function(n,t){return Zn(n.getFullYear()%100,t,2)},Y:function(n,t){return Zn(n.getFullYear()%1e4,t,4)},Z:at,"%":function(){return"%"}},C={a:r,A:i,b:u,B:o,c:a,d:tt,e:tt,H:rt,I:rt,j:et,L:ot,m:nt,M:it,p:f,S:ut,U:Bn,w:$n,W:Wn,x:l,X:c,y:Gn,Y:Jn,Z:Kn,"%":lt};return t}function Zn(n,t,e){var r=0>n?"-":"",i=(r?-n:n)+"",u=i.length;return r+(e>u?new Array(e-u+1).join(t)+i:i)}function Vn(n){return new RegExp("^(?:"+n.map(ao.requote).join("|")+")","i")}function Xn(n){for(var t=new c,e=-1,r=n.length;++e68?1900:2e3)}function nt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function tt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function et(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function rt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function it(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function ut(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ot(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function at(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=xo(t)/60|0,i=xo(t)%60;return e+Zn(r,"0",2)+Zn(i,"0",2)}function lt(n,t,e){Ma.lastIndex=0;var r=Ma.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ct(n){for(var t=n.length,e=-1;++e=0?1:-1,a=o*e,l=Math.cos(t),c=Math.sin(t),f=u*c,s=i*l+f*Math.cos(a),h=f*o*Math.sin(a);ka.add(Math.atan2(h,s)),r=n,i=l,u=c}var t,e,r,i,u;Na.point=function(o,a){Na.point=n,r=(t=o)*Yo,i=Math.cos(a=(e=a)*Yo/2+Fo/4),u=Math.sin(a)},Na.lineEnd=function(){n(t,e)}}function dt(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function yt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function mt(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Mt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function xt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function bt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function _t(n){return[Math.atan2(n[1],n[0]),tn(n[2])]}function wt(n,t){return xo(n[0]-t[0])a;++a)i.point((e=n[a])[0],e[1]);return void i.lineEnd()}var l=new Tt(e,n,null,!0),c=new Tt(e,null,l,!1);l.o=c,u.push(l),o.push(c),l=new Tt(r,n,null,!1),c=new Tt(r,null,l,!0),l.o=c,u.push(l),o.push(c)}}),o.sort(t),qt(u),qt(o),u.length){for(var a=0,l=e,c=o.length;c>a;++a)o[a].e=l=!l;for(var f,s,h=u[0];;){for(var p=h,g=!0;p.v;)if((p=p.n)===h)return;f=p.z,i.lineStart();do{if(p.v=p.o.v=!0,p.e){if(g)for(var a=0,c=f.length;c>a;++a)i.point((s=f[a])[0],s[1]);else r(p.x,p.n.x,1,i);p=p.n}else{if(g){f=p.p.z;for(var a=f.length-1;a>=0;--a)i.point((s=f[a])[0],s[1])}else r(p.x,p.p.x,-1,i);p=p.p}p=p.o,f=p.z,g=!g}while(!p.v);i.lineEnd()}}}function qt(n){if(t=n.length){for(var t,e,r=0,i=n[0];++r0){for(b||(u.polygonStart(),b=!0),u.lineStart();++o1&&2&t&&e.push(e.pop().concat(e.shift())),p.push(e.filter(Dt))}var p,g,v,d=t(u),y=i.invert(r[0],r[1]),m={point:o,lineStart:l,lineEnd:c,polygonStart:function(){m.point=f,m.lineStart=s,m.lineEnd=h,p=[],g=[]},polygonEnd:function(){m.point=o,m.lineStart=l,m.lineEnd=c,p=ao.merge(p);var n=Ot(y,g);p.length?(b||(u.polygonStart(),b=!0),Lt(p,Ut,n,e,u)):n&&(b||(u.polygonStart(),b=!0),u.lineStart(),e(null,null,1,u),u.lineEnd()),b&&(u.polygonEnd(),b=!1),p=g=null},sphere:function(){u.polygonStart(),u.lineStart(),e(null,null,1,u),u.lineEnd(),u.polygonEnd()}},M=Pt(),x=t(M),b=!1;return m}}function Dt(n){return n.length>1}function Pt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ut(n,t){return((n=n.x)[0]<0?n[1]-Io-Uo:Io-n[1])-((t=t.x)[0]<0?t[1]-Io-Uo:Io-t[1])}function jt(n){var t,e=NaN,r=NaN,i=NaN;return{lineStart:function(){n.lineStart(),t=1},point:function(u,o){var a=u>0?Fo:-Fo,l=xo(u-e);xo(l-Fo)0?Io:-Io),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(u,r),t=0):i!==a&&l>=Fo&&(xo(e-i)Uo?Math.atan((Math.sin(t)*(u=Math.cos(r))*Math.sin(e)-Math.sin(r)*(i=Math.cos(t))*Math.sin(n))/(i*u*o)):(t+r)/2}function Ht(n,t,e,r){var i;if(null==n)i=e*Io,r.point(-Fo,i),r.point(0,i),r.point(Fo,i),r.point(Fo,0),r.point(Fo,-i),r.point(0,-i),r.point(-Fo,-i),r.point(-Fo,0),r.point(-Fo,i);else if(xo(n[0]-t[0])>Uo){var u=n[0]a;++a){var c=t[a],f=c.length;if(f)for(var s=c[0],h=s[0],p=s[1]/2+Fo/4,g=Math.sin(p),v=Math.cos(p),d=1;;){d===f&&(d=0),n=c[d];var y=n[0],m=n[1]/2+Fo/4,M=Math.sin(m),x=Math.cos(m),b=y-h,_=b>=0?1:-1,w=_*b,S=w>Fo,k=g*M;if(ka.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),u+=S?b+_*Ho:b,S^h>=e^y>=e){var N=mt(dt(s),dt(n));bt(N);var E=mt(i,N);bt(E);var A=(S^b>=0?-1:1)*tn(E[2]);(r>A||r===A&&(N[0]||N[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=y,g=M,v=x,s=n}}return(-Uo>u||Uo>u&&-Uo>ka)^1&o}function It(n){function t(n,t){return Math.cos(n)*Math.cos(t)>u}function e(n){var e,u,l,c,f;return{lineStart:function(){c=l=!1,f=1},point:function(s,h){var p,g=[s,h],v=t(s,h),d=o?v?0:i(s,h):v?i(s+(0>s?Fo:-Fo),h):0;if(!e&&(c=l=v)&&n.lineStart(),v!==l&&(p=r(e,g),(wt(e,p)||wt(g,p))&&(g[0]+=Uo,g[1]+=Uo,v=t(g[0],g[1]))),v!==l)f=0,v?(n.lineStart(),p=r(g,e),n.point(p[0],p[1])):(p=r(e,g),n.point(p[0],p[1]),n.lineEnd()),e=p;else if(a&&e&&o^v){var y;d&u||!(y=r(g,e,!0))||(f=0,o?(n.lineStart(),n.point(y[0][0],y[0][1]),n.point(y[1][0],y[1][1]),n.lineEnd()):(n.point(y[1][0],y[1][1]),n.lineEnd(),n.lineStart(),n.point(y[0][0],y[0][1])))}!v||e&&wt(e,g)||n.point(g[0],g[1]),e=g,l=v,u=d},lineEnd:function(){l&&n.lineEnd(),e=null},clean:function(){return f|(c&&l)<<1}}}function r(n,t,e){var r=dt(n),i=dt(t),o=[1,0,0],a=mt(r,i),l=yt(a,a),c=a[0],f=l-c*c;if(!f)return!e&&n;var s=u*l/f,h=-u*c/f,p=mt(o,a),g=xt(o,s),v=xt(a,h);Mt(g,v);var d=p,y=yt(g,d),m=yt(d,d),M=y*y-m*(yt(g,g)-1);if(!(0>M)){var x=Math.sqrt(M),b=xt(d,(-y-x)/m);if(Mt(b,g),b=_t(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],N=t[1];w>S&&(_=w,w=S,S=_);var E=S-w,A=xo(E-Fo)E;if(!A&&k>N&&(_=k,k=N,N=_),C?A?k+N>0^b[1]<(xo(b[0]-w)Fo^(w<=b[0]&&b[0]<=S)){var z=xt(d,(-y+x)/m);return Mt(z,g),[b,_t(z)]}}}function i(t,e){var r=o?n:Fo-n,i=0;return-r>t?i|=1:t>r&&(i|=2),-r>e?i|=4:e>r&&(i|=8),i}var u=Math.cos(n),o=u>0,a=xo(u)>Uo,l=ve(n,6*Yo);return Rt(t,e,l,o?[0,-n]:[-Fo,n-Fo])}function Yt(n,t,e,r){return function(i){var u,o=i.a,a=i.b,l=o.x,c=o.y,f=a.x,s=a.y,h=0,p=1,g=f-l,v=s-c;if(u=n-l,g||!(u>0)){if(u/=g,0>g){if(h>u)return;p>u&&(p=u)}else if(g>0){if(u>p)return;u>h&&(h=u)}if(u=e-l,g||!(0>u)){if(u/=g,0>g){if(u>p)return;u>h&&(h=u)}else if(g>0){if(h>u)return;p>u&&(p=u)}if(u=t-c,v||!(u>0)){if(u/=v,0>v){if(h>u)return;p>u&&(p=u)}else if(v>0){if(u>p)return;u>h&&(h=u)}if(u=r-c,v||!(0>u)){if(u/=v,0>v){if(u>p)return;u>h&&(h=u)}else if(v>0){if(h>u)return;p>u&&(p=u)}return h>0&&(i.a={x:l+h*g,y:c+h*v}),1>p&&(i.b={x:l+p*g,y:c+p*v}),i}}}}}}function Zt(n,t,e,r){function i(r,i){return xo(r[0]-n)0?0:3:xo(r[0]-e)0?2:1:xo(r[1]-t)0?1:0:i>0?3:2}function u(n,t){return o(n.x,t.x)}function o(n,t){var e=i(n,1),r=i(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function l(n){for(var t=0,e=d.length,r=n[1],i=0;e>i;++i)for(var u,o=1,a=d[i],l=a.length,c=a[0];l>o;++o)u=a[o],c[1]<=r?u[1]>r&&Q(c,u,n)>0&&++t:u[1]<=r&&Q(c,u,n)<0&&--t,c=u;return 0!==t}function c(u,a,l,c){var f=0,s=0;if(null==u||(f=i(u,l))!==(s=i(a,l))||o(u,a)<0^l>0){do c.point(0===f||3===f?n:e,f>1?r:t);while((f=(f+l+4)%4)!==s)}else c.point(a[0],a[1])}function f(i,u){return i>=n&&e>=i&&u>=t&&r>=u}function s(n,t){f(n,t)&&a.point(n,t)}function h(){C.point=g,d&&d.push(y=[]),S=!0,w=!1,b=_=NaN}function p(){v&&(g(m,M),x&&w&&E.rejoin(),v.push(E.buffer())),C.point=s,w&&a.lineEnd()}function g(n,t){n=Math.max(-Ha,Math.min(Ha,n)),t=Math.max(-Ha,Math.min(Ha,t));var e=f(n,t);if(d&&y.push([n,t]),S)m=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};A(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,y,m,M,x,b,_,w,S,k,N=a,E=Pt(),A=Yt(n,t,e,r),C={point:s,lineStart:h,lineEnd:p,polygonStart:function(){a=E,v=[],d=[],k=!0},polygonEnd:function(){a=N,v=ao.merge(v);var t=l([n,r]),e=k&&t,i=v.length;(e||i)&&(a.polygonStart(),e&&(a.lineStart(),c(null,null,1,a),a.lineEnd()),i&&Lt(v,u,t,c,a),a.polygonEnd()),v=d=y=null}};return C}}function Vt(n){var t=0,e=Fo/3,r=ae(n),i=r(t,e);return i.parallels=function(n){return arguments.length?r(t=n[0]*Fo/180,e=n[1]*Fo/180):[t/Fo*180,e/Fo*180]},i}function Xt(n,t){function e(n,t){var e=Math.sqrt(u-2*i*Math.sin(t))/i;return[e*Math.sin(n*=i),o-e*Math.cos(n)]}var r=Math.sin(n),i=(r+Math.sin(t))/2,u=1+r*(2*i-r),o=Math.sqrt(u)/i;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/i,tn((u-(n*n+e*e)*i*i)/(2*i))]},e}function $t(){function n(n,t){Ia+=i*n-r*t,r=n,i=t}var t,e,r,i;$a.point=function(u,o){$a.point=n,t=r=u,e=i=o},$a.lineEnd=function(){n(t,e)}}function Bt(n,t){Ya>n&&(Ya=n),n>Va&&(Va=n),Za>t&&(Za=t),t>Xa&&(Xa=t)}function Wt(){function n(n,t){o.push("M",n,",",t,u)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function i(){o.push("Z")}var u=Jt(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return u=Jt(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Jt(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Gt(n,t){Ca+=n,za+=t,++La}function Kt(){function n(n,r){var i=n-t,u=r-e,o=Math.sqrt(i*i+u*u);qa+=o*(t+n)/2,Ta+=o*(e+r)/2,Ra+=o,Gt(t=n,e=r)}var t,e;Wa.point=function(r,i){Wa.point=n,Gt(t=r,e=i)}}function Qt(){Wa.point=Gt}function ne(){function n(n,t){var e=n-r,u=t-i,o=Math.sqrt(e*e+u*u);qa+=o*(r+n)/2,Ta+=o*(i+t)/2,Ra+=o,o=i*n-r*t,Da+=o*(r+n),Pa+=o*(i+t),Ua+=3*o,Gt(r=n,i=t)}var t,e,r,i;Wa.point=function(u,o){Wa.point=n,Gt(t=r=u,e=i=o)},Wa.lineEnd=function(){n(t,e)}}function te(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,Ho)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function i(){a.point=t}function u(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:i,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=i,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function ee(n){function t(n){return(a?r:e)(n)}function e(t){return ue(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=NaN,S.point=u,t.lineStart()}function u(e,r){var u=dt([e,r]),o=n(e,r);i(M,x,m,b,_,w,M=o[0],x=o[1],m=e,b=u[0],_=u[1],w=u[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function l(){ -r(),S.point=c,S.lineEnd=f}function c(n,t){u(s=n,h=t),p=M,g=x,v=b,d=_,y=w,S.point=u}function f(){i(M,x,m,b,_,w,p,g,s,v,d,y,a,t),S.lineEnd=o,o()}var s,h,p,g,v,d,y,m,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=l},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function i(t,e,r,a,l,c,f,s,h,p,g,v,d,y){var m=f-t,M=s-e,x=m*m+M*M;if(x>4*u&&d--){var b=a+p,_=l+g,w=c+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),N=xo(xo(w)-1)u||xo((m*z+M*L)/x-.5)>.3||o>a*p+l*g+c*v)&&(i(t,e,r,a,l,c,A,C,N,b/=S,_/=S,w,d,y),y.point(A,C),i(A,C,N,b,_,w,f,s,h,p,g,v,d,y))}}var u=.5,o=Math.cos(30*Yo),a=16;return t.precision=function(n){return arguments.length?(a=(u=n*n)>0&&16,t):Math.sqrt(u)},t}function re(n){var t=ee(function(t,e){return n([t*Zo,e*Zo])});return function(n){return le(t(n))}}function ie(n){this.stream=n}function ue(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function oe(n){return ae(function(){return n})()}function ae(n){function t(n){return n=a(n[0]*Yo,n[1]*Yo),[n[0]*h+l,c-n[1]*h]}function e(n){return n=a.invert((n[0]-l)/h,(c-n[1])/h),n&&[n[0]*Zo,n[1]*Zo]}function r(){a=Ct(o=se(y,M,x),u);var n=u(v,d);return l=p-n[0]*h,c=g+n[1]*h,i()}function i(){return f&&(f.valid=!1,f=null),t}var u,o,a,l,c,f,s=ee(function(n,t){return n=u(n,t),[n[0]*h+l,c-n[1]*h]}),h=150,p=480,g=250,v=0,d=0,y=0,M=0,x=0,b=Fa,_=m,w=null,S=null;return t.stream=function(n){return f&&(f.valid=!1),f=le(b(o,s(_(n)))),f.valid=!0,f},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Fa):It((w=+n)*Yo),i()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Zt(n[0][0],n[0][1],n[1][0],n[1][1]):m,i()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(p=+n[0],g=+n[1],r()):[p,g]},t.center=function(n){return arguments.length?(v=n[0]%360*Yo,d=n[1]%360*Yo,r()):[v*Zo,d*Zo]},t.rotate=function(n){return arguments.length?(y=n[0]%360*Yo,M=n[1]%360*Yo,x=n.length>2?n[2]%360*Yo:0,r()):[y*Zo,M*Zo,x*Zo]},ao.rebind(t,s,"precision"),function(){return u=n.apply(this,arguments),t.invert=u.invert&&e,r()}}function le(n){return ue(n,function(t,e){n.point(t*Yo,e*Yo)})}function ce(n,t){return[n,t]}function fe(n,t){return[n>Fo?n-Ho:-Fo>n?n+Ho:n,t]}function se(n,t,e){return n?t||e?Ct(pe(n),ge(t,e)):pe(n):t||e?ge(t,e):fe}function he(n){return function(t,e){return t+=n,[t>Fo?t-Ho:-Fo>t?t+Ho:t,e]}}function pe(n){var t=he(n);return t.invert=he(-n),t}function ge(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*r+a*i;return[Math.atan2(l*u-f*o,a*r-c*i),tn(f*u+l*o)]}var r=Math.cos(n),i=Math.sin(n),u=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*u-l*o;return[Math.atan2(l*u+c*o,a*r+f*i),tn(f*r-a*i)]},e}function ve(n,t){var e=Math.cos(n),r=Math.sin(n);return function(i,u,o,a){var l=o*t;null!=i?(i=de(e,i),u=de(e,u),(o>0?u>i:i>u)&&(i+=o*Ho)):(i=n+o*Ho,u=n-.5*l);for(var c,f=i;o>0?f>u:u>f;f-=l)a.point((c=_t([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function de(n,t){var e=dt(t);e[0]-=n,bt(e);var r=nn(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Uo)%(2*Math.PI)}function ye(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function me(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function Me(n){return n.source}function xe(n){return n.target}function be(n,t,e,r){var i=Math.cos(t),u=Math.sin(t),o=Math.cos(r),a=Math.sin(r),l=i*Math.cos(n),c=i*Math.sin(n),f=o*Math.cos(e),s=o*Math.sin(e),h=2*Math.asin(Math.sqrt(on(r-t)+i*o*on(e-n))),p=1/Math.sin(h),g=h?function(n){var t=Math.sin(n*=h)*p,e=Math.sin(h-n)*p,r=e*l+t*f,i=e*c+t*s,o=e*u+t*a;return[Math.atan2(i,r)*Zo,Math.atan2(o,Math.sqrt(r*r+i*i))*Zo]}:function(){return[n*Zo,t*Zo]};return g.distance=h,g}function _e(){function n(n,i){var u=Math.sin(i*=Yo),o=Math.cos(i),a=xo((n*=Yo)-t),l=Math.cos(a);Ja+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*u-e*o*l)*a),e*u+r*o*l),t=n,e=u,r=o}var t,e,r;Ga.point=function(i,u){t=i*Yo,e=Math.sin(u*=Yo),r=Math.cos(u),Ga.point=n},Ga.lineEnd=function(){Ga.point=Ga.lineEnd=b}}function we(n,t){function e(t,e){var r=Math.cos(t),i=Math.cos(e),u=n(r*i);return[u*i*Math.sin(t),u*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),i=t(r),u=Math.sin(i),o=Math.cos(i);return[Math.atan2(n*u,r*o),Math.asin(r&&e*u/r)]},e}function Se(n,t){function e(n,t){o>0?-Io+Uo>t&&(t=-Io+Uo):t>Io-Uo&&(t=Io-Uo);var e=o/Math.pow(i(t),u);return[e*Math.sin(u*n),o-e*Math.cos(u*n)]}var r=Math.cos(n),i=function(n){return Math.tan(Fo/4+n/2)},u=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(i(t)/i(n)),o=r*Math.pow(i(n),u)/u;return u?(e.invert=function(n,t){var e=o-t,r=K(u)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/u,2*Math.atan(Math.pow(o/r,1/u))-Io]},e):Ne}function ke(n,t){function e(n,t){var e=u-t;return[e*Math.sin(i*n),u-e*Math.cos(i*n)]}var r=Math.cos(n),i=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),u=r/i+n;return xo(i)i;i++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function qe(n,t){return n[0]-t[0]||n[1]-t[1]}function Te(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Re(n,t,e,r){var i=n[0],u=e[0],o=t[0]-i,a=r[0]-u,l=n[1],c=e[1],f=t[1]-l,s=r[1]-c,h=(a*(l-c)-s*(i-u))/(s*o-a*f);return[i+h*o,l+h*f]}function De(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Pe(){rr(this),this.edge=this.site=this.circle=null}function Ue(n){var t=cl.pop()||new Pe;return t.site=n,t}function je(n){Be(n),ol.remove(n),cl.push(n),rr(n)}function Fe(n){var t=n.circle,e=t.x,r=t.cy,i={x:e,y:r},u=n.P,o=n.N,a=[n];je(n);for(var l=u;l.circle&&xo(e-l.circle.x)f;++f)c=a[f],l=a[f-1],nr(c.edge,l.site,c.site,i);l=a[0],c=a[s-1],c.edge=Ke(l.site,c.site,null,i),$e(l),$e(c)}function He(n){for(var t,e,r,i,u=n.x,o=n.y,a=ol._;a;)if(r=Oe(a,o)-u,r>Uo)a=a.L;else{if(i=u-Ie(a,o),!(i>Uo)){r>-Uo?(t=a.P,e=a):i>-Uo?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var l=Ue(n);if(ol.insert(t,l),t||e){if(t===e)return Be(t),e=Ue(t.site),ol.insert(l,e),l.edge=e.edge=Ke(t.site,l.site),$e(t),void $e(e);if(!e)return void(l.edge=Ke(t.site,l.site));Be(t),Be(e);var c=t.site,f=c.x,s=c.y,h=n.x-f,p=n.y-s,g=e.site,v=g.x-f,d=g.y-s,y=2*(h*d-p*v),m=h*h+p*p,M=v*v+d*d,x={x:(d*m-p*M)/y+f,y:(h*M-v*m)/y+s};nr(e.edge,c,g,x),l.edge=Ke(c,n,null,x),e.edge=Ke(n,g,null,x),$e(t),$e(e)}}function Oe(n,t){var e=n.site,r=e.x,i=e.y,u=i-t;if(!u)return r;var o=n.P;if(!o)return-(1/0);e=o.site;var a=e.x,l=e.y,c=l-t;if(!c)return a;var f=a-r,s=1/u-1/c,h=f/c;return s?(-h+Math.sqrt(h*h-2*s*(f*f/(-2*c)-l+c/2+i-u/2)))/s+r:(r+a)/2}function Ie(n,t){var e=n.N;if(e)return Oe(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ye(n){this.site=n,this.edges=[]}function Ze(n){for(var t,e,r,i,u,o,a,l,c,f,s=n[0][0],h=n[1][0],p=n[0][1],g=n[1][1],v=ul,d=v.length;d--;)if(u=v[d],u&&u.prepare())for(a=u.edges,l=a.length,o=0;l>o;)f=a[o].end(),r=f.x,i=f.y,c=a[++o%l].start(),t=c.x,e=c.y,(xo(r-t)>Uo||xo(i-e)>Uo)&&(a.splice(o,0,new tr(Qe(u.site,f,xo(r-s)Uo?{x:s,y:xo(t-s)Uo?{x:xo(e-g)Uo?{x:h,y:xo(t-h)Uo?{x:xo(e-p)=-jo)){var p=l*l+c*c,g=f*f+s*s,v=(s*p-c*g)/h,d=(l*g-f*p)/h,s=d+a,y=fl.pop()||new Xe;y.arc=n,y.site=i,y.x=v+o,y.y=s+Math.sqrt(v*v+d*d),y.cy=s,n.circle=y;for(var m=null,M=ll._;M;)if(y.yd||d>=a)return;if(h>g){if(u){if(u.y>=c)return}else u={x:d,y:l};e={x:d,y:c}}else{if(u){if(u.yr||r>1)if(h>g){if(u){if(u.y>=c)return}else u={x:(l-i)/r,y:l};e={x:(c-i)/r,y:c}}else{if(u){if(u.yp){if(u){if(u.x>=a)return}else u={x:o,y:r*o+i};e={x:a,y:r*a+i}}else{if(u){if(u.xu||s>o||r>h||i>p)){if(g=n.point){var g,v=t-n.x,d=e-n.y,y=v*v+d*d;if(l>y){var m=Math.sqrt(l=y);r=t-m,i=e-m,u=t+m,o=e+m,a=g}}for(var M=n.nodes,x=.5*(f+h),b=.5*(s+p),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:c(n,f,s,x,b);break;case 1:c(n,x,s,h,b);break;case 2:c(n,f,b,x,p);break;case 3:c(n,x,b,h,p)}}}(n,r,i,u,o),a}function vr(n,t){n=ao.rgb(n),t=ao.rgb(t);var e=n.r,r=n.g,i=n.b,u=t.r-e,o=t.g-r,a=t.b-i;return function(n){return"#"+bn(Math.round(e+u*n))+bn(Math.round(r+o*n))+bn(Math.round(i+a*n))}}function dr(n,t){var e,r={},i={};for(e in n)e in t?r[e]=Mr(n[e],t[e]):i[e]=n[e];for(e in t)e in n||(i[e]=t[e]);return function(n){for(e in r)i[e]=r[e](n);return i}}function yr(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function mr(n,t){var e,r,i,u=hl.lastIndex=pl.lastIndex=0,o=-1,a=[],l=[];for(n+="",t+="";(e=hl.exec(n))&&(r=pl.exec(t));)(i=r.index)>u&&(i=t.slice(u,i),a[o]?a[o]+=i:a[++o]=i),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,l.push({i:o,x:yr(e,r)})),u=pl.lastIndex;return ur;++r)a[(e=l[r]).i]=e.x(n);return a.join("")})}function Mr(n,t){for(var e,r=ao.interpolators.length;--r>=0&&!(e=ao.interpolators[r](n,t)););return e}function xr(n,t){var e,r=[],i=[],u=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(Mr(n[e],t[e]));for(;u>e;++e)i[e]=n[e];for(;o>e;++e)i[e]=t[e];return function(n){for(e=0;a>e;++e)i[e]=r[e](n);return i}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function kr(n){return n*n*n}function Nr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Er(n){return function(t){return Math.pow(t,n)}}function Ar(n){return 1-Math.cos(n*Io)}function Cr(n){return Math.pow(2,10*(n-1))}function zr(n){return 1-Math.sqrt(1-n*n)}function Lr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Ho*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Ho/t)}}function qr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Tr(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=ao.hcl(n),t=ao.hcl(t);var e=n.h,r=n.c,i=n.l,u=t.h-e,o=t.c-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return sn(e+u*n,r+o*n,i+a*n)+""}}function Dr(n,t){n=ao.hsl(n),t=ao.hsl(t);var e=n.h,r=n.s,i=n.l,u=t.h-e,o=t.s-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return cn(e+u*n,r+o*n,i+a*n)+""}}function Pr(n,t){n=ao.lab(n),t=ao.lab(t);var e=n.l,r=n.a,i=n.b,u=t.l-e,o=t.a-r,a=t.b-i;return function(n){return pn(e+u*n,r+o*n,i+a*n)+""}}function Ur(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function jr(n){var t=[n.a,n.b],e=[n.c,n.d],r=Hr(t),i=Fr(t,e),u=Hr(Or(e,t,-i))||0;t[0]*e[1]180?t+=360:t-n>180&&(n+=360),r.push({i:e.push(Ir(e)+"rotate(",null,")")-2,x:yr(n,t)})):t&&e.push(Ir(e)+"rotate("+t+")")}function Vr(n,t,e,r){n!==t?r.push({i:e.push(Ir(e)+"skewX(",null,")")-2,x:yr(n,t)}):t&&e.push(Ir(e)+"skewX("+t+")")}function Xr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var i=e.push(Ir(e)+"scale(",null,",",null,")");r.push({i:i-4,x:yr(n[0],t[0])},{i:i-2,x:yr(n[1],t[1])})}else 1===t[0]&&1===t[1]||e.push(Ir(e)+"scale("+t+")")}function $r(n,t){var e=[],r=[];return n=ao.transform(n),t=ao.transform(t),Yr(n.translate,t.translate,e,r),Zr(n.rotate,t.rotate,e,r),Vr(n.skew,t.skew,e,r),Xr(n.scale,t.scale,e,r),n=t=null,function(n){for(var t,i=-1,u=r.length;++i=0;)e.push(i[r])}function oi(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(u=n.children)&&(i=u.length))for(var i,u,o=-1;++oe;++e)(t=n[e][1])>i&&(r=e,i=t);return r}function yi(n){return n.reduce(mi,0)}function mi(n,t){return n+t[1]}function Mi(n,t){return xi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function xi(n,t){for(var e=-1,r=+n[0],i=(n[1]-r)/t,u=[];++e<=t;)u[e]=i*e+r;return u}function bi(n){return[ao.min(n),ao.max(n)]}function _i(n,t){return n.value-t.value}function wi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Si(n,t){n._pack_next=t,t._pack_prev=n}function ki(n,t){var e=t.x-n.x,r=t.y-n.y,i=n.r+t.r;return.999*i*i>e*e+r*r}function Ni(n){function t(n){f=Math.min(n.x-n.r,f),s=Math.max(n.x+n.r,s),h=Math.min(n.y-n.r,h),p=Math.max(n.y+n.r,p)}if((e=n.children)&&(c=e.length)){var e,r,i,u,o,a,l,c,f=1/0,s=-(1/0),h=1/0,p=-(1/0);if(e.forEach(Ei),r=e[0],r.x=-r.r,r.y=0,t(r),c>1&&(i=e[1],i.x=i.r,i.y=0,t(i),c>2))for(u=e[2],zi(r,i,u),t(u),wi(r,u),r._pack_prev=u,wi(u,i),i=r._pack_next,o=3;c>o;o++){zi(r,i,u=e[o]);var g=0,v=1,d=1;for(a=i._pack_next;a!==i;a=a._pack_next,v++)if(ki(a,u)){g=1;break}if(1==g)for(l=r._pack_prev;l!==a._pack_prev&&!ki(l,u);l=l._pack_prev,d++);g?(d>v||v==d&&i.ro;o++)u=e[o],u.x-=y,u.y-=m,M=Math.max(M,u.r+Math.sqrt(u.x*u.x+u.y*u.y));n.r=M,e.forEach(Ai)}}function Ei(n){n._pack_next=n._pack_prev=n}function Ai(n){delete n._pack_next,delete n._pack_prev}function Ci(n,t,e,r){var i=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,i)for(var u=-1,o=i.length;++u=0;)t=i[u],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Pi(n,t,e){return n.a.parent===t.parent?n.a:e}function Ui(n){return 1+ao.max(n,function(n){return n.y})}function ji(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Fi(n){var t=n.children;return t&&t.length?Fi(t[0]):n}function Hi(n){var t,e=n.children;return e&&(t=e.length)?Hi(e[t-1]):n}function Oi(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Ii(n,t){var e=n.x+t[3],r=n.y+t[0],i=n.dx-t[1]-t[3],u=n.dy-t[0]-t[2];return 0>i&&(e+=i/2,i=0),0>u&&(r+=u/2,u=0),{x:e,y:r,dx:i,dy:u}}function Yi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Zi(n){return n.rangeExtent?n.rangeExtent():Yi(n.range())}function Vi(n,t,e,r){var i=e(n[0],n[1]),u=r(t[0],t[1]);return function(n){return u(i(n))}}function Xi(n,t){var e,r=0,i=n.length-1,u=n[r],o=n[i];return u>o&&(e=r,r=i,i=e,e=u,u=o,o=e),n[r]=t.floor(u),n[i]=t.ceil(o),n}function $i(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:Sl}function Bi(n,t,e,r){var i=[],u=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Bi:Vi,l=r?Wr:Br;return o=i(n,t,l,e),a=i(t,n,l,Mr),u}function u(n){return o(n)}var o,a;return u.invert=function(n){return a(n)},u.domain=function(t){return arguments.length?(n=t.map(Number),i()):n},u.range=function(n){return arguments.length?(t=n,i()):t},u.rangeRound=function(n){return u.range(n).interpolate(Ur)},u.clamp=function(n){return arguments.length?(r=n,i()):r},u.interpolate=function(n){return arguments.length?(e=n,i()):e},u.ticks=function(t){return Qi(n,t)},u.tickFormat=function(t,e){return nu(n,t,e)},u.nice=function(t){return Gi(n,t),i()},u.copy=function(){return Wi(n,t,e,r)},i()}function Ji(n,t){return ao.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Gi(n,t){return Xi(n,$i(Ki(n,t)[2])),Xi(n,$i(Ki(n,t)[2])),n}function Ki(n,t){null==t&&(t=10);var e=Yi(n),r=e[1]-e[0],i=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),u=t/r*i;return.15>=u?i*=10:.35>=u?i*=5:.75>=u&&(i*=2),e[0]=Math.ceil(e[0]/i)*i,e[1]=Math.floor(e[1]/i)*i+.5*i,e[2]=i,e}function Qi(n,t){return ao.range.apply(ao,Ki(n,t))}function nu(n,t,e){var r=Ki(n,t);if(e){var i=ha.exec(e);if(i.shift(),"s"===i[8]){var u=ao.formatPrefix(Math.max(xo(r[0]),xo(r[1])));return i[7]||(i[7]="."+tu(u.scale(r[2]))),i[8]="f",e=ao.format(i.join("")),function(n){return e(u.scale(n))+u.symbol}}i[7]||(i[7]="."+eu(i[8],r)),e=i.join("")}else e=",."+tu(r[2])+"f";return ao.format(e)}function tu(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function eu(n,t){var e=tu(t[2]);return n in kl?Math.abs(e-tu(Math.max(xo(t[0]),xo(t[1]))))+ +("e"!==n):e-2*("%"===n)}function ru(n,t,e,r){function i(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function u(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(i(t))}return o.invert=function(t){return u(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(i)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(i)),o):t},o.nice=function(){var t=Xi(r.map(i),e?Math:El);return n.domain(t),r=t.map(u),o},o.ticks=function(){var n=Yi(r),o=[],a=n[0],l=n[1],c=Math.floor(i(a)),f=Math.ceil(i(l)),s=t%1?2:t;if(isFinite(f-c)){if(e){for(;f>c;c++)for(var h=1;s>h;h++)o.push(u(c)*h);o.push(u(c))}else for(o.push(u(c));c++0;h--)o.push(u(c)*h);for(c=0;o[c]l;f--);o=o.slice(c,f)}return o},o.tickFormat=function(n,e){if(!arguments.length)return Nl;arguments.length<2?e=Nl:"function"!=typeof e&&(e=ao.format(e));var r=Math.max(1,t*n/o.ticks().length);return function(n){var o=n/u(Math.round(i(n)));return t-.5>o*t&&(o*=t),r>=o?e(n):""}},o.copy=function(){return ru(n.copy(),t,e,r)},Ji(o,n)}function iu(n,t,e){function r(t){return n(i(t))}var i=uu(t),u=uu(1/t);return r.invert=function(t){return u(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(i)),r):e},r.ticks=function(n){return Qi(e,n)},r.tickFormat=function(n,t){return nu(e,n,t)},r.nice=function(n){return r.domain(Gi(e,n))},r.exponent=function(o){return arguments.length?(i=uu(t=o),u=uu(1/t),n.domain(e.map(i)),r):t},r.copy=function(){return iu(n.copy(),t,e)},Ji(r,n)}function uu(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ou(n,t){function e(e){return u[((i.get(e)||("range"===t.t?i.set(e,n.push(e)):NaN))-1)%u.length]}function r(t,e){return ao.range(n.length).map(function(n){return t+e*n})}var i,u,o;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new c;for(var u,o=-1,a=r.length;++oe?[NaN,NaN]:[e>0?a[e-1]:n[0],et?NaN:t/u+n,[t,t+1/u]},r.copy=function(){return lu(n,t,e)},i()}function cu(n,t){function e(e){return e>=e?t[ao.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return cu(n,t)},e}function fu(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Qi(n,t)},t.tickFormat=function(t,e){return nu(n,t,e)},t.copy=function(){return fu(n)},t}function su(){return 0}function hu(n){return n.innerRadius}function pu(n){return n.outerRadius}function gu(n){return n.startAngle}function vu(n){return n.endAngle}function du(n){return n&&n.padAngle}function yu(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function mu(n,t,e,r,i){var u=n[0]-t[0],o=n[1]-t[1],a=(i?r:-r)/Math.sqrt(u*u+o*o),l=a*o,c=-a*u,f=n[0]+l,s=n[1]+c,h=t[0]+l,p=t[1]+c,g=(f+h)/2,v=(s+p)/2,d=h-f,y=p-s,m=d*d+y*y,M=e-r,x=f*p-h*s,b=(0>y?-1:1)*Math.sqrt(Math.max(0,M*M*m-x*x)),_=(x*y-d*b)/m,w=(-x*d-y*b)/m,S=(x*y+d*b)/m,k=(-x*d+y*b)/m,N=_-g,E=w-v,A=S-g,C=k-v;return N*N+E*E>A*A+C*C&&(_=S,w=k),[[_-l,w-c],[_*e/M,w*e/M]]}function Mu(n){function t(t){function o(){c.push("M",u(n(f),a))}for(var l,c=[],f=[],s=-1,h=t.length,p=En(e),g=En(r);++s1?n.join("L"):n+"Z"}function bu(n){return n.join("L")+"Z"}function _u(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t1&&i.push("H",r[0]),i.join("")}function wu(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t1){a=t[1],u=n[l],l++,r+="C"+(i[0]+o[0])+","+(i[1]+o[1])+","+(u[0]-a[0])+","+(u[1]-a[1])+","+u[0]+","+u[1];for(var c=2;c9&&(i=3*t/Math.sqrt(i),o[a]=i*e,o[a+1]=i*r));for(a=-1;++a<=l;)i=(n[Math.min(l,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),u.push([i||0,o[a]*i||0]);return u}function Fu(n){return n.length<3?xu(n):n[0]+Au(n,ju(n))}function Hu(n){for(var t,e,r,i=-1,u=n.length;++i=t?o(n-t):void(f.c=o)}function o(e){var i=g.active,u=g[i];u&&(u.timer.c=null,u.timer.t=NaN,--g.count,delete g[i],u.event&&u.event.interrupt.call(n,n.__data__,u.index));for(var o in g)if(r>+o){var c=g[o];c.timer.c=null,c.timer.t=NaN,--g.count,delete g[o]}f.c=a,qn(function(){return f.c&&a(e||1)&&(f.c=null,f.t=NaN),1},0,l),g.active=r,v.event&&v.event.start.call(n,n.__data__,t),p=[],v.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&p.push(r)}),h=v.ease,s=v.duration}function a(i){for(var u=i/s,o=h(u),a=p.length;a>0;)p[--a].call(n,o);return u>=1?(v.event&&v.event.end.call(n,n.__data__,t),--g.count?delete g[r]:delete n[e],1):void 0}var l,f,s,h,p,g=n[e]||(n[e]={active:0,count:0}),v=g[r];v||(l=i.time,f=qn(u,0,l),v=g[r]={tween:new c,time:l,timer:f,delay:i.delay,duration:i.duration,ease:i.ease,index:t},i=null,++g.count)}function no(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function to(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function eo(n){return n.toISOString()}function ro(n,t,e){function r(t){return n(t)}function i(n,e){var r=n[1]-n[0],i=r/e,u=ao.bisect(Kl,i);return u==Kl.length?[t.year,Ki(n.map(function(n){return n/31536e6}),e)[2]]:u?t[i/Kl[u-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Yi(r.domain()),u=null==n?i(e,10):"number"==typeof n?i(e,n):!n.range&&[{range:n},t];return u&&(n=u[0],t=u[1]),n.range(e[0],io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return ro(n.copy(),t,e)},Ji(r,n)}function io(n){return new Date(n)}function uo(n){return JSON.parse(n.responseText)}function oo(n){var t=fo.createRange();return t.selectNode(fo.body),t.createContextualFragment(n.responseText)}var ao={version:"3.5.17"},lo=[].slice,co=function(n){return lo.call(n)},fo=this.document;if(fo)try{co(fo.documentElement.childNodes)[0].nodeType}catch(so){co=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),fo)try{fo.createElement("DIV").style.setProperty("opacity",0,"")}catch(ho){var po=this.Element.prototype,go=po.setAttribute,vo=po.setAttributeNS,yo=this.CSSStyleDeclaration.prototype,mo=yo.setProperty;po.setAttribute=function(n,t){go.call(this,n,t+"")},po.setAttributeNS=function(n,t,e){vo.call(this,n,t,e+"")},yo.setProperty=function(n,t,e){mo.call(this,n,t+"",e)}}ao.ascending=e,ao.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:NaN},ao.min=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i=r){e=r;break}for(;++ir&&(e=r)}else{for(;++i=r){e=r;break}for(;++ir&&(e=r)}return e},ao.max=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i=r){e=r;break}for(;++ie&&(e=r)}else{for(;++i=r){e=r;break}for(;++ie&&(e=r)}return e},ao.extent=function(n,t){var e,r,i,u=-1,o=n.length;if(1===arguments.length){for(;++u=r){e=i=r;break}for(;++ur&&(e=r),r>i&&(i=r))}else{for(;++u=r){e=i=r;break}for(;++ur&&(e=r),r>i&&(i=r))}return[e,i]},ao.sum=function(n,t){var e,r=0,u=n.length,o=-1;if(1===arguments.length)for(;++o1?l/(f-1):void 0},ao.deviation=function(){var n=ao.variance.apply(this,arguments);return n?Math.sqrt(n):n};var Mo=u(e);ao.bisectLeft=Mo.left,ao.bisect=ao.bisectRight=Mo.right,ao.bisector=function(n){return u(1===n.length?function(t,r){return e(n(t),r)}:n)},ao.shuffle=function(n,t,e){(u=arguments.length)<3&&(e=n.length,2>u&&(t=0));for(var r,i,u=e-t;u;)i=Math.random()*u--|0,r=n[u+t],n[u+t]=n[i+t],n[i+t]=r;return n},ao.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ao.pairs=function(n){for(var t,e=0,r=n.length-1,i=n[0],u=new Array(0>r?0:r);r>e;)u[e]=[t=i,i=n[++e]];return u},ao.transpose=function(n){if(!(i=n.length))return[];for(var t=-1,e=ao.min(n,o),r=new Array(e);++t=0;)for(r=n[i],t=r.length;--t>=0;)e[--o]=r[t];return e};var xo=Math.abs;ao.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,i=[],u=a(xo(e)),o=-1;if(n*=u,t*=u,e*=u,0>e)for(;(r=n+e*++o)>t;)i.push(r/u);else for(;(r=n+e*++o)=u.length)return r?r.call(i,o):e?o.sort(e):o;for(var l,f,s,h,p=-1,g=o.length,v=u[a++],d=new c;++p=u.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,i={},u=[],o=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(ao.map,e,0),0)},i.key=function(n){return u.push(n),i},i.sortKeys=function(n){return o[u.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},ao.set=function(n){var t=new y;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(y,{has:h,add:function(n){return this._[f(n+="")]=!0,n},remove:p,values:g,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t))}}),ao.behavior={},ao.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ao.event=null,ao.requote=function(n){return n.replace(So,"\\$&")};var So=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ko={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},No=function(n,t){return t.querySelector(n)},Eo=function(n,t){return t.querySelectorAll(n)},Ao=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(Ao=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(No=function(n,t){return Sizzle(n,t)[0]||null},Eo=Sizzle,Ao=Sizzle.matchesSelector),ao.selection=function(){return ao.select(fo.documentElement)};var Co=ao.selection.prototype=[];Co.select=function(n){var t,e,r,i,u=[];n=A(n);for(var o=-1,a=this.length;++o=0&&"xmlns"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Lo.hasOwnProperty(e)?{space:Lo[e],local:n}:n}},Co.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ao.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Co.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,i=-1;if(t=e.classList){for(;++ii){if("string"!=typeof n){2>i&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>i){var u=this.node();return t(u).getComputedStyle(u,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},Co.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},Co.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},Co.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},Co.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Co.insert=function(n,t){return n=j(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Co.remove=function(){return this.each(F)},Co.data=function(n,t){function e(n,e){var r,i,u,o=n.length,s=e.length,h=Math.min(o,s),p=new Array(s),g=new Array(s),v=new Array(o);if(t){var d,y=new c,m=new Array(o);for(r=-1;++rr;++r)g[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}g.update=p,g.parentNode=p.parentNode=v.parentNode=n.parentNode,a.push(g),l.push(p),f.push(v)}var r,i,u=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++uu;u++){i.push(t=[]),t.parentNode=(e=this[u]).parentNode;for(var a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return E(i)},Co.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},Co.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,i=e.length;i>r;r++){var u=e[r];if(u)return u}return null},Co.size=function(){var n=0;return Y(this,function(){++n}),n};var qo=[];ao.selection.enter=Z,ao.selection.enter.prototype=qo,qo.append=Co.append,qo.empty=Co.empty,qo.node=Co.node,qo.call=Co.call,qo.size=Co.size,qo.select=function(n){for(var t,e,r,i,u,o=[],a=-1,l=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var To=ao.map({mouseenter:"mouseover",mouseleave:"mouseout"});fo&&To.forEach(function(n){"on"+n in fo&&To.remove(n)});var Ro,Do=0;ao.mouse=function(n){return J(n,k())};var Po=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ao.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,i=0,u=t.length;u>i;++i)if((r=t[i]).identifier===e)return J(n,r)},ao.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",o)}function e(n,t,e,u,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],g|=n|e,M=r,p({type:"drag",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(y.on(u+d,null).on(o+d,null),m(g),p({type:"dragend"}))}var c,f=this,s=ao.event.target.correspondingElement||ao.event.target,h=f.parentNode,p=r.of(f,arguments),g=0,v=n(),d=".drag"+(null==v?"":"-"+v),y=ao.select(e(s)).on(u+d,a).on(o+d,l),m=W(s),M=t(h,v);i?(c=i.apply(f,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],p({type:"dragstart"})}}var r=N(n,"drag","dragstart","dragend"),i=null,u=e(b,ao.mouse,t,"mousemove","mouseup"),o=e(G,ao.touch,m,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},ao.rebind(n,r,"on")},ao.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?co(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Uo=1e-6,jo=Uo*Uo,Fo=Math.PI,Ho=2*Fo,Oo=Ho-Uo,Io=Fo/2,Yo=Fo/180,Zo=180/Fo,Vo=Math.SQRT2,Xo=2,$o=4;ao.interpolateZoom=function(n,t){var e,r,i=n[0],u=n[1],o=n[2],a=t[0],l=t[1],c=t[2],f=a-i,s=l-u,h=f*f+s*s;if(jo>h)r=Math.log(c/o)/Vo,e=function(n){return[i+n*f,u+n*s,o*Math.exp(Vo*n*r)]};else{var p=Math.sqrt(h),g=(c*c-o*o+$o*h)/(2*o*Xo*p),v=(c*c-o*o-$o*h)/(2*c*Xo*p),d=Math.log(Math.sqrt(g*g+1)-g),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-d)/Vo,e=function(n){var t=n*r,e=rn(d),a=o/(Xo*p)*(e*un(Vo*t+d)-en(d));return[i+a*f,u+a*s,o*e/rn(Vo*t+d)]}}return e.duration=1e3*r,e},ao.behavior.zoom=function(){function n(n){n.on(L,s).on(Wo+".zoom",p).on("dblclick.zoom",g).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function i(n){k.k=Math.max(A[0],Math.min(A[1],n))}function u(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},i(Math.pow(2,o)),u(d=e,r),t=ao.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function l(n){z++||n({type:"zoomstart"})}function c(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function f(n){--z||(n({type:"zoomend"}),d=null)}function s(){function n(){a=1,u(ao.mouse(i),h),c(o)}function r(){s.on(q,null).on(T,null),p(a),f(o)}var i=this,o=D.of(i,arguments),a=0,s=ao.select(t(i)).on(q,n).on(T,r),h=e(ao.mouse(i)),p=W(i);Il.call(i),l(o)}function h(){function n(){var n=ao.touches(g);return p=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ao.event.target;ao.select(t).on(x,r).on(b,a),_.push(t);for(var e=ao.event.changedTouches,i=0,u=e.length;u>i;++i)d[e[i].identifier]=null;var l=n(),c=Date.now();if(1===l.length){if(500>c-M){var f=l[0];o(g,f,d[f.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=c}else if(l.length>1){var f=l[0],s=l[1],h=f[0]-s[0],p=f[1]-s[1];y=h*h+p*p}}function r(){var n,t,e,r,o=ao.touches(g);Il.call(g);for(var a=0,l=o.length;l>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var f=(f=e[0]-n[0])*f+(f=e[1]-n[1])*f,s=y&&Math.sqrt(f/y);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],i(s*p)}M=null,u(n,t),c(v)}function a(){if(ao.event.touches.length){for(var t=ao.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var i in d)return void n()}ao.selectAll(_).on(m,null),w.on(L,s).on(R,h),N(),f(v)}var p,g=this,v=D.of(g,arguments),d={},y=0,m=".zoom-"+ao.event.changedTouches[0].identifier,x="touchmove"+m,b="touchend"+m,_=[],w=ao.select(g),N=W(g);t(),l(v),w.on(L,null).on(R,t)}function p(){var n=D.of(this,arguments);m?clearTimeout(m):(Il.call(this),v=e(d=y||ao.mouse(this)),l(n)),m=setTimeout(function(){m=null,f(n)},50),S(),i(Math.pow(2,.002*Bo())*k.k),u(d,v),c(n)}function g(){var n=ao.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ao.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,y,m,M,x,b,_,w,k={x:0,y:0,k:1},E=[960,500],A=Jo,C=250,z=0,L="mousedown.zoom",q="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=N(n,"zoomstart","zoom","zoomend");return Wo||(Wo="onwheel"in fo?(Bo=function(){return-ao.event.deltaY*(ao.event.deltaMode?120:1)},"wheel"):"onmousewheel"in fo?(Bo=function(){return ao.event.wheelDelta},"mousewheel"):(Bo=function(){return-ao.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Hl?ao.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},l(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],i=d?d[0]:e/2,u=d?d[1]:r/2,o=ao.interpolateZoom([(i-k.x)/k.k,(u-k.y)/k.k,e/k.k],[(i-t.x)/t.k,(u-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:i-r[0]*a,y:u-r[1]*a,k:a},c(n)}}).each("interrupt.zoom",function(){f(n)}).each("end.zoom",function(){f(n)}):(this.__chart__=k,l(n),c(n),f(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:null},i(+t),a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(A=null==t?Jo:[+t[0],+t[1]],n):A},n.center=function(t){return arguments.length?(y=t&&[+t[0],+t[1]],n):y},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ao.rebind(n,D,"on")};var Bo,Wo,Jo=[0,1/0];ao.color=an,an.prototype.toString=function(){return this.rgb()+""},ao.hsl=ln;var Go=ln.prototype=new an;Go.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,this.l/n)},Go.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,n*this.l)},Go.rgb=function(){return cn(this.h,this.s,this.l)},ao.hcl=fn;var Ko=fn.prototype=new an;Ko.brighter=function(n){return new fn(this.h,this.c,Math.min(100,this.l+Qo*(arguments.length?n:1)))},Ko.darker=function(n){return new fn(this.h,this.c,Math.max(0,this.l-Qo*(arguments.length?n:1)))},Ko.rgb=function(){return sn(this.h,this.c,this.l).rgb()},ao.lab=hn;var Qo=18,na=.95047,ta=1,ea=1.08883,ra=hn.prototype=new an;ra.brighter=function(n){return new hn(Math.min(100,this.l+Qo*(arguments.length?n:1)),this.a,this.b)},ra.darker=function(n){return new hn(Math.max(0,this.l-Qo*(arguments.length?n:1)),this.a,this.b)},ra.rgb=function(){return pn(this.l,this.a,this.b)},ao.rgb=mn;var ia=mn.prototype=new an;ia.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,i=30;return t||e||r?(t&&i>t&&(t=i),e&&i>e&&(e=i),r&&i>r&&(r=i),new mn(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mn(i,i,i)},ia.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mn(n*this.r,n*this.g,n*this.b)},ia.hsl=function(){return wn(this.r,this.g,this.b)},ia.toString=function(){return"#"+bn(this.r)+bn(this.g)+bn(this.b)};var ua=ao.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});ua.forEach(function(n,t){ua.set(n,Mn(t))}),ao.functor=En,ao.xhr=An(m),ao.dsv=function(n,t){function e(n,e,u){arguments.length<3&&(u=e,e=null);var o=Cn(n,t,null==e?r:i(e),u);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:i(n)):e},o}function r(n){return e.parse(n.responseText)}function i(n){return function(t){return e.parse(t.responseText,n)}}function u(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var i=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(i(n),e)}:i})},e.parseRows=function(n,t){function e(){if(f>=c)return o;if(i)return i=!1,u;var t=f;if(34===n.charCodeAt(t)){for(var e=t;e++f;){var r=n.charCodeAt(f++),a=1;if(10===r)i=!0;else if(13===r)i=!0,10===n.charCodeAt(f)&&(++f,++a);else if(r!==l)continue;return n.slice(t,f-a)}return n.slice(t)}for(var r,i,u={},o={},a=[],c=n.length,f=0,s=0;(r=e())!==o;){for(var h=[];r!==u&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,s++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new y,i=[];return t.forEach(function(n){for(var t in n)r.has(t)||i.push(r.add(t))}),[i.map(o).join(n)].concat(t.map(function(t){return i.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(u).join("\n")},e},ao.csv=ao.dsv(",","text/csv"),ao.tsv=ao.dsv(" ","text/tab-separated-values");var oa,aa,la,ca,fa=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ao.timer=function(){qn.apply(this,arguments)},ao.timer.flush=function(){Rn(),Dn()},ao.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var sa=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Un);ao.formatPrefix=function(n,t){var e=0;return(n=+n)&&(0>n&&(n*=-1),t&&(n=ao.round(n,Pn(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),sa[8+e/3]};var ha=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,pa=ao.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ao.round(n,Pn(n,t))).toFixed(Math.max(0,Math.min(20,Pn(n*(1+1e-15),t))))}}),ga=ao.time={},va=Date;Hn.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){da.setUTCDate.apply(this._,arguments)},setDay:function(){da.setUTCDay.apply(this._,arguments)},setFullYear:function(){da.setUTCFullYear.apply(this._,arguments)},setHours:function(){da.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){da.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){da.setUTCMinutes.apply(this._,arguments)},setMonth:function(){da.setUTCMonth.apply(this._,arguments)},setSeconds:function(){da.setUTCSeconds.apply(this._,arguments)},setTime:function(){da.setTime.apply(this._,arguments)}};var da=Date.prototype;ga.year=On(function(n){return n=ga.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ga.years=ga.year.range,ga.years.utc=ga.year.utc.range,ga.day=On(function(n){var t=new va(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ga.days=ga.day.range,ga.days.utc=ga.day.utc.range,ga.dayOfYear=function(n){var t=ga.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ga[n]=On(function(n){return(n=ga.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ga[n+"s"]=e.range,ga[n+"s"].utc=e.utc.range,ga[n+"OfYear"]=function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)}}),ga.week=ga.sunday,ga.weeks=ga.sunday.range,ga.weeks.utc=ga.sunday.utc.range,ga.weekOfYear=ga.sundayOfYear;var ya={"-":"",_:" ",0:"0"},ma=/^\s*\d+/,Ma=/^%/;ao.locale=function(n){return{numberFormat:jn(n),timeFormat:Yn(n)}};var xa=ao.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], -shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ao.format=xa.numberFormat,ao.geo={},ft.prototype={s:0,t:0,add:function(n){st(n,this.t,ba),st(ba.s,this.s,this),this.s?this.t+=ba.t:this.s=ba.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var ba=new ft;ao.geo.stream=function(n,t){n&&_a.hasOwnProperty(n.type)?_a[n.type](n,t):ht(n,t)};var _a={Feature:function(n,t){ht(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,i=e.length;++rn?4*Fo+n:n,Na.lineStart=Na.lineEnd=Na.point=b}};ao.geo.bounds=function(){function n(n,t){M.push(x=[f=n,h=n]),s>t&&(s=t),t>p&&(p=t)}function t(t,e){var r=dt([t*Yo,e*Yo]);if(y){var i=mt(y,r),u=[i[1],-i[0],0],o=mt(u,i);bt(o),o=_t(o);var l=t-g,c=l>0?1:-1,v=o[0]*Zo*c,d=xo(l)>180;if(d^(v>c*g&&c*t>v)){var m=o[1]*Zo;m>p&&(p=m)}else if(v=(v+360)%360-180,d^(v>c*g&&c*t>v)){var m=-o[1]*Zo;s>m&&(s=m)}else s>e&&(s=e),e>p&&(p=e);d?g>t?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t):h>=f?(f>t&&(f=t),t>h&&(h=t)):t>g?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t)}else n(t,e);y=r,g=t}function e(){b.point=t}function r(){x[0]=f,x[1]=h,b.point=n,y=null}function i(n,e){if(y){var r=n-g;m+=xo(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Na.point(n,e),t(n,e)}function u(){Na.lineStart()}function o(){i(v,d),Na.lineEnd(),xo(m)>Uo&&(f=-(h=180)),x[0]=f,x[1]=h,y=null}function a(n,t){return(t-=n)<0?t+360:t}function l(n,t){return n[0]-t[0]}function c(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nka?(f=-(h=180),s=-(p=90)):m>Uo?p=90:-Uo>m&&(s=-90),x[0]=f,x[1]=h}};return function(n){p=h=-(f=s=1/0),M=[],ao.geo.stream(n,b);var t=M.length;if(t){M.sort(l);for(var e,r=1,i=M[0],u=[i];t>r;++r)e=M[r],c(e[0],i)||c(e[1],i)?(a(i[0],e[1])>a(i[0],i[1])&&(i[1]=e[1]),a(e[0],i[1])>a(i[0],i[1])&&(i[0]=e[0])):u.push(i=e);for(var o,e,g=-(1/0),t=u.length-1,r=0,i=u[t];t>=r;i=e,++r)e=u[r],(o=a(i[1],e[0]))>g&&(g=o,f=e[0],h=i[1])}return M=x=null,f===1/0||s===1/0?[[NaN,NaN],[NaN,NaN]]:[[f,s],[h,p]]}}(),ao.geo.centroid=function(n){Ea=Aa=Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,ja);var t=Da,e=Pa,r=Ua,i=t*t+e*e+r*r;return jo>i&&(t=qa,e=Ta,r=Ra,Uo>Aa&&(t=Ca,e=za,r=La),i=t*t+e*e+r*r,jo>i)?[NaN,NaN]:[Math.atan2(e,t)*Zo,tn(r/Math.sqrt(i))*Zo]};var Ea,Aa,Ca,za,La,qa,Ta,Ra,Da,Pa,Ua,ja={sphere:b,point:St,lineStart:Nt,lineEnd:Et,polygonStart:function(){ja.lineStart=At},polygonEnd:function(){ja.lineStart=Nt}},Fa=Rt(zt,jt,Ht,[-Fo,-Fo/2]),Ha=1e9;ao.geo.clipExtent=function(){var n,t,e,r,i,u,o={stream:function(n){return i&&(i.valid=!1),i=u(n),i.valid=!0,i},extent:function(a){return arguments.length?(u=Zt(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),i&&(i.valid=!1,i=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ao.geo.conicEqualArea=function(){return Vt(Xt)}).raw=Xt,ao.geo.albers=function(){return ao.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ao.geo.albersUsa=function(){function n(n){var u=n[0],o=n[1];return t=null,e(u,o),t||(r(u,o),t)||i(u,o),t}var t,e,r,i,u=ao.geo.albers(),o=ao.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ao.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=u.scale(),e=u.translate(),r=(n[0]-e[0])/t,i=(n[1]-e[1])/t;return(i>=.12&&.234>i&&r>=-.425&&-.214>r?o:i>=.166&&.234>i&&r>=-.214&&-.115>r?a:u).invert(n)},n.stream=function(n){var t=u.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,i){t.point(n,i),e.point(n,i),r.point(n,i)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(u.precision(t),o.precision(t),a.precision(t),n):u.precision()},n.scale=function(t){return arguments.length?(u.scale(t),o.scale(.35*t),a.scale(t),n.translate(u.translate())):u.scale()},n.translate=function(t){if(!arguments.length)return u.translate();var c=u.scale(),f=+t[0],s=+t[1];return e=u.translate(t).clipExtent([[f-.455*c,s-.238*c],[f+.455*c,s+.238*c]]).stream(l).point,r=o.translate([f-.307*c,s+.201*c]).clipExtent([[f-.425*c+Uo,s+.12*c+Uo],[f-.214*c-Uo,s+.234*c-Uo]]).stream(l).point,i=a.translate([f-.205*c,s+.212*c]).clipExtent([[f-.214*c+Uo,s+.166*c+Uo],[f-.115*c-Uo,s+.234*c-Uo]]).stream(l).point,n},n.scale(1070)};var Oa,Ia,Ya,Za,Va,Xa,$a={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Ia=0,$a.lineStart=$t},polygonEnd:function(){$a.lineStart=$a.lineEnd=$a.point=b,Oa+=xo(Ia/2)}},Ba={point:Bt,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Wa={point:Gt,lineStart:Kt,lineEnd:Qt,polygonStart:function(){Wa.lineStart=ne},polygonEnd:function(){Wa.point=Gt,Wa.lineStart=Kt,Wa.lineEnd=Qt}};ao.geo.path=function(){function n(n){return n&&("function"==typeof a&&u.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=i(u)),ao.geo.stream(n,o)),u.result()}function t(){return o=null,n}var e,r,i,u,o,a=4.5;return n.area=function(n){return Oa=0,ao.geo.stream(n,i($a)),Oa},n.centroid=function(n){return Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,i(Wa)),Ua?[Da/Ua,Pa/Ua]:Ra?[qa/Ra,Ta/Ra]:La?[Ca/La,za/La]:[NaN,NaN]},n.bounds=function(n){return Va=Xa=-(Ya=Za=1/0),ao.geo.stream(n,i(Ba)),[[Ya,Za],[Va,Xa]]},n.projection=function(n){return arguments.length?(i=(e=n)?n.stream||re(n):m,t()):e},n.context=function(n){return arguments.length?(u=null==(r=n)?new Wt:new te(n),"function"!=typeof a&&u.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(u.pointRadius(+t),+t),n):a},n.projection(ao.geo.albersUsa()).context(null)},ao.geo.transform=function(n){return{stream:function(t){var e=new ie(t);for(var r in n)e[r]=n[r];return e}}},ie.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ao.geo.projection=oe,ao.geo.projectionMutator=ae,(ao.geo.equirectangular=function(){return oe(ce)}).raw=ce.invert=ce,ao.geo.rotation=function(n){function t(t){return t=n(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t}return n=se(n[0]%360*Yo,n[1]*Yo,n.length>2?n[2]*Yo:0),t.invert=function(t){return t=n.invert(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t},t},fe.invert=ce,ao.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=se(-n[0]*Yo,-n[1]*Yo,0).invert,i=[];return e(null,null,1,{point:function(n,e){i.push(n=t(n,e)),n[0]*=Zo,n[1]*=Zo}}),{type:"Polygon",coordinates:[i]}}var t,e,r=[0,0],i=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=ve((t=+r)*Yo,i*Yo),n):t},n.precision=function(r){return arguments.length?(e=ve(t*Yo,(i=+r)*Yo),n):i},n.angle(90)},ao.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Yo,i=n[1]*Yo,u=t[1]*Yo,o=Math.sin(r),a=Math.cos(r),l=Math.sin(i),c=Math.cos(i),f=Math.sin(u),s=Math.cos(u);return Math.atan2(Math.sqrt((e=s*o)*e+(e=c*f-l*s*a)*e),l*f+c*s*a)},ao.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ao.range(Math.ceil(u/d)*d,i,d).map(h).concat(ao.range(Math.ceil(c/y)*y,l,y).map(p)).concat(ao.range(Math.ceil(r/g)*g,e,g).filter(function(n){return xo(n%d)>Uo}).map(f)).concat(ao.range(Math.ceil(a/v)*v,o,v).filter(function(n){return xo(n%y)>Uo}).map(s))}var e,r,i,u,o,a,l,c,f,s,h,p,g=10,v=g,d=90,y=360,m=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(u).concat(p(l).slice(1),h(i).reverse().slice(1),p(c).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(u=+t[0][0],i=+t[1][0],c=+t[0][1],l=+t[1][1],u>i&&(t=u,u=i,i=t),c>l&&(t=c,c=l,l=t),n.precision(m)):[[u,c],[i,l]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(m)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],y=+t[1],n):[d,y]},n.minorStep=function(t){return arguments.length?(g=+t[0],v=+t[1],n):[g,v]},n.precision=function(t){return arguments.length?(m=+t,f=ye(a,o,90),s=me(r,e,m),h=ye(c,l,90),p=me(u,i,m),n):m},n.majorExtent([[-180,-90+Uo],[180,90-Uo]]).minorExtent([[-180,-80-Uo],[180,80+Uo]])},ao.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||i.apply(this,arguments)]}}var t,e,r=Me,i=xe;return n.distance=function(){return ao.geo.distance(t||r.apply(this,arguments),e||i.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(i=t,e="function"==typeof t?null:t,n):i},n.precision=function(){return arguments.length?n:0},n},ao.geo.interpolate=function(n,t){return be(n[0]*Yo,n[1]*Yo,t[0]*Yo,t[1]*Yo)},ao.geo.length=function(n){return Ja=0,ao.geo.stream(n,Ga),Ja};var Ja,Ga={sphere:b,point:b,lineStart:_e,lineEnd:b,polygonStart:b,polygonEnd:b},Ka=we(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ao.geo.azimuthalEqualArea=function(){return oe(Ka)}).raw=Ka;var Qa=we(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},m);(ao.geo.azimuthalEquidistant=function(){return oe(Qa)}).raw=Qa,(ao.geo.conicConformal=function(){return Vt(Se)}).raw=Se,(ao.geo.conicEquidistant=function(){return Vt(ke)}).raw=ke;var nl=we(function(n){return 1/n},Math.atan);(ao.geo.gnomonic=function(){return oe(nl)}).raw=nl,Ne.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Io]},(ao.geo.mercator=function(){return Ee(Ne)}).raw=Ne;var tl=we(function(){return 1},Math.asin);(ao.geo.orthographic=function(){return oe(tl)}).raw=tl;var el=we(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ao.geo.stereographic=function(){return oe(el)}).raw=el,Ae.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Io]},(ao.geo.transverseMercator=function(){var n=Ee(Ae),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Ae,ao.geom={},ao.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,i=En(e),u=En(r),o=n.length,a=[],l=[];for(t=0;o>t;t++)a.push([+i.call(this,n[t],t),+u.call(this,n[t],t),t]);for(a.sort(qe),t=0;o>t;t++)l.push([a[t][0],-a[t][1]]);var c=Le(a),f=Le(l),s=f[0]===c[0],h=f[f.length-1]===c[c.length-1],p=[];for(t=c.length-1;t>=0;--t)p.push(n[a[c[t]][2]]);for(t=+s;t=r&&c.x<=u&&c.y>=i&&c.y<=o?[[r,o],[u,o],[u,i],[r,i]]:[];f.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(u(n,t)/Uo)*Uo,y:Math.round(o(n,t)/Uo)*Uo,i:t}})}var r=Ce,i=ze,u=r,o=i,a=sl;return n?t(n):(t.links=function(n){return ar(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return ar(e(n)).cells.forEach(function(e,r){for(var i,u,o=e.site,a=e.edges.sort(Ve),l=-1,c=a.length,f=a[c-1].edge,s=f.l===o?f.r:f.l;++l=c,h=r>=f,p=h<<1|s;n.leaf=!1,n=n.nodes[p]||(n.nodes[p]=hr()),s?i=c:a=c,h?o=f:l=f,u(n,t,e,r,i,o,a,l)}var f,s,h,p,g,v,d,y,m,M=En(a),x=En(l);if(null!=t)v=t,d=e,y=r,m=i;else if(y=m=-(v=d=1/0),s=[],h=[],g=n.length,o)for(p=0;g>p;++p)f=n[p],f.xy&&(y=f.x),f.y>m&&(m=f.y),s.push(f.x),h.push(f.y);else for(p=0;g>p;++p){var b=+M(f=n[p],p),_=+x(f,p);v>b&&(v=b),d>_&&(d=_),b>y&&(y=b),_>m&&(m=_),s.push(b),h.push(_)}var w=y-v,S=m-d;w>S?m=d+w:y=v+S;var k=hr();if(k.add=function(n){u(k,n,+M(n,++p),+x(n,p),v,d,y,m)},k.visit=function(n){pr(n,k,v,d,y,m)},k.find=function(n){return gr(k,n[0],n[1],v,d,y,m)},p=-1,null==t){for(;++p=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=vl.get(e)||gl,r=dl.get(r)||m,br(r(e.apply(null,lo.call(arguments,1))))},ao.interpolateHcl=Rr,ao.interpolateHsl=Dr,ao.interpolateLab=Pr,ao.interpolateRound=Ur,ao.transform=function(n){var t=fo.createElementNS(ao.ns.prefix.svg,"g");return(ao.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new jr(e?e.matrix:yl)})(n)},jr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var yl={a:1,b:0,c:0,d:1,e:0,f:0};ao.interpolateTransform=$r,ao.layout={},ao.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/y){if(v>l){var c=t.charge/l;n.px-=u*c,n.py-=o*c}return!0}if(t.point&&l&&v>l){var c=t.pointCharge/l;n.px-=u*c,n.py-=o*c}}return!t.charge}}function t(n){n.px=ao.event.x,n.py=ao.event.y,l.resume()}var e,r,i,u,o,a,l={},c=ao.dispatch("start","tick","end"),f=[1,1],s=.9,h=ml,p=Ml,g=-30,v=xl,d=.1,y=.64,M=[],x=[];return l.tick=function(){if((i*=.99)<.005)return e=null,c.end({type:"end",alpha:i=0}),!0;var t,r,l,h,p,v,y,m,b,_=M.length,w=x.length;for(r=0;w>r;++r)l=x[r],h=l.source,p=l.target,m=p.x-h.x,b=p.y-h.y,(v=m*m+b*b)&&(v=i*o[r]*((v=Math.sqrt(v))-u[r])/v,m*=v,b*=v,p.x-=m*(y=h.weight+p.weight?h.weight/(h.weight+p.weight):.5),p.y-=b*y,h.x+=m*(y=1-y),h.y+=b*y);if((y=i*d)&&(m=f[0]/2,b=f[1]/2,r=-1,y))for(;++r<_;)l=M[r],l.x+=(m-l.x)*y,l.y+=(b-l.y)*y;if(g)for(ri(t=ao.geom.quadtree(M),i,a),r=-1;++r<_;)(l=M[r]).fixed||t.visit(n(l));for(r=-1;++r<_;)l=M[r],l.fixed?(l.x=l.px,l.y=l.py):(l.x-=(l.px-(l.px=l.x))*s,l.y-=(l.py-(l.py=l.y))*s);c.tick({type:"tick",alpha:i})},l.nodes=function(n){return arguments.length?(M=n,l):M},l.links=function(n){return arguments.length?(x=n,l):x},l.size=function(n){return arguments.length?(f=n,l):f},l.linkDistance=function(n){return arguments.length?(h="function"==typeof n?n:+n,l):h},l.distance=l.linkDistance,l.linkStrength=function(n){return arguments.length?(p="function"==typeof n?n:+n,l):p},l.friction=function(n){return arguments.length?(s=+n,l):s},l.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,l):g},l.chargeDistance=function(n){return arguments.length?(v=n*n,l):Math.sqrt(v)},l.gravity=function(n){return arguments.length?(d=+n,l):d},l.theta=function(n){return arguments.length?(y=n*n,l):Math.sqrt(y)},l.alpha=function(n){return arguments.length?(n=+n,i?n>0?i=n:(e.c=null,e.t=NaN,e=null,c.end({type:"end",alpha:i=0})):n>0&&(c.start({type:"start",alpha:i=n}),e=qn(l.tick)),l):i},l.start=function(){function n(n,r){if(!e){for(e=new Array(i),l=0;i>l;++l)e[l]=[];for(l=0;c>l;++l){var u=x[l];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var o,a=e[t],l=-1,f=a.length;++lt;++t)(r=M[t]).index=t,r.weight=0;for(t=0;c>t;++t)r=x[t],"number"==typeof r.source&&(r.source=M[r.source]),"number"==typeof r.target&&(r.target=M[r.target]),++r.source.weight,++r.target.weight;for(t=0;i>t;++t)r=M[t],isNaN(r.x)&&(r.x=n("x",s)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof h)for(t=0;c>t;++t)u[t]=+h.call(this,x[t],t);else for(t=0;c>t;++t)u[t]=h;if(o=[],"function"==typeof p)for(t=0;c>t;++t)o[t]=+p.call(this,x[t],t);else for(t=0;c>t;++t)o[t]=p;if(a=[],"function"==typeof g)for(t=0;i>t;++t)a[t]=+g.call(this,M[t],t);else for(t=0;i>t;++t)a[t]=g;return l.resume()},l.resume=function(){return l.alpha(.1)},l.stop=function(){return l.alpha(0)},l.drag=function(){return r||(r=ao.behavior.drag().origin(m).on("dragstart.force",Qr).on("drag.force",t).on("dragend.force",ni)),arguments.length?void this.on("mouseover.force",ti).on("mouseout.force",ei).call(r):r},ao.rebind(l,c,"on")};var ml=20,Ml=1,xl=1/0;ao.layout.hierarchy=function(){function n(i){var u,o=[i],a=[];for(i.depth=0;null!=(u=o.pop());)if(a.push(u),(c=e.call(n,u,u.depth))&&(l=c.length)){for(var l,c,f;--l>=0;)o.push(f=c[l]),f.parent=u,f.depth=u.depth+1;r&&(u.value=0),u.children=c}else r&&(u.value=+r.call(n,u,u.depth)||0),delete u.children;return oi(i,function(n){var e,i;t&&(e=n.children)&&e.sort(t),r&&(i=n.parent)&&(i.value+=n.value)}),a}var t=ci,e=ai,r=li;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(ui(t,function(n){n.children&&(n.value=0)}),oi(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ao.layout.partition=function(){function n(t,e,r,i){var u=t.children;if(t.x=e,t.y=t.depth*i,t.dx=r,t.dy=i,u&&(o=u.length)){var o,a,l,c=-1;for(r=t.value?r/t.value:0;++cs?-1:1),g=ao.sum(c),v=g?(s-l*p)/g:0,d=ao.range(l),y=[];return null!=e&&d.sort(e===bl?function(n,t){return c[t]-c[n]}:function(n,t){return e(o[n],o[t])}),d.forEach(function(n){y[n]={data:o[n],value:a=c[n],startAngle:f,endAngle:f+=a*v+p,padAngle:h}}),y}var t=Number,e=bl,r=0,i=Ho,u=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(i=t,n):i},n.padAngle=function(t){return arguments.length?(u=t,n):u},n};var bl={};ao.layout.stack=function(){function n(a,l){if(!(h=a.length))return a;var c=a.map(function(e,r){return t.call(n,e,r)}),f=c.map(function(t){return t.map(function(t,e){return[u.call(n,t,e),o.call(n,t,e)]})}),s=e.call(n,f,l);c=ao.permute(c,s),f=ao.permute(f,s);var h,p,g,v,d=r.call(n,f,l),y=c[0].length;for(g=0;y>g;++g)for(i.call(n,c[0][g],v=d[g],f[0][g][1]),p=1;h>p;++p)i.call(n,c[p][g],v+=f[p-1][g][1],f[p][g][1]);return a}var t=m,e=gi,r=vi,i=pi,u=si,o=hi;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:_l.get(t)||gi,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:wl.get(t)||vi,n):r},n.x=function(t){return arguments.length?(u=t,n):u},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(i=t,n):i},n};var _l=ao.map({"inside-out":function(n){var t,e,r=n.length,i=n.map(di),u=n.map(yi),o=ao.range(r).sort(function(n,t){return i[n]-i[t]}),a=0,l=0,c=[],f=[];for(t=0;r>t;++t)e=o[t],l>a?(a+=u[e],c.push(e)):(l+=u[e],f.push(e));return f.reverse().concat(c)},reverse:function(n){return ao.range(n.length).reverse()},"default":gi}),wl=ao.map({silhouette:function(n){var t,e,r,i=n.length,u=n[0].length,o=[],a=0,l=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;u>e;++e)l[e]=(a-o[e])/2;return l},wiggle:function(n){var t,e,r,i,u,o,a,l,c,f=n.length,s=n[0],h=s.length,p=[];for(p[0]=l=c=0,e=1;h>e;++e){for(t=0,i=0;f>t;++t)i+=n[t][e][1];for(t=0,u=0,a=s[e][0]-s[e-1][0];f>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;u+=o*n[t][e][1]}p[e]=l-=i?u/i*a:0,c>l&&(c=l)}for(e=0;h>e;++e)p[e]-=c;return p},expand:function(n){var t,e,r,i=n.length,u=n[0].length,o=1/i,a=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];if(r)for(t=0;i>t;t++)n[t][e][1]/=r;else for(t=0;i>t;t++)n[t][e][1]=o}for(e=0;u>e;++e)a[e]=0;return a},zero:vi});ao.layout.histogram=function(){function n(n,u){for(var o,a,l=[],c=n.map(e,this),f=r.call(this,c,u),s=i.call(this,f,c,u),u=-1,h=c.length,p=s.length-1,g=t?1:1/h;++u0)for(u=-1;++u=f[0]&&a<=f[1]&&(o=l[ao.bisect(s,a,1,p)-1],o.y+=g,o.push(n[u]));return l}var t=!0,e=Number,r=bi,i=Mi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=En(t),n):r},n.bins=function(t){return arguments.length?(i="number"==typeof t?function(n){return xi(n,t)}:En(t),n):i},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ao.layout.pack=function(){function n(n,u){var o=e.call(this,n,u),a=o[0],l=i[0],c=i[1],f=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,oi(a,function(n){n.r=+f(n.value)}),oi(a,Ni),r){var s=r*(t?1:Math.max(2*a.r/l,2*a.r/c))/2;oi(a,function(n){n.r+=s}),oi(a,Ni),oi(a,function(n){n.r-=s})}return Ci(a,l/2,c/2,t?1:1/Math.max(2*a.r/l,2*a.r/c)),o}var t,e=ao.layout.hierarchy().sort(_i),r=0,i=[1,1];return n.size=function(t){return arguments.length?(i=t,n):i},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},ii(n,e)},ao.layout.tree=function(){function n(n,i){var f=o.call(this,n,i),s=f[0],h=t(s);if(oi(h,e),h.parent.m=-h.z,ui(h,r),c)ui(s,u);else{var p=s,g=s,v=s;ui(s,function(n){n.xg.x&&(g=n),n.depth>v.depth&&(v=n)});var d=a(p,g)/2-p.x,y=l[0]/(g.x+a(g,p)/2+d),m=l[1]/(v.depth||1);ui(s,function(n){n.x=(n.x+d)*y,n.y=n.depth*m})}return f}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var i,u=t.children,o=0,a=u.length;a>o;++o)r.push((u[o]=i={_:u[o],parent:t,children:(i=u[o].children)&&i.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=i);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Di(n);var u=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-u):n.z=u}else r&&(n.z=r.z+a(n._,r._));n.parent.A=i(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function i(n,t,e){if(t){for(var r,i=n,u=n,o=t,l=i.parent.children[0],c=i.m,f=u.m,s=o.m,h=l.m;o=Ti(o),i=qi(i),o&&i;)l=qi(l),u=Ti(u),u.a=n,r=o.z+s-i.z-c+a(o._,i._),r>0&&(Ri(Pi(o,n,e),n,r),c+=r,f+=r),s+=o.m,c+=i.m,h+=l.m,f+=u.m;o&&!Ti(u)&&(u.t=o,u.m+=s-f),i&&!qi(l)&&(l.t=i,l.m+=c-h,e=n)}return e}function u(n){n.x*=l[0],n.y=n.depth*l[1]}var o=ao.layout.hierarchy().sort(null).value(null),a=Li,l=[1,1],c=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(c=null==(l=t)?u:null,n):c?null:l},n.nodeSize=function(t){return arguments.length?(c=null==(l=t)?null:u,n):c?l:null},ii(n,o)},ao.layout.cluster=function(){function n(n,u){var o,a=t.call(this,n,u),l=a[0],c=0;oi(l,function(n){var t=n.children;t&&t.length?(n.x=ji(t),n.y=Ui(t)):(n.x=o?c+=e(n,o):0,n.y=0,o=n)});var f=Fi(l),s=Hi(l),h=f.x-e(f,s)/2,p=s.x+e(s,f)/2;return oi(l,i?function(n){n.x=(n.x-l.x)*r[0],n.y=(l.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(p-h)*r[0],n.y=(1-(l.y?n.y/l.y:1))*r[1]}),a}var t=ao.layout.hierarchy().sort(null).value(null),e=Li,r=[1,1],i=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(i=null==(r=t),n):i?null:r},n.nodeSize=function(t){return arguments.length?(i=null!=(r=t),n):i?r:null},ii(n,t)},ao.layout.treemap=function(){function n(n,t){for(var e,r,i=-1,u=n.length;++it?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var u=e.children;if(u&&u.length){var o,a,l,c=s(e),f=[],h=u.slice(),g=1/0,v="slice"===p?c.dx:"dice"===p?c.dy:"slice-dice"===p?1&e.depth?c.dy:c.dx:Math.min(c.dx,c.dy);for(n(h,c.dx*c.dy/e.value),f.area=0;(l=h.length)>0;)f.push(o=h[l-1]),f.area+=o.area,"squarify"!==p||(a=r(f,v))<=g?(h.pop(),g=a):(f.area-=f.pop().area,i(f,v,c,!1),v=Math.min(c.dx,c.dy),f.length=f.area=0,g=1/0);f.length&&(i(f,v,c,!0),f.length=f.area=0),u.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var u,o=s(t),a=r.slice(),l=[];for(n(a,o.dx*o.dy/t.value),l.area=0;u=a.pop();)l.push(u),l.area+=u.area,null!=u.z&&(i(l,u.z?o.dx:o.dy,o,!a.length),l.length=l.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,i=0,u=1/0,o=-1,a=n.length;++oe&&(u=e),e>i&&(i=e));return r*=r,t*=t,r?Math.max(t*i*g/r,r/(t*u*g)):1/0}function i(n,t,e,r){var i,u=-1,o=n.length,a=e.x,c=e.y,f=t?l(n.area/t):0; -if(t==e.dx){for((r||f>e.dy)&&(f=e.dy);++ue.dx)&&(f=e.dx);++ue&&(t=1),1>e&&(n=0),function(){var e,r,i;do e=2*Math.random()-1,r=2*Math.random()-1,i=e*e+r*r;while(!i||i>1);return n+t*e*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var n=ao.random.normal.apply(ao,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ao.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ao.scale={};var Sl={floor:m,ceil:m};ao.scale.linear=function(){return Wi([0,1],[0,1],Mr,!1)};var kl={s:1,g:1,p:1,r:1,e:1};ao.scale.log=function(){return ru(ao.scale.linear().domain([0,1]),10,!0,[1,10])};var Nl=ao.format(".0e"),El={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ao.scale.pow=function(){return iu(ao.scale.linear(),1,[0,1])},ao.scale.sqrt=function(){return ao.scale.pow().exponent(.5)},ao.scale.ordinal=function(){return ou([],{t:"range",a:[[]]})},ao.scale.category10=function(){return ao.scale.ordinal().range(Al)},ao.scale.category20=function(){return ao.scale.ordinal().range(Cl)},ao.scale.category20b=function(){return ao.scale.ordinal().range(zl)},ao.scale.category20c=function(){return ao.scale.ordinal().range(Ll)};var Al=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(xn),Cl=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(xn),zl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(xn),Ll=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(xn);ao.scale.quantile=function(){return au([],[])},ao.scale.quantize=function(){return lu(0,1,[0,1])},ao.scale.threshold=function(){return cu([.5],[0,1])},ao.scale.identity=function(){return fu([0,1])},ao.svg={},ao.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),c=Math.max(0,+r.apply(this,arguments)),f=o.apply(this,arguments)-Io,s=a.apply(this,arguments)-Io,h=Math.abs(s-f),p=f>s?0:1;if(n>c&&(g=c,c=n,n=g),h>=Oo)return t(c,p)+(n?t(n,1-p):"")+"Z";var g,v,d,y,m,M,x,b,_,w,S,k,N=0,E=0,A=[];if((y=(+l.apply(this,arguments)||0)/2)&&(d=u===ql?Math.sqrt(n*n+c*c):+u.apply(this,arguments),p||(E*=-1),c&&(E=tn(d/c*Math.sin(y))),n&&(N=tn(d/n*Math.sin(y)))),c){m=c*Math.cos(f+E),M=c*Math.sin(f+E),x=c*Math.cos(s-E),b=c*Math.sin(s-E);var C=Math.abs(s-f-2*E)<=Fo?0:1;if(E&&yu(m,M,x,b)===p^C){var z=(f+s)/2;m=c*Math.cos(z),M=c*Math.sin(z),x=b=null}}else m=M=0;if(n){_=n*Math.cos(s-N),w=n*Math.sin(s-N),S=n*Math.cos(f+N),k=n*Math.sin(f+N);var L=Math.abs(f-s+2*N)<=Fo?0:1;if(N&&yu(_,w,S,k)===1-p^L){var q=(f+s)/2;_=n*Math.cos(q),w=n*Math.sin(q),S=k=null}}else _=w=0;if(h>Uo&&(g=Math.min(Math.abs(c-n)/2,+i.apply(this,arguments)))>.001){v=c>n^p?0:1;var T=g,R=g;if(Fo>h){var D=null==S?[_,w]:null==x?[m,M]:Re([m,M],[S,k],[x,b],[_,w]),P=m-D[0],U=M-D[1],j=x-D[0],F=b-D[1],H=1/Math.sin(Math.acos((P*j+U*F)/(Math.sqrt(P*P+U*U)*Math.sqrt(j*j+F*F)))/2),O=Math.sqrt(D[0]*D[0]+D[1]*D[1]);R=Math.min(g,(n-O)/(H-1)),T=Math.min(g,(c-O)/(H+1))}if(null!=x){var I=mu(null==S?[_,w]:[S,k],[m,M],c,T,p),Y=mu([x,b],[_,w],c,T,p);g===T?A.push("M",I[0],"A",T,",",T," 0 0,",v," ",I[1],"A",c,",",c," 0 ",1-p^yu(I[1][0],I[1][1],Y[1][0],Y[1][1]),",",p," ",Y[1],"A",T,",",T," 0 0,",v," ",Y[0]):A.push("M",I[0],"A",T,",",T," 0 1,",v," ",Y[0])}else A.push("M",m,",",M);if(null!=S){var Z=mu([m,M],[S,k],n,-R,p),V=mu([_,w],null==x?[m,M]:[x,b],n,-R,p);g===R?A.push("L",V[0],"A",R,",",R," 0 0,",v," ",V[1],"A",n,",",n," 0 ",p^yu(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-p," ",Z[1],"A",R,",",R," 0 0,",v," ",Z[0]):A.push("L",V[0],"A",R,",",R," 0 0,",v," ",Z[0])}else A.push("L",_,",",w)}else A.push("M",m,",",M),null!=x&&A.push("A",c,",",c," 0 ",C,",",p," ",x,",",b),A.push("L",_,",",w),null!=S&&A.push("A",n,",",n," 0 ",L,",",1-p," ",S,",",k);return A.push("Z"),A.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=hu,r=pu,i=su,u=ql,o=gu,a=vu,l=du;return n.innerRadius=function(t){return arguments.length?(e=En(t),n):e},n.outerRadius=function(t){return arguments.length?(r=En(t),n):r},n.cornerRadius=function(t){return arguments.length?(i=En(t),n):i},n.padRadius=function(t){return arguments.length?(u=t==ql?ql:En(t),n):u},n.startAngle=function(t){return arguments.length?(o=En(t),n):o},n.endAngle=function(t){return arguments.length?(a=En(t),n):a},n.padAngle=function(t){return arguments.length?(l=En(t),n):l},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Io;return[Math.cos(t)*n,Math.sin(t)*n]},n};var ql="auto";ao.svg.line=function(){return Mu(m)};var Tl=ao.map({linear:xu,"linear-closed":bu,step:_u,"step-before":wu,"step-after":Su,basis:zu,"basis-open":Lu,"basis-closed":qu,bundle:Tu,cardinal:Eu,"cardinal-open":ku,"cardinal-closed":Nu,monotone:Fu});Tl.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Rl=[0,2/3,1/3,0],Dl=[0,1/3,2/3,0],Pl=[0,1/6,2/3,1/6];ao.svg.line.radial=function(){var n=Mu(Hu);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},wu.reverse=Su,Su.reverse=wu,ao.svg.area=function(){return Ou(m)},ao.svg.area.radial=function(){var n=Ou(Hu);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ao.svg.chord=function(){function n(n,a){var l=t(this,u,n,a),c=t(this,o,n,a);return"M"+l.p0+r(l.r,l.p1,l.a1-l.a0)+(e(l,c)?i(l.r,l.p1,l.r,l.p0):i(l.r,l.p1,c.r,c.p0)+r(c.r,c.p1,c.a1-c.a0)+i(c.r,c.p1,l.r,l.p0))+"Z"}function t(n,t,e,r){var i=t.call(n,e,r),u=a.call(n,i,r),o=l.call(n,i,r)-Io,f=c.call(n,i,r)-Io;return{r:u,a0:o,a1:f,p0:[u*Math.cos(o),u*Math.sin(o)],p1:[u*Math.cos(f),u*Math.sin(f)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Fo)+",1 "+t}function i(n,t,e,r){return"Q 0,0 "+r}var u=Me,o=xe,a=Iu,l=gu,c=vu;return n.radius=function(t){return arguments.length?(a=En(t),n):a},n.source=function(t){return arguments.length?(u=En(t),n):u},n.target=function(t){return arguments.length?(o=En(t),n):o},n.startAngle=function(t){return arguments.length?(l=En(t),n):l},n.endAngle=function(t){return arguments.length?(c=En(t),n):c},n},ao.svg.diagonal=function(){function n(n,i){var u=t.call(this,n,i),o=e.call(this,n,i),a=(u.y+o.y)/2,l=[u,{x:u.x,y:a},{x:o.x,y:a},o];return l=l.map(r),"M"+l[0]+"C"+l[1]+" "+l[2]+" "+l[3]}var t=Me,e=xe,r=Yu;return n.source=function(e){return arguments.length?(t=En(e),n):t},n.target=function(t){return arguments.length?(e=En(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ao.svg.diagonal.radial=function(){var n=ao.svg.diagonal(),t=Yu,e=n.projection;return n.projection=function(n){return arguments.length?e(Zu(t=n)):t},n},ao.svg.symbol=function(){function n(n,r){return(Ul.get(t.call(this,n,r))||$u)(e.call(this,n,r))}var t=Xu,e=Vu;return n.type=function(e){return arguments.length?(t=En(e),n):t},n.size=function(t){return arguments.length?(e=En(t),n):e},n};var Ul=ao.map({circle:$u,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Fl)),e=t*Fl;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ao.svg.symbolTypes=Ul.keys();var jl=Math.sqrt(3),Fl=Math.tan(30*Yo);Co.transition=function(n){for(var t,e,r=Hl||++Zl,i=Ku(n),u=[],o=Ol||{time:Date.now(),ease:Nr,delay:0,duration:250},a=-1,l=this.length;++au;u++){i.push(t=[]);for(var e=this[u],a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return Wu(i,this.namespace,this.id)},Yl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(i){i[r][e].tween.set(n,t)})},Yl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function i(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function u(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?$r:Mr,a=ao.ns.qualify(n);return Ju(this,"attr."+n,t,a.local?u:i)},Yl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(i));return r&&function(n){this.setAttribute(i,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(i.space,i.local));return r&&function(n){this.setAttributeNS(i.space,i.local,r(n))}}var i=ao.ns.qualify(n);return this.tween("attr."+n,i.local?r:e)},Yl.style=function(n,e,r){function i(){this.style.removeProperty(n)}function u(e){return null==e?i:(e+="",function(){var i,u=t(this).getComputedStyle(this,null).getPropertyValue(n);return u!==e&&(i=Mr(u,e),function(t){this.style.setProperty(n,i(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Ju(this,"style."+n,e,u)},Yl.styleTween=function(n,e,r){function i(i,u){var o=e.call(this,i,u,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,i)},Yl.text=function(n){return Ju(this,"text",n,Gu)},Yl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Yl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ao.ease.apply(ao,arguments)),Y(this,function(r){r[e][t].ease=n}))},Yl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,i,u){r[e][t].delay=+n.call(r,r.__data__,i,u)}:(n=+n,function(r){r[e][t].delay=n}))},Yl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,i,u){r[e][t].duration=Math.max(1,n.call(r,r.__data__,i,u))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Yl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var i=Ol,u=Hl;try{Hl=e,Y(this,function(t,i,u){Ol=t[r][e],n.call(t,t.__data__,i,u)})}finally{Ol=i,Hl=u}}else Y(this,function(i){var u=i[r][e];(u.event||(u.event=ao.dispatch("start","end","interrupt"))).on(n,t)});return this},Yl.transition=function(){for(var n,t,e,r,i=this.id,u=++Zl,o=this.namespace,a=[],l=0,c=this.length;c>l;l++){a.push(n=[]);for(var t=this[l],f=0,s=t.length;s>f;f++)(e=t[f])&&(r=e[o][i],Qu(e,f,o,u,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Wu(a,o,u)},ao.svg.axis=function(){function n(n){n.each(function(){var n,c=ao.select(this),f=this.__chart__||e,s=this.__chart__=e.copy(),h=null==l?s.ticks?s.ticks.apply(s,a):s.domain():l,p=null==t?s.tickFormat?s.tickFormat.apply(s,a):m:t,g=c.selectAll(".tick").data(h,s),v=g.enter().insert("g",".domain").attr("class","tick").style("opacity",Uo),d=ao.transition(g.exit()).style("opacity",Uo).remove(),y=ao.transition(g.order()).style("opacity",1),M=Math.max(i,0)+o,x=Zi(s),b=c.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ao.transition(b));v.append("line"),v.append("text");var w,S,k,N,E=v.select("line"),A=y.select("line"),C=g.select("text").text(p),z=v.select("text"),L=y.select("text"),q="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=no,w="x",k="y",S="x2",N="y2",C.attr("dy",0>q?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+q*u+"V0H"+x[1]+"V"+q*u)):(n=to,w="y",k="x",S="y2",N="x2",C.attr("dy",".32em").style("text-anchor",0>q?"end":"start"),_.attr("d","M"+q*u+","+x[0]+"H0V"+x[1]+"H"+q*u)),E.attr(N,q*i),z.attr(k,q*M),A.attr(S,0).attr(N,q*i),L.attr(w,0).attr(k,q*M),s.rangeBand){var T=s,R=T.rangeBand()/2;f=s=function(n){return T(n)+R}}else f.rangeBand?f=s:d.call(n,s,f);v.call(n,f,s),y.call(n,s,s)})}var t,e=ao.scale.linear(),r=Vl,i=6,u=6,o=3,a=[10],l=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Xl?t+"":Vl,n):r},n.ticks=function(){return arguments.length?(a=co(arguments),n):a},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(i=+t,u=+arguments[e-1],n):i},n.innerTickSize=function(t){return arguments.length?(i=+t,n):i},n.outerTickSize=function(t){return arguments.length?(u=+t,n):u},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Vl="bottom",Xl={top:1,right:1,bottom:1,left:1};ao.svg.brush=function(){function n(t){t.each(function(){var t=ao.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,m);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return $l[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,s=ao.transition(t),h=ao.transition(o);c&&(l=Zi(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),r(s)),f&&(l=Zi(f),h.attr("y",l[0]).attr("height",l[1]-l[0]),i(s)),e(s)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+s[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",s[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1]-s[0])}function i(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function u(){function u(){32==ao.event.keyCode&&(C||(M=null,L[0]-=s[1],L[1]-=h[1],C=2),S())}function v(){32==ao.event.keyCode&&2==C&&(L[0]+=s[1],L[1]+=h[1],C=0,S())}function d(){var n=ao.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ao.event.altKey?(M||(M=[(s[0]+s[1])/2,(h[0]+h[1])/2]),L[0]=s[+(n[0]f?(i=r,r=f):i=f),v[0]!=r||v[1]!=i?(e?a=null:o=null,v[0]=r,v[1]=i,!0):void 0}function m(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ao.select("body").style("cursor",null),q.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ao.select(ao.event.target),w=l.of(b,arguments),k=ao.select(b),N=_.datum(),E=!/^(n|s)$/.test(N)&&c,A=!/^(e|w)$/.test(N)&&f,C=_.classed("extent"),z=W(b),L=ao.mouse(b),q=ao.select(t(b)).on("keydown.brush",u).on("keyup.brush",v);if(ao.event.changedTouches?q.on("touchmove.brush",d).on("touchend.brush",m):q.on("mousemove.brush",d).on("mouseup.brush",m),k.interrupt().selectAll("*").interrupt(),C)L[0]=s[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[s[1-T]-L[0],h[1-R]-L[1]],L[0]=s[T],L[1]=h[R]}else ao.event.altKey&&(M=L.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ao.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,l=N(n,"brushstart","brush","brushend"),c=null,f=null,s=[0,0],h=[0,0],p=!0,g=!0,v=Bl[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:s,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Hl?ao.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,s=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=xr(s,t.x),r=xr(h,t.y);return o=a=null,function(i){s=t.x=e(i),h=t.y=r(i),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,v=Bl[!c<<1|!f],n):c},n.y=function(t){return arguments.length?(f=t,v=Bl[!c<<1|!f],n):f},n.clamp=function(t){return arguments.length?(c&&f?(p=!!t[0],g=!!t[1]):c?p=!!t:f&&(g=!!t),n):c&&f?[p,g]:c?p:f?g:null},n.extent=function(t){var e,r,i,u,l;return arguments.length?(c&&(e=t[0],r=t[1],f&&(e=e[0],r=r[0]),o=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),e==s[0]&&r==s[1]||(s=[e,r])),f&&(i=t[0],u=t[1],c&&(i=i[1],u=u[1]),a=[i,u],f.invert&&(i=f(i),u=f(u)),i>u&&(l=i,i=u,u=l),i==h[0]&&u==h[1]||(h=[i,u])),n):(c&&(o?(e=o[0],r=o[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),f&&(a?(i=a[0],u=a[1]):(i=h[0],u=h[1],f.invert&&(i=f.invert(i),u=f.invert(u)),i>u&&(l=i,i=u,u=l))),c&&f?[[e,i],[r,u]]:c?[e,r]:f&&[i,u])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!f&&h[0]==h[1]},ao.rebind(n,l,"on")};var $l={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Bl=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Wl=ga.format=xa.timeFormat,Jl=Wl.utc,Gl=Jl("%Y-%m-%dT%H:%M:%S.%LZ");Wl.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?eo:Gl,eo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},eo.toString=Gl.toString,ga.second=On(function(n){return new va(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ga.seconds=ga.second.range,ga.seconds.utc=ga.second.utc.range,ga.minute=On(function(n){return new va(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ga.minutes=ga.minute.range,ga.minutes.utc=ga.minute.utc.range,ga.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new va(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ga.hours=ga.hour.range,ga.hours.utc=ga.hour.utc.range,ga.month=On(function(n){return n=ga.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ga.months=ga.month.range,ga.months.utc=ga.month.utc.range;var Kl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ql=[[ga.second,1],[ga.second,5],[ga.second,15],[ga.second,30],[ga.minute,1],[ga.minute,5],[ga.minute,15],[ga.minute,30],[ga.hour,1],[ga.hour,3],[ga.hour,6],[ga.hour,12],[ga.day,1],[ga.day,2],[ga.week,1],[ga.month,1],[ga.month,3],[ga.year,1]],nc=Wl.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",zt]]),tc={range:function(n,t,e){return ao.range(Math.ceil(n/e)*e,+t,e).map(io)},floor:m,ceil:m};Ql.year=ga.year,ga.scale=function(){return ro(ao.scale.linear(),Ql,nc)};var ec=Ql.map(function(n){return[n[0].utc,n[1]]}),rc=Jl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",zt]]);ec.year=ga.year.utc,ga.scale.utc=function(){return ro(ao.scale.linear(),ec,rc)},ao.text=An(function(n){return n.responseText}),ao.json=function(n,t){return Cn(n,"application/json",uo,t)},ao.html=function(n,t){return Cn(n,"text/html",oo,t)},ao.xml=An(function(n){return n.responseXML}),"function"==typeof define&&define.amd?(this.d3=ao,define(ao)):"object"==typeof module&&module.exports?module.exports=ao:this.d3=ao}(); \ No newline at end of file diff --git a/tests/coverage/_js/file.js b/tests/coverage/_js/file.js deleted file mode 100644 index 29cacd4..0000000 --- a/tests/coverage/_js/file.js +++ /dev/null @@ -1,62 +0,0 @@ - $(function() { - var $window = $(window) - , $top_link = $('#toplink') - , $body = $('body, html') - , offset = $('#code').offset().top - , hidePopover = function ($target) { - $target.data('popover-hover', false); - - setTimeout(function () { - if (!$target.data('popover-hover')) { - $target.popover('hide'); - } - }, 300); - }; - - $top_link.hide().click(function(event) { - event.preventDefault(); - $body.animate({scrollTop:0}, 800); - }); - - $window.scroll(function() { - if($window.scrollTop() > offset) { - $top_link.fadeIn(); - } else { - $top_link.fadeOut(); - } - }).scroll(); - - $('.popin') - .popover({trigger: 'manual'}) - .on({ - 'mouseenter.popover': function () { - var $target = $(this); - var $container = $target.children().first(); - - $target.data('popover-hover', true); - - // popover already displayed - if ($target.next('.popover').length) { - return; - } - - // show the popover - $container.popover('show'); - - // register mouse events on the popover - $target.next('.popover:not(.popover-initialized)') - .on({ - 'mouseenter': function () { - $target.data('popover-hover', true); - }, - 'mouseleave': function () { - hidePopover($container); - } - }) - .addClass('popover-initialized'); - }, - 'mouseleave.popover': function () { - hidePopover($(this).children().first()); - } - }); - }); diff --git a/tests/coverage/_js/jquery.min.js b/tests/coverage/_js/jquery.min.js deleted file mode 100644 index 2c69bc9..0000000 --- a/tests/coverage/_js/jquery.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0f&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},"undefined"!=typeof module&&"undefined"!=typeof exports&&(module.exports=a),"undefined"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.write(a):a()},a.dom.read=function(a){return void 0!==window.fastdom?fastdom.read(a):a()},a.interactiveGuideline=function(){"use strict";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],i=!0,j=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,"svg"!==d3.event.target.tagName&&(i=!1),d3.event.target.className.baseVal.match("nv-legend")&&(j=!0)),i&&(d-=f.left,e-=f.top),0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||j){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(c.nvPointerEventsClass)))return;return h.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void c.hidden(!0)}c.hidden(!1);var l=g.invert(d);h.elementMousemove({mouseX:d,mouseY:e,pointXValue:l}),"dblclick"===d3.event.type&&h.elementDblclick({mouseX:d,mouseY:e,pointXValue:l}),"click"===d3.event.type&&h.elementClick({mouseX:d,mouseY:e,pointXValue:l})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([l]),r=q.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");r.append("g").attr("class","nv-interactiveGuideLine"),j&&(j.on("touchmove",m).on("mousemove",m,!0).on("mouseout",m,!0).on("dblclick",m).on("click",m),b.guideLine=null,b.renderGuideLine=function(c){i&&(b.guideLine&&b.guideLine.attr("x1")===c||a.dom.write(function(){var b=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append("line").attr("class","nv-guideline").attr("x1",function(a){return a}).attr("x2",function(a){return a}).attr("y1",p).attr("y2",0),b.exit().remove()}))})})}var c=a.models.tooltip();c.duration(0).hideDelay(0)._isInteractiveLayer(!0).hidden(!1);var d=null,e=null,f={left:0,top:0},g=d3.scale.linear(),h=d3.dispatch("elementMousemove","elementMouseout","elementClick","elementDblclick"),i=!0,j=null,k="ActiveXObject"in window;return b.dispatch=h,b.tooltip=c,b.margin=function(a){return arguments.length?(f.top="undefined"!=typeof a.top?a.top:f.top,f.left="undefined"!=typeof a.left?a.left:f.left,b):f},b.width=function(a){return arguments.length?(d=a,b):d},b.height=function(a){return arguments.length?(e=a,b):e},b.xScale=function(a){return arguments.length?(g=a,b):g},b.showGuideLine=function(a){return arguments.length?(i=a,b):i},b.svgContainer=function(a){return arguments.length?(j=a,b):j},b},a.interactiveBisect=function(a,b,c){"use strict";if(!(a instanceof Array))return null;var d;d="function"!=typeof c?function(a){return a.x}:c;var e=function(a,b){return d(a)-b},f=d3.bisector(e).left,g=d3.max([0,f(a,b)-1]),h=d(a[g]);if("undefined"==typeof h&&(h=g),h===b)return g;var i=d3.min([g+1,a.length-1]),j=d(a[i]);return"undefined"==typeof j&&(j=i),Math.abs(j-b)>=Math.abs(h-b)?g:i},a.nearestValueIndex=function(a,b,c){"use strict";var d=1/0,e=null;return a.forEach(function(a,f){var g=Math.abs(b-a);null!=a&&d>=g&&c>g&&(d=g,e=f)}),e},function(){"use strict";a.models.tooltip=function(){function b(){if(k){var a=d3.select(k);"svg"!==a.node().tagName&&(a=a.select("svg"));var b=a.node()?a.attr("viewBox"):null;if(b){b=b.split(" ");var c=parseInt(a.style("width"),10)/b[2];p.left=p.left*c,p.top=p.top*c}}}function c(){if(!n){var a;a=k?k:document.body,n=d3.select(a).append("div").attr("class","nvtooltip "+(j?j:"xy-tooltip")).attr("id",v),n.style("top",0).style("left",0),n.style("opacity",0),n.selectAll("div, table, td, tr").classed(w,!0),n.classed(w,!0),o=n.node()}}function d(){if(r&&B(e)){b();var f=p.left,g=null!==i?i:p.top;return a.dom.write(function(){c();var b=A(e);b&&(o.innerHTML=b),k&&u?a.dom.read(function(){var a=k.getElementsByTagName("svg")[0],b={left:0,top:0};if(a){var c=a.getBoundingClientRect(),d=k.getBoundingClientRect(),e=c.top;if(0>e){var i=k.getBoundingClientRect();e=Math.abs(e)>i.height?0:e}b.top=Math.abs(e-d.top),b.left=Math.abs(c.left-d.left)}f+=k.offsetLeft+b.left-2*k.scrollLeft,g+=k.offsetTop+b.top-2*k.scrollTop,h&&h>0&&(g=Math.floor(g/h)*h),C([f,g])}):C([f,g])}),d}}var e=null,f="w",g=25,h=0,i=null,j=null,k=null,l=!0,m=400,n=null,o=null,p={left:null,top:null},q={left:0,top:0},r=!0,s=100,t=!0,u=!1,v="nvtooltip-"+Math.floor(1e5*Math.random()),w="nv-pointer-events-none",x=function(a){return a},y=function(a){return a},z=function(a){return a},A=function(a){if(null===a)return"";var b=d3.select(document.createElement("table"));if(t){var c=b.selectAll("thead").data([a]).enter().append("thead");c.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(y(a.value))}var d=b.selectAll("tbody").data([a]).enter().append("tbody"),e=d.selectAll("tr").data(function(a){return a.series}).enter().append("tr").classed("highlight",function(a){return a.highlight});e.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(a){return a.color}),e.append("td").classed("key",!0).html(function(a,b){return z(a.key,b)}),e.append("td").classed("value",!0).html(function(a,b){return x(a.value,b)}),e.selectAll("td").each(function(a){if(a.highlight){var b=d3.scale.linear().domain([0,1]).range(["#fff",a.color]),c=.6;d3.select(this).style("border-bottom-color",b(c)).style("border-top-color",b(c))}});var f=b.node().outerHTML;return void 0!==a.footer&&(f+=""),f},B=function(a){if(a&&a.series){if(a.series instanceof Array)return!!a.series.length;if(a.series instanceof Object)return a.series=[a.series],!0}return!1},C=function(b){o&&a.dom.read(function(){var c,d,e=parseInt(o.offsetHeight,10),h=parseInt(o.offsetWidth,10),i=a.utils.windowSize().width,j=a.utils.windowSize().height,k=window.pageYOffset,p=window.pageXOffset;j=window.innerWidth>=document.body.scrollWidth?j:j-16,i=window.innerHeight>=document.body.scrollHeight?i:i-16;var r,t,u=function(a){var b=d;do isNaN(a.offsetTop)||(b+=a.offsetTop),a=a.offsetParent;while(a);return b},v=function(a){var b=c;do isNaN(a.offsetLeft)||(b+=a.offsetLeft),a=a.offsetParent;while(a);return b};switch(f){case"e":c=b[0]-h-g,d=b[1]-e/2,r=v(o),t=u(o),p>r&&(c=b[0]+g>p?b[0]+g:p-r+c),k>t&&(d=k-t+d),t+e>k+j&&(d=k+j-t+d-e);break;case"w":c=b[0]+g,d=b[1]-e/2,r=v(o),t=u(o),r+h>i&&(c=b[0]-h-g),k>t&&(d=k+5),t+e>k+j&&(d=k+j-t+d-e);break;case"n":c=b[0]-h/2-5,d=b[1]+g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),t+e>k+j&&(d=k+j-t+d-e);break;case"s":c=b[0]-h/2,d=b[1]-e-g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),k>t&&(d=k);break;case"none":c=b[0],d=b[1]-g,r=v(o),t=u(o)}c-=q.left,d-=q.top;var w=o.getBoundingClientRect(),k=window.pageYOffset||document.documentElement.scrollTop,p=window.pageXOffset||document.documentElement.scrollLeft,x="translate("+(w.left+p)+"px, "+(w.top+k)+"px)",y="translate("+c+"px, "+d+"px)",z=d3.interpolateString(x,y),A=n.style("opacity")<.1;l?n.transition().delay(m).duration(0).style("opacity",0):n.interrupt().transition().duration(A?0:s).styleTween("transform",function(){return z},"important").style("-webkit-transform",y).style("opacity",1)})};return d.nvPointerEventsClass=w,d.options=a.utils.optionsFunc.bind(d),d._options=Object.create({},{duration:{get:function(){return s},set:function(a){s=a}},gravity:{get:function(){return f},set:function(a){f=a}},distance:{get:function(){return g},set:function(a){g=a}},snapDistance:{get:function(){return h},set:function(a){h=a}},classes:{get:function(){return j},set:function(a){j=a}},chartContainer:{get:function(){return k},set:function(a){k=a}},fixedTop:{get:function(){return i},set:function(a){i=a}},enabled:{get:function(){return r},set:function(a){r=a}},hideDelay:{get:function(){return m},set:function(a){m=a}},contentGenerator:{get:function(){return A},set:function(a){A=a}},valueFormatter:{get:function(){return x},set:function(a){x=a}},headerFormatter:{get:function(){return y},set:function(a){y=a}},keyFormatter:{get:function(){return z},set:function(a){z=a}},headerEnabled:{get:function(){return t},set:function(a){t=a}},_isInteractiveLayer:{get:function(){return u},set:function(a){u=!!a}},position:{get:function(){return p},set:function(a){p.left=void 0!==a.left?a.left:p.left,p.top=void 0!==a.top?a.top:p.top}},offset:{get:function(){return q},set:function(a){q.left=void 0!==a.left?a.left:q.left,q.top=void 0!==a.top?a.top:q.top}},hidden:{get:function(){return l},set:function(a){l!=a&&(l=!!a,d())}},data:{get:function(){return e},set:function(a){a.point&&(a.value=a.point.x,a.series=a.series||{},a.series.value=a.point.y,a.series.color=a.point.color||a.series.color),e=a}},tooltipElem:{get:function(){return o},set:function(){}},id:{get:function(){return v},set:function(){}}}),a.utils.initOptions(d),d}}(),a.utils.windowSize=function(){var a={width:640,height:480};return window.innerWidth&&window.innerHeight?(a.width=window.innerWidth,a.height=window.innerHeight,a):"CSS1Compat"==document.compatMode&&document.documentElement&&document.documentElement.offsetWidth?(a.width=document.documentElement.offsetWidth,a.height=document.documentElement.offsetHeight,a):document.body&&document.body.offsetWidth?(a.width=document.body.offsetWidth,a.height=document.body.offsetHeight,a):a},a.utils.windowResize=function(b){return window.addEventListener?window.addEventListener("resize",b):a.log("ERROR: Failed to bind to window.resize with: ",b),{callback:b,clear:function(){window.removeEventListener("resize",b)}}},a.utils.getColor=function(b){if(void 0===b)return a.utils.defaultColor();if(Array.isArray(b)){var c=d3.scale.ordinal().range(b);return function(a,b){var d=void 0===b?a:b;return a.color||c(d)}}return b},a.utils.defaultColor=function(){return a.utils.getColor(d3.scale.category20().range())},a.utils.customTheme=function(a,b,c){b=b||function(a){return a.key},c=c||d3.scale.category20().range();var d=c.length;return function(e){var f=b(e);return"function"==typeof a[f]?a[f]():void 0!==a[f]?a[f]:(d||(d=c.length),d-=1,c[d])}},a.utils.pjax=function(b,c){var d=function(d){d3.html(d,function(d){var e=d3.select(c).node();e.parentNode.replaceChild(d3.select(d).select(c).node(),e),a.utils.pjax(b,c)})};d3.selectAll(b).on("click",function(){history.pushState(this.href,this.textContent,this.href),d(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&d(d3.event.state)})},a.utils.calcApproxTextWidth=function(a){if("function"==typeof a.style&&"function"==typeof a.text){var b=parseInt(a.style("font-size").replace("px",""),10),c=a.text().length;return c*b*.5}return 0},a.utils.NaNtoZero=function(a){return"number"!=typeof a||isNaN(a)||null===a||1/0===a||a===-1/0?0:a},d3.selection.prototype.watchTransition=function(a){var b=[this].concat([].slice.call(arguments,1));return a.transition.apply(a,b)},a.utils.renderWatch=function(b,c){if(!(this instanceof a.utils.renderWatch))return new a.utils.renderWatch(b,c);var d=void 0!==c?c:250,e=[],f=this;this.models=function(a){return a=[].slice.call(arguments,0),a.forEach(function(a){a.__rendered=!1,function(a){a.dispatch.on("renderEnd",function(){a.__rendered=!0,f.renderEnd("model")})}(a),e.indexOf(a)<0&&e.push(a)}),this},this.reset=function(a){void 0!==a&&(d=a),e=[]},this.transition=function(a,b,c){if(b=arguments.length>1?[].slice.call(arguments,1):[],c=b.length>1?b.pop():void 0!==d?d:250,a.__rendered=!1,e.indexOf(a)<0&&e.push(a),0===c)return a.__rendered=!0,a.delay=function(){return this},a.duration=function(){return this},a;a.__rendered=0===a.length?!0:a.every(function(a){return!a.length})?!0:!1;var g=0;return a.transition().duration(c).each(function(){++g}).each("end",function(){0===--g&&(a.__rendered=!0,f.renderEnd.apply(this,b))})},this.renderEnd=function(){e.every(function(a){return a.__rendered})&&(e.forEach(function(a){a.__rendered=!1}),b.renderEnd.apply(this,arguments))}},a.utils.deepExtend=function(b){var c=arguments.length>1?[].slice.call(arguments,1):[];c.forEach(function(c){for(var d in c){var e=b[d]instanceof Array,f="object"==typeof b[d],g="object"==typeof c[d];f&&!e&&g?a.utils.deepExtend(b[d],c[d]):b[d]=c[d]}})},a.utils.state=function(){if(!(this instanceof a.utils.state))return new a.utils.state;var b={},c=function(){},d=function(){return{}},e=null,f=null;this.dispatch=d3.dispatch("change","set"),this.dispatch.on("set",function(a){c(a,!0)}),this.getter=function(a){return d=a,this},this.setter=function(a,b){return b||(b=function(){}),c=function(c,d){a(c),d&&b()},this},this.init=function(b){e=e||{},a.utils.deepExtend(e,b)};var g=function(){var a=d();if(JSON.stringify(a)===JSON.stringify(b))return!1;for(var c in a)void 0===b[c]&&(b[c]={}),b[c]=a[c],f=!0;return!0};this.update=function(){e&&(c(e,!1),e=null),g.call(this)&&this.dispatch.change(b)}},a.utils.optionsFunc=function(a){return a&&d3.map(a).forEach(function(a,b){"function"==typeof this[a]&&this[a](b)}.bind(this)),this},a.utils.calcTicksX=function(b,c){var d=1,e=0;for(e;ed?f:d}return a.log("Requested number of ticks: ",b),a.log("Calculated max values to be: ",d),b=b>d?b=d-1:b,b=1>b?1:b,b=Math.floor(b),a.log("Calculating tick count as: ",b),b},a.utils.calcTicksY=function(b,c){return a.utils.calcTicksX(b,c)},a.utils.initOption=function(a,b){a._calls&&a._calls[b]?a[b]=a._calls[b]:(a[b]=function(c){return arguments.length?(a._overrides[b]=!0,a._options[b]=c,a):a._options[b]},a["_"+b]=function(c){return arguments.length?(a._overrides[b]||(a._options[b]=c),a):a._options[b]})},a.utils.initOptions=function(b){b._overrides=b._overrides||{};var c=Object.getOwnPropertyNames(b._options||{}),d=Object.getOwnPropertyNames(b._calls||{});c=c.concat(d);for(var e in c)a.utils.initOption(b,c[e])},a.utils.inheritOptionsD3=function(a,b,c){a._d3options=c.concat(a._d3options||[]),c.unshift(b),c.unshift(a),d3.rebind.apply(this,c)},a.utils.arrayUnique=function(a){return a.sort().filter(function(b,c){return!c||b!=a[c-1]})},a.utils.symbolMap=d3.map(),a.utils.symbol=function(){function b(b,e){var f=c.call(this,b,e),g=d.call(this,b,e);return-1!==d3.svg.symbolTypes.indexOf(f)?d3.svg.symbol().type(f).size(g)():a.utils.symbolMap.get(f)(g)}var c,d=64;return b.type=function(a){return arguments.length?(c=d3.functor(a),b):c},b.size=function(a){return arguments.length?(d=d3.functor(a),b):d},b},a.utils.inheritOptions=function(b,c){var d=Object.getOwnPropertyNames(c._options||{}),e=Object.getOwnPropertyNames(c._calls||{}),f=c._inherited||[],g=c._d3options||[],h=d.concat(e).concat(f).concat(g);h.unshift(c),h.unshift(b),d3.rebind.apply(this,h),b._inherited=a.utils.arrayUnique(d.concat(e).concat(f).concat(d).concat(b._inherited||[])),b._d3options=a.utils.arrayUnique(g.concat(b._d3options||[]))},a.utils.initSVG=function(a){a.classed({"nvd3-svg":!0})},a.utils.sanitizeHeight=function(a,b){return a||parseInt(b.style("height"),10)||400},a.utils.sanitizeWidth=function(a,b){return a||parseInt(b.style("width"),10)||960},a.utils.availableHeight=function(b,c,d){return a.utils.sanitizeHeight(b,c)-d.top-d.bottom},a.utils.availableWidth=function(b,c,d){return a.utils.sanitizeWidth(b,c)-d.left-d.right},a.utils.noData=function(b,c){var d=b.options(),e=d.margin(),f=d.noData(),g=null==f?["No Data Available."]:[f],h=a.utils.availableHeight(d.height(),c,e),i=a.utils.availableWidth(d.width(),c,e),j=e.left+i/2,k=e.top+h/2;c.selectAll("g").remove();var l=c.selectAll(".nv-noData").data(g);l.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),l.attr("x",j).attr("y",k).text(function(a){return a})},a.models.axis=function(){"use strict";function b(g){return s.reset(),g.each(function(b){var g=d3.select(this);a.utils.initSVG(g);var p=g.selectAll("g.nv-wrap.nv-axis").data([b]),q=p.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),t=(q.append("g"),p.select("g"));null!==n?c.ticks(n):("top"==c.orient()||"bottom"==c.orient())&&c.ticks(Math.abs(d.range()[1]-d.range()[0])/100),t.watchTransition(s,"axis").call(c),r=r||c.scale();var u=c.tickFormat();null==u&&(u=r.tickFormat());var v=t.selectAll("text.nv-axislabel").data([h||null]);v.exit().remove();var w,x,y;switch(c.orient()){case"top":v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",0).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b))+",0)"}).select("text").attr("dy","-0.5em").attr("y",-c.tickPadding()).attr("text-anchor","middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max top").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d.range()[c])+",0)"}));break;case"bottom":w=o+36;var z=30,A=0,B=t.selectAll("g").select("text"),C="";if(j%360){B.each(function(){var a=this.getBoundingClientRect(),b=a.width;A=a.height,b>z&&(z=b)}),C="rotate("+j+" 0,"+(A/2+c.tickPadding())+")";var D=Math.abs(Math.sin(j*Math.PI/180));w=(D?D*z:z)+30,B.attr("transform",C).style("text-anchor",j%360>0?"start":"end")}v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",w).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data([d.domain()[0],d.domain()[d.domain().length-1]]),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",c.tickPadding()).attr("transform",C).style("text-anchor",j?j%360>0?"start":"end":"middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max bottom").attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"})),l&&B.attr("transform",function(a,b){return"translate(0,"+(b%2==0?"0":"12")+")"});break;case"right":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"begin").attr("transform",k?"rotate(90)":"").attr("y",k?-Math.max(e.right,f)+12:-10).attr("x",k?d3.max(d.range())/2:c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(d(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",c.tickPadding()).style("text-anchor","start").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1));break;case"left":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"end").attr("transform",k?"rotate(-90)":"").attr("y",k?-Math.max(e.left,f)+25-(o||0):-10).attr("x",k?-d3.max(d.range())/2:-c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(r(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-c.tickPadding()).attr("text-anchor","end").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1))}if(v.text(function(a){return a}),!i||"left"!==c.orient()&&"right"!==c.orient()||(t.selectAll("g").each(function(a){d3.select(this).select("text").attr("opacity",1),(d(a)d.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),d.domain()[0]==d.domain()[1]&&0==d.domain()[0]&&p.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===c.orient()||"bottom"===c.orient())){var E=[];p.selectAll("g.nv-axisMaxMin").each(function(a,b){try{E.push(b?d(a)-this.getBoundingClientRect().width-4:d(a)+this.getBoundingClientRect().width+4)}catch(c){E.push(b?d(a)-4:d(a)+4)}}),t.selectAll("g").each(function(a){(d(a)E[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}t.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*a)/1e6)&&void 0!==a}).classed("zero",!0),r=d.copy()}),s.renderEnd("axis immediate"),b}var c=d3.svg.axis(),d=d3.scale.linear(),e={top:0,right:0,bottom:0,left:0},f=75,g=60,h=null,i=!0,j=0,k=!0,l=!1,m=!1,n=null,o=0,p=250,q=d3.dispatch("renderEnd");c.scale(d).orient("bottom").tickFormat(function(a){return a});var r,s=a.utils.renderWatch(q,p);return b.axis=c,b.dispatch=q,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{axisLabelDistance:{get:function(){return o},set:function(a){o=a}},staggerLabels:{get:function(){return l},set:function(a){l=a}},rotateLabels:{get:function(){return j},set:function(a){j=a}},rotateYLabel:{get:function(){return k},set:function(a){k=a}},showMaxMin:{get:function(){return i},set:function(a){i=a}},axisLabel:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return g},set:function(a){g=a}},ticks:{get:function(){return n},set:function(a){n=a}},width:{get:function(){return f},set:function(a){f=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},duration:{get:function(){return p},set:function(a){p=a,s.reset(p)}},scale:{get:function(){return d},set:function(e){d=e,c.scale(d),m="function"==typeof d.rangeBands,a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"])}}}),a.utils.initOptions(b),a.utils.inheritOptionsD3(b,c,["orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"]),a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"]),b},a.models.boxPlot=function(){"use strict";function b(l){return v.reset(),l.each(function(b){var l=j-i.left-i.right,p=k-i.top-i.bottom;r=d3.select(this),a.utils.initSVG(r),m.domain(c||b.map(function(a,b){return o(a,b)})).rangeBands(e||[0,l],.1);var w=[];if(!d){var x=d3.min(b.map(function(a){var b=[];return b.push(a.values.Q1),a.values.hasOwnProperty("whisker_low")&&null!==a.values.whisker_low&&b.push(a.values.whisker_low),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.min(b)})),y=d3.max(b.map(function(a){var b=[];return b.push(a.values.Q3),a.values.hasOwnProperty("whisker_high")&&null!==a.values.whisker_high&&b.push(a.values.whisker_high),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.max(b)}));w=[x,y]}n.domain(d||w),n.range(f||[p,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);{var z=r.selectAll("g.nv-wrap").data([b]);z.enter().append("g").attr("class","nvd3 nv-wrap")}z.attr("transform","translate("+i.left+","+i.top+")");var A=z.selectAll(".nv-boxplot").data(function(a){return a}),B=A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);A.attr("class","nv-boxplot").attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}).classed("hover",function(a){return a.hover}),A.watchTransition(v,"nv-boxplot: boxplots").style("stroke-opacity",1).style("fill-opacity",.75).delay(function(a,c){return c*t/b.length}).attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}),A.exit().remove(),B.each(function(a,b){var c=d3.select(this);["low","high"].forEach(function(d){a.values.hasOwnProperty("whisker_"+d)&&null!==a.values["whisker_"+d]&&(c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-whisker nv-boxplot-"+d),c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-tick nv-boxplot-"+d))})});var C=A.selectAll(".nv-boxplot-outlier").data(function(a){return a.values.hasOwnProperty("outliers")&&null!==a.values.outliers?a.values.outliers:[]});C.enter().append("circle").style("fill",function(a,b,c){return q(a,c)}).style("stroke",function(a,b,c){return q(a,c)}).on("mouseover",function(a,b,c){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:a,color:q(a,c)},e:d3.event})}).on("mouseout",function(a,b,c){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:a,color:q(a,c)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),C.attr("class","nv-boxplot-outlier"),C.watchTransition(v,"nv-boxplot: nv-boxplot-outlier").attr("cx",.45*m.rangeBand()).attr("cy",function(a){return n(a)}).attr("r","3"),C.exit().remove();var D=function(){return null===u?.9*m.rangeBand():Math.min(75,.9*m.rangeBand())},E=function(){return.45*m.rangeBand()-D()/2},F=function(){return.45*m.rangeBand()+D()/2};["low","high"].forEach(function(a){var b="low"===a?"Q1":"Q3";A.select("line.nv-boxplot-whisker.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",.45*m.rangeBand()).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",.45*m.rangeBand()).attr("y2",function(a){return n(a.values[b])}),A.select("line.nv-boxplot-tick.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",E).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",F).attr("y2",function(b){return n(b.values["whisker_"+a])})}),["low","high"].forEach(function(a){B.selectAll(".nv-boxplot-"+a).on("mouseover",function(b,c,d){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mouseout",function(b,c,d){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})})}),B.append("rect").attr("class","nv-boxplot-box").on("mouseover",function(a,b){d3.select(this).classed("hover",!0),s.elementMouseover({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),s.elementMouseout({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),A.select("rect.nv-boxplot-box").watchTransition(v,"nv-boxplot: boxes").attr("y",function(a){return n(a.values.Q3)}).attr("width",D).attr("x",E).attr("height",function(a){return Math.abs(n(a.values.Q3)-n(a.values.Q1))||1}).style("fill",function(a,b){return a.color||q(a,b)}).style("stroke",function(a,b){return a.color||q(a,b)}),B.append("line").attr("class","nv-boxplot-median"),A.select("line.nv-boxplot-median").watchTransition(v,"nv-boxplot: boxplots line").attr("x1",E).attr("y1",function(a){return n(a.values.Q2)}).attr("x2",F).attr("y2",function(a){return n(a.values.Q2)}),g=m.copy(),h=n.copy()}),v.renderEnd("nv-boxplot immediate"),b}var c,d,e,f,g,h,i={top:0,right:0,bottom:0,left:0},j=960,k=500,l=Math.floor(1e4*Math.random()),m=d3.scale.ordinal(),n=d3.scale.linear(),o=function(a){return a.x},p=function(a){return a.y},q=a.utils.defaultColor(),r=null,s=d3.dispatch("elementMouseover","elementMouseout","elementMousemove","renderEnd"),t=250,u=null,v=a.utils.renderWatch(s,t);return b.dispatch=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},maxBoxWidth:{get:function(){return u},set:function(a){u=a}},x:{get:function(){return o},set:function(a){o=a}},y:{get:function(){return p},set:function(a){p=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return l},set:function(a){l=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}},duration:{get:function(){return t},set:function(a){t=a,v.reset(t)}}}),a.utils.initOptions(b),b},a.models.boxPlotChart=function(){"use strict";function b(k){return t.reset(),t.models(e),l&&t.models(f),m&&t.models(g),k.each(function(k){var p=d3.select(this);a.utils.initSVG(p);var t=(i||parseInt(p.style("width"))||960)-h.left-h.right,u=(j||parseInt(p.style("height"))||400)-h.top-h.bottom;if(b.update=function(){r.beforeUpdate(),p.transition().duration(s).call(b)},b.container=this,!(k&&k.length&&k.filter(function(a){return a.values.hasOwnProperty("Q1")&&a.values.hasOwnProperty("Q2")&&a.values.hasOwnProperty("Q3")}).length)){var v=p.selectAll(".nv-noData").data([q]);return v.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),v.attr("x",h.left+t/2).attr("y",h.top+u/2).text(function(a){return a}),b}p.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var w=p.selectAll("g.nv-wrap.nv-boxPlotWithAxes").data([k]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-boxPlotWithAxes").append("g"),y=x.append("defs"),z=w.select("g"); -x.append("g").attr("class","nv-x nv-axis"),x.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),x.append("g").attr("class","nv-barsWrap"),z.attr("transform","translate("+h.left+","+h.top+")"),n&&z.select(".nv-y.nv-axis").attr("transform","translate("+t+",0)"),e.width(t).height(u);var A=z.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));if(A.transition().call(e),y.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),z.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(o?2:1)).attr("height",16).attr("x",-c.rangeBand()/(o?1:2)),l){f.scale(c).ticks(a.utils.calcTicksX(t/100,k)).tickSize(-u,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),z.select(".nv-x.nv-axis").call(f);var B=z.select(".nv-x.nv-axis").selectAll("g");o&&B.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}m&&(g.scale(d).ticks(Math.floor(u/36)).tickSize(-t,0),z.select(".nv-y.nv-axis").call(g)),z.select(".nv-zeroLine line").attr("x1",0).attr("x2",t).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("nv-boxplot chart immediate"),b}var c,d,e=a.models.boxPlot(),f=a.models.axis(),g=a.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=a.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=a.models.tooltip(),q="No Data Available.",r=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(n?"right":"left").tickFormat(d3.format(",.1f")),p.duration(0);var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){p.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){p.data(a).hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){p.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.boxplot=e,b.xAxis=f,b.yAxis=g,b.tooltip=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},staggerLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return l},set:function(a){l=a}},showYAxis:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return tooltips},set:function(a){tooltips=a}},tooltipContent:{get:function(){return p},set:function(a){p=a}},noData:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!==a.top?a.top:h.top,h.right=void 0!==a.right?a.right:h.right,h.bottom=void 0!==a.bottom?a.bottom:h.bottom,h.left=void 0!==a.left?a.left:h.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}},rightAlignYAxis:{get:function(){return n},set:function(a){n=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.bullet=function(){"use strict";function b(d){return d.each(function(b,d){var p=m-c.left-c.right,s=n-c.top-c.bottom;o=d3.select(this),a.utils.initSVG(o);{var t=f.call(this,b,d).slice().sort(d3.descending),u=g.call(this,b,d).slice().sort(d3.descending),v=h.call(this,b,d).slice().sort(d3.descending),w=i.call(this,b,d).slice(),x=j.call(this,b,d).slice(),y=k.call(this,b,d).slice(),z=d3.scale.linear().domain(d3.extent(d3.merge([l,t]))).range(e?[p,0]:[0,p]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range())}this.__chart__=z;var A=d3.min(t),B=d3.max(t),C=t[1],D=o.selectAll("g.nv-wrap.nv-bullet").data([b]),E=D.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),F=E.append("g"),G=D.select("g");F.append("rect").attr("class","nv-range nv-rangeMax"),F.append("rect").attr("class","nv-range nv-rangeAvg"),F.append("rect").attr("class","nv-range nv-rangeMin"),F.append("rect").attr("class","nv-measure"),D.attr("transform","translate("+c.left+","+c.top+")");var H=function(a){return Math.abs(z(a)-z(0))},I=function(a){return z(0>a?a:0)};G.select("rect.nv-rangeMax").attr("height",s).attr("width",H(B>0?B:A)).attr("x",I(B>0?B:A)).datum(B>0?B:A),G.select("rect.nv-rangeAvg").attr("height",s).attr("width",H(C)).attr("x",I(C)).datum(C),G.select("rect.nv-rangeMin").attr("height",s).attr("width",H(B)).attr("x",I(B)).attr("width",H(B>0?A:B)).attr("x",I(B>0?A:B)).datum(B>0?A:B),G.select("rect.nv-measure").style("fill",q).attr("height",s/3).attr("y",s/3).attr("width",0>v?z(0)-z(v[0]):z(v[0])-z(0)).attr("x",I(v)).on("mouseover",function(){r.elementMouseover({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mouseout",function(){r.elementMouseout({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})});var J=s/6,K=u.map(function(a,b){return{value:a,label:x[b]}});F.selectAll("path.nv-markerTriangle").data(K).enter().append("path").attr("class","nv-markerTriangle").attr("transform",function(a){return"translate("+z(a.value)+","+s/2+")"}).attr("d","M0,"+J+"L"+J+","+-J+" "+-J+","+-J+"Z").on("mouseover",function(a){r.elementMouseover({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill"),pos:[z(a.value),s/2]})}).on("mousemove",function(a){r.elementMousemove({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a){r.elementMouseout({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}),D.selectAll(".nv-range").on("mouseover",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseover({value:a,label:c,color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseout({value:a,label:c,color:d3.select(this).style("fill")})})}),b}var c={top:0,right:0,bottom:0,left:0},d="left",e=!1,f=function(a){return a.ranges},g=function(a){return a.markers?a.markers:[0]},h=function(a){return a.measures},i=function(a){return a.rangeLabels?a.rangeLabels:[]},j=function(a){return a.markerLabels?a.markerLabels:[]},k=function(a){return a.measureLabels?a.measureLabels:[]},l=[0],m=380,n=30,o=null,p=null,q=a.utils.getColor(["#1f77b4"]),r=d3.dispatch("elementMouseover","elementMouseout","elementMousemove");return b.dispatch=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return f},set:function(a){f=a}},markers:{get:function(){return g},set:function(a){g=a}},measures:{get:function(){return h},set:function(a){h=a}},forceX:{get:function(){return l},set:function(a){l=a}},width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},tickFormat:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},orient:{get:function(){return d},set:function(a){d=a,e="right"==d||"bottom"==d}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.bulletChart=function(){"use strict";function b(d){return d.each(function(e,o){var p=d3.select(this);a.utils.initSVG(p);var q=a.utils.availableWidth(k,p,g),r=l-g.top-g.bottom;if(b.update=function(){b(d)},b.container=this,!e||!h.call(this,e,o))return a.utils.noData(b,p),b;p.selectAll(".nv-noData").remove();var s=h.call(this,e,o).slice().sort(d3.descending),t=i.call(this,e,o).slice().sort(d3.descending),u=j.call(this,e,o).slice().sort(d3.descending),v=p.selectAll("g.nv-wrap.nv-bulletChart").data([e]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),x=w.append("g"),y=v.select("g");x.append("g").attr("class","nv-bulletWrap"),x.append("g").attr("class","nv-titles"),v.attr("transform","translate("+g.left+","+g.top+")");var z=d3.scale.linear().domain([0,Math.max(s[0],t[0],u[0])]).range(f?[q,0]:[0,q]),A=this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range());this.__chart__=z;var B=x.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(l-g.top-g.bottom)/2+")");B.append("text").attr("class","nv-title").text(function(a){return a.title}),B.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),c.width(q).height(r);var C=y.select(".nv-bulletWrap");d3.transition(C).call(c);var D=m||z.tickFormat(q/100),E=y.selectAll("g.nv-tick").data(z.ticks(n?n:q/50),function(a){return this.textContent||D(a)}),F=E.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+A(a)+",0)"}).style("opacity",1e-6);F.append("line").attr("y1",r).attr("y2",7*r/6),F.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*r/6).text(D);var G=d3.transition(E).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1);G.select("line").attr("y1",r).attr("y2",7*r/6),G.select("text").attr("y",7*r/6),d3.transition(E.exit()).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1e-6).remove()}),d3.timer.flush(),b}var c=a.models.bullet(),d=a.models.tooltip(),e="left",f=!1,g={top:5,right:40,bottom:20,left:120},h=function(a){return a.ranges},i=function(a){return a.markers?a.markers:[0]},j=function(a){return a.measures},k=null,l=55,m=null,n=null,o=null,p=d3.dispatch("tooltipShow","tooltipHide");return d.duration(0).headerEnabled(!1),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.label,value:a.value,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.bullet=c,b.dispatch=p,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return h},set:function(a){h=a}},markers:{get:function(){return i},set:function(a){i=a}},measures:{get:function(){return j},set:function(a){j=a}},width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},tickFormat:{get:function(){return m},set:function(a){m=a}},ticks:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return o},set:function(a){o=a}},tooltips:{get:function(){return d.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),d.enabled(!!b)}},tooltipContent:{get:function(){return d.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),d.contentGenerator(b)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},orient:{get:function(){return e},set:function(a){e=a,f="right"==e||"bottom"==e}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.candlestickBar=function(){"use strict";function b(x){return x.each(function(b){c=d3.select(this);var x=a.utils.availableWidth(i,c,h),y=a.utils.availableHeight(j,c,h);a.utils.initSVG(c);var A=x/b[0].values.length*.45;l.domain(d||d3.extent(b[0].values.map(n).concat(t))),l.range(v?f||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:f||[5+A/2,x-A/2-5]),m.domain(e||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(g||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var B=d3.select(this).selectAll("g.nv-wrap.nv-candlestickBar").data([b[0].values]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-candlestickBar"),D=C.append("defs"),E=C.append("g"),F=B.select("g");E.append("g").attr("class","nv-ticks"),B.attr("transform","translate("+h.left+","+h.top+")"),c.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:k})}),D.append("clipPath").attr("id","nv-chart-clip-path-"+k).append("rect"),B.select("#nv-chart-clip-path-"+k+" rect").attr("width",x).attr("height",y),F.attr("clip-path",w?"url(#nv-chart-clip-path-"+k+")":"");var G=B.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});G.exit().remove();{var H=G.enter().append("g").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b});H.append("line").attr("class","nv-candlestick-lines").attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),H.append("rect").attr("class","nv-candlestick-rects nv-bars").attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}c.selectAll(".nv-candlestick-lines").transition().attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),c.selectAll(".nv-candlestick-rects").transition().attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}),b}var c,d,e,f,g,h={top:0,right:0,bottom:0,left:0},i=null,j=null,k=Math.floor(1e4*Math.random()),l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,d){b.clearHighlights(),c.select(".nv-candlestickBar .nv-tick-0-"+a).classed("hover",d)},b.clearHighlights=function(){c.select(".nv-candlestickBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return k},set:function(a){k=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!=a.top?a.top:h.top,h.right=void 0!=a.right?a.right:h.right,h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){"use strict";function b(l){return H.reset(),H.models(f),r&&H.models(g),s&&H.models(h),l.each(function(l){function A(){d3.select(b.container).style("cursor","ew-resize")}function E(){G.x=d3.event.x,G.i=Math.round(F.invert(G.x)),K()}function H(){d3.select(b.container).style("cursor","auto"),y.index=G.i,C.stateChange(y)}function K(){bb.data([G]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var L=d3.select(this);a.utils.initSVG(L),L.classed("nv-chart-"+x,!0);var M=this,N=a.utils.availableWidth(o,L,m),O=a.utils.availableHeight(p,L,m);if(b.update=function(){0===D?L.call(b):L.transition().duration(D).call(b)},b.container=this,y.setter(J(l),b.update).getter(I(l)).update(),y.disabled=l.map(function(a){return!!a.disabled}),!z){var P;z={};for(P in y)z[P]=y[P]instanceof Array?y[P].slice(0):y[P]}var Q=d3.behavior.drag().on("dragstart",A).on("drag",E).on("dragend",H);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,L),b;if(L.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),w)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a){var b=d3.extent(a.values,f.y());return b[0]<-.95&&(b[0]=-.95),[(b[0]-b[1])/(1+b[1]),(b[1]-b[0])/(1+b[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}F.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(G.i,l),T=v?"none":"all",U=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([l]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),W=U.select("g");if(V.append("g").attr("class","nv-interactive"),V.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),V.append("g").attr("class","nv-y nv-axis"),V.append("g").attr("class","nv-background"),V.append("g").attr("class","nv-linesWrap").style("pointer-events",T),V.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),V.append("g").attr("class","nv-legendWrap"),V.append("g").attr("class","nv-controlsWrap"),q&&(i.width(N),W.select(".nv-legendWrap").datum(l).call(i),m.top!=i.height()&&(m.top=i.height(),O=a.utils.availableHeight(p,L,m)),W.select(".nv-legendWrap").attr("transform","translate(0,"+-m.top+")")),u){var X=[{key:"Re-scale y-axis",disabled:!w}];j.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(".nv-controlsWrap").datum(X).attr("transform","translate(0,"+-m.top+")").call(j)}U.attr("transform","translate("+m.left+","+m.top+")"),t&&W.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)");var Y=l.filter(function(a){return a.tempDisabled});U.select(".tempDisabled").remove(),Y.length&&U.append("text").attr("class","tempDisabled").attr("x",N/2).attr("y","-.71em").style("text-anchor","end").text(Y.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),v&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(L).xScale(d),U.select(".nv-interactive").call(k)),V.select(".nv-background").append("rect"),W.select(".nv-background rect").attr("width",N).attr("height",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(".nv-linesWrap").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!B(a)}),_=W.select(".nv-avgLinesWrap").selectAll("line").data($,function(a){return a.key}),ab=function(a){var b=e(B(a));return 0>b?0:b>O?O:b};_.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.style("stroke-opacity",function(a){var b=e(B(a));return 0>b||b>O?0:1}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.exit().remove();var bb=Z.selectAll(".nv-indexLine").data([G]);bb.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(Q),bb.attr("transform",function(a){return"translate("+F(a.i)+",0)"}).attr("height",O),r&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),W.select(".nv-x.nv-axis").call(g)),s&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(".nv-y.nv-axis").call(h)),W.select(".nv-background rect").on("click",function(){G.x=d3.mouse(this)[0],G.i=Math.round(F.invert(G.x)),y.index=G.i,C.stateChange(y),K()}),f.dispatch.on("elementClick",function(a){G.i=a.pointIndex,G.x=F(G.i),y.index=G.i,C.stateChange(y),K()}),j.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,w=!a.disabled,y.rescaleY=w,C.stateChange(y),b.update()}),i.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];C.stateChange(y),b.update()}),k.dispatch.on("elementMousemove",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:n(g,g.seriesIndex)}))}),j.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(j.map(function(a){return a.value}),o,q);null!==r&&(j[r].highlight=!0)}var s=g.tickFormat()(b.x()(d,e),e);k.tooltip.position({left:i+m.left,top:c.mouseY+m.top}).chartContainer(M.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:s,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(){f.clearHighlights()}),C.on("changeState",function(a){"undefined"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),"undefined"!=typeof a.index&&(G.i=a.index,G.x=F(G.i),y.index=a.index,bb.data([G])),"undefined"!=typeof a.rescaleY&&(w=a.rescaleY),b.update()})}),H.renderEnd("cumulativeLineChart immediate"),b}function c(a,b){return K||(K=f.y()),b.map(function(b){if(!b.values)return b;var c=b.values[a];if(null==c)return b;var d=K(c,a);return-.95>d&&!E?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(K(a,b)-d)/(1+d)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=a.utils.defaultColor(),o=null,p=null,q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=!0,x=f.id(),y=a.utils.state(),z=null,A=null,B=function(a){return a.average},C=d3.dispatch("stateChange","changeState","renderEnd"),D=250,E=!1;y.index=0,y.rescaleY=w,g.orient("bottom").tickPadding(7),h.orient(t?"right":"left"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var F=d3.scale.linear(),G={i:0,x:0},H=a.utils.renderWatch(C,D),I=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:G.i,rescaleY:w}}},J=function(a){return function(b){void 0!==b.index&&(G.i=b.index),void 0!==b.rescaleY&&(w=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on("elementMouseover.tooltip",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).position(a.pos).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){l.hidden(!0)});var K=null;return b.dispatch=C,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=y,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},rescaleY:{get:function(){return w},set:function(a){w=a}},showControls:{get:function(){return u},set:function(a){u=a}},showLegend:{get:function(){return q},set:function(a){q=a}},average:{get:function(){return B},set:function(a){B=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return A},set:function(a){A=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},noErrorCheck:{get:function(){return E},set:function(a){E=a}},tooltips:{get:function(){return l.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),l.enabled(!!b)}},tooltipContent:{get:function(){return l.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),l.contentGenerator(b)}},margin:{get:function(){return m},set:function(a){m.top=void 0!==a.top?a.top:m.top,m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),i.color(n)}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,h.orient(a?"right":"left")}},duration:{get:function(){return D},set:function(a){D=a,f.duration(D),g.duration(D),h.duration(D),H.reset(D)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){"use strict";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),o.range(t?g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]:g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);{var A=c.selectAll("g.nv-wrap.nv-discretebar").data([b]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),C=B.append("g");A.select("g")}C.append("g").attr("class","nv-groups"),A.attr("transform","translate("+j.left+","+j.top+")");var D=A.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().watchTransition(y,"discreteBar: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),D.watchTransition(y,"discreteBar: groups").style("stroke-opacity",1).style("fill-opacity",.75);var E=D.selectAll("g.nv-bar").data(function(a){return a.values});E.exit().remove();var F=E.enter().append("g").attr("transform",function(a,b){return"translate("+(n(p(a,b))+.05*n.rangeBand())+", "+o(0)+")"}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()});F.append("rect").attr("height",0).attr("width",.9*n.rangeBand()/b.length),t?(F.append("text").attr("text-anchor","middle"),E.select("text").text(function(a,b){return u(q(a,b))}).watchTransition(y,"discreteBar: bars text").attr("x",.9*n.rangeBand()/2).attr("y",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll("text").remove(),E.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(a,b){return a.color||s(a,b)}).style("stroke",function(a,b){return a.color||s(a,b)}).select("rect").attr("class",w).watchTransition(y,"discreteBar: bars rect").attr("width",.9*n.rangeBand()/b.length),E.watchTransition(y,"discreteBar: bars").attr("transform",function(a,b){var c=n(p(a,b))+.05*n.rangeBand(),d=q(a,b)<0?o(0):o(0)-o(q(a,b))<1?o(0)-1:o(q(a,b));return"translate("+c+", "+d+")"}).select("rect").attr("height",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(e&&e[0]||0))||1)}),h=n.copy(),i=o.copy()}),y.renderEnd("discreteBar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=d3.scale.ordinal(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=[0],s=a.utils.defaultColor(),t=!1,u=d3.format(",.2f"),v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),w="discreteBar",x=250,y=a.utils.renderWatch(v,x);return b.dispatch=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},forceY:{get:function(){return r},set:function(a){r=a}},showValues:{get:function(){return t},set:function(a){t=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},xScale:{get:function(){return n},set:function(a){n=a}},yScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},valueFormat:{get:function(){return u},set:function(a){u=a}},id:{get:function(){return m},set:function(a){m=a}},rectClass:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b)}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x)}}}),a.utils.initOptions(b),b},a.models.discreteBarChart=function(){"use strict";function b(h){return t.reset(),t.models(e),m&&t.models(f),n&&t.models(g),h.each(function(h){var l=d3.select(this);a.utils.initSVG(l);var q=a.utils.availableWidth(j,l,i),t=a.utils.availableHeight(k,l,i);if(b.update=function(){r.beforeUpdate(),l.transition().duration(s).call(b)},b.container=this,!(h&&h.length&&h.filter(function(a){return a.values.length}).length))return a.utils.noData(b,l),b;l.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var u=l.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([h]),v=u.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),w=v.append("defs"),x=u.select("g");v.append("g").attr("class","nv-x nv-axis"),v.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),v.append("g").attr("class","nv-barsWrap"),x.attr("transform","translate("+i.left+","+i.top+")"),o&&x.select(".nv-y.nv-axis").attr("transform","translate("+q+",0)"),e.width(q).height(t);var y=x.select(".nv-barsWrap").datum(h.filter(function(a){return!a.disabled}));if(y.transition().call(e),w.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),x.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(p?2:1)).attr("height",16).attr("x",-c.rangeBand()/(p?1:2)),m){f.scale(c)._ticks(a.utils.calcTicksX(q/100,h)).tickSize(-t,0),x.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),x.select(".nv-x.nv-axis").call(f); -var z=x.select(".nv-x.nv-axis").selectAll("g");p&&z.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}n&&(g.scale(d)._ticks(a.utils.calcTicksY(t/36,h)).tickSize(-q,0),x.select(".nv-y.nv-axis").call(g)),x.select(".nv-zeroLine line").attr("x1",0).attr("x2",q).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("discreteBar chart immediate"),b}var c,d,e=a.models.discreteBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.tooltip(),i={top:15,right:10,bottom:50,left:60},j=null,k=null,l=a.utils.getColor(),m=!0,n=!0,o=!1,p=!1,q=null,r=d3.dispatch("beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(o?"right":"left").tickFormat(d3.format(",.1f")),h.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).keyFormatter(function(a,b){return f.tickFormat()(a,b)});var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},h.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){h.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){h.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.discretebar=e,b.xAxis=f,b.yAxis=g,b.tooltip=h,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},staggerLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return m},set:function(a){m=a}},showYAxis:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return q},set:function(a){q=a}},tooltips:{get:function(){return h.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),h.enabled(!!b)}},tooltipContent:{get:function(){return h.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),h.contentGenerator(b)}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),e.color(l)}},rightAlignYAxis:{get:function(){return o},set:function(a){o=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.distribution=function(){"use strict";function b(k){return m.reset(),k.each(function(b){var k=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),l=d3.select(this);a.utils.initSVG(l),c=c||j;var n=l.selectAll("g.nv-distribution").data([b]),o=n.enter().append("g").attr("class","nvd3 nv-distribution"),p=(o.append("g"),n.select("g"));n.attr("transform","translate("+d.left+","+d.top+")");var q=p.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});q.enter().append("g"),q.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var r=q.selectAll("line.nv-dist"+g).data(function(a){return a.values});r.enter().append("line").attr(g+"1",function(a,b){return c(h(a,b))}).attr(g+"2",function(a,b){return c(h(a,b))}),m.transition(q.exit().selectAll("line.nv-dist"+g),"dist exit").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}).style("stroke-opacity",0).remove(),r.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(k+"1",0).attr(k+"2",f),m.transition(r,"dist").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),c=j.copy()}),m.renderEnd("distribution immediate"),b}var c,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=a.utils.defaultColor(),j=d3.scale.linear(),k=250,l=d3.dispatch("renderEnd"),m=a.utils.renderWatch(l,k);return b.options=a.utils.optionsFunc.bind(b),b.dispatch=l,b.margin=function(a){return arguments.length?(d.top="undefined"!=typeof a.top?a.top:d.top,d.right="undefined"!=typeof a.right?a.right:d.right,d.bottom="undefined"!=typeof a.bottom?a.bottom:d.bottom,d.left="undefined"!=typeof a.left?a.left:d.left,b):d},b.width=function(a){return arguments.length?(e=a,b):e},b.axis=function(a){return arguments.length?(g=a,b):g},b.size=function(a){return arguments.length?(f=a,b):f},b.getData=function(a){return arguments.length?(h=d3.functor(a),b):h},b.scale=function(a){return arguments.length?(j=a,b):j},b.color=function(c){return arguments.length?(i=a.utils.getColor(c),b):i},b.duration=function(a){return arguments.length?(k=a,m.reset(k),b):k},b},a.models.furiousLegend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?g(a,b):"#fff":m?void 0:a.disabled?g(a,b):"#fff"}function r(a,b){return m&&"furious"==o?a.disengaged?"#fff":g(a,b):a.disabled?"#fff":g(a,b)}return p.each(function(b){var p=d-c.left-c.right,s=d3.select(this);a.utils.initSVG(s);var t=s.selectAll("g.nv-legend").data([b]),u=(t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),t.select("g"));t.attr("transform","translate("+c.left+","+c.top+")");var v,w=u.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),x=w.enter().append("g").attr("class","nv-series");if("classic"==o)x.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),v=w.select("circle");else if("furious"==o){x.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),v=w.select("rect"),x.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var y=w.select(".nv-check-box");y.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}x.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var z=w.select("text.nv-legend-text");w.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=w.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=w.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),w.classed("nv-disabled",function(a){return a.userDisabled}),w.exit().remove(),z.attr("fill",q).text(f);var A;switch(o){case"furious":A=23;break;case"classic":A=20}if(h){var B=[];w.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}B.push(b+i)});for(var C=0,D=0,E=[];p>D&&Cp&&C>1;){E=[],C--;for(var F=0;F(E[F%C]||0)&&(E[F%C]=B[F]);D=E.reduce(function(a,b){return a+b})}for(var G=[],H=0,I=0;C>H;H++)G[H]=I,I+=E[H];w.attr("transform",function(a,b){return"translate("+G[b%C]+","+(5+Math.floor(b/C)*A)+")"}),j?u.attr("transform","translate("+(d-c.right-D)+","+c.top+")"):u.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(B.length/C)*A}else{var J,K=5,L=5,M=0;w.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return J=L,dM&&(M=L),"translate("+J+","+K+")"}),u.attr("transform","translate("+(d-c.right-M)+","+c.top+")"),e=c.top+c.bottom+K+15}"furious"==o&&v.attr("width",function(a,b){return z[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),v.style("fill",r).style("stroke",function(a,b){return a.color||g(a,b)})}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=28,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBar=function(){"use strict";function b(x){return x.each(function(b){w.reset(),k=d3.select(this);var x=a.utils.availableWidth(h,k,g),y=a.utils.availableHeight(i,k,g);a.utils.initSVG(k),l.domain(c||d3.extent(b[0].values.map(n).concat(p))),l.range(r?e||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:e||[0,x]),m.domain(d||d3.extent(b[0].values.map(o).concat(q))).range(f||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var z=k.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([b[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),B=A.append("defs"),C=A.append("g"),D=z.select("g");C.append("g").attr("class","nv-bars"),z.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){u.chartClick({data:a,index:b,pos:d3.event,id:j})}),B.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),z.select("#nv-chart-clip-path-"+j+" rect").attr("width",x).attr("height",y),D.attr("clip-path",s?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return n(a,b)});E.exit().remove(),E.enter().append("rect").attr("x",0).attr("y",function(b,c){return a.utils.NaNtoZero(m(Math.max(0,o(b,c))))}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.abs(m(o(b,c))-m(0)))}).attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).on("mouseover",function(a,b){v&&(d3.select(this).classed("hover",!0),u.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mouseout",function(a,b){v&&(d3.select(this).classed("hover",!1),u.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mousemove",function(a,b){v&&u.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v&&(u.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}).on("dblclick",function(a,b){v&&(u.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}),E.attr("fill",function(a,b){return t(a,b)}).attr("class",function(a,b,c){return(o(a,b)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+c+"-"+b}).watchTransition(w,"bars").attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).attr("width",x/b[0].values.length*.9),E.watchTransition(w,"bars").attr("y",function(b,c){var d=o(b,c)<0?m(0):m(0)-m(o(b,c))<1?m(0)-1:m(o(b,c));return a.utils.NaNtoZero(d)}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.max(Math.abs(m(o(b,c))-m(0)),1))})}),w.renderEnd("historicalBar immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=[],q=[0],r=!1,s=!0,t=a.utils.defaultColor(),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),v=!0,w=a.utils.renderWatch(u,0);return b.highlightPoint=function(a,b){k.select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},b.clearHighlights=function(){k.select(".nv-bars .nv-bar.hover").classed("hover",!1)},b.dispatch=u,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},forceX:{get:function(){return p},set:function(a){p=a}},forceY:{get:function(){return q},set:function(a){q=a}},padData:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},clipEdge:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBarChart=function(b){"use strict";function c(b){return b.each(function(k){z.reset(),z.models(f),q&&z.models(g),r&&z.models(h);var w=d3.select(this),A=this;a.utils.initSVG(w);var B=a.utils.availableWidth(n,w,l),C=a.utils.availableHeight(o,w,l);if(c.update=function(){w.transition().duration(y).call(c)},c.container=this,u.disabled=k.map(function(a){return!!a.disabled}),!v){var D;v={};for(D in u)v[D]=u[D]instanceof Array?u[D].slice(0):u[D]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(c,w),c;w.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale();var E=w.selectAll("g.nv-wrap.nv-historicalBarChart").data([k]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),G=E.select("g");F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-barsWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),p&&(i.width(B),G.select(".nv-legendWrap").datum(k).call(i),l.top!=i.height()&&(l.top=i.height(),C=a.utils.availableHeight(o,w,l)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")),E.attr("transform","translate("+l.left+","+l.top+")"),s&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),t&&(j.width(B).height(C).margin({left:l.left,top:l.top}).svgContainer(w).xScale(d),E.select(".nv-interactive").call(j)),f.width(B).height(C).color(k.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!k[b].disabled}));var H=G.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));H.transition().call(f),q&&(g.scale(d)._ticks(a.utils.calcTicksX(B/100,k)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),G.select(".nv-x.nv-axis").transition().call(g)),r&&(h.scale(e)._ticks(a.utils.calcTicksY(C/36,k)).tickSize(-B,0),G.select(".nv-y.nv-axis").transition().call(h)),j.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,n=[];k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g){e=a.interactiveBisect(g.values,b.pointXValue,c.x()),f.highlightPoint(e,!0);var h=g.values[e];void 0!==h&&(void 0===d&&(d=h),void 0===i&&(i=c.xScale()(c.x()(h,e))),n.push({key:g.key,value:c.y()(h,e),color:m(g,g.seriesIndex),data:g.values[e]}))});var o=g.tickFormat()(c.x()(d,e));j.tooltip.position({left:i+l.left,top:b.mouseY+l.top}).chartContainer(A.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:o,index:e,series:n})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(){x.tooltipHide(),f.clearHighlights()}),i.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,k.filter(function(a){return!a.disabled}).length||k.map(function(a){return a.disabled=!1,E.selectAll(".nv-series").classed("disabled",!1),a}),u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),b.transition().call(c)}),i.dispatch.on("legendDblclick",function(a){k.forEach(function(a){a.disabled=!0}),a.disabled=!1,u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),c.update()}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),c.update()})}),z.renderEnd("historicalBarChart immediate"),c}var d,e,f=b||a.models.historicalBar(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:90,bottom:50,left:90},m=a.utils.defaultColor(),n=null,o=null,p=!1,q=!0,r=!0,s=!1,t=!1,u={},v=null,w=null,x=d3.dispatch("tooltipHide","stateChange","changeState","renderEnd"),y=250;g.orient("bottom").tickPadding(7),h.orient(s?"right":"left"),k.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)});var z=a.utils.renderWatch(x,0);return f.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:c.x()(a.data),value:c.y()(a.data),color:a.color},k.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),f.dispatch.on("elementMousemove.tooltip",function(){k.position({top:d3.event.pageY,left:d3.event.pageX})()}),c.dispatch=x,c.bars=f,c.legend=i,c.xAxis=g,c.yAxis=h,c.interactiveLayer=j,c.tooltip=k,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return n},set:function(a){n=a}},height:{get:function(){return o},set:function(a){o=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),i.color(m),f.color(m)}},duration:{get:function(){return y},set:function(a){y=a,z.reset(y),h.duration(y),g.duration(y)}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,h.orient(a?"right":"left")}},useInteractiveGuideline:{get:function(){return t},set:function(a){t=a,a===!0&&c.interactive(!1)}}}),a.utils.inheritOptions(c,f),a.utils.initOptions(c),c},a.models.ohlcBarChart=function(){var b=a.models.historicalBarChart(a.models.ohlcBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
open:"+b.yAxis.tickFormat()(c.open)+"
close:"+b.yAxis.tickFormat()(c.close)+"
high"+b.yAxis.tickFormat()(c.high)+"
low:"+b.yAxis.tickFormat()(c.low)+"
"}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
open:"+b.yAxis.tickFormat()(c.open)+"
close:"+b.yAxis.tickFormat()(c.close)+"
high"+b.yAxis.tickFormat()(c.high)+"
low:"+b.yAxis.tickFormat()(c.low)+"
"}),b},a.models.legend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?"#000":"#fff":m?void 0:(a.color||(a.color=g(a,b)),a.disabled?a.color:"#fff")}function r(a,b){return m&&"furious"==o&&a.disengaged?"#eee":a.color||g(a,b)}function s(a){return m&&"furious"==o?1:a.disabled?0:1}return p.each(function(b){var g=d-c.left-c.right,p=d3.select(this);a.utils.initSVG(p);var t=p.selectAll("g.nv-legend").data([b]),u=t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),v=t.select("g");t.attr("transform","translate("+c.left+","+c.top+")");var w,x,y=v.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),z=y.enter().append("g").attr("class","nv-series");switch(o){case"furious":x=23;break;case"classic":x=20}if("classic"==o)z.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),w=y.select("circle");else if("furious"==o){z.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),w=y.select(".nv-legend-symbol"),z.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var A=y.select(".nv-check-box");A.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}z.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var B=y.select("text.nv-legend-text");y.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=y.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=y.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),y.classed("nv-disabled",function(a){return a.userDisabled}),y.exit().remove(),B.attr("fill",q).text(f);var C=0;if(h){var D=[];y.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}D.push(b+i)});var E=0,F=[];for(C=0;g>C&&Eg&&E>1;){F=[],E--;for(var G=0;G(F[G%E]||0)&&(F[G%E]=D[G]);C=F.reduce(function(a,b){return a+b})}for(var H=[],I=0,J=0;E>I;I++)H[I]=J,J+=F[I];y.attr("transform",function(a,b){return"translate("+H[b%E]+","+(5+Math.floor(b/E)*x)+")"}),j?v.attr("transform","translate("+(d-c.right-C)+","+c.top+")"):v.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(D.length/E)*x}else{var K,L=5,M=5,N=0;y.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return K=M,dN&&(N=M),K+N>C&&(C=K+N),"translate("+K+","+L+")"}),v.attr("transform","translate("+(d-c.right-N)+","+c.top+")"),e=c.top+c.bottom+L+15}if("furious"==o){w.attr("width",function(a,b){return B[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),u.insert("rect",":first-child").attr("class","nv-legend-bg").attr("fill","#eee").attr("opacity",0);var O=v.select(".nv-legend-bg");O.transition().duration(300).attr("x",-x).attr("width",C+x-12).attr("height",e+10).attr("y",-c.top-10).attr("opacity",m?1:0)}w.style("fill",r).style("fill-opacity",s).style("stroke",r)}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=32,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.line=function(){"use strict";function b(r){return v.reset(),v.models(e),r.each(function(b){i=d3.select(this);var r=a.utils.availableWidth(g,i,f),s=a.utils.availableHeight(h,i,f);a.utils.initSVG(i),c=e.xScale(),d=e.yScale(),t=t||c,u=u||d;var w=i.selectAll("g.nv-wrap.nv-line").data([b]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),y=x.append("defs"),z=x.append("g"),A=w.select("g");z.append("g").attr("class","nv-groups"),z.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+f.left+","+f.top+")"),e.width(r).height(s);var B=w.select(".nv-scatterWrap");B.call(e),y.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),w.select("#nv-edge-clip-"+e.id()+" rect").attr("width",r).attr("height",s>0?s:0),A.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":""),B.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":"");var C=w.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});C.enter().append("g").style("stroke-opacity",1e-6).style("stroke-width",function(a){return a.strokeWidth||j}).style("fill-opacity",1e-6),C.exit().remove(),C.attr("class",function(a,b){return(a.classed||"")+" nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return k(a,b)}).style("stroke",function(a,b){return k(a,b)}),C.watchTransition(v,"line: groups").style("stroke-opacity",1).style("fill-opacity",function(a){return a.fillOpacity||.5});var D=C.selectAll("path.nv-area").data(function(a){return o(a)?[a]:[]});D.enter().append("path").attr("class","nv-area").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y0(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))}).y1(function(){return u(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])}),C.exit().selectAll("path.nv-area").remove(),D.watchTransition(v,"line: areaPaths").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y0(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))}).y1(function(){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])});var E=C.selectAll("path.nv-line").data(function(a){return[a.values]});E.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))})),E.watchTransition(v,"line: linePaths").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))})),t=c.copy(),u=d.copy()}),v.renderEnd("line immediate"),b}var c,d,e=a.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=null,j=1.5,k=a.utils.defaultColor(),l=function(a){return a.x},m=function(a){return a.y},n=function(a,b){return!isNaN(m(a,b))&&null!==m(a,b)},o=function(a){return a.area},p=!1,q="linear",r=250,s=d3.dispatch("elementClick","elementMouseover","elementMouseout","renderEnd");e.pointSize(16).pointDomain([16,256]);var t,u,v=a.utils.renderWatch(s,r);return b.dispatch=s,b.scatter=e,e.dispatch.on("elementClick",function(){s.elementClick.apply(this,arguments)}),e.dispatch.on("elementMouseover",function(){s.elementMouseover.apply(this,arguments)}),e.dispatch.on("elementMouseout",function(){s.elementMouseout.apply(this,arguments)}),b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},defined:{get:function(){return n},set:function(a){n=a}},interpolate:{get:function(){return q},set:function(a){q=a}},clipEdge:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},duration:{get:function(){return r},set:function(a){r=a,v.reset(r),e.duration(r)}},isArea:{get:function(){return o},set:function(a){o=d3.functor(a)}},x:{get:function(){return l},set:function(a){l=a,e.x(a)}},y:{get:function(){return m},set:function(a){m=a,e.y(a)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineChart=function(){"use strict";function b(j){return y.reset(),y.models(e),p&&y.models(f),q&&y.models(g),j.each(function(j){var v=d3.select(this),y=this;a.utils.initSVG(v);var B=a.utils.availableWidth(m,v,k),C=a.utils.availableHeight(n,v,k);if(b.update=function(){0===x?v.call(b):v.transition().duration(x).call(b)},b.container=this,t.setter(A(j),b.update).getter(z(j)).update(),t.disabled=j.map(function(a){return!!a.disabled}),!u){var D;u={};for(D in t)u[D]=t[D]instanceof Array?t[D].slice(0):t[D] -}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,v),b;v.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var E=v.selectAll("g.nv-wrap.nv-lineChart").data([j]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),G=E.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-linesWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),G.select("rect").attr("width",B).attr("height",C>0?C:0),o&&(h.width(B),G.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),C=a.utils.availableHeight(n,v,k)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-k.top+")")),E.attr("transform","translate("+k.left+","+k.top+")"),r&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),s&&(i.width(B).height(C).margin({left:k.left,top:k.top}).svgContainer(v).xScale(c),E.select(".nv-interactive").call(i)),e.width(B).height(C).color(j.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!j[b].disabled}));var H=G.select(".nv-linesWrap").datum(j.filter(function(a){return!a.disabled}));H.call(e),p&&(f.scale(c)._ticks(a.utils.calcTicksX(B/100,j)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),G.select(".nv-x.nv-axis").call(f)),q&&(g.scale(d)._ticks(a.utils.calcTicksY(C/36,j)).tickSize(-B,0),G.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)t[c]=a[c];w.stateChange(t),b.update()}),i.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,h,m,n=[];if(j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=a.interactiveBisect(f.values,c.pointXValue,b.x());var i=f.values[h],j=b.y()(i,h);null!=j&&e.highlightPoint(g,h,!0),void 0!==i&&(void 0===d&&(d=i),void 0===m&&(m=b.xScale()(b.x()(i,h))),n.push({key:f.key,value:j,color:l(f,f.seriesIndex)}))}),n.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(n.map(function(a){return a.value}),o,q);null!==r&&(n[r].highlight=!0)}var s=f.tickFormat()(b.x()(d,h));i.tooltip.position({left:c.mouseX+k.left,top:c.mouseY+k.top}).chartContainer(y.parentNode).valueFormatter(function(a){return null==a?"N/A":g.tickFormat()(a)}).data({value:s,index:h,series:n})(),i.renderGuideLine(m)}),i.dispatch.on("elementClick",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if("undefined"!=typeof h){"undefined"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on("elementMouseout",function(){e.clearHighlights()}),w.on("changeState",function(a){"undefined"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),t.disabled=a.disabled),b.update()})}),y.renderEnd("lineChart immediate"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=a.utils.defaultColor(),m=null,n=null,o=!0,p=!0,q=!0,r=!1,s=!1,t=a.utils.state(),u=null,v=null,w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),x=250;f.orient("bottom").tickPadding(7),g.orient(r?"right":"left"),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var y=a.utils.renderWatch(w,x),z=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},A=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){j.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),b.dispatch=w,b.lines=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.interactiveLayer=i,b.tooltip=j,b.dispatch=w,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return p},set:function(a){p=a}},showYAxis:{get:function(){return q},set:function(a){q=a}},defaultState:{get:function(){return u},set:function(a){u=a}},noData:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x),e.duration(x),f.duration(x),g.duration(x)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),h.color(l),e.color(l)}},rightAlignYAxis:{get:function(){return r},set:function(a){r=a,g.orient(r?"right":"left")}},useInteractiveGuideline:{get:function(){return s},set:function(a){s=a,s&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.linePlusBarChart=function(){"use strict";function b(v){return v.each(function(v){function J(a){var b=+("e"==a),c=b?1:-1,d=X/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function S(){u.empty()||u.extent(I),kb.data([u.empty()?e.domain():I]).each(function(a){var b=e(a[0])-e.range()[0],c=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>c?0:c)})}function T(){I=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),K.brush({extent:c,brush:u}),S(),l.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=db.select(".nv-focus .nv-barsWrap").datum(Z.length?Z.map(function(a){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=db.select(".nv-focus .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$.map(function(a){return{area:a.area,fillOpacity:a.fillOpacity,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=Z.length?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-W,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),db.select(".nv-x.nv-axis").transition().duration(L).call(n),b.transition().duration(L).call(l),h.transition().duration(L).call(j),db.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(-V,0),q.scale(g)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(Z.length?0:-V,0),db.select(".nv-focus .nv-y1.nv-axis").style("opacity",Z.length?1:0),db.select(".nv-focus .nv-y2.nv-axis").style("opacity",$.length&&!$[0].disabled?1:0).attr("transform","translate("+d.range()[1]+",0)"),db.select(".nv-focus .nv-y1.nv-axis").transition().duration(L).call(p),db.select(".nv-focus .nv-y2.nv-axis").transition().duration(L).call(q)}var U=d3.select(this);a.utils.initSVG(U);var V=a.utils.availableWidth(y,U,w),W=a.utils.availableHeight(z,U,w)-(E?H:0),X=H-x.top-x.bottom;if(b.update=function(){U.transition().duration(L).call(b)},b.container=this,M.setter(R(v),b.update).getter(Q(v)).update(),M.disabled=v.map(function(a){return!!a.disabled}),!N){var Y;N={};for(Y in M)N[Y]=M[Y]instanceof Array?M[Y].slice(0):M[Y]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,U),b;U.selectAll(".nv-noData").remove();var Z=v.filter(function(a){return!a.disabled&&a.bar}),$=v.filter(function(a){return!a.bar});d=l.xScale(),e=o.scale(),f=l.yScale(),g=j.yScale(),h=m.yScale(),i=k.yScale();var _=v.filter(function(a){return!a.disabled&&a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})}),ab=v.filter(function(a){return!a.disabled&&!a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})});d.range([0,V]),e.domain(d3.extent(d3.merge(_.concat(ab)),function(a){return a.x})).range([0,V]);var bb=U.selectAll("g.nv-wrap.nv-linePlusBar").data([v]),cb=bb.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),db=bb.select("g");cb.append("g").attr("class","nv-legendWrap");var eb=cb.append("g").attr("class","nv-focus");eb.append("g").attr("class","nv-x nv-axis"),eb.append("g").attr("class","nv-y1 nv-axis"),eb.append("g").attr("class","nv-y2 nv-axis"),eb.append("g").attr("class","nv-barsWrap"),eb.append("g").attr("class","nv-linesWrap");var fb=cb.append("g").attr("class","nv-context");if(fb.append("g").attr("class","nv-x nv-axis"),fb.append("g").attr("class","nv-y1 nv-axis"),fb.append("g").attr("class","nv-y2 nv-axis"),fb.append("g").attr("class","nv-barsWrap"),fb.append("g").attr("class","nv-linesWrap"),fb.append("g").attr("class","nv-brushBackground"),fb.append("g").attr("class","nv-x nv-brush"),D){var gb=t.align()?V/2:V,hb=t.align()?gb:0;t.width(gb),db.select(".nv-legendWrap").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?O:P),a})).call(t),w.top!=t.height()&&(w.top=t.height(),W=a.utils.availableHeight(z,U,w)-H),db.select(".nv-legendWrap").attr("transform","translate("+hb+","+-w.top+")")}bb.attr("transform","translate("+w.left+","+w.top+")"),db.select(".nv-context").style("display",E?"initial":"none"),m.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var ib=db.select(".nv-context .nv-barsWrap").datum(Z.length?Z:[{values:[]}]),jb=db.select(".nv-context .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$);db.select(".nv-context").attr("transform","translate(0,"+(W+w.bottom+x.top)+")"),ib.transition().call(m),jb.transition().call(k),G&&(o._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-X,0),db.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),db.select(".nv-context .nv-x.nv-axis").transition().call(o)),F&&(r.scale(h)._ticks(X/36).tickSize(-V,0),s.scale(i)._ticks(X/36).tickSize(Z.length?0:-V,0),db.select(".nv-context .nv-y3.nv-axis").style("opacity",Z.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),db.select(".nv-context .nv-y2.nv-axis").style("opacity",$.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),db.select(".nv-context .nv-y1.nv-axis").transition().call(r),db.select(".nv-context .nv-y2.nv-axis").transition().call(s)),u.x(e).on("brush",T),I&&u.extent(I);var kb=db.select(".nv-brushBackground").selectAll("g").data([I||u.extent()]),lb=kb.enter().append("g");lb.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",X),lb.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",X);var mb=db.select(".nv-x.nv-brush").call(u);mb.selectAll("rect").attr("height",X),mb.selectAll(".resize").append("path").attr("d",J),t.dispatch.on("stateChange",function(a){for(var c in a)M[c]=a[c];K.stateChange(M),b.update()}),K.on("changeState",function(a){"undefined"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),M.disabled=a.disabled),b.update()}),T()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x={top:0,right:30,bottom:20,left:60},y=null,z=null,A=function(a){return a.x},B=function(a){return a.y},C=a.utils.defaultColor(),D=!0,E=!0,F=!1,G=!0,H=50,I=null,J=null,K=d3.dispatch("brush","stateChange","changeState"),L=0,M=a.utils.state(),N=null,O=" (left axis)",P=" (right axis)";j.clipEdge(!0),k.interactive(!1),n.orient("bottom").tickPadding(5),p.orient("left"),q.orient("right"),o.orient("bottom").tickPadding(5),r.orient("left"),s.orient("right"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var Q=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},R=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return j.dispatch.on("elementMouseover.tooltip",function(a){v.duration(100).valueFormatter(function(a,b){return q.tickFormat()(a,b)}).data(a).position(a.pos).hidden(!1)}),j.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={value:b.y()(a.data),color:a.color},v.duration(0).valueFormatter(function(a,b){return p.tickFormat()(a,b)}).data(a).hidden(!1)}),l.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMousemove.tooltip",function(){v.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=K,b.legend=t,b.lines=j,b.lines2=k,b.bars=l,b.bars2=m,b.xAxis=n,b.x2Axis=o,b.y1Axis=p,b.y2Axis=q,b.y3Axis=r,b.y4Axis=s,b.tooltip=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return y},set:function(a){y=a}},height:{get:function(){return z},set:function(a){z=a}},showLegend:{get:function(){return D},set:function(a){D=a}},brushExtent:{get:function(){return I},set:function(a){I=a}},noData:{get:function(){return J},set:function(a){J=a}},focusEnable:{get:function(){return E},set:function(a){E=a}},focusHeight:{get:function(){return H},set:function(a){H=a}},focusShowAxisX:{get:function(){return G},set:function(a){G=a}},focusShowAxisY:{get:function(){return F},set:function(a){F=a}},legendLeftAxisHint:{get:function(){return O},set:function(a){O=a}},legendRightAxisHint:{get:function(){return P},set:function(a){P=a}},tooltips:{get:function(){return v.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),v.enabled(!!b)}},tooltipContent:{get:function(){return v.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),v.contentGenerator(b)}},margin:{get:function(){return w},set:function(a){w.top=void 0!==a.top?a.top:w.top,w.right=void 0!==a.right?a.right:w.right,w.bottom=void 0!==a.bottom?a.bottom:w.bottom,w.left=void 0!==a.left?a.left:w.left}},duration:{get:function(){return L},set:function(a){L=a}},color:{get:function(){return C},set:function(b){C=a.utils.getColor(b),t.color(C)}},x:{get:function(){return A},set:function(a){A=a,j.x(a),k.x(a),l.x(a),m.x(a)}},y:{get:function(){return B},set:function(a){B=a,j.y(a),k.y(a),l.y(a),m.y(a)}}}),a.utils.inheritOptions(b,j),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){"use strict";function b(o){return o.each(function(o){function z(a){var b=+("e"==a),c=b?1:-1,d=M/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function G(){n.empty()||n.extent(y),U.data([n.empty()?e.domain():y]).each(function(a){var b=e(a[0])-c.range()[0],d=K-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>d?0:d)})}function H(){y=n.empty()?null:n.extent();var a=n.empty()?e.domain():n.extent();if(!(Math.abs(a[0]-a[1])<=1)){A.brush({extent:a,brush:n}),G();var b=Q.select(".nv-focus .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}).map(function(b){return{key:b.key,area:b.area,values:b.values.filter(function(b,c){return g.x()(b,c)>=a[0]&&g.x()(b,c)<=a[1]})}}));b.transition().duration(B).call(g),Q.select(".nv-focus .nv-x.nv-axis").transition().duration(B).call(i),Q.select(".nv-focus .nv-y.nv-axis").transition().duration(B).call(j)}}var I=d3.select(this),J=this;a.utils.initSVG(I);var K=a.utils.availableWidth(t,I,q),L=a.utils.availableHeight(u,I,q)-v,M=v-r.top-r.bottom;if(b.update=function(){I.transition().duration(B).call(b)},b.container=this,C.setter(F(o),b.update).getter(E(o)).update(),C.disabled=o.map(function(a){return!!a.disabled}),!D){var N;D={};for(N in C)D[N]=C[N]instanceof Array?C[N].slice(0):C[N]}if(!(o&&o.length&&o.filter(function(a){return a.values.length}).length))return a.utils.noData(b,I),b;I.selectAll(".nv-noData").remove(),c=g.xScale(),d=g.yScale(),e=h.xScale(),f=h.yScale();var O=I.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([o]),P=O.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),Q=O.select("g");P.append("g").attr("class","nv-legendWrap");var R=P.append("g").attr("class","nv-focus");R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-linesWrap"),R.append("g").attr("class","nv-interactive");var S=P.append("g").attr("class","nv-context");S.append("g").attr("class","nv-x nv-axis"),S.append("g").attr("class","nv-y nv-axis"),S.append("g").attr("class","nv-linesWrap"),S.append("g").attr("class","nv-brushBackground"),S.append("g").attr("class","nv-x nv-brush"),x&&(m.width(K),Q.select(".nv-legendWrap").datum(o).call(m),q.top!=m.height()&&(q.top=m.height(),L=a.utils.availableHeight(u,I,q)-v),Q.select(".nv-legendWrap").attr("transform","translate(0,"+-q.top+")")),O.attr("transform","translate("+q.left+","+q.top+")"),w&&(p.width(K).height(L).margin({left:q.left,top:q.top}).svgContainer(I).xScale(c),O.select(".nv-interactive").call(p)),g.width(K).height(L).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),h.defined(g.defined()).width(K).height(M).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),Q.select(".nv-context").attr("transform","translate(0,"+(L+q.bottom+r.top)+")");var T=Q.select(".nv-context .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}));d3.transition(T).call(h),i.scale(c)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-L,0),j.scale(d)._ticks(a.utils.calcTicksY(L/36,o)).tickSize(-K,0),Q.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L+")"),n.x(e).on("brush",function(){H()}),y&&n.extent(y);var U=Q.select(".nv-brushBackground").selectAll("g").data([y||n.extent()]),V=U.enter().append("g");V.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",M),V.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M);var W=Q.select(".nv-x.nv-brush").call(n);W.selectAll("rect").attr("height",M),W.selectAll(".resize").append("path").attr("d",z),H(),k.scale(e)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-M,0),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),d3.transition(Q.select(".nv-context .nv-x.nv-axis")).call(k),l.scale(f)._ticks(a.utils.calcTicksY(M/36,o)).tickSize(-K,0),d3.transition(Q.select(".nv-context .nv-y.nv-axis")).call(l),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),m.dispatch.on("stateChange",function(a){for(var c in a)C[c]=a[c];A.stateChange(C),b.update()}),p.dispatch.on("elementMousemove",function(c){g.clearHighlights();var d,f,h,k=[];if(o.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(i,j){var l=n.empty()?e.domain():n.extent(),m=i.values.filter(function(a,b){return g.x()(a,b)>=l[0]&&g.x()(a,b)<=l[1]});f=a.interactiveBisect(m,c.pointXValue,g.x());var o=m[f],p=b.y()(o,f);null!=p&&g.highlightPoint(j,f,!0),void 0!==o&&(void 0===d&&(d=o),void 0===h&&(h=b.xScale()(b.x()(o,f))),k.push({key:i.key,value:b.y()(o,f),color:s(i,i.seriesIndex)}))}),k.length>2){var l=b.yScale().invert(c.mouseY),m=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),r=.03*m,t=a.nearestValueIndex(k.map(function(a){return a.value}),l,r);null!==t&&(k[t].highlight=!0)}var u=i.tickFormat()(b.x()(d,f));p.tooltip.position({left:c.mouseX+q.left,top:c.mouseY+q.top}).chartContainer(J.parentNode).valueFormatter(function(a){return null==a?"N/A":j.tickFormat()(a)}).data({value:u,index:f,series:k})(),p.renderGuideLine(h)}),p.dispatch.on("elementMouseout",function(){g.clearHighlights()}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&o.forEach(function(b,c){b.disabled=a.disabled[c]}),b.update()})}),b}var c,d,e,f,g=a.models.line(),h=a.models.line(),i=a.models.axis(),j=a.models.axis(),k=a.models.axis(),l=a.models.axis(),m=a.models.legend(),n=d3.svg.brush(),o=a.models.tooltip(),p=a.interactiveGuideline(),q={top:30,right:30,bottom:30,left:60},r={top:0,right:30,bottom:20,left:60},s=a.utils.defaultColor(),t=null,u=null,v=50,w=!1,x=!0,y=null,z=null,A=d3.dispatch("brush","stateChange","changeState"),B=250,C=a.utils.state(),D=null;g.clipEdge(!0).duration(0),h.interactive(!1),i.orient("bottom").tickPadding(5),j.orient("left"),k.orient("bottom").tickPadding(5),l.orient("left"),o.valueFormatter(function(a,b){return j.tickFormat()(a,b)}).headerFormatter(function(a,b){return i.tickFormat()(a,b)});var E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return g.dispatch.on("elementMouseover.tooltip",function(a){o.data(a).position(a.pos).hidden(!1)}),g.dispatch.on("elementMouseout.tooltip",function(){o.hidden(!0)}),b.dispatch=A,b.legend=m,b.lines=g,b.lines2=h,b.xAxis=i,b.yAxis=j,b.x2Axis=k,b.y2Axis=l,b.interactiveLayer=p,b.tooltip=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return t},set:function(a){t=a}},height:{get:function(){return u},set:function(a){u=a}},focusHeight:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return x},set:function(a){x=a}},brushExtent:{get:function(){return y},set:function(a){y=a}},defaultState:{get:function(){return D},set:function(a){D=a}},noData:{get:function(){return z},set:function(a){z=a}},tooltips:{get:function(){return o.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),o.enabled(!!b)}},tooltipContent:{get:function(){return o.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),o.contentGenerator(b)}},margin:{get:function(){return q},set:function(a){q.top=void 0!==a.top?a.top:q.top,q.right=void 0!==a.right?a.right:q.right,q.bottom=void 0!==a.bottom?a.bottom:q.bottom,q.left=void 0!==a.left?a.left:q.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b),m.color(s)}},interpolate:{get:function(){return g.interpolate()},set:function(a){g.interpolate(a),h.interpolate(a)}},xTickFormat:{get:function(){return i.tickFormat()},set:function(a){i.tickFormat(a),k.tickFormat(a)}},yTickFormat:{get:function(){return j.tickFormat()},set:function(a){j.tickFormat(a),l.tickFormat(a)}},duration:{get:function(){return B},set:function(a){B=a,j.duration(B),l.duration(B),i.duration(B),k.duration(B)}},x:{get:function(){return g.x()},set:function(a){g.x(a),h.x(a)}},y:{get:function(){return g.y()},set:function(a){g.y(a),h.y(a)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,w&&(g.interactive(!1),g.useVoronoi(!1))}}}),a.utils.inheritOptions(b,g),a.utils.initOptions(b),b},a.models.multiBar=function(){"use strict";function b(E){return C.reset(),E.each(function(b){var E=k-j.left-j.right,F=l-j.top-j.bottom;p=d3.select(this),a.utils.initSVG(p);var G=0;if(x&&b.length&&(x=[{values:b[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),u){var H=d3.layout.stack().offset(v).values(function(a){return a.values}).y(r)(!b.length&&x?x:b);H.forEach(function(a,c){a.nonStackable?(b[c].nonStackableSeries=G++,H[c]=b[c]):c>0&&H[c-1].nonStackable&&H[c].values.map(function(a,b){a.y0-=H[c-1].values[b].y,a.y1=a.y0+a.y})}),b=H}b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),u&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a,f){if(!b[f].nonStackable){var g=a.values[c];g.size=Math.abs(g.y),g.y<0?(g.y1=e,e-=g.size):(g.y1=g.size+d,d+=g.size)}})});var I=d&&e?[]:b.map(function(a,b){return a.values.map(function(a,c){return{x:q(a,c),y:r(a,c),y0:a.y0,y1:a.y1,idx:b}})});m.domain(d||d3.merge(I).map(function(a){return a.x})).rangeBands(f||[0,E],A),n.domain(e||d3.extent(d3.merge(I).map(function(a){var c=a.y;return u&&!b[a.idx].nonStackable&&(c=a.y>0?a.y1:a.y1+a.y),c}).concat(s))).range(g||[F,0]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]:[-1,1]),h=h||m,i=i||n;var J=p.selectAll("g.nv-wrap.nv-multibar").data([b]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),L=K.append("defs"),M=K.append("g"),N=J.select("g");M.append("g").attr("class","nv-groups"),J.attr("transform","translate("+j.left+","+j.top+")"),L.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),J.select("#nv-edge-clip-"+o+" rect").attr("width",E).attr("height",F),N.attr("clip-path",t?"url(#nv-edge-clip-"+o+")":"");var O=J.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});O.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);var P=C.transition(O.exit().selectAll("rect.nv-bar"),"multibarExit",Math.min(100,z)).attr("y",function(a){var c=i(0)||0;return u&&b[a.series]&&!b[a.series].nonStackable&&(c=i(a.y0)),c}).attr("height",0).remove();P.delay&&P.delay(function(a,b){var c=b*(z/(D+1))-b;return c}),O.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return w(a,b)}).style("stroke",function(a,b){return w(a,b)}),O.style("stroke-opacity",1).style("fill-opacity",.75);var Q=O.selectAll("rect.nv-bar").data(function(a){return x&&!b.length?x.values:a.values});Q.exit().remove();Q.enter().append("rect").attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(a,c,d){return u&&!b[d].nonStackable?0:d*m.rangeBand()/b.length}).attr("y",function(a,c,d){return i(u&&!b[d].nonStackable?a.y0:0)||0}).attr("height",0).attr("width",function(a,c,d){return m.rangeBand()/(u&&!b[d].nonStackable?1:b.length)}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"});Q.style("fill",function(a,b,c){return w(a,c,b)}).style("stroke",function(a,b,c){return w(a,c,b)}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),B.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),B.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){B.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){B.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){B.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),Q.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"}),y&&(c||(c=b.map(function(){return!0})),Q.style("fill",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}));var R=Q.watchTransition(C,"multibar",Math.min(250,z)).delay(function(a,c){return c*z/b[0].values.length});u?R.attr("y",function(a,c,d){var e=0;return e=b[d].nonStackable?r(a,c)<0?n(0):n(0)-n(r(a,c))<-1?n(0)-1:n(r(a,c))||0:n(a.y1)}).attr("height",function(a,c,d){return b[d].nonStackable?Math.max(Math.abs(n(r(a,c))-n(0)),1)||0:Math.max(Math.abs(n(a.y+a.y0)-n(a.y0)),1)}).attr("x",function(a,c,d){var e=0;return b[d].nonStackable&&(e=a.series*m.rangeBand()/b.length,b.length!==G&&(e=b[d].nonStackableSeries*m.rangeBand()/(2*G))),e}).attr("width",function(a,c,d){if(b[d].nonStackable){var e=m.rangeBand()/G;return b.length!==G&&(e=m.rangeBand()/(2*G)),e}return m.rangeBand()}):R.attr("x",function(a){return a.series*m.rangeBand()/b.length}).attr("width",m.rangeBand()/b.length).attr("y",function(a,b){return r(a,b)<0?n(0):n(0)-n(r(a,b))<1?n(0)-1:n(r(a,b))||0}).attr("height",function(a,b){return Math.max(Math.abs(n(r(a,b))-n(0)),1)||0}),h=m.copy(),i=n.copy(),b[0]&&b[0].values&&(D=b[0].values.length)}),C.renderEnd("multibar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=d3.scale.ordinal(),n=d3.scale.linear(),o=Math.floor(1e4*Math.random()),p=null,q=function(a){return a.x},r=function(a){return a.y},s=[0],t=!0,u=!1,v="zero",w=a.utils.defaultColor(),x=!1,y=null,z=500,A=.1,B=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),C=a.utils.renderWatch(B,z),D=0;return b.dispatch=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return s},set:function(a){s=a}},stacked:{get:function(){return u},set:function(a){u=a}},stackOffset:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return t},set:function(a){t=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return o},set:function(a){o=a}},hideable:{get:function(){return x},set:function(a){x=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z)}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}},barColor:{get:function(){return y},set:function(b){y=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarChart=function(){"use strict";function b(j){return D.reset(),D.models(e),r&&D.models(f),s&&D.models(g),j.each(function(j){var z=d3.select(this);a.utils.initSVG(z);var D=a.utils.availableWidth(l,z,k),H=a.utils.availableHeight(m,z,k);if(b.update=function(){0===C?z.call(b):z.transition().duration(C).call(b)},b.container=this,x.setter(G(j),b.update).getter(F(j)).update(),x.disabled=j.map(function(a){return!!a.disabled}),!y){var I;y={};for(I in x)y[I]=x[I]instanceof Array?x[I].slice(0):x[I]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,z),b;z.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale(); -var J=z.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([j]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),L=J.select("g");if(K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-legendWrap"),K.append("g").attr("class","nv-controlsWrap"),q&&(h.width(D-B()),L.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),H=a.utils.availableHeight(m,z,k)),L.select(".nv-legendWrap").attr("transform","translate("+B()+","+-k.top+")")),o){var M=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(B()).color(["#444","#444","#444"]),L.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+-k.top+")").call(i)}J.attr("transform","translate("+k.left+","+k.top+")"),t&&L.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),e.disabled(j.map(function(a){return a.disabled})).width(D).height(H).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var N=L.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(N.call(e),r){f.scale(c)._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-H,0),L.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),L.select(".nv-x.nv-axis").call(f);var O=L.select(".nv-x.nv-axis > g").selectAll("g");if(O.selectAll("line, text").style("opacity",1),v){var P=function(a,b){return"translate("+a+","+b+")"},Q=5,R=17;O.selectAll("text").attr("transform",function(a,b,c){return P(0,c%2==0?Q:R)});var S=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;L.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return P(0,0===b||S%2!==0?R:Q)})}u&&O.filter(function(a,b){return b%Math.ceil(j[0].values.length/(D/100))!==0}).selectAll("text, line").style("opacity",0),w&&O.selectAll(".tick text").attr("transform","rotate("+w+" 0,0)").style("text-anchor",w>0?"start":"end"),L.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}s&&(g.scale(d)._ticks(a.utils.calcTicksY(H/36,j)).tickSize(-D,0),L.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];A.stateChange(x),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(M=M.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":case p.grouped:e.stacked(!1);break;case"Stacked":case p.stacked:e.stacked(!0)}x.stacked=e.stacked(),A.stateChange(x),b.update()}}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),x.stacked=a.stacked,E=a.stacked),b.update()})}),D.renderEnd("multibarchart immediate"),b}var c,d,e=a.models.multiBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=0,x=a.utils.state(),y=null,z=null,A=d3.dispatch("stateChange","changeState","renderEnd"),B=function(){return o?180:0},C=250;x.stacked=!1,e.stacked(!1),f.orient("bottom").tickPadding(7).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(t?"right":"left").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var D=a.utils.renderWatch(A),E=!1,F=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:E}}},G=function(a){return function(b){void 0!==b.stacked&&(E=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=A,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=x,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},reduceXTicks:{get:function(){return u},set:function(a){u=a}},rotateLabels:{get:function(){return w},set:function(a){w=a}},staggerLabels:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return C},set:function(a){C=a,e.duration(C),f.duration(C),g.duration(C),D.reset(C)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiBarHorizontal=function(){"use strict";function b(m){return E.reset(),m.each(function(b){var m=k-j.left-j.right,C=l-j.top-j.bottom;n=d3.select(this),a.utils.initSVG(n),w&&(b=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(r)(b)),b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),w&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e-b.size,e-=b.size):(b.y1=d,d+=b.size)})});var F=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:q(a,b),y:r(a,b),y0:a.y0,y1:a.y1}})});o.domain(d||d3.merge(F).map(function(a){return a.x})).rangeBands(f||[0,C],A),p.domain(e||d3.extent(d3.merge(F).map(function(a){return w?a.y>0?a.y1+a.y:a.y1:a.y}).concat(t))),p.range(x&&!w?g||[p.domain()[0]<0?z:0,m-(p.domain()[1]>0?z:0)]:g||[0,m]),h=h||o,i=i||d3.scale.linear().domain(p.domain()).range([p(0),p(0)]);{var G=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([b]),H=G.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),I=(H.append("defs"),H.append("g"));G.select("g")}I.append("g").attr("class","nv-groups"),G.attr("transform","translate("+j.left+","+j.top+")");var J=G.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});J.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),J.exit().watchTransition(E,"multibarhorizontal: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),J.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return u(a,b)}).style("stroke",function(a,b){return u(a,b)}),J.watchTransition(E,"multibarhorizontal: groups").style("stroke-opacity",1).style("fill-opacity",.75);var K=J.selectAll("g.nv-bar").data(function(a){return a.values});K.exit().remove();var L=K.enter().append("g").attr("transform",function(a,c,d){return"translate("+i(w?a.y0:0)+","+(w?0:d*o.rangeBand()/b.length+o(q(a,c)))+")"});L.append("rect").attr("width",0).attr("height",o.rangeBand()/(w?1:b.length)),K.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),D.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){D.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){D.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){D.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0],0)&&(L.append("polyline"),K.select("polyline").attr("fill","none").attr("points",function(a,c){var d=s(a,c),e=.8*o.rangeBand()/(2*(w?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return p(a)-p(0)});var f=[[d[0],-e],[d[0],e],[d[0],0],[d[1],0],[d[1],-e],[d[1],e]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=o.rangeBand()/(2*(w?1:b.length));return"translate("+(r(a,c)<0?0:p(r(a,c))-p(0))+", "+d+")"})),L.append("text"),x&&!w?(K.select("text").attr("text-anchor",function(a,b){return r(a,b)<0?"end":"start"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){var c=B(r(a,b)),d=s(a,b);return void 0===d?c:d.length?c+"+"+B(Math.abs(d[1]))+"-"+B(Math.abs(d[0])):c+"±"+B(Math.abs(d))}),K.watchTransition(E,"multibarhorizontal: bars").select("text").attr("x",function(a,b){return r(a,b)<0?-4:p(r(a,b))-p(0)+4})):K.selectAll("text").text(""),y&&!w?(L.append("text").classed("nv-bar-label",!0),K.select("text.nv-bar-label").attr("text-anchor",function(a,b){return r(a,b)<0?"start":"end"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){return q(a,b)}),K.watchTransition(E,"multibarhorizontal: bars").select("text.nv-bar-label").attr("x",function(a,b){return r(a,b)<0?p(0)-p(r(a,b))+4:-4})):K.selectAll("text.nv-bar-label").text(""),K.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),v&&(c||(c=b.map(function(){return!0})),K.style("fill",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()})),w?K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,b){return"translate("+p(a.y1)+","+o(q(a,b))+")"}).select("rect").attr("width",function(a,b){return Math.abs(p(r(a,b)+a.y0)-p(a.y0))}).attr("height",o.rangeBand()):K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,c){return"translate("+p(r(a,c)<0?r(a,c):0)+","+(a.series*o.rangeBand()/b.length+o(q(a,c)))+")"}).select("rect").attr("height",o.rangeBand()/b.length).attr("width",function(a,b){return Math.max(Math.abs(p(r(a,b))-p(0)),1)}),h=o.copy(),i=p.copy()}),E.renderEnd("multibarHorizontal immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=null,o=d3.scale.ordinal(),p=d3.scale.linear(),q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=a.utils.defaultColor(),v=null,w=!1,x=!1,y=!1,z=60,A=.1,B=d3.format(",.2f"),C=250,D=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),E=a.utils.renderWatch(D,C);return b.dispatch=D,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return o},set:function(a){o=a}},yScale:{get:function(){return p},set:function(a){p=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return w},set:function(a){w=a}},showValues:{get:function(){return x},set:function(a){x=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return m},set:function(a){m=a}},valueFormat:{get:function(){return B},set:function(a){B=a}},valuePadding:{get:function(){return z},set:function(a){z=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return C},set:function(a){C=a,E.reset(C)}},color:{get:function(){return u},set:function(b){u=a.utils.getColor(b)}},barColor:{get:function(){return v},set:function(b){v=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarHorizontalChart=function(){"use strict";function b(j){return C.reset(),C.models(e),r&&C.models(f),s&&C.models(g),j.each(function(j){var w=d3.select(this);a.utils.initSVG(w);var C=a.utils.availableWidth(l,w,k),D=a.utils.availableHeight(m,w,k);if(b.update=function(){w.transition().duration(z).call(b)},b.container=this,t=e.stacked(),u.setter(B(j),b.update).getter(A(j)).update(),u.disabled=j.map(function(a){return!!a.disabled}),!v){var E;v={};for(E in u)v[E]=u[E]instanceof Array?u[E].slice(0):u[E]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,w),b;w.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var F=w.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([j]),G=F.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),H=F.select("g");if(G.append("g").attr("class","nv-x nv-axis"),G.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),G.append("g").attr("class","nv-barsWrap"),G.append("g").attr("class","nv-legendWrap"),G.append("g").attr("class","nv-controlsWrap"),q&&(h.width(C-y()),H.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),D=a.utils.availableHeight(m,w,k)),H.select(".nv-legendWrap").attr("transform","translate("+y()+","+-k.top+")")),o){var I=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(y()).color(["#444","#444","#444"]),H.select(".nv-controlsWrap").datum(I).attr("transform","translate(0,"+-k.top+")").call(i)}F.attr("transform","translate("+k.left+","+k.top+")"),e.disabled(j.map(function(a){return a.disabled})).width(C).height(D).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var J=H.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(J.transition().call(e),r){f.scale(c)._ticks(a.utils.calcTicksY(D/24,j)).tickSize(-C,0),H.select(".nv-x.nv-axis").call(f);var K=H.select(".nv-x.nv-axis").selectAll("g");K.selectAll("line, text")}s&&(g.scale(d)._ticks(a.utils.calcTicksX(C/100,j)).tickSize(-D,0),H.select(".nv-y.nv-axis").attr("transform","translate(0,"+D+")"),H.select(".nv-y.nv-axis").call(g)),H.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-D),h.dispatch.on("stateChange",function(a){for(var c in a)u[c]=a[c];x.stateChange(u),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(I=I.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}u.stacked=e.stacked(),x.stateChange(u),t=e.stacked(),b.update()}}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),u.stacked=a.stacked,t=a.stacked),b.update()})}),C.renderEnd("multibar horizontal chart immediate"),b}var c,d,e=a.models.multiBarHorizontal(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend().height(30),i=a.models.legend().height(30),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=a.utils.state(),v=null,w=null,x=d3.dispatch("stateChange","changeState","renderEnd"),y=function(){return o?180:0},z=250;u.stacked=!1,e.stacked(t),f.orient("left").tickPadding(5).showMaxMin(!1).tickFormat(function(a){return a}),g.orient("bottom").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var A=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:t}}},B=function(a){return function(b){void 0!==b.stacked&&(t=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},C=a.utils.renderWatch(x,z);return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=x,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=u,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z),e.duration(z),f.duration(z),g.duration(z)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiChart=function(){"use strict";function b(j){return j.each(function(j){function k(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color},B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function l(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.point.x=v.x()(a.point),a.point.y=v.y()(a.point),B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function n(a){var b=2===j[a.data.series].yAxis?z:y;a.value=t.x()(a.data),a.series={value:t.y()(a.data),color:a.color},B.duration(0).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}var C=d3.select(this);a.utils.initSVG(C),b.update=function(){C.transition().call(b)},b.container=this;var D=a.utils.availableWidth(g,C,e),E=a.utils.availableHeight(h,C,e),F=j.filter(function(a){return"line"==a.type&&1==a.yAxis}),G=j.filter(function(a){return"line"==a.type&&2==a.yAxis}),H=j.filter(function(a){return"bar"==a.type&&1==a.yAxis}),I=j.filter(function(a){return"bar"==a.type&&2==a.yAxis}),J=j.filter(function(a){return"area"==a.type&&1==a.yAxis}),K=j.filter(function(a){return"area"==a.type&&2==a.yAxis});if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,C),b;C.selectAll(".nv-noData").remove();var L=j.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})}),M=j.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})});o.domain(d3.extent(d3.merge(L.concat(M)),function(a){return a.x})).range([0,D]);var N=C.selectAll("g.wrap.multiChart").data([j]),O=N.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y1 nv-axis"),O.append("g").attr("class","nv-y2 nv-axis"),O.append("g").attr("class","lines1Wrap"),O.append("g").attr("class","lines2Wrap"),O.append("g").attr("class","bars1Wrap"),O.append("g").attr("class","bars2Wrap"),O.append("g").attr("class","stack1Wrap"),O.append("g").attr("class","stack2Wrap"),O.append("g").attr("class","legendWrap");var P=N.select("g"),Q=j.map(function(a,b){return j[b].color||f(a,b)});if(i){var R=A.align()?D/2:D,S=A.align()?R:0;A.width(R),A.color(Q),P.select(".legendWrap").datum(j.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(1==a.yAxis?"":" (right axis)"),a})).call(A),e.top!=A.height()&&(e.top=A.height(),E=a.utils.availableHeight(h,C,e)),P.select(".legendWrap").attr("transform","translate("+S+","+-e.top+")")}r.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"line"==j[b].type})),s.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"line"==j[b].type})),t.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"bar"==j[b].type})),u.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"bar"==j[b].type})),v.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"area"==j[b].type})),w.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"area"==j[b].type})),P.attr("transform","translate("+e.left+","+e.top+")");var T=P.select(".lines1Wrap").datum(F.filter(function(a){return!a.disabled})),U=P.select(".bars1Wrap").datum(H.filter(function(a){return!a.disabled})),V=P.select(".stack1Wrap").datum(J.filter(function(a){return!a.disabled})),W=P.select(".lines2Wrap").datum(G.filter(function(a){return!a.disabled})),X=P.select(".bars2Wrap").datum(I.filter(function(a){return!a.disabled})),Y=P.select(".stack2Wrap").datum(K.filter(function(a){return!a.disabled})),Z=J.length?J.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[],$=K.length?K.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[];p.domain(c||d3.extent(d3.merge(L).concat(Z),function(a){return a.y})).range([0,E]),q.domain(d||d3.extent(d3.merge(M).concat($),function(a){return a.y})).range([0,E]),r.yDomain(p.domain()),t.yDomain(p.domain()),v.yDomain(p.domain()),s.yDomain(q.domain()),u.yDomain(q.domain()),w.yDomain(q.domain()),J.length&&d3.transition(V).call(v),K.length&&d3.transition(Y).call(w),H.length&&d3.transition(U).call(t),I.length&&d3.transition(X).call(u),F.length&&d3.transition(T).call(r),G.length&&d3.transition(W).call(s),x._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-E,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+E+")"),d3.transition(P.select(".nv-x.nv-axis")).call(x),y._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y1.nv-axis")).call(y),z._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y2.nv-axis")).call(z),P.select(".nv-y1.nv-axis").classed("nv-disabled",L.length?!1:!0).attr("transform","translate("+o.range()[0]+",0)"),P.select(".nv-y2.nv-axis").classed("nv-disabled",M.length?!1:!0).attr("transform","translate("+o.range()[1]+",0)"),A.dispatch.on("stateChange",function(){b.update()}),r.dispatch.on("elementMouseover.tooltip",k),s.dispatch.on("elementMouseover.tooltip",k),r.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),s.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),v.dispatch.on("elementMouseover.tooltip",l),w.dispatch.on("elementMouseover.tooltip",l),v.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),w.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),t.dispatch.on("elementMouseover.tooltip",n),u.dispatch.on("elementMouseover.tooltip",n),t.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),u.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),t.dispatch.on("elementMousemove.tooltip",function(){B.position({top:d3.event.pageY,left:d3.event.pageX})()}),u.dispatch.on("elementMousemove.tooltip",function(){B.position({top:d3.event.pageY,left:d3.event.pageX})()})}),b}var c,d,e={top:30,right:20,bottom:50,left:60},f=a.utils.defaultColor(),g=null,h=null,i=!0,j=null,k=function(a){return a.x},l=function(a){return a.y},m="monotone",n=!0,o=d3.scale.linear(),p=d3.scale.linear(),q=d3.scale.linear(),r=a.models.line().yScale(p),s=a.models.line().yScale(q),t=a.models.multiBar().stacked(!1).yScale(p),u=a.models.multiBar().stacked(!1).yScale(q),v=a.models.stackedArea().yScale(p),w=a.models.stackedArea().yScale(q),x=a.models.axis().scale(o).orient("bottom").tickPadding(5),y=a.models.axis().scale(p).orient("left"),z=a.models.axis().scale(q).orient("right"),A=a.models.legend().height(30),B=a.models.tooltip(),C=d3.dispatch();return b.dispatch=C,b.lines1=r,b.lines2=s,b.bars1=t,b.bars2=u,b.stack1=v,b.stack2=w,b.xAxis=x,b.yAxis1=y,b.yAxis2=z,b.tooltip=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},showLegend:{get:function(){return i},set:function(a){i=a}},yDomain1:{get:function(){return c},set:function(a){c=a}},yDomain2:{get:function(){return d},set:function(a){d=a}},noData:{get:function(){return j},set:function(a){j=a}},interpolate:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return B.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),B.enabled(!!b)}},tooltipContent:{get:function(){return B.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),B.contentGenerator(b)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return f},set:function(b){f=a.utils.getColor(b)}},x:{get:function(){return k},set:function(a){k=a,r.x(a),s.x(a),t.x(a),u.x(a),v.x(a),w.x(a)}},y:{get:function(){return l},set:function(a){l=a,r.y(a),s.y(a),v.y(a),w.y(a),t.y(a),u.y(a)}},useVoronoi:{get:function(){return n},set:function(a){n=a,r.useVoronoi(a),s.useVoronoi(a),v.useVoronoi(a),w.useVoronoi(a)}}}),a.utils.initOptions(b),b},a.models.ohlcBar=function(){"use strict";function b(y){return y.each(function(b){k=d3.select(this);var y=a.utils.availableWidth(h,k,g),A=a.utils.availableHeight(i,k,g);a.utils.initSVG(k);var B=y/b[0].values.length*.9;l.domain(c||d3.extent(b[0].values.map(n).concat(t))),l.range(v?e||[.5*y/b[0].values.length,y*(b[0].values.length-.5)/b[0].values.length]:e||[5+B/2,y-B/2-5]),m.domain(d||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(f||[A,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var C=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([b[0].values]),D=C.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),E=D.append("defs"),F=D.append("g"),G=C.select("g");F.append("g").attr("class","nv-ticks"),C.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:j})}),E.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),C.select("#nv-chart-clip-path-"+j+" rect").attr("width",y).attr("height",A),G.attr("clip-path",w?"url(#nv-chart-clip-path-"+j+")":"");var H=C.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});H.exit().remove(),H.enter().append("path").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}).attr("d",function(a,b){return"m0,0l0,"+(m(p(a,b))-m(r(a,b)))+"l"+-B/2+",0l"+B/2+",0l0,"+(m(s(a,b))-m(p(a,b)))+"l0,"+(m(q(a,b))-m(s(a,b)))+"l"+B/2+",0l"+-B/2+",0z"}).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("fill",function(){return x[0]}).attr("stroke",function(){return x[0]}).attr("x",0).attr("y",function(a,b){return m(Math.max(0,o(a,b)))}).attr("height",function(a,b){return Math.abs(m(o(a,b))-m(0))}),H.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(H).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("d",function(a,c){var d=y/b[0].values.length*.9;return"m0,0l0,"+(m(p(a,c))-m(r(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(m(s(a,c))-m(p(a,c)))+"l0,"+(m(q(a,c))-m(s(a,c)))+"l"+d/2+",0l"+-d/2+",0z"})}),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,c){b.clearHighlights(),k.select(".nv-ohlcBar .nv-tick-0-"+a).classed("hover",c)},b.clearHighlights=function(){k.select(".nv-ohlcBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!=a.top?a.top:g.top,g.right=void 0!=a.right?a.right:g.right,g.bottom=void 0!=a.bottom?a.bottom:g.bottom,g.left=void 0!=a.left?a.left:g.left -}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinates=function(){"use strict";function b(p){return p.each(function(b){function p(a){return F(h.map(function(b){if(isNaN(a[b])||isNaN(parseFloat(a[b]))){var c=g[b].domain(),d=g[b].range(),e=c[0]-(c[1]-c[0])/9;if(J.indexOf(b)<0){var h=d3.scale.linear().domain([e,c[1]]).range([x-12,d[1]]);g[b].brush.y(h),J.push(b)}return[f(b),g[b](e)]}return J.length>0?(D.style("display","inline"),E.style("display","inline")):(D.style("display","none"),E.style("display","none")),[f(b),g[b](a[b])]}))}function q(){var a=h.filter(function(a){return!g[a].brush.empty()}),b=a.map(function(a){return g[a].brush.extent()});k=[],a.forEach(function(a,c){k[c]={dimension:a,extent:b[c]}}),l=[],M.style("display",function(c){var d=a.every(function(a,d){return isNaN(c[a])&&b[d][0]==g[a].brush.y().domain()[0]?!0:b[d][0]<=c[a]&&c[a]<=b[d][1]});return d&&l.push(c),d?null:"none"}),o.brush({filters:k,active:l})}function r(a){m[a]=this.parentNode.__origin__=f(a),L.attr("visibility","hidden")}function s(a){m[a]=Math.min(w,Math.max(0,this.parentNode.__origin__+=d3.event.x)),M.attr("d",p),h.sort(function(a,b){return u(a)-u(b)}),f.domain(h),N.attr("transform",function(a){return"translate("+u(a)+")"})}function t(a){delete this.parentNode.__origin__,delete m[a],d3.select(this.parentNode).attr("transform","translate("+f(a)+")"),M.attr("d",p),L.attr("d",p).attr("visibility",null)}function u(a){var b=m[a];return null==b?f(a):b}var v=d3.select(this),w=a.utils.availableWidth(d,v,c),x=a.utils.availableHeight(e,v,c);a.utils.initSVG(v),l=b,f.rangePoints([0,w],1).domain(h);var y={};h.forEach(function(a){var c=d3.extent(b,function(b){return+b[a]});return y[a]=!1,void 0===c[0]&&(y[a]=!0,c[0]=0,c[1]=0),c[0]===c[1]&&(c[0]=c[0]-1,c[1]=c[1]+1),g[a]=d3.scale.linear().domain(c).range([.9*(x-12),0]),g[a].brush=d3.svg.brush().y(g[a]).on("brush",q),"name"!=a});var z=v.selectAll("g.nv-wrap.nv-parallelCoordinates").data([b]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-parallelCoordinates"),B=A.append("g"),C=z.select("g");B.append("g").attr("class","nv-parallelCoordinates background"),B.append("g").attr("class","nv-parallelCoordinates foreground"),B.append("g").attr("class","nv-parallelCoordinates missingValuesline"),z.attr("transform","translate("+c.left+","+c.top+")");var D,E,F=d3.svg.line().interpolate("cardinal").tension(n),G=d3.svg.axis().orient("left"),H=d3.behavior.drag().on("dragstart",r).on("drag",s).on("dragend",t),I=f.range()[1]-f.range()[0],J=[],K=[0+I/2,x-12,w-I/2,x-12];D=z.select(".missingValuesline").selectAll("line").data([K]),D.enter().append("line"),D.exit().remove(),D.attr("x1",function(a){return a[0]}).attr("y1",function(a){return a[1]}).attr("x2",function(a){return a[2]}).attr("y2",function(a){return a[3]}),E=z.select(".missingValuesline").selectAll("text").data(["undefined values"]),E.append("text").data(["undefined values"]),E.enter().append("text"),E.exit().remove(),E.attr("y",x).attr("x",w-92-I/2).text(function(a){return a});var L=z.select(".background").selectAll("path").data(b);L.enter().append("path"),L.exit().remove(),L.attr("d",p);var M=z.select(".foreground").selectAll("path").data(b);M.enter().append("path"),M.exit().remove(),M.attr("d",p).attr("stroke",j),M.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),o.elementMouseover({label:a.name,data:a.data,index:b,pos:[d3.mouse(this.parentNode)[0],d3.mouse(this.parentNode)[1]]})}),M.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),o.elementMouseout({label:a.name,data:a.data,index:b})});var N=C.selectAll(".dimension").data(h),O=N.enter().append("g").attr("class","nv-parallelCoordinates dimension");O.append("g").attr("class","nv-parallelCoordinates nv-axis"),O.append("g").attr("class","nv-parallelCoordinates-brush"),O.append("text").attr("class","nv-parallelCoordinates nv-label"),N.attr("transform",function(a){return"translate("+f(a)+",0)"}),N.exit().remove(),N.select(".nv-label").style("cursor","move").attr("dy","-1em").attr("text-anchor","middle").text(String).on("mouseover",function(a){o.elementMouseover({dim:a,pos:[d3.mouse(this.parentNode.parentNode)[0],d3.mouse(this.parentNode.parentNode)[1]]})}).on("mouseout",function(a){o.elementMouseout({dim:a})}).call(H),N.select(".nv-axis").each(function(a,b){d3.select(this).call(G.scale(g[a]).tickFormat(d3.format(i[b])))}),N.select(".nv-parallelCoordinates-brush").each(function(a){d3.select(this).call(g[a].brush)}).selectAll("rect").attr("x",-8).attr("width",16)}),b}var c={top:30,right:0,bottom:10,left:0},d=null,e=null,f=d3.scale.ordinal(),g={},h=[],i=[],j=a.utils.defaultColor(),k=[],l=[],m=[],n=1,o=d3.dispatch("brush","elementMouseover","elementMouseout");return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},dimensionNames:{get:function(){return h},set:function(a){h=a}},dimensionFormats:{get:function(){return i},set:function(a){i=a}},lineTension:{get:function(){return n},set:function(a){n=a}},dimensions:{get:function(){return h},set:function(b){a.deprecated("dimensions","use dimensionNames instead"),h=b}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.pie=function(){"use strict";function b(E){return D.reset(),E.each(function(b){function E(a,b){a.endAngle=isNaN(a.endAngle)?0:a.endAngle,a.startAngle=isNaN(a.startAngle)?0:a.startAngle,p||(a.innerRadius=0);var c=d3.interpolate(this._current,a);return this._current=c(0),function(a){return B[b](c(a))}}var F=d-c.left-c.right,G=e-c.top-c.bottom,H=Math.min(F,G)/2,I=[],J=[];if(i=d3.select(this),0===z.length)for(var K=H-H/5,L=y*H,M=0;Mc)return"";if("function"==typeof n)d=n(a,b,{key:f(a.data),value:g(a.data),percent:k(c)});else switch(n){case"key":d=f(a.data);break;case"value":d=k(g(a.data));break;case"percent":d=d3.format("%")(c)}return d})}}),D.renderEnd("pie immediate"),b}var c={top:0,right:0,bottom:0,left:0},d=500,e=500,f=function(a){return a.x},g=function(a){return a.y},h=Math.floor(1e4*Math.random()),i=null,j=a.utils.defaultColor(),k=d3.format(",.2f"),l=!0,m=!1,n="key",o=.02,p=!1,q=!1,r=!0,s=0,t=!1,u=!1,v=!1,w=!1,x=0,y=.5,z=[],A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),B=[],C=[],D=a.utils.renderWatch(A);return b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{arcsRadius:{get:function(){return z},set:function(a){z=a}},width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},showLabels:{get:function(){return l},set:function(a){l=a}},title:{get:function(){return q},set:function(a){q=a}},titleOffset:{get:function(){return s},set:function(a){s=a}},labelThreshold:{get:function(){return o},set:function(a){o=a}},valueFormat:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return h},set:function(a){h=a}},endAngle:{get:function(){return w},set:function(a){w=a}},startAngle:{get:function(){return u},set:function(a){u=a}},padAngle:{get:function(){return v},set:function(a){v=a}},cornerRadius:{get:function(){return x},set:function(a){x=a}},donutRatio:{get:function(){return y},set:function(a){y=a}},labelsOutside:{get:function(){return m},set:function(a){m=a}},labelSunbeamLayout:{get:function(){return t},set:function(a){t=a}},donut:{get:function(){return p},set:function(a){p=a}},growOnHover:{get:function(){return r},set:function(a){r=a}},pieLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("pieLabelsOutside","use labelsOutside instead")}},donutLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("donutLabelsOutside","use labelsOutside instead")}},labelFormat:{get:function(){return k},set:function(b){k=b,a.deprecated("labelFormat","use valueFormat instead")}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},y:{get:function(){return g},set:function(a){g=d3.functor(a)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},labelType:{get:function(){return n},set:function(a){n=a||"key"}}}),a.utils.initOptions(b),b},a.models.pieChart=function(){"use strict";function b(e){return q.reset(),q.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var n=a.utils.availableWidth(g,k,f),o=a.utils.availableHeight(h,k,f);if(b.update=function(){k.transition().call(b)},b.container=this,l.setter(s(e),b.update).getter(r(e)).update(),l.disabled=e.map(function(a){return!!a.disabled}),!m){var q;m={};for(q in l)m[q]=l[q]instanceof Array?l[q].slice(0):l[q]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(".nv-noData").remove();var t=k.selectAll("g.nv-wrap.nv-pieChart").data([e]),u=t.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),v=t.select("g");if(u.append("g").attr("class","nv-pieWrap"),u.append("g").attr("class","nv-legendWrap"),i)if("top"===j)d.width(n).key(c.x()),t.select(".nv-legendWrap").datum(e).call(d),f.top!=d.height()&&(f.top=d.height(),o=a.utils.availableHeight(h,k,f)),t.select(".nv-legendWrap").attr("transform","translate(0,"+-f.top+")");else if("right"===j){var w=a.models.legend().width();w>n/2&&(w=n/2),d.height(o).key(c.x()),d.width(w),n-=d.width(),t.select(".nv-legendWrap").datum(e).call(d).attr("transform","translate("+n+",0)")}t.attr("transform","translate("+f.left+","+f.top+")"),c.width(n).height(o);var x=v.select(".nv-pieWrap").datum([e]);d3.transition(x).call(c),d.dispatch.on("stateChange",function(a){for(var c in a)l[c]=a[c];p.stateChange(l),b.update()}),p.on("changeState",function(a){"undefined"!=typeof a.disabled&&(e.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),q.renderEnd("pieChart immediate"),b}var c=a.models.pie(),d=a.models.legend(),e=a.models.tooltip(),f={top:30,right:20,bottom:20,left:20},g=null,h=null,i=!0,j="top",k=a.utils.defaultColor(),l=a.utils.state(),m=null,n=null,o=250,p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd");e.headerEnabled(!1).duration(0).valueFormatter(function(a,b){return c.valueFormat()(a,b)});var q=a.utils.renderWatch(p),r=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},s=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},e.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){e.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){e.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.legend=d,b.dispatch=p,b.pie=c,b.tooltip=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return i},set:function(a){i=a}},legendPosition:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return e.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),e.enabled(!!b)}},tooltipContent:{get:function(){return e.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),e.contentGenerator(b)}},color:{get:function(){return k},set:function(a){k=a,d.color(k),c.color(k)}},duration:{get:function(){return o},set:function(a){o=a,q.reset(o)}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.scatter=function(){"use strict";function b(N){return P.reset(),N.each(function(b){function N(){if(O=!1,!w)return!1;if(M===!0){var a=d3.merge(b.map(function(a,b){return a.values.map(function(a,c){var d=p(a,c),e=q(a,c);return[m(d)+1e-4*Math.random(),n(e)+1e-4*Math.random(),b,c,a]}).filter(function(a,b){return x(a[4],b)})}));if(0==a.length)return!1;a.length<3&&(a.push([m.range()[0]-20,n.range()[0]-20,null,null]),a.push([m.range()[1]+20,n.range()[1]+20,null,null]),a.push([m.range()[0]-20,n.range()[0]+20,null,null]),a.push([m.range()[1]+20,n.range()[1]-20,null,null]));var c=d3.geom.polygon([[-10,-10],[-10,i+10],[h+10,i+10],[h+10,-10]]),d=d3.geom.voronoi(a).map(function(b,d){return{data:c.clip(b),series:a[d][2],point:a[d][3]}});U.select(".nv-point-paths").selectAll("path").remove();var e=U.select(".nv-point-paths").selectAll("path").data(d),f=e.enter().append("svg:path").attr("d",function(a){return a&&a.data&&0!==a.data.length?"M"+a.data.join(",")+"Z":"M 0 0"}).attr("id",function(a,b){return"nv-path-"+b}).attr("clip-path",function(a,b){return"url(#nv-clip-"+b+")"});C&&f.style("fill",d3.rgb(230,230,230)).style("fill-opacity",.4).style("stroke-opacity",1).style("stroke",d3.rgb(200,200,200)),B&&(U.select(".nv-point-clips").selectAll("clipPath").remove(),U.select(".nv-point-clips").selectAll("clipPath").data(a).enter().append("svg:clipPath").attr("id",function(a,b){return"nv-clip-"+b}).append("svg:circle").attr("cx",function(a){return a[0]}).attr("cy",function(a){return a[1]}).attr("r",D));var k=function(a,c){if(O)return 0;var d=b[a.series];if(void 0!==d){var e=d.values[a.point];e.color=j(d,a.series),e.x=p(e),e.y=q(e);var f=l.node().getBoundingClientRect(),h=window.pageYOffset||document.documentElement.scrollTop,i=window.pageXOffset||document.documentElement.scrollLeft,k={left:m(p(e,a.point))+f.left+i+g.left+10,top:n(q(e,a.point))+f.top+h+g.top+10};c({point:e,series:d,pos:k,seriesIndex:a.series,pointIndex:a.point})}};e.on("click",function(a){k(a,L.elementClick)}).on("dblclick",function(a){k(a,L.elementDblClick)}).on("mouseover",function(a){k(a,L.elementMouseover)}).on("mouseout",function(a){k(a,L.elementMouseout)})}else U.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("dblclick",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementDblClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("mouseover",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseover({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c,color:j(a,c)})}).on("mouseout",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseout({point:e,series:d,seriesIndex:a.series,pointIndex:c,color:j(a,c)})})}l=d3.select(this);var R=a.utils.availableWidth(h,l,g),S=a.utils.availableHeight(i,l,g);a.utils.initSVG(l),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var T=E&&F&&I?[]:d3.merge(b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),size:r(a,b)}})}));m.domain(E||d3.extent(T.map(function(a){return a.x}).concat(t))),m.range(y&&b[0]?G||[(R*z+R)/(2*b[0].values.length),R-R*(1+z)/(2*b[0].values.length)]:G||[0,R]),n.domain(F||d3.extent(T.map(function(a){return a.y}).concat(u))).range(H||[S,0]),o.domain(I||d3.extent(T.map(function(a){return a.size}).concat(v))).range(J||Q),K=m.domain()[0]===m.domain()[1]||n.domain()[0]===n.domain()[1],m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]-.01*n.domain()[0],n.domain()[1]+.01*n.domain()[1]]:[-1,1]),isNaN(m.domain()[0])&&m.domain([-1,1]),isNaN(n.domain()[0])&&n.domain([-1,1]),c=c||m,d=d||n,e=e||o;var U=l.selectAll("g.nv-wrap.nv-scatter").data([b]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+k),W=V.append("defs"),X=V.append("g"),Y=U.select("g");U.classed("nv-single-point",K),X.append("g").attr("class","nv-groups"),X.append("g").attr("class","nv-point-paths"),V.append("g").attr("class","nv-point-clips"),U.attr("transform","translate("+g.left+","+g.top+")"),W.append("clipPath").attr("id","nv-edge-clip-"+k).append("rect"),U.select("#nv-edge-clip-"+k+" rect").attr("width",R).attr("height",S>0?S:0),Y.attr("clip-path",A?"url(#nv-edge-clip-"+k+")":""),O=!0;var Z=U.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});Z.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),Z.exit().remove(),Z.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),Z.watchTransition(P,"scatter: groups").style("fill",function(a,b){return j(a,b)}).style("stroke",function(a,b){return j(a,b)}).style("stroke-opacity",1).style("fill-opacity",.5);var $=Z.selectAll("path.nv-point").data(function(a){return a.values.map(function(a,b){return[a,b]}).filter(function(a,b){return x(a[0],b)})});$.enter().append("path").style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("transform",function(a){return"translate("+c(p(a[0],a[1]))+","+d(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),$.exit().remove(),Z.exit().selectAll("path.nv-point").watchTransition(P,"scatter exit").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).remove(),$.each(function(a){d3.select(this).classed("nv-point",!0).classed("nv-point-"+a[1],!0).classed("nv-noninteractive",!w).classed("hover",!1)}),$.watchTransition(P,"scatter points").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),clearTimeout(f),f=setTimeout(N,300),c=m.copy(),d=n.copy(),e=o.copy()}),P.renderEnd("scatter immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=a.utils.defaultColor(),k=Math.floor(1e5*Math.random()),l=null,m=d3.scale.linear(),n=d3.scale.linear(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=function(a){return a.size||1},s=function(a){return a.shape||"circle"},t=[],u=[],v=[],w=!0,x=function(a){return!a.notActive},y=!1,z=.1,A=!1,B=!0,C=!1,D=function(){return 25},E=null,F=null,G=null,H=null,I=null,J=null,K=!1,L=d3.dispatch("elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),M=!0,N=250,O=!1,P=a.utils.renderWatch(L,N),Q=[16,256];return b.dispatch=L,b.options=a.utils.optionsFunc.bind(b),b._calls=new function(){this.clearHighlights=function(){return a.dom.write(function(){l.selectAll(".nv-point.hover").classed("hover",!1)}),null},this.highlightPoint=function(b,c,d){a.dom.write(function(){l.select(" .nv-series-"+b+" .nv-point-"+c).classed("hover",d)})}},L.on("elementMouseover.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!0)}),L.on("elementMouseout.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!1)}),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},pointScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return E},set:function(a){E=a}},yDomain:{get:function(){return F},set:function(a){F=a}},pointDomain:{get:function(){return I},set:function(a){I=a}},xRange:{get:function(){return G},set:function(a){G=a}},yRange:{get:function(){return H},set:function(a){H=a}},pointRange:{get:function(){return J},set:function(a){J=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},forcePoint:{get:function(){return v},set:function(a){v=a}},interactive:{get:function(){return w},set:function(a){w=a}},pointActive:{get:function(){return x},set:function(a){x=a}},padDataOuter:{get:function(){return z},set:function(a){z=a}},padData:{get:function(){return y},set:function(a){y=a}},clipEdge:{get:function(){return A},set:function(a){A=a}},clipVoronoi:{get:function(){return B},set:function(a){B=a}},clipRadius:{get:function(){return D},set:function(a){D=a}},showVoronoi:{get:function(){return C},set:function(a){C=a}},id:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return p},set:function(a){p=d3.functor(a)}},y:{get:function(){return q},set:function(a){q=d3.functor(a)}},pointSize:{get:function(){return r},set:function(a){r=d3.functor(a)}},pointShape:{get:function(){return s},set:function(a){s=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},duration:{get:function(){return N},set:function(a){N=a,P.reset(N)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},useVoronoi:{get:function(){return M},set:function(a){M=a,M===!1&&(B=!1)}}}),a.utils.initOptions(b),b},a.models.scatterChart=function(){"use strict";function b(z){return D.reset(),D.models(c),t&&D.models(d),u&&D.models(e),q&&D.models(g),r&&D.models(h),z.each(function(z){m=d3.select(this),a.utils.initSVG(m);var G=a.utils.availableWidth(k,m,j),H=a.utils.availableHeight(l,m,j);if(b.update=function(){0===A?m.call(b):m.transition().duration(A).call(b)},b.container=this,w.setter(F(z),b.update).getter(E(z)).update(),w.disabled=z.map(function(a){return!!a.disabled}),!x){var I;x={};for(I in w)x[I]=w[I]instanceof Array?w[I].slice(0):w[I]}if(!(z&&z.length&&z.filter(function(a){return a.values.length}).length))return a.utils.noData(b,m),D.renderEnd("scatter immediate"),b;m.selectAll(".nv-noData").remove(),o=c.xScale(),p=c.yScale();var J=m.selectAll("g.nv-wrap.nv-scatterChart").data([z]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+c.id()),L=K.append("g"),M=J.select("g");if(L.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-scatterWrap"),L.append("g").attr("class","nv-regressionLinesWrap"),L.append("g").attr("class","nv-distWrap"),L.append("g").attr("class","nv-legendWrap"),v&&M.select(".nv-y.nv-axis").attr("transform","translate("+G+",0)"),s){var N=G;f.width(N),J.select(".nv-legendWrap").datum(z).call(f),j.top!=f.height()&&(j.top=f.height(),H=a.utils.availableHeight(l,m,j)),J.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")}J.attr("transform","translate("+j.left+","+j.top+")"),c.width(G).height(H).color(z.map(function(a,b){return a.color=a.color||n(a,b),a.color}).filter(function(a,b){return!z[b].disabled})),J.select(".nv-scatterWrap").datum(z.filter(function(a){return!a.disabled})).call(c),J.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+c.id()+")");var O=J.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});O.enter().append("g").attr("class","nv-regLines");var P=O.selectAll(".nv-regLine").data(function(a){return[a]});P.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),P.filter(function(a){return a.intercept&&a.slope}).watchTransition(D,"scatterPlusLineChart: regline").attr("x1",o.range()[0]).attr("x2",o.range()[1]).attr("y1",function(a){return p(o.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a){return p(o.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return n(a,c)}).style("stroke-opacity",function(a){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),t&&(d.scale(o)._ticks(a.utils.calcTicksX(G/100,z)).tickSize(-H,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(d)),u&&(e.scale(p)._ticks(a.utils.calcTicksY(H/36,z)).tickSize(-G,0),M.select(".nv-y.nv-axis").call(e)),q&&(g.getData(c.x()).scale(o).width(G).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),M.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(z.filter(function(a){return!a.disabled})).call(g)),r&&(h.getData(c.y()).scale(p).width(H).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),M.select(".nv-distributionY").attr("transform","translate("+(v?G:-h.size())+",0)").datum(z.filter(function(a){return!a.disabled})).call(h)),f.dispatch.on("stateChange",function(a){for(var c in a)w[c]=a[c];y.stateChange(w),b.update()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(z.forEach(function(b,c){b.disabled=a.disabled[c]}),w.disabled=a.disabled),b.update()}),c.dispatch.on("elementMouseout.tooltip",function(a){i.hidden(!0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",h.size())}),c.dispatch.on("elementMouseover.tooltip",function(a){m.select(".nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.pos.top-H-j.top),m.select(".nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.pos.left+g.size()-j.left),i.position(a.pos).data(a).hidden(!1)}),B=o.copy(),C=p.copy()}),D.renderEnd("scatter with line immediate"),b}var c=a.models.scatter(),d=a.models.axis(),e=a.models.axis(),f=a.models.legend(),g=a.models.distribution(),h=a.models.distribution(),i=a.models.tooltip(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=null,n=a.utils.defaultColor(),o=c.xScale(),p=c.yScale(),q=!1,r=!1,s=!0,t=!0,u=!0,v=!1,w=a.utils.state(),x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=null,A=250;c.xScale(o).yScale(p),d.orient("bottom").tickPadding(10),e.orient(v?"right":"left").tickPadding(10),g.axis("x"),h.axis("y"),i.headerFormatter(function(a,b){return d.tickFormat()(a,b)}).valueFormatter(function(a,b){return e.tickFormat()(a,b)});var B,C,D=a.utils.renderWatch(y,A),E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return b.dispatch=y,b.scatter=c,b.legend=f,b.xAxis=d,b.yAxis=e,b.distX=g,b.distY=h,b.tooltip=i,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},container:{get:function(){return m},set:function(a){m=a}},showDistX:{get:function(){return q},set:function(a){q=a}},showDistY:{get:function(){return r},set:function(a){r=a}},showLegend:{get:function(){return s},set:function(a){s=a}},showXAxis:{get:function(){return t},set:function(a){t=a}},showYAxis:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return x},set:function(a){x=a}},noData:{get:function(){return z},set:function(a){z=a}},duration:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return i.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),i.enabled(!!b) -}},tooltipContent:{get:function(){return i.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),i.contentGenerator(b)}},tooltipXContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},tooltipYContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},rightAlignYAxis:{get:function(){return v},set:function(a){v=a,e.orient(a?"right":"left")}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),f.color(n),g.color(n),h.color(n)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sparkline=function(){"use strict";function b(k){return k.each(function(b){var k=h-g.left-g.right,q=i-g.top-g.bottom;j=d3.select(this),a.utils.initSVG(j),l.domain(c||d3.extent(b,n)).range(e||[0,k]),m.domain(d||d3.extent(b,o)).range(f||[q,0]);{var r=j.selectAll("g.nv-wrap.nv-sparkline").data([b]),s=r.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");s.append("g"),r.select("g")}r.attr("transform","translate("+g.left+","+g.top+")");var t=r.selectAll("path").data(function(a){return[a]});t.enter().append("path"),t.exit().remove(),t.style("stroke",function(a,b){return a.color||p(a,b)}).attr("d",d3.svg.line().x(function(a,b){return l(n(a,b))}).y(function(a,b){return m(o(a,b))}));var u=r.selectAll("circle.nv-point").data(function(a){function b(b){if(-1!=b){var c=a[b];return c.pointIndex=b,c}return null}var c=a.map(function(a,b){return o(a,b)}),d=b(c.lastIndexOf(m.domain()[1])),e=b(c.indexOf(m.domain()[0])),f=b(c.length-1);return[e,d,f].filter(function(a){return null!=a})});u.enter().append("circle"),u.exit().remove(),u.attr("cx",function(a){return l(n(a,a.pointIndex))}).attr("cy",function(a){return m(o(a,a.pointIndex))}).attr("r",2).attr("class",function(a){return n(a,a.pointIndex)==l.domain()[1]?"nv-point nv-currentValue":o(a,a.pointIndex)==m.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),b}var c,d,e,f,g={top:2,right:0,bottom:2,left:0},h=400,i=32,j=null,k=!0,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=a.utils.getColor(["#000"]);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},animate:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return n},set:function(a){n=d3.functor(a)}},y:{get:function(){return o},set:function(a){o=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sparklinePlus=function(){"use strict";function b(p){return p.each(function(p){function q(){if(!j){var a=z.selectAll(".nv-hoverValue").data(i),b=a.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);a.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),a.attr("transform",function(a){return"translate("+c(e.x()(p[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(b.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",u),b.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),z.select(".nv-hoverValue .nv-xValue").text(k(e.x()(p[i[0]],i[0]))),b.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),z.select(".nv-hoverValue .nv-yValue").text(l(e.y()(p[i[0]],i[0]))))}}function r(){function a(a,b){for(var c=Math.abs(e.x()(a[0],0)-b),d=0,f=0;fc;++c){for(b=0,d=0;bb;b++)a[b][c][1]/=d;else for(b=0;e>b;b++)a[b][c][1]=0}for(c=0;f>c;++c)g[c]=0;return g}}),u.renderEnd("stackedArea immediate"),b}var c,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=a.utils.defaultColor(),i=Math.floor(1e5*Math.random()),j=null,k=function(a){return a.x},l=function(a){return a.y},m="stack",n="zero",o="default",p="linear",q=!1,r=a.models.scatter(),s=250,t=d3.dispatch("areaClick","areaMouseover","areaMouseout","renderEnd","elementClick","elementMouseover","elementMouseout");r.pointSize(2.2).pointDomain([2.2,2.2]);var u=a.utils.renderWatch(t,s);return b.dispatch=t,b.scatter=r,r.dispatch.on("elementClick",function(){t.elementClick.apply(this,arguments)}),r.dispatch.on("elementMouseover",function(){t.elementMouseover.apply(this,arguments)}),r.dispatch.on("elementMouseout",function(){t.elementMouseout.apply(this,arguments)}),b.interpolate=function(a){return arguments.length?(p=a,b):p},b.duration=function(a){return arguments.length?(s=a,u.reset(s),r.duration(s),b):s},b.dispatch=t,b.scatter=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return f},set:function(a){f=a}},height:{get:function(){return g},set:function(a){g=a}},clipEdge:{get:function(){return q},set:function(a){q=a}},offset:{get:function(){return n},set:function(a){n=a}},order:{get:function(){return o},set:function(a){o=a}},interpolate:{get:function(){return p},set:function(a){p=a}},x:{get:function(){return k},set:function(a){k=d3.functor(a)}},y:{get:function(){return l},set:function(a){l=d3.functor(a)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},style:{get:function(){return m},set:function(a){switch(m=a){case"stack":b.offset("zero"),b.order("default");break;case"stream":b.offset("wiggle"),b.order("inside-out");break;case"stream-center":b.offset("silhouette"),b.order("inside-out");break;case"expand":b.offset("expand"),b.order("default");break;case"stack_percent":b.offset(b.d3_stackedOffset_stackPercent),b.order("default")}}},duration:{get:function(){return s},set:function(a){s=a,u.reset(s),r.duration(s)}}}),a.utils.inheritOptions(b,r),a.utils.initOptions(b),b},a.models.stackedAreaChart=function(){"use strict";function b(k){return F.reset(),F.models(e),r&&F.models(f),s&&F.models(g),k.each(function(k){var x=d3.select(this),F=this;a.utils.initSVG(x);var K=a.utils.availableWidth(m,x,l),L=a.utils.availableHeight(n,x,l);if(b.update=function(){x.transition().duration(C).call(b)},b.container=this,v.setter(I(k),b.update).getter(H(k)).update(),v.disabled=k.map(function(a){return!!a.disabled}),!w){var M;w={};for(M in v)w[M]=v[M]instanceof Array?v[M].slice(0):v[M]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(b,x),b;x.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var N=x.selectAll("g.nv-wrap.nv-stackedAreaChart").data([k]),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),P=N.select("g");if(O.append("rect").style("opacity",0),O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-stackedWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),O.append("g").attr("class","nv-interactive"),P.select("rect").attr("width",K).attr("height",L),q){var Q=p?K-z:K;h.width(Q),P.select(".nv-legendWrap").datum(k).call(h),l.top!=h.height()&&(l.top=h.height(),L=a.utils.availableHeight(n,x,l)),P.select(".nv-legendWrap").attr("transform","translate("+(K-Q)+","+-l.top+")")}if(p){var R=[{key:B.stacked||"Stacked",metaKey:"Stacked",disabled:"stack"!=e.style(),style:"stack"},{key:B.stream||"Stream",metaKey:"Stream",disabled:"stream"!=e.style(),style:"stream"},{key:B.expanded||"Expanded",metaKey:"Expanded",disabled:"expand"!=e.style(),style:"expand"},{key:B.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:"stack_percent"!=e.style(),style:"stack_percent"}];z=A.length/3*260,R=R.filter(function(a){return-1!==A.indexOf(a.metaKey)}),i.width(z).color(["#444","#444","#444"]),P.select(".nv-controlsWrap").datum(R).call(i),l.top!=Math.max(i.height(),h.height())&&(l.top=Math.max(i.height(),h.height()),L=a.utils.availableHeight(n,x,l)),P.select(".nv-controlsWrap").attr("transform","translate(0,"+-l.top+")")}N.attr("transform","translate("+l.left+","+l.top+")"),t&&P.select(".nv-y.nv-axis").attr("transform","translate("+K+",0)"),u&&(j.width(K).height(L).margin({left:l.left,top:l.top}).svgContainer(x).xScale(c),N.select(".nv-interactive").call(j)),e.width(K).height(L);var S=P.select(".nv-stackedWrap").datum(k);if(S.transition().call(e),r&&(f.scale(c)._ticks(a.utils.calcTicksX(K/100,k)).tickSize(-L,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+L+")"),P.select(".nv-x.nv-axis").transition().duration(0).call(f)),s){var T;if(T="wiggle"===e.offset()?0:a.utils.calcTicksY(L/36,k),g.scale(d)._ticks(T).tickSize(-K,0),"expand"===e.style()||"stack_percent"===e.style()){var U=g.tickFormat();D&&U===J||(D=U),g.tickFormat(J)}else D&&(g.tickFormat(D),D=null);P.select(".nv-y.nv-axis").transition().duration(0).call(g)}e.dispatch.on("areaClick.toggle",function(a){k.forEach(1===k.filter(function(a){return!a.disabled}).length?function(a){a.disabled=!1}:function(b,c){b.disabled=c!=a.seriesIndex}),v.disabled=k.map(function(a){return!!a.disabled}),y.stateChange(v),b.update()}),h.dispatch.on("stateChange",function(a){for(var c in a)v[c]=a[c];y.stateChange(v),b.update()}),i.dispatch.on("legendClick",function(a){a.disabled&&(R=R.map(function(a){return a.disabled=!0,a}),a.disabled=!1,e.style(a.style),v.style=e.style(),y.stateChange(v),b.update())}),j.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,g,h,i=[];if(k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,j){g=a.interactiveBisect(f.values,c.pointXValue,b.x());var k=f.values[g],l=b.y()(k,g);if(null!=l&&e.highlightPoint(j,g,!0),"undefined"!=typeof k){"undefined"==typeof d&&(d=k),"undefined"==typeof h&&(h=b.xScale()(b.x()(k,g)));var m="expand"==e.style()?k.display.y:b.y()(k,g);i.push({key:f.key,value:m,color:o(f,f.seriesIndex),stackedValue:k.display})}}),i.reverse(),i.length>2){var m=b.yScale().invert(c.mouseY),n=null;i.forEach(function(a,b){m=Math.abs(m);var c=Math.abs(a.stackedValue.y0),d=Math.abs(a.stackedValue.y);return m>=c&&d+c>=m?void(n=b):void 0}),null!=n&&(i[n].highlight=!0)}var p=f.tickFormat()(b.x()(d,g)),q=j.tooltip.valueFormatter();"expand"===e.style()||"stack_percent"===e.style()?(E||(E=q),q=d3.format(".1%")):E&&(q=E,E=null),j.tooltip.position({left:h+l.left,top:c.mouseY+l.top}).chartContainer(F.parentNode).valueFormatter(q).data({value:p,series:i})(),j.renderGuideLine(h)}),j.dispatch.on("elementMouseout",function(){e.clearHighlights()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&k.length===a.disabled.length&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),"undefined"!=typeof a.style&&(e.style(a.style),G=a.style),b.update()})}),F.renderEnd("stacked Area chart immediate"),b}var c,d,e=a.models.stackedArea(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:25,bottom:50,left:60},m=null,n=null,o=a.utils.defaultColor(),p=!0,q=!0,r=!0,s=!0,t=!1,u=!1,v=a.utils.state(),w=null,x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=250,A=["Stacked","Stream","Expanded"],B={},C=250;v.style=e.style(),f.orient("bottom").tickPadding(7),g.orient(t?"right":"left"),k.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)}),j.tooltip.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)});var D=null,E=null;i.updateState(!1);var F=a.utils.renderWatch(y),G=e.style(),H=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),style:e.style()}}},I=function(a){return function(b){void 0!==b.style&&(G=b.style),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},J=d3.format("%");return e.dispatch.on("elementMouseover.tooltip",function(a){a.point.x=e.x()(a.point),a.point.y=e.y()(a.point),k.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),b.dispatch=y,b.stacked=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.interactiveLayer=j,b.tooltip=k,b.dispatch=y,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},showControls:{get:function(){return p},set:function(a){p=a}},controlLabels:{get:function(){return B},set:function(a){B=a}},controlOptions:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return C},set:function(a){C=a,F.reset(C),e.duration(C),f.duration(C),g.duration(C)}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),h.color(o),e.color(o)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},useInteractiveGuideline:{get:function(){return u},set:function(a){u=!!a,b.interactive(!a),b.useVoronoi(!a),e.scatter.interactive(!a)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.sunburst=function(){"use strict";function b(u){return t.reset(),u.each(function(b){function t(a){a.x0=a.x,a.dx0=a.dx}function u(a){var b=d3.interpolate(p.domain(),[a.x,a.x+a.dx]),c=d3.interpolate(q.domain(),[a.y,1]),d=d3.interpolate(q.range(),[a.y?20:0,y]);return function(a,e){return e?function(){return s(a)}:function(e){return p.domain(b(e)),q.domain(c(e)).range(d(e)),s(a)}}}l=d3.select(this);var v,w=a.utils.availableWidth(g,l,f),x=a.utils.availableHeight(h,l,f),y=Math.min(w,x)/2;a.utils.initSVG(l);var z=l.selectAll(".nv-wrap.nv-sunburst").data(b),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburst nv-chart-"+k),B=A.selectAll("nv-sunburst");z.attr("transform","translate("+w/2+","+x/2+")"),l.on("click",function(a,b){o.chartClick({data:a,index:b,pos:d3.event,id:k})}),q.range([0,y]),c=c||b,e=b[0],r.value(j[i]||j.count),v=B.data(r.nodes).enter().append("path").attr("d",s).style("fill",function(a){return m((a.children?a:a.parent).name)}).style("stroke","#FFF").on("click",function(a){d!==c&&c!==a&&(d=c),c=a,v.transition().duration(n).attrTween("d",u(a))}).each(t).on("dblclick",function(a){d.parent==a&&v.transition().duration(n).attrTween("d",u(e))}).each(t).on("mouseover",function(a){d3.select(this).classed("hover",!0).style("opacity",.8),o.elementMouseover({data:a,color:d3.select(this).style("fill")})}).on("mouseout",function(a){d3.select(this).classed("hover",!1).style("opacity",1),o.elementMouseout({data:a})}).on("mousemove",function(a){o.elementMousemove({data:a})})}),t.renderEnd("sunburst immediate"),b}var c,d,e,f={top:0,right:0,bottom:0,left:0},g=null,h=null,i="count",j={count:function(){return 1},size:function(a){return a.size}},k=Math.floor(1e4*Math.random()),l=null,m=a.utils.defaultColor(),n=500,o=d3.dispatch("chartClick","elementClick","elementDblClick","elementMousemove","elementMouseover","elementMouseout","renderEnd"),p=d3.scale.linear().range([0,2*Math.PI]),q=d3.scale.sqrt(),r=d3.layout.partition().sort(null).value(function(){return 1}),s=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,q(a.y))}).outerRadius(function(a){return Math.max(0,q(a.y+a.dy))}),t=a.utils.renderWatch(o);return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},mode:{get:function(){return i},set:function(a){i=a}},id:{get:function(){return k},set:function(a){k=a}},duration:{get:function(){return n},set:function(a){n=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!=a.top?a.top:f.top,f.right=void 0!=a.right?a.right:f.right,f.bottom=void 0!=a.bottom?a.bottom:f.bottom,f.left=void 0!=a.left?a.left:f.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sunburstChart=function(){"use strict";function b(d){return m.reset(),m.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);if(b.update=function(){0===k?h.call(b):h.transition().duration(k).call(b)},b.container=this,!d||!d.length)return a.utils.noData(b,h),b;h.selectAll(".nv-noData").remove();var l=h.selectAll("g.nv-wrap.nv-sunburstChart").data(d),m=l.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburstChart").append("g"),n=l.select("g");m.append("g").attr("class","nv-sunburstWrap"),l.attr("transform","translate("+e.left+","+e.top+")"),c.width(i).height(j);var o=n.select(".nv-sunburstWrap").datum(d);d3.transition(o).call(c)}),m.renderEnd("sunburstChart immediate"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),i=(Math.round(1e5*Math.random()),null),j=null,k=250,l=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),m=a.utils.renderWatch(l);return d.headerEnabled(!1).duration(0).valueFormatter(function(a){return a}),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.data.name,value:a.data.size,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=l,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return k},set:function(a){k=a,m.reset(k),c.duration(k)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version="1.8.1"}(); \ No newline at end of file diff --git a/tests/coverage/_js/popper.min.js b/tests/coverage/_js/popper.min.js deleted file mode 100644 index bb1aaae..0000000 --- a/tests/coverage/_js/popper.min.js +++ /dev/null @@ -1,5 +0,0 @@ -/* - Copyright (C) Federico Zivolo 2020 - Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). - */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=e.ownerDocument.defaultView,n=o.getComputedStyle(e,null);return t?n[t]:n}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e)return document.body;switch(e.nodeName){case'HTML':case'BODY':return e.ownerDocument.body;case'#document':return e.body;}var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll|overlay)/.test(r+s+p)?e:n(o(e))}function i(e){return e&&e.referenceNode?e.referenceNode:e}function r(e){return 11===e?re:10===e?pe:re||pe}function p(e){if(!e)return document.documentElement;for(var o=r(10)?document.body:null,n=e.offsetParent||null;n===o&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TH','TD','TABLE'].indexOf(n.nodeName)&&'static'===t(n,'position')?p(n):n:e?e.ownerDocument.documentElement:document.documentElement}function s(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||p(e.firstElementChild)===e)}function d(e){return null===e.parentNode?e:d(e.parentNode)}function a(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,n=o?e:t,i=o?t:e,r=document.createRange();r.setStart(n,0),r.setEnd(i,0);var l=r.commonAncestorContainer;if(e!==l&&t!==l||n.contains(i))return s(l)?l:p(l);var f=d(e);return f.host?a(f.host,t):a(e,d(t).host)}function l(e){var t=1=o.clientWidth&&n>=o.clientHeight}),l=0a[e]&&!t.escapeWithReference&&(n=Q(f[o],a[e]-('right'===e?f.width:f.height))),ae({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=le({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!K(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-us[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f]),E=parseFloat(w['border'+f+'Width']),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},ae(n,m,$(v)),ae(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ce.FLIP:p=[n,i];break;case ce.CLOCKWISE:p=G(n);break;case ce.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)f(l.top)||'bottom'===n&&f(a.top)f(o.right),g=f(a.top)f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,w=-1!==['top','bottom'].indexOf(n),y=!!t.flipVariations&&(w&&'start'===r&&h||w&&'end'===r&&c||!w&&'start'===r&&g||!w&&'end'===r&&u),E=!!t.flipVariationsByContent&&(w&&'start'===r&&c||w&&'end'===r&&h||!w&&'start'===r&&u||!w&&'end'===r&&g),v=y||E;(m||b||v)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),v&&(r=z(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=le({},e.offsets.popper,C(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport',flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!K(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=D(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.rightwindow.devicePixelRatio||!fe),c='bottom'===o?'top':'bottom',g='right'===n?'left':'right',b=B('transform');if(d='bottom'==c?'HTML'===l.nodeName?-l.clientHeight+h.bottom:-f.height+h.bottom:h.top,s='right'==g?'HTML'===l.nodeName?-l.clientWidth+h.right:-f.width+h.right:h.left,a&&b)m[b]='translate3d('+s+'px, '+d+'px, 0)',m[c]=0,m[g]=0,m.willChange='transform';else{var w='bottom'==c?-1:1,y='right'==g?-1:1;m[c]=d*w,m[g]=s*y,m.willChange=c+', '+g}var E={"x-placement":e.placement};return e.attributes=le({},E,e.attributes),e.styles=le({},m,e.styles),e.arrowStyles=le({},e.offsets.arrow,e.arrowStyles),e},gpuAcceleration:!0,x:'bottom',y:'right'},applyStyle:{order:900,enabled:!0,fn:function(e){return V(e.instance.popper,e.styles),j(e.instance.popper,e.attributes),e.arrowElement&&Object.keys(e.arrowStyles).length&&V(e.arrowElement,e.arrowStyles),e},onLoad:function(e,t,o,n,i){var r=L(i,t,e,o.positionFixed),p=O(o.placement,r,t,e,o.modifiers.flip.boundariesElement,o.modifiers.flip.padding);return t.setAttribute('x-placement',p),V(t,{position:o.positionFixed?'fixed':'absolute'}),o},gpuAcceleration:void 0}}},ge}); -//# sourceMappingURL=popper.min.js.map diff --git a/tests/coverage/app/Console/Commands/CreateAdmin.php.html b/tests/coverage/app/Console/Commands/CreateAdmin.php.html deleted file mode 100644 index 013b2c8..0000000 --- a/tests/coverage/app/Console/Commands/CreateAdmin.php.html +++ /dev/null @@ -1,345 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console/Commands/CreateAdmin.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
CreateAdmin
n/a
0 / 0
n/a
0 / 0
13
n/a
0 / 0
 handle
n/a
0 / 0
n/a
0 / 0
1
 addFirstname
n/a
0 / 0
n/a
0 / 0
3
 addLastname
n/a
0 / 0
n/a
0 / 0
3
 addEmail
n/a
0 / 0
n/a
0 / 0
3
 addPassword
n/a
0 / 0
n/a
0 / 0
3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Console\Commands;
4
5use App\Models\User;
6use Illuminate\Console\Command;
7use Illuminate\Support\Facades\Validator;
8use Illuminate\Validation\ValidationException;
9
10/**
11 * Creates a new user
12 *
13 * @codeCoverageIgnore
14 */
15class CreateAdmin extends Command
16{
17    /**
18     * The name and signature of the console command.
19     *
20     * @var string
21     */
22    protected $signature = 'user:create';
23
24    /**
25     * The console command description.
26     *
27     * @var string
28     */
29    protected $description = 'Create a backend admin user';
30
31    /**
32     * The firstname of the new user.
33     *
34     * @var string
35     */
36    protected $firstname;
37
38    /**
39     * The lastname of the new user.
40     *
41     * @var string
42     */
43    protected $lastname;
44
45    /**
46     * The email of the new user.
47     *
48     * @var string
49     */
50    protected $email;
51
52    /**
53     * The password of the new user.
54     *
55     * @var string
56     */
57    protected $password;
58
59    /**
60     * Execute the console command.
61     *
62     * @return integer
63     */
64    public function handle(): int
65    {
66        $this->firstname = null;
67        $this->addFirstname();
68
69        $this->lastname = null;
70        $this->addLastname();
71
72        $this->email = null;
73        $this->addEmail();
74
75        $this->password = null;
76        $this->addPassword();
77
78        $user = new User([
79            'firstname' => $this->firstname,
80            'lastname' => $this->lastname,
81            'email' => $this->email,
82            'password' => $this->password,
83            'remember_token' => null,
84        ]);
85        $user->saveOrFail();
86
87        $this->info('User created 👌');
88
89        return 0;
90    }
91
92    /**
93     * Add a firstname to the user.
94     *
95     * @return void
96     */
97    private function addFirstname(): void
98    {
99        while (is_null($this->firstname)) {
100            try {
101                $tmp       = $this->ask('Type the wanted user firstname', 'Admin');
102                $validator = Validator::make(['firstname' => $tmp], [
103                    'firstname' => 'required|min:3|max:255'
104                ]);
105                $validator->validate();
106                $this->firstname = $tmp;
107            } catch (ValidationException $e) {
108                $this->error(sprintf(
109                    'Please provide a valid firstname %s',
110                    \implode(',', collect($e->errors())->flatten()->all())
111                ));
112                continue;
113            } //end try
114        }; //end while
115    }
116
117    /**
118     * Add a lastname to the user.
119     *
120     * @return void
121     */
122    private function addLastname(): void
123    {
124        while (is_null($this->lastname)) {
125            try {
126                $tmp       = $this->ask('Type the wanted user lastname', 'Saïtama');
127                $validator = Validator::make(['lastname' => $tmp], [
128                    'lastname' => 'required|min:3|max:255'
129                ]);
130                $validator->validate();
131                $this->lastname = $tmp;
132            } catch (ValidationException $e) {
133                $this->error(sprintf(
134                    'Please provide a valid lastname %s',
135                    \implode(',', collect($e->errors())->flatten()->all())
136                ));
137                continue;
138            } //end try
139        }; //end while
140    }
141
142    /**
143     * Add an email to the user.
144     *
145     * @return void
146     */
147    private function addEmail(): void
148    {
149        while (is_null($this->email)) {
150            try {
151                $tmp       = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
152                $validator = Validator::make(['email' => $tmp], [
153                    'email' => 'required|unique:users,email|email:rfc,dns'
154                ]);
155                $validator->validate();
156                $this->email = $tmp;
157            } catch (ValidationException $e) {
158                $this->error(sprintf(
159                    'Please provide a valid email %s',
160                    \implode(',', collect($e->errors())->flatten()->all())
161                ));
162                continue;
163            } //end try
164        }; //end while
165    }
166
167    /**
168     * Add a password to the user.
169     *
170     * @return void
171     */
172    private function addPassword(): void
173    {
174        while (
175            ($this->password = $this->secret(
176                (!\is_null($this->password) ? 'Failed to confirm, ' : '') . 'Type the wanted user password'
177            )) !== $this->secret('Confirm the password')
178        ) {
179            continue;
180        }; //end while
181    }
182}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Console/Commands/DeleteUnconfirmedCustomers.php.html b/tests/coverage/app/Console/Commands/DeleteUnconfirmedCustomers.php.html deleted file mode 100644 index c0eae5c..0000000 --- a/tests/coverage/app/Console/Commands/DeleteUnconfirmedCustomers.php.html +++ /dev/null @@ -1,187 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console/Commands/DeleteUnconfirmedCustomers.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
DeleteUnconfirmedCustomers
n/a
0 / 0
n/a
0 / 0
2
n/a
0 / 0
 handle
n/a
0 / 0
n/a
0 / 0
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Console\Commands;
4
5use App\Models\Customer;
6use App\Models\CustomerLogin;
7use App\Models\CustomerOptInHistory;
8use Carbon\Carbon;
9use Illuminate\Console\Command;
10use Illuminate\Support\Facades\DB;
11use Illuminate\Support\Facades\Log;
12
13/**
14 * @codeCoverageIgnore
15 */
16class DeleteUnconfirmedCustomers extends Command
17{
18    /**
19     * The name and signature of the console command.
20     *
21     * @var string
22     */
23    protected $signature = 'customer:deleteuc';
24
25    /**
26     * The console command description.
27     *
28     * @var string
29     */
30    protected $description = 'Delete the customers that haven\'t
31    confirmed their acocunt within 24 hours after the registeration.';
32
33    /**
34     * Execute the console command.
35     *
36     * @return integer
37     */
38    public function handle(): int
39    {
40        /** @var \Illuminate\Database\Eloquent\Collection $customersLogins */
41        $customersLogins = CustomerLogin::query()
42            ->where('status', false)
43            ->where('created_at', '<', Carbon::now()->subDay(1))
44            ->with(['brand', 'customer'])
45            ->get();
46        $customersLogins->map(function (CustomerLogin $customerLogin) {
47            Log::info($customerLogin->customer_id);
48            DB::transaction(function () use ($customerLogin) {
49                /** @var \App\Models\Customer $customer */
50                $customer = $customerLogin->customer;
51
52                /** @var \App\Models\Brand */
53                $brand = $customerLogin->brand;
54
55                // * Suppression de ses infos de login pour la marque.
56                $customer->info($brand, Customer::FIRST_OR_FAIL)->deleteOrFail();
57                $customer->login($brand, Customer::FIRST_OR_FAIL)->deleteOrFail();
58
59                // * Si le customer n'a plus d'info il n'a donc plus besoin de compte en crm.
60                if (!$customer->infos()->count()) {
61                    // * Suppression du customer une fois tout le reste supprimé.
62                    $customer->optInHistory()->get()
63                        ->map(function (CustomerOptInHistory $customerOptInHistory) {
64                            $customerOptInHistory->deleteOrFail();
65                        });
66                    $customer->deleteOrFail();
67                }
68            });
69        });
70        return 0;
71    }
72}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Console/Commands/GenerateClient.php.html b/tests/coverage/app/Console/Commands/GenerateClient.php.html deleted file mode 100644 index 70aa64c..0000000 --- a/tests/coverage/app/Console/Commands/GenerateClient.php.html +++ /dev/null @@ -1,417 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console/Commands/GenerateClient.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
GenerateClient
n/a
0 / 0
n/a
0 / 0
19
n/a
0 / 0
 handle
n/a
0 / 0
n/a
0 / 0
1
 copyApiConfigInfo
n/a
0 / 0
n/a
0 / 0
2
 copyRoutesList
n/a
0 / 0
n/a
0 / 0
4
 copyExceptions
n/a
0 / 0
n/a
0 / 0
2
 copyTraits
n/a
0 / 0
n/a
0 / 0
2
 copyEnums
n/a
0 / 0
n/a
0 / 0
2
 copyToFolder
n/a
0 / 0
n/a
0 / 0
3
 replaceInPhpFile
n/a
0 / 0
n/a
0 / 0
3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Console\Commands;
4
5use App\Enums\ApiError;
6use App\Enums\ApiStatus;
7use App\Enums\ArcadiaOrderType;
8use App\Enums\Country;
9use App\Enums\QuestionType;
10use App\Exceptions\Api\V4\ApiErrorException;
11use App\Exceptions\Api\V4\CrmException;
12use App\Traits\Enums\BaseEnum;
13use Illuminate\Console\Command;
14use Illuminate\Support\Facades\File;
15use Illuminate\Support\Facades\Route;
16use Illuminate\Support\Str;
17
18/**
19 * @codeCoverageIgnore
20 */
21class GenerateClient extends Command
22{
23    private const TARGET          = 'client/src';
24    private const CLIENTNAMESPACE = 'LDC\\LDCCRM';
25
26    /**
27     * The name and signature of the console command.
28     *
29     * @var string
30     */
31    protected $signature = 'client:generate';
32
33    /**
34     * The console command description.
35     *
36     * @var string
37     */
38    protected $description = 'Generate the crm V4 client in client folder';
39
40    /**
41     * Execute the console command.
42     *
43     * @return integer
44     */
45    public function handle(): int
46    {
47        $this->copyTraits();
48        $this->copyEnums();
49        $this->copyExceptions();
50        $this->copyRoutesList();
51        $this->copyApiConfigInfo();
52        return 0;
53    }
54
55    /**
56     * Copy config files
57     *
58     * @return void
59     */
60    private function copyApiConfigInfo(): void
61    {
62        $this->info('Copy Api Config');
63        $rootTarget = app_path('../' . self::TARGET);
64        if (File::exists("$rootTarget/../apiConfig.readonly.json")) {
65            File::delete("$rootTarget/../apiConfig.readonly.json");
66        }
67        File::put(
68            "$rootTarget/../apiConfig.readonly.json",
69            \json_encode(config('api'), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
70        );
71    }
72
73    /**
74     * Copy routes into a json file
75     *
76     * @return void
77     */
78    private function copyRoutesList(): void
79    {
80        $this->info('Copy Routes');
81        $routes = [];
82        /** @var \Illuminate\Routing\Route */
83        foreach (Route::getRoutes() as $route) {
84            if (\strpos($route->getPrefix(), 'v4') !== false) {
85                $routes[$route->getName()] = [
86                    'uri' => $route->uri(),
87                    'methods' => $route->methods()
88                ];
89            }
90        }
91        $rootTarget = app_path('../' . self::TARGET);
92        if (File::exists("$rootTarget/routes.json")) {
93            File::delete("$rootTarget/routes.json");
94        }
95        File::put(
96            "$rootTarget/routes.json",
97            \json_encode($routes, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
98        );
99    }
100
101    /**
102     * Copy Exeption classes
103     *
104     * @return void
105     */
106    private function copyExceptions(): void
107    {
108        $this->info('Copy Exceptions');
109        $rootTarget = app_path('../' . self::TARGET);
110        $classes    = [
111            CrmException::class,
112            ApiErrorException::class
113        ];
114        $this->copyToFolder($classes, 'Exceptions');
115        foreach ($classes as $class) {
116            $classBasename = class_basename($class);
117            $dest          = "$rootTarget/Exceptions/$classBasename.php";
118            $this->replaceInPhpFile($dest, 'App\\', self::CLIENTNAMESPACE . '\\');
119        }
120    }
121
122    /**
123     * Copy base enums classes
124     *
125     * @return void
126     */
127    private function copyTraits(): void
128    {
129        $this->info('Copy Traits');
130        $rootTarget = app_path('../' . self::TARGET);
131        $classes    = [
132            BaseEnum::class
133        ];
134        $this->copyToFolder($classes, 'Traits');
135        foreach ($classes as $class) {
136            $classBasename = class_basename($class);
137            $dest          = "$rootTarget/Traits/$classBasename.php";
138            $this->replaceInPhpFile($dest, 'App\\', self::CLIENTNAMESPACE . '\\');
139        }
140    }
141
142    /**
143     * Copy enums classes
144     *
145     * @return void
146     */
147    private function copyEnums(): void
148    {
149        $this->info('Copy Enums');
150        $rootTarget = app_path('../' . self::TARGET);
151        $classes    = [
152            ApiError::class,
153            ApiStatus::class,
154            ArcadiaOrderType::class,
155            Country::class,
156            QuestionType::class
157        ];
158        $this->copyToFolder($classes, 'Enums');
159        foreach ($classes as $class) {
160            $classBasename = class_basename($class);
161            $dest          = "$rootTarget/Enums/$classBasename.php";
162            $this->replaceInPhpFile($dest, 'App\\', self::CLIENTNAMESPACE . '\\');
163        }
164    }
165
166    /**
167     * Copy Classes to specified folder
168     *
169     * @param array  $classes
170     * @param string $folder
171     * @return void
172     */
173    private function copyToFolder(array $classes, string $folder): void
174    {
175        $rootTarget      = app_path('../' . self::TARGET);
176        $folderNamespace = \str_replace('/', '\\', $folder);
177        foreach ($classes as $class) {
178            $classFileName = \str_replace("App\\$folderNamespace\\", '', sprintf('%s.php', $class));
179            $classFileName = \str_replace('\\', '/', $classFileName);
180            $classBasename = class_basename($class);
181            $source        = \app_path("$folder/$classFileName");
182            $dest          = "$rootTarget/$folder/$classBasename.php";
183            if (File::exists($dest)) {
184                File::delete($dest);
185            }
186            File::copy($source, $dest);
187            $this->replaceInPhpFile($dest, 'namespace App', 'namespace ' . self::CLIENTNAMESPACE);
188        }
189    }
190
191    /**
192     * Replaces a specific string with another on a file
193     *
194     * @param string $source
195     * @param string $search
196     * @param string $replace
197     * @return void
198     */
199    private function replaceInPhpFile(string $source, string $search, string $replace): void
200    {
201        $fContent = File::get($source);
202
203        // Remove trailing \Api\V4 .
204        if ($pos = strpos($fContent, '\Api\V4')) {
205            $fContent = substr_replace($fContent, '', $pos, strlen('\Api\V4'));
206        }
207
208        // Remove trailing \Api .
209        $fContent = Str::of($fContent)->replaceMatches("/\\\(Api)([\s;\\\])/", '$2');
210        $fContent = Str::of($fContent)->replaceMatches("/\\\Traits\\\Enums/", '\Traits');
211
212        // Replace namespace top level.
213        $pos = strpos($fContent, $search);
214        if ($pos !== false) {
215            File::put($source, \str_replace($search, $replace, $fContent));
216        }
217    }
218}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Console/Commands/LdcWebStatusChecker.php.html b/tests/coverage/app/Console/Commands/LdcWebStatusChecker.php.html deleted file mode 100644 index 02264e0..0000000 --- a/tests/coverage/app/Console/Commands/LdcWebStatusChecker.php.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console/Commands/LdcWebStatusChecker.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
LdcWebStatusChecker
n/a
0 / 0
n/a
0 / 0
5
n/a
0 / 0
 handle
n/a
0 / 0
n/a
0 / 0
5
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Console\Commands;
4
5use Illuminate\Console\Command;
6
7/**
8 * Command Name: LDC Web Status Checker
9 * Description: Envoi des infos Serveur/Laravel vers LDC Web
10 * Version: 1.1
11 * Author:  Vincent BRIDIER
12 * Author URI: vincent.bridier@ldc.fr
13 *
14 * @codeCoverageIgnore
15 *
16 */
17class LdcWebStatusChecker extends Command
18{
19    /**
20     * The name and signature of the console command.
21     *
22     * @var string
23     */
24    protected $signature = 'ldcweb:statuschecker';
25
26    /**
27     * The console command description.
28     *
29     * @var string
30     */
31    protected $description = 'Envoi des infos Serveur/Laravel vers LDC Web';
32
33    /**
34     * Execute the console command.
35     *
36     * @return mixed
37     */
38    public function handle(): mixed
39    {
40        $data         = [];
41        $data['uuid'] = config('ldcweb.project_uuid');
42
43        // Sitemap.xml ?
44        if (file_exists(public_path() . '/sitemap.xml')) {
45            $data['sitemap'] = 'true';
46        } else {
47            $data['sitemap'] = 'false';
48        }
49
50        // Robots.txt ?
51        if (file_exists(public_path() . '/robots.txt')) {
52            $data['robots'] = 'true';
53        } else {
54            $data['robots'] = 'false';
55        }
56
57        // Check logs.
58        $data['logs'] = 0;
59        $patherror    = storage_path('/logs');
60        $files        = glob($patherror . '/*.log');
61        if (count($files) > 0) {
62            foreach ($files as $file) {
63                $data['logs'] = $data['logs'] + filesize($file);
64            }
65        }
66
67        $data['code']['version'] = app()->version();
68
69        // Send by cURL.
70        $url     = 'https://ldc-web.ldc.fr/api/status-checker';
71        $ch      = curl_init($url);
72        $payload = ['token' => 'CE8S52Qq7stf5k8frF4T', 'datas' => json_encode($data)];
73        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
74        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
75        curl_exec($ch);
76        curl_close($ch);
77        return 0;
78    }
79}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Console/Commands/MigrateCrmUsers.php.html b/tests/coverage/app/Console/Commands/MigrateCrmUsers.php.html deleted file mode 100644 index e9636e3..0000000 --- a/tests/coverage/app/Console/Commands/MigrateCrmUsers.php.html +++ /dev/null @@ -1,187 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console/Commands/MigrateCrmUsers.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
MigrateCrmUsers
n/a
0 / 0
n/a
0 / 0
6
n/a
0 / 0
 handle
n/a
0 / 0
n/a
0 / 0
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Console\Commands;
4
5use App\Lib\MigrateOldData;
6use App\Models\Brand;
7use Illuminate\Console\Command;
8use Illuminate\Support\Facades\DB;
9
10/**
11 * @codeCoverageIgnore
12 */
13class MigrateCrmUsers extends Command
14{
15    /**
16     * The name and signature of the console command.
17     *
18     * @var string
19     */
20    protected $signature = 'migrate:crm';
21
22    /**
23     * The console command description.
24     *
25     * @var string
26     */
27    protected $description = 'Migrate crm users';
28
29
30    /**
31     * Execute the console command.
32     *
33     * @return integer
34     */
35    public function handle(): int
36    {
37        try {
38            $table = $this->ask('What is the tmp table name with users data ?');
39
40            try {
41                DB::connection(config('database.oldDB'))->table($table)->exists();
42            } catch (\Exception $e) {
43                $this->error(sprintf('%s table not found on old crm database', $table));
44                return -1;
45            }
46
47            $brandname = $this->ask('What is the brand name ?');
48            $brand     = Brand::query()->where('name', 'LIKE', "%$brandname%")->first();
49            if (!$brand) {
50                if (!$this->confirm(sprintf('Would you like to use %s ? ', $brandname))) {
51                    $this->info('Command cancelled');
52                    return 0;
53                }
54                if ($this->confirm('Would you like to create a new one ?')) {
55                    $brand       = new Brand();
56                    $brand->name = $brandname;
57                    $brand->save();
58                } else {
59                    $this->info('Command cancelled');
60                    return 0;
61                }
62            }
63
64            $mgOldData = new MigrateOldData();
65            $mgOldData->runMigration($brand, $table);
66        } catch (\Exception $e) {
67            $this->error(sprintf('Failed %s', $e));
68            return -1;
69        } //end try
70        return 0;
71    }
72}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Console/Commands/StartStatJobs.php.html b/tests/coverage/app/Console/Commands/StartStatJobs.php.html deleted file mode 100644 index 636dc86..0000000 --- a/tests/coverage/app/Console/Commands/StartStatJobs.php.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console/Commands/StartStatJobs.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
StartStatJobs
n/a
0 / 0
n/a
0 / 0
1
n/a
0 / 0
 handle
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Console\Commands;
4
5use App\Jobs\StartStatJobs as JobsStartStatJobs;
6use Illuminate\Console\Command;
7
8/**
9 * @codeCoverageIgnore
10 */
11class StartStatJobs extends Command
12{
13    /**
14     * The name and signature of the console command.
15     *
16     * @var string
17     */
18    protected $signature = 'stats:collect';
19
20    /**
21     * The console command description.
22     *
23     * @var string
24     */
25    protected $description = 'Force push the collect stats jobs into the queue (stats)';
26
27    /**
28     * Execute the console command.
29     *
30     * @return integer
31     */
32    public function handle(): int
33    {
34        \dispatch(new JobsStartStatJobs())->afterResponse();
35        return 0;
36    }
37}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Console/Commands/TestMail.php.html b/tests/coverage/app/Console/Commands/TestMail.php.html deleted file mode 100644 index 57cb007..0000000 --- a/tests/coverage/app/Console/Commands/TestMail.php.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console/Commands/TestMail.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
TestMail
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 handle
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Console\Commands;
4
5use Illuminate\Console\Command;
6use Illuminate\Support\Facades\Mail;
7
8class TestMail extends Command
9{
10    /**
11     * The name and signature of the console command.
12     *
13     * @var string
14     */
15    protected $signature = 'uwil:mail:test';
16
17    /**
18     * The console command description.
19     *
20     * @var string
21     */
22    protected $description = 'Send test email to equipe.web@ldc.fr';
23
24    /**
25     * Execute the console command.
26     *
27     * @return void
28     */
29    public function handle()
30    {
31        Mail::raw(sprintf('UWIL mail-test from %s %s', \config('app.name'), \config('app.url')), function ($msg) {
32            $msg->to('equipe.web@ldc.fr')->subject('Test Email');
33        });
34    }
35}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Console/Commands/UserCreate.php.html b/tests/coverage/app/Console/Commands/UserCreate.php.html deleted file mode 100644 index d929655..0000000 --- a/tests/coverage/app/Console/Commands/UserCreate.php.html +++ /dev/null @@ -1,496 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console/Commands/UserCreate.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 90
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UserCreate
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 90
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
380
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 handle
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 22
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 addFirstName
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 addLastName
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 addEmail
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 addPassword
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 addRole
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
42
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Console\Commands;
4
5use App\Enums\Users\RoleEnum;
6use App\Models\User;
7use Carbon\Carbon;
8use Illuminate\Console\Command;
9use Illuminate\Support\Facades\Validator;
10use Illuminate\Validation\ValidationException;
11
12class UserCreate extends Command
13{
14    /**
15     * The name and signature of the console command.
16     *
17     * @var string
18     */
19    protected $signature = 'uwil:user:create';
20
21    /**
22     * The console command description.
23     *
24     * @var string
25     */
26    protected $description = 'Create a backend admin user';
27
28    /**
29     * The first name of the new user.
30     *
31     * @var string
32     */
33    protected $first_name;
34
35    /**
36     * The last name of the new user.
37     *
38     * @var string
39     */
40    protected $last_name;
41
42    /**
43     * The email of the new user.
44     *
45     * @var string
46     */
47    protected $email;
48
49    /**
50     * The password of the new user.
51     *
52     * @var string
53     */
54    protected $password;
55
56    /**
57     * The role of the new user.
58     *
59     * @var string
60     */
61    protected $role;
62
63    /**
64     * Execute the console command.
65     *
66     * @return integer
67     */
68    public function handle(): int
69    {
70        $this->first_name = null;
71        $this->addFirstName();
72
73        $this->last_name = null;
74        $this->addLastName();
75
76        $this->email = null;
77        $this->addEmail();
78
79        $this->password = null;
80        $this->addPassword();
81
82        $this->role = null;
83        $this->addRole();
84
85        $user = new User([
86            'first_name' => $this->first_name,
87            'last_name' => $this->last_name,
88            'email' => $this->email,
89            'password' => $this->password,
90            'role' => $this->role,
91            'published' => true,
92            'published_at' => Carbon::now(),
93        ]);
94        $user->saveOrFail();
95
96        $this->info('User created 👌');
97
98        return 0;
99    }
100
101    /**
102     * Add a first name to the user.
103     *
104     * @return void
105     */
106    private function addFirstName(): void
107    {
108        while (is_null($this->first_name)) {
109            try {
110                $tmp       = $this->ask('Type the wanted user first name', 'Admin');
111                $validator = Validator::make(['first_name' => $tmp], [
112                    'first_name' => 'required|min:3|max:255'
113                ]);
114                $validator->validate();
115                $this->first_name = $tmp;
116            } catch (ValidationException $e) {
117                $this->error(sprintf(
118                    'Please provide a valid first name %s',
119                    \implode(',', collect($e->errors())->flatten()->all())
120                ));
121                continue;
122            } //end try
123        }; //end while
124    }
125
126    /**
127     * Add a last name to the user.
128     *
129     * @return void
130     */
131    private function addLastName(): void
132    {
133        while (is_null($this->last_name)) {
134            try {
135                $tmp       = $this->ask('Type the wanted user last name', 'Saïtama');
136                $validator = Validator::make(['last_name' => $tmp], [
137                    'last_name' => 'required|min:3|max:255'
138                ]);
139                $validator->validate();
140                $this->last_name = $tmp;
141            } catch (ValidationException $e) {
142                $this->error(sprintf(
143                    'Please provide a valid last_name %s',
144                    \implode(',', collect($e->errors())->flatten()->all())
145                ));
146                continue;
147            } //end try
148        }; //end while
149    }
150
151    /**
152     * Add an email to the user.
153     *
154     * @return void
155     */
156    private function addEmail(): void
157    {
158        while (is_null($this->email)) {
159            try {
160                $tmp       = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
161                $validator = Validator::make(['email' => $tmp], [
162                    'email' => 'required|unique:users,email|email:rfc,dns'
163                ]);
164                $validator->validate();
165                $this->email = $tmp;
166            } catch (ValidationException $e) {
167                $this->error(sprintf(
168                    'Please provide a valid email %s',
169                    \implode(',', collect($e->errors())->flatten()->all())
170                ));
171                continue;
172            } //end try
173        }; //end while
174    }
175
176    /**
177     * Add a password to the user.
178     *
179     * @return void
180     */
181    private function addPassword(): void
182    {
183        while (
184            ($this->password = $this->secret(
185                (!\is_null($this->password) ? 'Failed to confirm, ' : '') . 'Type the wanted user password'
186            )) !== $this->secret('Confirm the password')
187        ) {
188            continue;
189        }; //end while
190    }
191
192    /**
193     * Add a role to the user.
194     *
195     * @return void
196     */
197    private function addRole(): void
198    {
199        while (is_null($this->role)) {
200            try {
201                $tmp                         = $this->choice(
202                    'Select his role',
203                    [RoleEnum::conceptor->name, RoleEnum::admin->name, RoleEnum::visitor->name],
204                    RoleEnum::visitor->name,
205                    $maxAttempts             = null,
206                    $allowMultipleSelections = false
207                );
208                if ($tmp === RoleEnum::conceptor->name) {
209                    $tmp = RoleEnum::conceptor;
210                }
211                if ($tmp === RoleEnum::admin->name) {
212                    $tmp = RoleEnum::admin;
213                }
214                if ($tmp === RoleEnum::visitor->name) {
215                    $tmp = RoleEnum::visitor;
216                }
217                $validator = Validator::make(['role' => $tmp], [
218                    'role' => 'required'
219                ]);
220                $validator->validate();
221                $this->role = $tmp;
222            } catch (ValidationException $e) {
223                $this->error(sprintf(
224                    'Please choose from the selection',
225                    \implode(',', collect($e->errors())->flatten()->all())
226                ));
227                continue;
228            } //end try
229        }; //end while
230    }
231}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Console/Commands/dashboard.html b/tests/coverage/app/Console/Commands/dashboard.html deleted file mode 100644 index d210cdf..0000000 --- a/tests/coverage/app/Console/Commands/dashboard.html +++ /dev/null @@ -1,301 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Console/Commands - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
ClassCoverage
App\Console\Commands\TestMail0%
App\Console\Commands\UserCreate0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
ClassCRAP
App\Console\Commands\UserCreate380
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - -
MethodCoverage
handle0%
handle0%
addFirstName0%
addLastName0%
addEmail0%
addPassword0%
addRole0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - -
MethodCRAP
addRole42
addFirstName12
addLastName12
addEmail12
addPassword12
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Console/Commands/index.html b/tests/coverage/app/Console/Commands/index.html deleted file mode 100644 index f04ec41..0000000 --- a/tests/coverage/app/Console/Commands/index.html +++ /dev/null @@ -1,214 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console/Commands - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 93
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
DeleteUnconfirmedCustomers.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
GenerateClient.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
LdcWebStatusChecker.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
MigrateCrmUsers.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
StartStatJobs.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
TestMail.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UserCreate.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 90
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Console/Kernel.php.html b/tests/coverage/app/Console/Kernel.php.html deleted file mode 100644 index ebcc1ca..0000000 --- a/tests/coverage/app/Console/Kernel.php.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console/Kernel.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
Kernel
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 schedule
n/a
0 / 0
n/a
0 / 0
1
 commands
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Console;
4
5use App\Console\Commands\DeleteUnconfirmedCustomers;
6use App\Jobs\StartStatJobs;
7use Illuminate\Console\Scheduling\Schedule;
8use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
9
10class Kernel extends ConsoleKernel
11{
12    /**
13     * The Artisan commands provided by your application.
14     *
15     * @var array
16     */
17    protected $commands = [];
18
19    /**
20     * Define the application's command schedule.
21     *
22     * @param  \Illuminate\Console\Scheduling\Schedule $schedule
23     * @return void
24     */
25    protected function schedule(Schedule $schedule): void
26    {
27        // @codeCoverageIgnoreStart
28        $schedule->job(StartStatJobs::class)->dailyAt('03:30');
29        $schedule->command(DeleteUnconfirmedCustomers::class)->dailyAt('05:30');
30        // @codeCoverageIgnoreEnd
31    }
32
33    /**
34     * Register the commands for the application.
35     *
36     * @return void
37     */
38    protected function commands(): void
39    {
40        $this->load(__DIR__ . '/Commands');
41
42        require base_path('routes/console.php');
43    }
44}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Console/dashboard.html b/tests/coverage/app/Console/dashboard.html deleted file mode 100644 index bcf4530..0000000 --- a/tests/coverage/app/Console/dashboard.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Console - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
ClassCoverage
App\Console\Commands\TestMail0%
App\Console\Commands\UserCreate0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
ClassCRAP
App\Console\Commands\UserCreate380
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - -
MethodCoverage
handle0%
handle0%
addFirstName0%
addLastName0%
addEmail0%
addPassword0%
addRole0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - -
MethodCRAP
addRole42
addFirstName12
addLastName12
addEmail12
addPassword12
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Console/index.html b/tests/coverage/app/Console/index.html deleted file mode 100644 index b50f6a6..0000000 --- a/tests/coverage/app/Console/index.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Console - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 2.11% covered (danger) -
-
-
2.11%
2 / 95
-
- 12.50% covered (danger) -
-
-
12.50%
1 / 8
-
- 33.33% covered (danger) -
-
-
33.33%
1 / 3
Commands
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 93
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
Kernel.php
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- -
- - diff --git a/tests/coverage/app/Enums/ActivityLogs/ActivityLogsEventEnum.php.html b/tests/coverage/app/Enums/ActivityLogs/ActivityLogsEventEnum.php.html deleted file mode 100644 index d3893b6..0000000 --- a/tests/coverage/app/Enums/ActivityLogs/ActivityLogsEventEnum.php.html +++ /dev/null @@ -1,201 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/ActivityLogs/ActivityLogsEventEnum.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ActivityLogsEventEnum
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 bootstrapClass
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums\ActivityLogs;
4
5use App\Traits\Enums\BaseEnum;
6
7enum ActivityLogsEventEnum: int
8{
9    use BaseEnum;
10
11    case created    = 1;
12    case updated    = 2;
13    case duplicated = 3;
14    case deleted    = 4;
15
16    /**
17     * Optionnal labels definition
18     */
19    private const LABELS = [
20        self::created->name    => 'Création',
21        self::updated->name    => 'Mise à jour',
22        self::duplicated->name => 'Duplication',
23        self::deleted->name    => 'Suppression',
24    ];
25
26
27    /**
28     * Custom added classes definition
29     */
30    private const BOOTSTRAPCLASS = [
31        self::created->name    => 'success',
32        self::updated->name    => 'warning',
33        self::duplicated->name => 'secondary',
34        self::deleted->name    => 'danger',
35    ];
36
37    /**
38     * Get Class
39     *
40     * @return string
41     */
42    public function bootstrapClass(): string
43    {
44        return self::BOOTSTRAPCLASS[$this->name];
45    }
46}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/ActivityLogs/dashboard.html b/tests/coverage/app/Enums/ActivityLogs/dashboard.html deleted file mode 100644 index bbfb300..0000000 --- a/tests/coverage/app/Enums/ActivityLogs/dashboard.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Enums/ActivityLogs - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Enums\ActivityLogs\ActivityLogsEventEnum0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
MethodCoverage
bootstrapClass0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Enums/ActivityLogs/index.html b/tests/coverage/app/Enums/ActivityLogs/index.html deleted file mode 100644 index bb48648..0000000 --- a/tests/coverage/app/Enums/ActivityLogs/index.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/ActivityLogs - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ActivityLogsEventEnum.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Enums/ApiError.php.html b/tests/coverage/app/Enums/ApiError.php.html deleted file mode 100644 index a08af4f..0000000 --- a/tests/coverage/app/Enums/ApiError.php.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/ApiError.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums;
4
5use App\Traits\Enums\BaseEnum;
6
7enum ApiError: int
8{
9    use BaseEnum;
10
11    case modelNotFound             = 101;
12    case validationFailed          = 102;
13    case customerExists            = 103;
14    case customerAlreadyActive     = 110;
15    case customerNotActivated      = 116;
16    case authFailed                = 117;
17    case apiAuthFailed             = 119;
18    case singleOptinCustomerExists = 120;
19    case methodNotAllowed          = 150;
20    case wrongTimeStamp            = 151;
21    case missingParameter          = 400;
22    case authorizationException    = 403;
23    case throttleRequestsException = 429;
24
25    /**
26     * Optionnal labels definition
27     */
28    private const LABELS = [
29        self::modelNotFound->name             => '%s introuvable.',
30        self::validationFailed->name          => 'Impossible de valider les données',
31        self::customerExists->name            => 'L\'utilisateur est déjà enregistré sur ce site',
32        self::customerNotActivated->name      => 'Le compte n\'est pas activé',
33        self::customerAlreadyActive->name     => 'Le compte est déjà activé',
34        self::singleOptinCustomerExists->name => 'Le single optin ne peut être ajouté car un compte existe.',
35        self::authFailed->name                => 'Echec de l\'authentification du compte',
36        self::apiAuthFailed->name             => 'Echec de l\'authentification client à l\'Api LDC-CRM pour ce service',
37        self::methodNotAllowed->name          => 'This method is not allowed for this request',
38        self::wrongTimeStamp->name            => 'Your request is malformed, please check timestamp header and
39            parameter',
40        self::missingParameter->name          => 'The request is missing some parameters',
41        self::authorizationException->name    => 'You are not autorized to access this',
42        self::throttleRequestsException->name => 'Throttle: too many request have been attempted, please retry later'
43    ];
44}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/ApiStatus.php.html b/tests/coverage/app/Enums/ApiStatus.php.html deleted file mode 100644 index ca488bb..0000000 --- a/tests/coverage/app/Enums/ApiStatus.php.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/ApiStatus.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums;
4
5use App\Traits\Enums\BaseEnum;
6
7enum ApiStatus: int
8{
9    use BaseEnum;
10
11    case OK = 1;
12    case KO = 2;
13}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/ArcadiaMailType.php.html b/tests/coverage/app/Enums/ArcadiaMailType.php.html deleted file mode 100644 index ba2aa1d..0000000 --- a/tests/coverage/app/Enums/ArcadiaMailType.php.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/ArcadiaMailType.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums;
4
5use App\Traits\Enums\BaseEnum;
6
7enum ArcadiaMailType: int
8{
9    use BaseEnum;
10
11    case default = 1;
12    case game    = 2;
13}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/ArcadiaOrderType.php.html b/tests/coverage/app/Enums/ArcadiaOrderType.php.html deleted file mode 100644 index d0c50cf..0000000 --- a/tests/coverage/app/Enums/ArcadiaOrderType.php.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/ArcadiaOrderType.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums;
4
5use App\Traits\Enums\BaseEnum;
6
7enum ArcadiaOrderType: int
8{
9    use BaseEnum;
10
11    case cb    = 0;
12    case check = 1;
13}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/Country.php.html b/tests/coverage/app/Enums/Country.php.html deleted file mode 100644 index ed6860f..0000000 --- a/tests/coverage/app/Enums/Country.php.html +++ /dev/null @@ -1,875 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/Country.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 97.62% covered (success) -
-
-
97.62%
41 / 42
-
- 83.33% covered (warning) -
-
-
83.33%
5 / 6
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Country
-
- 97.62% covered (success) -
-
-
97.62%
41 / 42
-
- 83.33% covered (warning) -
-
-
83.33%
5 / 6
7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 getValidCountriesLabel
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getValidCountriesValues
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getValidIsoAplha2Codes
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getValidCountries
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 isoCodes
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 get
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.15
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums;
4
5use App\Traits\Enums\BaseEnum;
6
7enum Country: int
8{
9    use BaseEnum;
10
11    case afghanistan                            = 1;
12    case alandIslands                           = 2;
13    case albania                                = 3;
14    case algeria                                = 4;
15    case americanSamoa                          = 5;
16    case andorra                                = 6;
17    case angola                                 = 7;
18    case anguilla                               = 8;
19    case antarctica                             = 9;
20    case antiguaAndBarbuda                      = 10;
21    case argentina                              = 11;
22    case armenia                                = 12;
23    case aruba                                  = 13;
24    case australia                              = 14;
25    case austria                                = 15;
26    case azerbaijan                             = 16;
27    case bahrain                                = 17;
28    case bahamas                                = 18;
29    case bangladesh                             = 19;
30    case barbados                               = 20;
31    case belarus                                = 21;
32    case belgium                                = 22;
33    case belize                                 = 23;
34    case benin                                  = 24;
35    case bermuda                                = 25;
36    case bhutan                                 = 26;
37    case boliviaPlurinationalStateOf            = 27;
38    case bonaireSintEustatiusAndSaba            = 28;
39    case bosniaAndHerzegovina                   = 29;
40    case botswana                               = 30;
41    case bouvetIsland                           = 31;
42    case brazil                                 = 32;
43    case britishIndianOceanTerritory            = 33;
44    case bruneiDarussalam                       = 34;
45    case bulgaria                               = 35;
46    case burkinaFaso                            = 36;
47    case burundi                                = 37;
48    case cambodia                               = 38;
49    case cameroon                               = 39;
50    case canada                                 = 40;
51    case capeVerde                              = 41;
52    case caymanIslands                          = 42;
53    case centralAfricanRepublic                 = 43;
54    case chad                                   = 44;
55    case chile                                  = 45;
56    case china                                  = 46;
57    case christmasIsland                        = 47;
58    case cocosKeelingIslands                    = 48;
59    case colombia                               = 49;
60    case comoros                                = 50;
61    case congo                                  = 51;
62    case congoTheDemocraticRepublicOfThe        = 52;
63    case cookIslands                            = 53;
64    case costaRica                              = 54;
65    case coteDivoire                            = 55;
66    case croatia                                = 56;
67    case cuba                                   = 57;
68    case curacao                                = 58;
69    case cyprus                                 = 59;
70    case czechRepublic                          = 60;
71    case denmark                                = 61;
72    case djibouti                               = 62;
73    case dominica                               = 63;
74    case dominicanRepublic                      = 64;
75    case ecuador                                = 65;
76    case egypt                                  = 66;
77    case elSalvador                             = 67;
78    case equatorialGuinea                       = 68;
79    case eritrea                                = 69;
80    case estonia                                = 70;
81    case ethiopia                               = 71;
82    case falklandIslandsMalvinas                = 72;
83    case faroeIslands                           = 73;
84    case fiji                                   = 74;
85    case finland                                = 75;
86    case france                                 = 76;
87    case frenchGuiana                           = 77;
88    case frenchPolynesia                        = 78;
89    case frenchSouthernTerritories              = 79;
90    case gabon                                  = 80;
91    case gambia                                 = 81;
92    case georgia                                = 82;
93    case germany                                = 83;
94    case ghana                                  = 84;
95    case gibraltar                              = 85;
96    case greece                                 = 86;
97    case greenland                              = 87;
98    case grenada                                = 88;
99    case guadeloupe                             = 89;
100    case guam                                   = 90;
101    case guatemala                              = 91;
102    case guernsey                               = 92;
103    case guinea                                 = 93;
104    case guineaBissau                           = 94;
105    case guyana                                 = 95;
106    case haiti                                  = 96;
107    case heardIslandAndMcdonaldIslands          = 97;
108    case holySeeVaticanCityState                = 98;
109    case honduras                               = 99;
110    case hongKong                               = 100;
111    case hungary                                = 101;
112    case iceland                                = 102;
113    case india                                  = 103;
114    case indonesia                              = 104;
115    case iranIslamicRepublicOf                  = 105;
116    case iraq                                   = 106;
117    case ireland                                = 107;
118    case isleOfMan                              = 108;
119    case israel                                 = 109;
120    case italy                                  = 110;
121    case jamaica                                = 111;
122    case japan                                  = 112;
123    case jersey                                 = 113;
124    case jordan                                 = 114;
125    case kazakhstan                             = 115;
126    case kenya                                  = 116;
127    case kiribati                               = 117;
128    case koreaDemocraticPeoplesRepublicOf       = 118;
129    case koreaRepublicOf                        = 119;
130    case kuwait                                 = 120;
131    case kyrgyzstan                             = 121;
132    case laoPeoplesDemocraticRepublic           = 122;
133    case latvia                                 = 123;
134    case lebanon                                = 124;
135    case lesotho                                = 125;
136    case liberia                                = 126;
137    case libya                                  = 127;
138    case liechtenstein                          = 128;
139    case lithuania                              = 129;
140    case luxembourg                             = 130;
141    case macao                                  = 131;
142    case macedoniaTheFormerYugoslavRepublicOf   = 132;
143    case madagascar                             = 133;
144    case malawi                                 = 134;
145    case malaysia                               = 135;
146    case maldives                               = 136;
147    case mali                                   = 137;
148    case malta                                  = 138;
149    case marshallIslands                        = 139;
150    case martinique                             = 140;
151    case mauritania                             = 141;
152    case mauritius                              = 142;
153    case mayotte                                = 143;
154    case mexico                                 = 144;
155    case micronesiaFederatedStatesOf            = 145;
156    case moldovaRepublicOf                      = 146;
157    case monaco                                 = 147;
158    case mongolia                               = 148;
159    case montenegro                             = 149;
160    case montserrat                             = 150;
161    case morocco                                = 151;
162    case mozambique                             = 152;
163    case myanmar                                = 153;
164    case namibia                                = 154;
165    case nauru                                  = 155;
166    case nepal                                  = 156;
167    case netherlands                            = 157;
168    case newCaledonia                           = 158;
169    case newZealand                             = 159;
170    case nicaragua                              = 160;
171    case niger                                  = 161;
172    case nigeria                                = 162;
173    case niue                                   = 163;
174    case norfolkIsland                          = 164;
175    case northernMarianaIslands                 = 165;
176    case norway                                 = 166;
177    case oman                                   = 167;
178    case pakistan                               = 168;
179    case palau                                  = 169;
180    case palestineStateOf                       = 170;
181    case panama                                 = 171;
182    case papuaNewGuinea                         = 172;
183    case paraguay                               = 173;
184    case peru                                   = 174;
185    case philippines                            = 175;
186    case pitcairn                               = 176;
187    case poland                                 = 177;
188    case portugal                               = 178;
189    case puertoRico                             = 179;
190    case qatar                                  = 180;
191    case reunion                                = 181;
192    case romania                                = 182;
193    case russianFederation                      = 183;
194    case rwanda                                 = 184;
195    case saintBarthelemy                        = 185;
196    case saintHelenaAscensionAndTristanDaCunha  = 186;
197    case saintKittsAndNevis                     = 187;
198    case saintLucia                             = 188;
199    case saintMartinFrenchPart                  = 189;
200    case saintPierreAndMiquelon                 = 190;
201    case saintVincentAndTheGrenadines           = 191;
202    case samoa                                  = 192;
203    case sanMarino                              = 193;
204    case saoTomeAndPrincipe                     = 194;
205    case saudiArabia                            = 195;
206    case senegal                                = 196;
207    case serbia                                 = 197;
208    case seychelles                             = 198;
209    case sierraLeone                            = 199;
210    case singapore                              = 200;
211    case sintMaartenDutchPart                   = 201;
212    case slovakia                               = 202;
213    case slovenia                               = 203;
214    case solomonIslands                         = 204;
215    case somalia                                = 205;
216    case southAfrica                            = 206;
217    case southGeorgiaAndTheSouthSandwichIslands = 207;
218    case southSudan                             = 208;
219    case spain                                  = 209;
220    case sriLanka                               = 210;
221    case sudan                                  = 211;
222    case suriname                               = 212;
223    case svalbardAndJanMayen                    = 213;
224    case swaziland                              = 214;
225    case sweden                                 = 215;
226    case switzerland                            = 216;
227    case syrianArabRepublic                     = 217;
228    case taiwanProvinceOfChina                  = 218;
229    case tajikistan                             = 219;
230    case tanzaniaUnitedRepublicOf               = 220;
231    case thailand                               = 221;
232    case timorLeste                             = 222;
233    case togo                                   = 223;
234    case tokelau                                = 224;
235    case tonga                                  = 225;
236    case trinidadAndTobago                      = 226;
237    case tunisia                                = 227;
238    case turkey                                 = 228;
239    case turkmenistan                           = 229;
240    case turksAndCaicosIslands                  = 230;
241    case tuvalu                                 = 231;
242    case uganda                                 = 232;
243    case ukraine                                = 233;
244    case unitedArabEmirates                     = 234;
245    case unitedKingdom                          = 235;
246    case unitedStates                           = 236;
247    case unitedStatesMinorOutlyingIslands       = 237;
248    case uruguay                                = 238;
249    case uzbekistan                             = 239;
250    case vanuatu                                = 240;
251    case venezuelaBolivarianRepublicOf          = 241;
252    case vietNam                                = 242;
253    case virginIslandsBritish                   = 243;
254    case virginIslandsUs                        = 244;
255    case wallisAndFutuna                        = 245;
256    case westernSahara                          = 246;
257    case yemen                                  = 247;
258    case zambia                                 = 248;
259    case zimbabwe                               = 249;
260
261    /**
262     * Optionnal labels definition
263     */
264    private const LABELS = [
265        self::afghanistan->name                            => 'Afghanistan',
266        self::alandIslands->name                           => 'Åland Islands',
267        self::albania->name                                => 'Albania',
268        self::algeria->name                                => 'Algeria',
269        self::americanSamoa->name                          => 'American Samoa',
270        self::andorra->name                                => 'Andorra',
271        self::angola->name                                 => 'Angola',
272        self::anguilla->name                               => 'Anguilla',
273        self::antarctica->name                             => 'Antarctica',
274        self::antiguaAndBarbuda->name                      => 'Antigua and Barbuda',
275        self::argentina->name                              => 'Argentina',
276        self::armenia->name                                => 'Armenia',
277        self::aruba->name                                  => 'Aruba',
278        self::australia->name                              => 'Australia',
279        self::austria->name                                => 'Austria',
280        self::azerbaijan->name                             => 'Azerbaijan',
281        self::bahrain->name                                => 'Bahrain',
282        self::bahamas->name                                => 'Bahamas',
283        self::bangladesh->name                             => 'Bangladesh',
284        self::barbados->name                               => 'Barbados',
285        self::belarus->name                                => 'Belarus',
286        self::belgium->name                                => 'Belgium',
287        self::belize->name                                 => 'Belize',
288        self::benin->name                                  => 'Benin',
289        self::bermuda->name                                => 'Bermuda',
290        self::bhutan->name                                 => 'Bhutan',
291        self::boliviaPlurinationalStateOf->name            => 'Bolivia, Plurinational State of',
292        self::bonaireSintEustatiusAndSaba->name            => 'Bonaire, Sint Eustatius and Saba',
293        self::bosniaAndHerzegovina->name                   => 'Bosnia and Herzegovina',
294        self::botswana->name                               => 'Botswana',
295        self::bouvetIsland->name                           => 'Bouvet Island',
296        self::brazil->name                                 => 'Brazil',
297        self::britishIndianOceanTerritory->name            => 'British Indian Ocean Territory',
298        self::bruneiDarussalam->name                       => 'Brunei Darussalam',
299        self::bulgaria->name                               => 'Bulgaria',
300        self::burkinaFaso->name                            => 'Burkina Faso',
301        self::burundi->name                                => 'Burundi',
302        self::cambodia->name                               => 'Cambodia',
303        self::cameroon->name                               => 'Cameroon',
304        self::canada->name                                 => 'Canada',
305        self::capeVerde->name                              => 'Cape Verde',
306        self::caymanIslands->name                          => 'Cayman Islands',
307        self::centralAfricanRepublic->name                 => 'Central African Republic',
308        self::chad->name                                   => 'Chad',
309        self::chile->name                                  => 'Chile',
310        self::china->name                                  => 'China',
311        self::christmasIsland->name                        => 'Christmas Island',
312        self::cocosKeelingIslands->name                    => 'Cocos (Keeling) Islands',
313        self::colombia->name                               => 'Colombia',
314        self::comoros->name                                => 'Comoros',
315        self::congo->name                                  => 'Congo',
316        self::congoTheDemocraticRepublicOfThe->name        => 'Congo, the Democratic Republic of the',
317        self::cookIslands->name                            => 'Cook Islands',
318        self::costaRica->name                              => 'Costa Rica',
319        self::coteDivoire->name                            => 'Côte d\'Ivoire',
320        self::croatia->name                                => 'Croatia',
321        self::cuba->name                                   => 'Cuba',
322        self::curacao->name                                => 'Curaçao',
323        self::cyprus->name                                 => 'Cyprus',
324        self::czechRepublic->name                          => 'Czech Republic',
325        self::denmark->name                                => 'Denmark',
326        self::djibouti->name                               => 'Djibouti',
327        self::dominica->name                               => 'Dominica',
328        self::dominicanRepublic->name                      => 'Dominican Republic',
329        self::ecuador->name                                => 'Ecuador',
330        self::egypt->name                                  => 'Egypt',
331        self::elSalvador->name                             => 'El Salvador',
332        self::equatorialGuinea->name                       => 'Equatorial Guinea',
333        self::eritrea->name                                => 'Eritrea',
334        self::estonia->name                                => 'Estonia',
335        self::ethiopia->name                               => 'Ethiopia',
336        self::falklandIslandsMalvinas->name                => 'Falkland Islands (Malvinas)',
337        self::faroeIslands->name                           => 'Faroe Islands',
338        self::fiji->name                                   => 'Fiji',
339        self::finland->name                                => 'Finland',
340        self::france->name                                 => 'France',
341        self::frenchGuiana->name                           => 'French Guiana',
342        self::frenchPolynesia->name                        => 'French Polynesia',
343        self::frenchSouthernTerritories->name              => 'French Southern Territories',
344        self::gabon->name                                  => 'Gabon',
345        self::gambia->name                                 => 'Gambia',
346        self::georgia->name                                => 'Georgia',
347        self::germany->name                                => 'Germany',
348        self::ghana->name                                  => 'Ghana',
349        self::gibraltar->name                              => 'Gibraltar',
350        self::greece->name                                 => 'Greece',
351        self::greenland->name                              => 'Greenland',
352        self::grenada->name                                => 'Grenada',
353        self::guadeloupe->name                             => 'Guadeloupe',
354        self::guam->name                                   => 'Guam',
355        self::guatemala->name                              => 'Guatemala',
356        self::guernsey->name                               => 'Guernsey',
357        self::guinea->name                                 => 'Guinea',
358        self::guineaBissau->name                           => 'GuineaBissau',
359        self::guyana->name                                 => 'Guyana',
360        self::haiti->name                                  => 'Haiti',
361        self::heardIslandAndMcdonaldIslands->name          => 'Heard Island and McDonald Islands',
362        self::holySeeVaticanCityState->name                => 'Holy See (Vatican City State)',
363        self::honduras->name                               => 'Honduras',
364        self::hongKong->name                               => 'Hong Kong',
365        self::hungary->name                                => 'Hungary',
366        self::iceland->name                                => 'Iceland',
367        self::india->name                                  => 'India',
368        self::indonesia->name                              => 'Indonesia',
369        self::iranIslamicRepublicOf->name                  => 'Iran, Islamic Republic of',
370        self::iraq->name                                   => 'Iraq',
371        self::ireland->name                                => 'Ireland',
372        self::isleOfMan->name                              => 'Isle of Man',
373        self::israel->name                                 => 'Israel',
374        self::italy->name                                  => 'Italy',
375        self::jamaica->name                                => 'Jamaica',
376        self::japan->name                                  => 'Japan',
377        self::jersey->name                                 => 'Jersey',
378        self::jordan->name                                 => 'Jordan',
379        self::kazakhstan->name                             => 'Kazakhstan',
380        self::kenya->name                                  => 'Kenya',
381        self::kiribati->name                               => 'Kiribati',
382        self::koreaDemocraticPeoplesRepublicOf->name       => 'Korea, Democratic People\'s Republic of',
383        self::koreaRepublicOf->name                        => 'Korea, Republic of',
384        self::kuwait->name                                 => 'Kuwait',
385        self::kyrgyzstan->name                             => 'Kyrgyzstan',
386        self::laoPeoplesDemocraticRepublic->name           => 'Lao People\'s Democratic Republic',
387        self::latvia->name                                 => 'Latvia',
388        self::lebanon->name                                => 'Lebanon',
389        self::lesotho->name                                => 'Lesotho',
390        self::liberia->name                                => 'Liberia',
391        self::libya->name                                  => 'Libya',
392        self::liechtenstein->name                          => 'Liechtenstein',
393        self::lithuania->name                              => 'Lithuania',
394        self::luxembourg->name                             => 'Luxembourg',
395        self::macao->name                                  => 'Macao',
396        self::macedoniaTheFormerYugoslavRepublicOf->name   => 'Macedonia, the Former Yugoslav Republic of',
397        self::madagascar->name                             => 'Madagascar',
398        self::malawi->name                                 => 'Malawi',
399        self::malaysia->name                               => 'Malaysia',
400        self::maldives->name                               => 'Maldives',
401        self::mali->name                                   => 'Mali',
402        self::malta->name                                  => 'Malta',
403        self::marshallIslands->name                        => 'Marshall Islands',
404        self::martinique->name                             => 'Martinique',
405        self::mauritania->name                             => 'Mauritania',
406        self::mauritius->name                              => 'Mauritius',
407        self::mayotte->name                                => 'Mayotte',
408        self::mexico->name                                 => 'Mexico',
409        self::micronesiaFederatedStatesOf->name            => 'Micronesia, Federated States of',
410        self::moldovaRepublicOf->name                      => 'Moldova, Republic of',
411        self::monaco->name                                 => 'Monaco',
412        self::mongolia->name                               => 'Mongolia',
413        self::montenegro->name                             => 'Montenegro',
414        self::montserrat->name                             => 'Montserrat',
415        self::morocco->name                                => 'Morocco',
416        self::mozambique->name                             => 'Mozambique',
417        self::myanmar->name                                => 'Myanmar',
418        self::namibia->name                                => 'Namibia',
419        self::nauru->name                                  => 'Nauru',
420        self::nepal->name                                  => 'Nepal',
421        self::netherlands->name                            => 'Netherlands',
422        self::newCaledonia->name                           => 'New Caledonia',
423        self::newZealand->name                             => 'New Zealand',
424        self::nicaragua->name                              => 'Nicaragua',
425        self::niger->name                                  => 'Niger',
426        self::nigeria->name                                => 'Nigeria',
427        self::niue->name                                   => 'Niue',
428        self::norfolkIsland->name                          => 'Norfolk Island',
429        self::northernMarianaIslands->name                 => 'Northern Mariana Islands',
430        self::norway->name                                 => 'Norway',
431        self::oman->name                                   => 'Oman',
432        self::pakistan->name                               => 'Pakistan',
433        self::palau->name                                  => 'Palau',
434        self::palestineStateOf->name                       => 'Palestine, State of',
435        self::panama->name                                 => 'Panama',
436        self::papuaNewGuinea->name                         => 'Papua New Guinea',
437        self::paraguay->name                               => 'Paraguay',
438        self::peru->name                                   => 'Peru',
439        self::philippines->name                            => 'Philippines',
440        self::pitcairn->name                               => 'Pitcairn',
441        self::poland->name                                 => 'Poland',
442        self::portugal->name                               => 'Portugal',
443        self::puertoRico->name                             => 'Puerto Rico',
444        self::qatar->name                                  => 'Qatar',
445        self::reunion->name                                => 'Réunion',
446        self::romania->name                                => 'Romania',
447        self::russianFederation->name                      => 'Russian Federation',
448        self::rwanda->name                                 => 'Rwanda',
449        self::saintBarthelemy->name                        => 'Saint Barthélemy',
450        self::saintHelenaAscensionAndTristanDaCunha->name  => 'Saint Helena, Ascension and Tristan da Cunha',
451        self::saintKittsAndNevis->name                     => 'Saint Kitts and Nevis',
452        self::saintLucia->name                             => 'Saint Lucia',
453        self::saintMartinFrenchPart->name                  => 'Saint Martin (French part)',
454        self::saintPierreAndMiquelon->name                 => 'Saint Pierre and Miquelon',
455        self::saintVincentAndTheGrenadines->name           => 'Saint Vincent and the Grenadines',
456        self::samoa->name                                  => 'Samoa',
457        self::sanMarino->name                              => 'San Marino',
458        self::saoTomeAndPrincipe->name                     => 'Sao Tome and Principe',
459        self::saudiArabia->name                            => 'Saudi Arabia',
460        self::senegal->name                                => 'Senegal',
461        self::serbia->name                                 => 'Serbia',
462        self::seychelles->name                             => 'Seychelles',
463        self::sierraLeone->name                            => 'Sierra Leone',
464        self::singapore->name                              => 'Singapore',
465        self::sintMaartenDutchPart->name                   => 'Sint Maarten (Dutch part)',
466        self::slovakia->name                               => 'Slovakia',
467        self::slovenia->name                               => 'Slovenia',
468        self::solomonIslands->name                         => 'Solomon Islands',
469        self::somalia->name                                => 'Somalia',
470        self::southAfrica->name                            => 'South Africa',
471        self::southGeorgiaAndTheSouthSandwichIslands->name => 'South Georgia and the South Sandwich Islands',
472        self::southSudan->name                             => 'South Sudan',
473        self::spain->name                                  => 'Spain',
474        self::sriLanka->name                               => 'Sri Lanka',
475        self::sudan->name                                  => 'Sudan',
476        self::suriname->name                               => 'Suriname',
477        self::svalbardAndJanMayen->name                    => 'Svalbard and Jan Mayen',
478        self::swaziland->name                              => 'Swaziland',
479        self::sweden->name                                 => 'Sweden',
480        self::switzerland->name                            => 'Switzerland',
481        self::syrianArabRepublic->name                     => 'Syrian Arab Republic',
482        self::taiwanProvinceOfChina->name                  => 'Taiwan, Province of China',
483        self::tajikistan->name                             => 'Tajikistan',
484        self::tanzaniaUnitedRepublicOf->name               => 'Tanzania, United Republic of',
485        self::thailand->name                               => 'Thailand',
486        self::timorLeste->name                             => 'TimorLeste',
487        self::togo->name                                   => 'Togo',
488        self::tokelau->name                                => 'Tokelau',
489        self::tonga->name                                  => 'Tonga',
490        self::trinidadAndTobago->name                      => 'Trinidad and Tobago',
491        self::tunisia->name                                => 'Tunisia',
492        self::turkey->name                                 => 'Turkey',
493        self::turkmenistan->name                           => 'Turkmenistan',
494        self::turksAndCaicosIslands->name                  => 'Turks and Caicos Islands',
495        self::tuvalu->name                                 => 'Tuvalu',
496        self::uganda->name                                 => 'Uganda',
497        self::ukraine->name                                => 'Ukraine',
498        self::unitedArabEmirates->name                     => 'United Arab Emirates',
499        self::unitedKingdom->name                          => 'United Kingdom',
500        self::unitedStates->name                           => 'United States',
501        self::unitedStatesMinorOutlyingIslands->name       => 'United States Minor Outlying Islands',
502        self::uruguay->name                                => 'Uruguay',
503        self::uzbekistan->name                             => 'Uzbekistan',
504        self::vanuatu->name                                => 'Vanuatu',
505        self::venezuelaBolivarianRepublicOf->name          => 'Venezuela, Bolivarian Republic of',
506        self::vietNam->name                                => 'Viet Nam',
507        self::virginIslandsBritish->name                   => 'Virgin Islands, British',
508        self::virginIslandsUs->name                        => 'Virgin Islands, U.S.',
509        self::wallisAndFutuna->name                        => 'Wallis and Futuna',
510        self::westernSahara->name                          => 'Western Sahara',
511        self::yemen->name                                  => 'Yemen',
512        self::zambia->name                                 => 'Zambia',
513        self::zimbabwe->name                               => 'Zimbabwe'
514    ];
515
516    /**
517     * Get valid countries label.
518     *
519     * @return array<string>
520     */
521    public static function getValidCountriesLabel(): array
522    {
523        return collect(self::getValidCountries())->map(function (self $country) {
524            return $country->label();
525        })->all();
526    }
527
528    /**
529     * Get valid countries value.
530     *
531     * @return array<string|integer>
532     */
533    public static function getValidCountriesValues(): array
534    {
535        return collect(self::getValidCountries())->map(function (self $country) {
536            return $country->value();
537        })->all();
538    }
539
540    /**
541     * Get Alpha 2 ISO code of valid countries
542     *
543     * @return array
544     */
545    public static function getValidIsoAplha2Codes(): array
546    {
547        return \array_values(self::isoCodes());
548    }
549
550    /**
551     * Get valid countries
552     *
553     * @return array
554     */
555    public static function getValidCountries(): array
556    {
557        return [
558            Country::belgium,
559            Country::luxembourg,
560            Country::france,
561            Country::guadeloupe,
562            Country::martinique,
563            Country::frenchGuiana,
564            Country::reunion,
565            Country::saintPierreAndMiquelon,
566            Country::mayotte,
567            Country::saintBarthelemy,
568            Country::saintMartinFrenchPart,
569            Country::wallisAndFutuna,
570            Country::frenchPolynesia,
571            Country::newCaledonia
572        ];
573    }
574
575    /**
576     * Enum classes
577     *
578     * @return array
579     */
580    protected static function isoCodes(): array
581    {
582        return [
583            'france' => 'FR',
584            'belgium' => 'BE',
585            'luxembourg' => 'LU',
586            'guadeloupe' => 'GP',
587            'martinique' => 'MQ',
588            'frenchGuiana' => 'GF',
589            'reunion' => 'RE',
590            'saintPierreAndMiquelon' => 'PM',
591            'mayotte' => 'YT',
592            'saintBarthelemy' => 'BL',
593            'saintMartinFrenchPart' => 'MF',
594            'wallisAndFutuna' => 'WF',
595            'frenchPolynesia' => 'PF',
596            'newCaledonia' => 'NC',
597        ];
598    }
599
600    /**
601     * @param string $attribute
602     * @return integer|string|null
603     */
604    public function get(string $attribute): int|string|null
605    {
606        if ($attribute === 'iso') {
607            return $this->isoCodes()[$this->name] ?? null;
608        }
609        return $this->{$attribute};
610    }
611}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/CustomerExportType.php.html b/tests/coverage/app/Enums/CustomerExportType.php.html deleted file mode 100644 index 1c26e44..0000000 --- a/tests/coverage/app/Enums/CustomerExportType.php.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/CustomerExportType.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums;
4
5use App\Traits\Enums\BaseEnum;
6
7enum CustomerExportType: int
8{
9    use BaseEnum;
10
11    case singleOptin = 1;
12    case customer    = 2;
13    case both        = 3;
14
15    /**
16     * Optionnal labels definition
17     */
18    private const LABELS = [
19        self::singleOptin->name => 'Les single optins uniquement',
20        self::customer->name    => 'Les clients uniquement acceptant de recevoir les newsletters',
21        self::both->name        => 'La totalité des client acceptant de recevoir les newsletters',
22    ];
23}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/Pagination/ItemsPerPaginationEnum.php.html b/tests/coverage/app/Enums/Pagination/ItemsPerPaginationEnum.php.html deleted file mode 100644 index 37d870b..0000000 --- a/tests/coverage/app/Enums/Pagination/ItemsPerPaginationEnum.php.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/Pagination/ItemsPerPaginationEnum.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums\Pagination;
4
5use App\Traits\Enums\BaseEnum;
6
7enum ItemsPerPaginationEnum: int
8{
9    use BaseEnum;
10
11    case five       = 5;
12    case twelve     = 12;
13    case twentyfive = 25;
14    case fifty      = 50;
15    case onehundred = 100;
16}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/Pagination/dashboard.html b/tests/coverage/app/Enums/Pagination/dashboard.html deleted file mode 100644 index 6532767..0000000 --- a/tests/coverage/app/Enums/Pagination/dashboard.html +++ /dev/null @@ -1,286 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Enums/Pagination - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Enums/Pagination/index.html b/tests/coverage/app/Enums/Pagination/index.html deleted file mode 100644 index 1dc3c4c..0000000 --- a/tests/coverage/app/Enums/Pagination/index.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/Pagination - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ItemsPerPaginationEnum.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Enums/QuestionType.php.html b/tests/coverage/app/Enums/QuestionType.php.html deleted file mode 100644 index f801a15..0000000 --- a/tests/coverage/app/Enums/QuestionType.php.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/QuestionType.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums;
4
5use App\Traits\Enums\BaseEnum;
6
7enum QuestionType: int
8{
9    use BaseEnum;
10
11    case select   = 1;
12    case radio    = 2;
13    case checkbox = 3;
14}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/Theme/BootstrapThemeEnum.php.html b/tests/coverage/app/Enums/Theme/BootstrapThemeEnum.php.html deleted file mode 100644 index 34fa57b..0000000 --- a/tests/coverage/app/Enums/Theme/BootstrapThemeEnum.php.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/Theme/BootstrapThemeEnum.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums\Theme;
4
5use App\Traits\Enums\BaseEnum;
6
7enum BootstrapThemeEnum: int
8{
9    use BaseEnum;
10
11    case light = 1;
12    case dark  = 2;
13
14    /**
15     * Optionnal labels definition
16     */
17    private const LABELS = [
18        self::light->name => 'Light',
19        self::dark->name  => 'Dark',
20    ];
21}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/Theme/dashboard.html b/tests/coverage/app/Enums/Theme/dashboard.html deleted file mode 100644 index f7b56a4..0000000 --- a/tests/coverage/app/Enums/Theme/dashboard.html +++ /dev/null @@ -1,286 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Enums/Theme - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Enums/Theme/index.html b/tests/coverage/app/Enums/Theme/index.html deleted file mode 100644 index 74ea6c8..0000000 --- a/tests/coverage/app/Enums/Theme/index.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/Theme - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
BootstrapThemeEnum.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Enums/Users/RoleEnum.php.html b/tests/coverage/app/Enums/Users/RoleEnum.php.html deleted file mode 100644 index 469c255..0000000 --- a/tests/coverage/app/Enums/Users/RoleEnum.php.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/Users/RoleEnum.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Enums\Users;
4
5use App\Traits\Enums\BaseEnum;
6
7enum RoleEnum: int
8{
9    use BaseEnum;
10
11    case conceptor = 1;
12    case admin     = 2;
13    case visitor   = 3;
14
15    /**
16     * Optionnal labels definition.
17     */
18    private const LABELS = [
19        self::conceptor->name => 'Concepteur',
20        self::admin->name     => 'Administrateur',
21        self::visitor->name   => 'Visiteur',
22    ];
23}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Enums/Users/dashboard.html b/tests/coverage/app/Enums/Users/dashboard.html deleted file mode 100644 index 29ccc82..0000000 --- a/tests/coverage/app/Enums/Users/dashboard.html +++ /dev/null @@ -1,286 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Enums/Users - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Enums/Users/index.html b/tests/coverage/app/Enums/Users/index.html deleted file mode 100644 index 7c65037..0000000 --- a/tests/coverage/app/Enums/Users/index.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums/Users - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
RoleEnum.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Enums/dashboard.html b/tests/coverage/app/Enums/dashboard.html deleted file mode 100644 index f68fbd2..0000000 --- a/tests/coverage/app/Enums/dashboard.html +++ /dev/null @@ -1,289 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Enums - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Enums\ActivityLogs\ActivityLogsEventEnum0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
MethodCoverage
bootstrapClass0%
get66%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
MethodCRAP
get2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Enums/index.html b/tests/coverage/app/Enums/index.html deleted file mode 100644 index 2b2ed76..0000000 --- a/tests/coverage/app/Enums/index.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Enums - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 95.35% covered (success) -
-
-
95.35%
41 / 43
-
- 71.43% covered (warning) -
-
-
71.43%
5 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
ActivityLogs
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Pagination
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
Theme
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
Users
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ApiError.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ApiStatus.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ArcadiaMailType.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ArcadiaOrderType.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
Country.php
-
- 97.62% covered (success) -
-
-
97.62%
41 / 42
-
- 83.33% covered (warning) -
-
-
83.33%
5 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerExportType.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
QuestionType.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Exceptions/AbortRowImportException.php.html b/tests/coverage/app/Exceptions/AbortRowImportException.php.html deleted file mode 100644 index 60820df..0000000 --- a/tests/coverage/app/Exceptions/AbortRowImportException.php.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Exceptions/AbortRowImportException.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
AbortRowImportException
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Exceptions;
4
5/**
6 * This class Exception is used to skip a row import from
7 * database migration (2016 -> 2020)
8 *
9 * @author Jérémy Munsch <jeremy.munsch@ldc.fr>
10 */
11class AbortRowImportException extends \RuntimeException
12{
13}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Exceptions/Api/V2/ApiErrorException.php.html b/tests/coverage/app/Exceptions/Api/V2/ApiErrorException.php.html deleted file mode 100644 index fa563f8..0000000 --- a/tests/coverage/app/Exceptions/Api/V2/ApiErrorException.php.html +++ /dev/null @@ -1,316 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Exceptions/Api/V2/ApiErrorException.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 90.00% covered (success) -
-
-
90.00%
9 / 10
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ApiErrorException
-
- 90.00% covered (success) -
-
-
90.00%
9 / 10
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
5.03
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 getApiError
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getStatusCode
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 report
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Exceptions\Api\V2;
4
5use App\Enums\ApiError;
6use Exception;
7use Illuminate\Support\Facades\Log;
8use Throwable;
9
10/**
11 * This would be thrown if any of the case
12 * referenced in \App\Enums\ApiError would
13 * occur within the crm.
14 *
15 * On the client an ApiErrorException would
16 * also be throw with the ApiError corresponding to
17 * the situation.
18 *
19 * @package LDCCrmClient
20 * @subpackage exceptions
21 */
22class ApiErrorException extends Exception
23{
24    /**
25     * Api Error
26     * This value makes the error more explicit.
27     * Handling these errors are normal as inputs or
28     * request may be undesired or refused by the crm.
29     *
30     * @var \App\Enums\ApiError
31     */
32    protected $error;
33
34    /**
35     * This is an explicit error message,
36     * ou may print this to the front or not depending
37     * on $error value.
38     *
39     * @var string
40     */
41    protected $message;
42
43    /**
44     * This is the http code returned by the crm.
45     * This value could be used to handle errors.
46     * But please take in consideration $error first
47     *
48     * @var integer
49     */
50    protected $httpCode;
51
52    /**
53     * Create a new exception base on ApiError enum.
54     *
55     * @param \App\Enums\ApiError $error
56     * @param integer             $httpCode
57     * @param string              $message
58     * @param Throwable|null      $previous
59     */
60    public function __construct(ApiError $error, int $httpCode = 400, string $message = '', Throwable $previous = null)
61    {
62        $this->error    = $error;
63        $this->message  = $message;
64        $this->httpCode = $httpCode;
65        parent::__construct(
66            strlen($this->message) ? $this->message : $error->label(),
67            $error->value(),
68            $previous
69        );
70    }
71
72    /**
73     * Get the Api Error.
74     *
75     * @return \App\Enums\ApiError
76     */
77    public function getApiError(): ApiError
78    {
79        return $this->error;
80    }
81
82    /**
83     * Get the http code.
84     *
85     * @return integer
86     */
87    public function getStatusCode(): int
88    {
89        return $this->httpCode;
90    }
91
92    /**
93     * This is used by laravel only.
94     * It uses Log class to print the error.
95     *
96     * @return void
97     */
98    public function report(): void
99    {
100        // @codeCoverageIgnoreStart
101        Log::debug(sprintf('CRM API: %s', $this->getMessage()));
102        // @codeCoverageIgnoreEnd
103    }
104}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Exceptions/Api/V2/CrmException.php.html b/tests/coverage/app/Exceptions/Api/V2/CrmException.php.html deleted file mode 100644 index ad67d07..0000000 --- a/tests/coverage/app/Exceptions/Api/V2/CrmException.php.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Exceptions/Api/V2/CrmException.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CrmException
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 report
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Exceptions\Api\V2;
4
5use Exception;
6use Illuminate\Support\Facades\Log;
7
8/**
9 * This is a critical error.
10 * The request could not be handled. You may dump any value you can
11 * get before submitting a ticker to https://supportweb.ldc.fr
12 *
13 * @package LDCCrmClient
14 * @subpackage exceptions
15 */
16class CrmException extends Exception
17{
18    /**
19     * This is used by laravel only.
20     * It uses Log class to print the error.
21     *
22     * @return void
23     */
24    public function report(): void
25    {
26        Log::critical(sprintf('CRM API: %s', $this->getMessage()));
27    }
28}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Exceptions/Api/V2/dashboard.html b/tests/coverage/app/Exceptions/Api/V2/dashboard.html deleted file mode 100644 index db3cd6b..0000000 --- a/tests/coverage/app/Exceptions/Api/V2/dashboard.html +++ /dev/null @@ -1,290 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Exceptions/Api/V2 - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Exceptions\Api\V2\CrmException0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
MethodCoverage
getApiError0%
report0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Exceptions/Api/V2/index.html b/tests/coverage/app/Exceptions/Api/V2/index.html deleted file mode 100644 index b5180b8..0000000 --- a/tests/coverage/app/Exceptions/Api/V2/index.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Exceptions/Api/V2 - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 81.82% covered (warning) -
-
-
81.82%
9 / 11
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
ApiErrorException.php
-
- 90.00% covered (success) -
-
-
90.00%
9 / 10
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CrmException.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Exceptions/Api/V4/ApiErrorException.php.html b/tests/coverage/app/Exceptions/Api/V4/ApiErrorException.php.html deleted file mode 100644 index bf94031..0000000 --- a/tests/coverage/app/Exceptions/Api/V4/ApiErrorException.php.html +++ /dev/null @@ -1,314 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Exceptions/Api/V4/ApiErrorException.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 90.00% covered (success) -
-
-
90.00%
9 / 10
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ApiErrorException
-
- 90.00% covered (success) -
-
-
90.00%
9 / 10
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
5.03
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 getApiError
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getStatusCode
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 report
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Exceptions\Api\V4;
4
5use App\Enums\ApiError;
6use Illuminate\Support\Facades\Log;
7
8/**
9 * This would be thrown if any of the case
10 * referenced in \App\Enums\ApiError would
11 * occur within the crm.
12 *
13 * On the client an ApiErrorException would
14 * also be throw with the ApiError corresponding to
15 * the situation.
16 *
17 * @package LDCCrmClient
18 * @subpackage exceptions
19 */
20class ApiErrorException extends \RuntimeException
21{
22    /**
23     * Api Error
24     * This value makes the error more explicit.
25     * Handling these errors are normal as inputs or
26     * request may be undesired or refused by the crm.
27     *
28     * @var \App\Enums\ApiError
29     */
30    protected $error;
31
32    /**
33     * This is an explicit error message,
34     * ou may print this to the front or not depending
35     * on $error value.
36     *
37     * @var string
38     */
39    protected $message;
40
41    /**
42     * This is the http code returned by the crm.
43     * This value could be used to handle errors.
44     * But please take in consideration $error first.
45     *
46     * @var integer
47     */
48    protected $httpCode;
49
50    /**
51     * Create a new exception base on ApiError enum.
52     *
53     * @param \App\Enums\ApiError $error
54     * @param integer             $httpCode
55     * @param string              $message
56     * @param \Throwable|null     $previous
57     */
58    public function __construct(ApiError $error, int $httpCode = 400, string $message = '', \Throwable $previous = null)
59    {
60        $this->error    = $error;
61        $this->message  = $message;
62        $this->httpCode = $httpCode;
63        parent::__construct(
64            strlen($this->message) ? $this->message : $error->label(),
65            $error->value(),
66            $previous
67        );
68    }
69
70    /**
71     * Get the Api Error.
72     *
73     * @return \App\Enums\ApiError
74     */
75    public function getApiError(): ApiError
76    {
77        return $this->error;
78    }
79
80    /**
81     * Get the http code.
82     *
83     * @return integer
84     */
85    public function getStatusCode(): int
86    {
87        return $this->httpCode;
88    }
89
90    /**
91     * This is used by laravel only.
92     * It uses Log class to print the error.
93     *
94     * @return void
95     */
96    public function report(): void
97    {
98        // @codeCoverageIgnoreStart
99        Log::debug(sprintf('CRM API: %s', $this->getMessage()));
100        // @codeCoverageIgnoreEnd
101    }
102}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Exceptions/Api/V4/CrmException.php.html b/tests/coverage/app/Exceptions/Api/V4/CrmException.php.html deleted file mode 100644 index ee74860..0000000 --- a/tests/coverage/app/Exceptions/Api/V4/CrmException.php.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Exceptions/Api/V4/CrmException.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CrmException
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 report
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Exceptions\Api\V4;
4
5use Illuminate\Support\Facades\Log;
6
7/**
8 * This is a critical error.
9 * The request could not be handled. You may dump any value you can
10 * get before submitting a ticker to https://support.uwil.fr/
11 *
12 * @package LDCCrmClient
13 * @subpackage exceptions
14 *
15 */
16class CrmException extends \RuntimeException
17{
18    /**
19     * This is used by laravel only.
20     * It uses Log class to print the error.
21     *
22     * @return void
23     */
24    public function report(): void
25    {
26        Log::critical(sprintf('CRM API: %s', $this->getMessage()));
27    }
28}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Exceptions/Api/V4/dashboard.html b/tests/coverage/app/Exceptions/Api/V4/dashboard.html deleted file mode 100644 index 65eaba4..0000000 --- a/tests/coverage/app/Exceptions/Api/V4/dashboard.html +++ /dev/null @@ -1,290 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Exceptions/Api/V4 - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Exceptions\Api\V4\CrmException0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
MethodCoverage
getApiError0%
report0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Exceptions/Api/V4/index.html b/tests/coverage/app/Exceptions/Api/V4/index.html deleted file mode 100644 index 593abe3..0000000 --- a/tests/coverage/app/Exceptions/Api/V4/index.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Exceptions/Api/V4 - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 81.82% covered (warning) -
-
-
81.82%
9 / 11
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
ApiErrorException.php
-
- 90.00% covered (success) -
-
-
90.00%
9 / 10
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CrmException.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Exceptions/Api/dashboard.html b/tests/coverage/app/Exceptions/Api/dashboard.html deleted file mode 100644 index 97b5d8e..0000000 --- a/tests/coverage/app/Exceptions/Api/dashboard.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Exceptions/Api - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
ClassCoverage
App\Exceptions\Api\V2\CrmException0%
App\Exceptions\Api\V4\CrmException0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - -
MethodCoverage
getApiError0%
report0%
getApiError0%
report0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Exceptions/Api/index.html b/tests/coverage/app/Exceptions/Api/index.html deleted file mode 100644 index b18cefe..0000000 --- a/tests/coverage/app/Exceptions/Api/index.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Exceptions/Api - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 81.82% covered (warning) -
-
-
81.82%
18 / 22
-
- 50.00% covered (danger) -
-
-
50.00%
4 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
V2
-
- 81.82% covered (warning) -
-
-
81.82%
9 / 11
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
V4
-
- 81.82% covered (warning) -
-
-
81.82%
9 / 11
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- -
- - diff --git a/tests/coverage/app/Exceptions/Handler.php.html b/tests/coverage/app/Exceptions/Handler.php.html deleted file mode 100644 index 1ee945b..0000000 --- a/tests/coverage/app/Exceptions/Handler.php.html +++ /dev/null @@ -1,412 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Exceptions/Handler.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 88.24% covered (warning) -
-
-
88.24%
60 / 68
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Handler
-
- 88.24% covered (warning) -
-
-
88.24%
60 / 68
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
18.53
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 register
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.50
 render
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 handleApiException
-
- 88.68% covered (warning) -
-
-
88.68%
47 / 53
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
10.15
 getReponse
-
- 100.00% covered (success) -
-
-
100.00%
9 / 9
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Exceptions;
4
5use App\Enums\ApiError;
6use App\Enums\ApiStatus;
7use App\Exceptions\Api\V2\ApiErrorException as V2ApiErrorException;
8use App\Exceptions\Api\V4\ApiErrorException as V4ApiErrorException;
9use App\Http\Resources\Api\V2\ApiResponse as V2ApiResponse;
10use App\Http\Resources\Api\V4\ApiResponse as V4ApiResponse;
11use App\Lib\Helper;
12use Illuminate\Auth\Access\AuthorizationException;
13use Illuminate\Auth\AuthenticationException;
14use Illuminate\Database\Eloquent\ModelNotFoundException;
15use Illuminate\Http\Exceptions\ThrottleRequestsException;
16use Illuminate\Http\JsonResponse;
17use Illuminate\Http\Request;
18use Illuminate\Validation\ValidationException;
19use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
20use Symfony\Component\HttpFoundation\Response;
21use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
22
23class Handler extends ExceptionHandler
24{
25    /**
26     * A list of the exception types that are not reported.
27     *
28     * @var array
29     */
30    protected $dontReport = [
31        ApiErrorException::class,
32        RedirectTo::class
33    ];
34
35    /**
36     * A list of the inputs that are never flashed for validation exceptions.
37     *
38     * @var array
39     */
40    protected $dontFlash = [
41        'password',
42        'password_confirmation',
43    ];
44
45    /**
46     * Register the exception handling callbacks for the application.
47     *
48     * @return void
49     */
50    public function register(): void
51    {
52        $this->reportable(function (\Throwable $e) {
53            if (app()->bound('sentry')) {
54                app('sentry')->captureException($e);
55            }
56        });
57    }
58
59    /**
60     * Render an exception into an HTTP response.
61     *
62     * @param  mixed      $request
63     * @param  \Throwable $e
64     * @return \Symfony\Component\HttpFoundation\Response
65     */
66    public function render(mixed $request, \Throwable $e): Response
67    {
68        if ((Helper::isRequestForApiV2($request) || Helper::isRequestForApiV4($request)) and $request->isJson()) {
69            return $this->handleApiException($request, $e);
70        } //end if
71        // @codeCoverageIgnoreStart
72        return parent::render($request, $e);
73        // @codeCoverageIgnoreEnd
74    }
75
76    /**
77     * Generate a json response for any apiV4 error case.
78     *
79     * @param \Illuminate\Http\Request $request
80     * @param \Throwable               $e
81     * @return \Illuminate\Http\JsonResponse
82     */
83    private function handleApiException(Request $request, \Throwable $e): JsonResponse
84    {
85        switch (get_class($e)) {
86            case AuthenticationException::class:
87                /** @var AuthenticationException $e */
88                return $this->getReponse(
89                    $request,
90                    401,
91                    ApiError::apiAuthFailed->value(),
92                    sprintf('%s, %s', ApiError::apiAuthFailed->label(), $e->getMessage())
93                );
94            case MethodNotAllowedHttpException::class:
95                /** @var MethodNotAllowedHttpException $e */
96                return $this->getReponse(
97                    $request,
98                    $e->getStatusCode(),
99                    ApiError::methodNotAllowed->value(),
100                    sprintf('%s, %s', ApiError::methodNotAllowed->label(), $e->getMessage())
101                );
102            case ValidationException::class:
103                /** @var ValidationException $e */
104                return $this->getReponse(
105                    $request,
106                    $e->status,
107                    ApiError::validationFailed->value(),
108                    sprintf(ApiError::validationFailed->label(), $e->getMessage()),
109                    ['errors' => $e->errors()]
110                );
111            case ModelNotFoundException::class:
112                /** @var ModelNotFoundException $e */
113                return $this->getReponse(
114                    $request,
115                    404,
116                    ApiError::modelNotFound->value(),
117                    sprintf(
118                        ApiError::modelNotFound->label(),
119                        \array_slice(explode('\\', $e->getModel()), -1)[0]
120                    )
121                );
122            case V4ApiErrorException::class:
123                /** @var \App\Exceptions\Api\V4\ApiErrorException $e */
124                return $this->getReponse(
125                    $request,
126                    $e->getStatusCode(),
127                    $e->getCode(),
128                    $e->getMessage()
129                );
130            case V2ApiErrorException::class:
131                /** @var \App\Exceptions\Api\V2\ApiErrorException $e */
132                return $this->getReponse(
133                    $request,
134                    $e->getStatusCode(),
135                    $e->getCode(),
136                    $e->getMessage()
137                );
138            case ThrottleRequestsException::class:
139                /** @var ThrottleRequestsException $e */
140                return $this->getReponse(
141                    $request,
142                    429,
143                    ApiError::throttleRequestsException->value(),
144                    ApiError::throttleRequestsException->label()
145                );
146            case AuthorizationException::class:
147                /** @var AuthorizationException $e */
148                return $this->getReponse(
149                    $request,
150                    403,
151                    ApiError::authorizationException->value(),
152                    ApiError::authorizationException->label()
153                );
154        } //end switch
155        // @codeCoverageIgnoreStart
156        if (config('app.env') === 'testing') {
157            // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Found
158            print_r((string)$e);
159        }
160        return $this->getReponse($request, 500, \intval($e->getCode()), $e->getMessage());
161        // @codeCoverageIgnoreEnd
162    }
163
164    /**
165     * Generate an ApiV4 json response.
166     *
167     * @param \Illuminate\Http\Request $request
168     * @param integer                  $httpCode
169     * @param integer                  $apiCode
170     * @param string                   $message
171     * @param array                    $data
172     * @return \Illuminate\Http\JsonResponse
173     */
174    private static function getReponse(
175        Request $request,
176        int $httpCode,
177        int $apiCode,
178        string $message,
179        array $data = []
180    ): JsonResponse {
181        if (Helper::isRequestForApiV2($request)) {
182            return (new V2ApiResponse(
183                (object)array_merge($data, ['message' => $message, 'code' => $apiCode]),
184                ApiStatus::KO
185            ))->toResponse($request)->setStatusCode($httpCode);
186        }
187        return (new V4ApiResponse(
188            (object)array_merge($data, ['message' => $message, 'code' => $apiCode]),
189            ApiStatus::KO
190        ))->toResponse($request)->setStatusCode($httpCode);
191    }
192}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Exceptions/dashboard.html b/tests/coverage/app/Exceptions/dashboard.html deleted file mode 100644 index 9d1e811..0000000 --- a/tests/coverage/app/Exceptions/dashboard.html +++ /dev/null @@ -1,297 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Exceptions - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

- -
-
-

Project Risks

-
- - - - - - - - - - - -
ClassCRAP
App\Exceptions\Handler18
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - -
MethodCoverage
getApiError0%
report0%
getApiError0%
report0%
register50%
handleApiException88%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - -
MethodCRAP
handleApiException10
register2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Exceptions/index.html b/tests/coverage/app/Exceptions/index.html deleted file mode 100644 index 3736b74..0000000 --- a/tests/coverage/app/Exceptions/index.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Exceptions - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 86.67% covered (warning) -
-
-
86.67%
78 / 90
-
- 50.00% covered (danger) -
-
-
50.00%
6 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
Api
-
- 81.82% covered (warning) -
-
-
81.82%
18 / 22
-
- 50.00% covered (danger) -
-
-
50.00%
4 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
AbortRowImportException.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
Handler.php
-
- 88.24% covered (warning) -
-
-
88.24%
60 / 68
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Controllers/AnswerController.php.html b/tests/coverage/app/Http/Controllers/AnswerController.php.html deleted file mode 100644 index 5b844ec..0000000 --- a/tests/coverage/app/Http/Controllers/AnswerController.php.html +++ /dev/null @@ -1,427 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/AnswerController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 66
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
AnswerController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 66
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
110
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 store
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 edit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 destroy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Answers\StoreAnswerRequest;
7use App\Http\Requests\Answers\UpdateAnswerRequest;
8use App\Models\Answer;
9use App\Models\Question;
10use Illuminate\Http\Request;
11use Illuminate\Support\Facades\DB;
12use Illuminate\Support\Str;
13
14class AnswerController extends Controller
15{
16    /**
17     * Display a listing of the resource.
18     *
19     * @param \Illuminate\Http\Request $request
20     * @return \Illuminate\Contracts\View\View
21     */
22    public function index(Request $request): \Illuminate\Contracts\View\View
23    {
24        /** @var \App\Models\Question $questionModel */
25        $questionModel = $request->question;
26
27        /** @var \Illuminate\Database\Eloquent\Builder $answers */
28        $answers = Answer::query()->where('question_id', $questionModel->id);
29
30        if ($request->search) {
31            $this->searchQuery(
32                $answers,
33                $request->search,
34                null,
35                'answer',
36            );
37        }
38
39        $this->sortQuery($answers);
40        $searchFields = trans('Réponse');
41
42        $answerModels = $answers->paginate(12);
43
44        return view('answers.index', compact('answerModels', 'questionModel', 'searchFields'));
45    }
46
47    /**
48     * Show the form for creating a new resource.
49     *
50     * @param \Illuminate\Http\Request $request
51     * @param \App\Models\Answer       $answer
52     * @return \Illuminate\Contracts\View\View
53     */
54    public function create(Request $request, Answer $answer): \Illuminate\Contracts\View\View
55    {
56        /** @var \App\Models\Question $questionModel */
57        $questionModel = $request->question;
58
59        return view('answers.create', [
60            'answerModel' => $answer,
61            'questionModel' => $questionModel
62        ]);
63    }
64
65    /**
66     * Store a newly created resource in storage.
67     *
68     * @param \App\Http\Requests\Answers\StoreAnswerRequest $request
69     * @return \Illuminate\Http\RedirectResponse
70     */
71    public function store(StoreAnswerRequest $request): \Illuminate\Http\RedirectResponse
72    {
73        return DB::transaction(function () use ($request) {
74            $answer = new Answer();
75            $answer->fill($request->validated());
76            if ($answer->saveOrFail()) {
77                return redirect()
78                    ->route('answers.edit', $answer)
79                    ->with('success', trans(
80                        ':model a été créé.',
81                        ['model' => Str::singular(trans('models.classes.answers'))]
82                    ));
83            }
84            return redirect()
85                ->back()
86                ->with('error', trans(
87                    ':model n\'a pas été créé.',
88                    ['model' => Str::singular(trans('models.classes.answers'))]
89                ));
90        });
91    }
92
93    /**
94     * Show the form for editing the specified resource.
95     *
96     * @param \App\Models\Question $question
97     * @param \App\Models\Answer   $answers
98     * @return \Illuminate\Contracts\View\View
99     */
100    public function edit(Question $question, Answer $answers): \Illuminate\Contracts\View\View
101    {
102        return view('answers.edit', [
103            'answerModel' => $answers,
104            'questionModel' => $question
105        ]);
106    }
107
108    /**
109     * Update a spacific resource in storage.
110     *
111     * @param \App\Http\Requests\Answers\UpdateAnswerRequest $request
112     * @param \App\Models\Question                           $question
113     * @param \App\Models\Answer                             $answer
114     * @return \Illuminate\Http\RedirectResponse
115     */
116    public function update(
117        UpdateAnswerRequest $request,
118        Question $question,
119        Answer $answer
120    ): \Illuminate\Http\RedirectResponse {
121        return DB::transaction(function () use ($request, $question, $answer) {
122            $answer->fill($request->validated());
123            if ($answer->saveOrFail()) {
124                return redirect()
125                    ->route('questions.answers.edit', ['question' => $question, 'answer' => $answer])
126                    ->with('success', trans(
127                        ':model a été mis à jour.',
128                        ['model' => Str::singular(trans('models.classes.answers'))]
129                    ));
130            }
131            return redirect()
132                ->back()
133                ->with('error', trans(
134                    ':model n\'a pas été mis à jour.',
135                    ['model' => Str::singular(trans('models.classes.answers'))]
136                ));
137        });
138    }
139
140    /**
141     * Remove the specified resource from storage.
142     *
143     * @param \App\Models\Question $question
144     * @param \App\Models\Answer   $answer
145     * @return \Illuminate\Http\RedirectResponse
146     */
147    public function destroy(Question $question, Answer $answer): \Illuminate\Http\RedirectResponse
148    {
149        if ($answer->deleteOrFail()) {
150            return redirect()->route('questions.answers.index', $question)
151                ->with('success', trans(
152                    ':model a été supprimé.',
153                    ['model' => Str::singular(trans('models.classes.answers'))]
154                ));
155        }
156        return redirect()->back()
157            ->with('error', trans(
158                ':model n\'a pas pu être supprimé.',
159                ['model' => Str::singular(trans('models.classes.answers'))]
160            ));
161    }
162}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V2/AnswerController.php.html b/tests/coverage/app/Http/Controllers/Api/V2/AnswerController.php.html deleted file mode 100644 index f99bb50..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V2/AnswerController.php.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V2/AnswerController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
AnswerController
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 storeCustomerAnswers
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V2;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Api\V2\StoreCustomerAnswers;
7use App\Models\Answer;
8use App\Models\Customer;
9use App\Models\Service;
10use Illuminate\Http\JsonResponse;
11
12class AnswerController extends Controller
13{
14    /**
15     * Store the customer answers.
16     *
17     * @param \App\Http\Requests\Api\V2\StoreCustomerAnswers $request
18     * @param \App\Models\Service                            $service
19     * @param \App\Models\Customer                           $customer
20     * @return \Illuminate\Http\JsonResponse
21     */
22    public function storeCustomerAnswers(
23        StoreCustomerAnswers $request,
24        Service $service,
25        Customer $customer
26    ): JsonResponse {
27        // * Make sure we are accessing a customer that belongs to our service.
28        $this->authorize('customerBelongsToService', $customer);
29
30        $existingAnswerIds = $customer->getAnswers($service)->pluck('id');
31        $answersID         = Answer::query()->whereIn('id', $request->answers)->pluck('id');
32        $customer->answers()->sync($answersID->merge($existingAnswerIds));
33        return response()->json();
34    }
35}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V2/ApiController.php.html b/tests/coverage/app/Http/Controllers/Api/V2/ApiController.php.html deleted file mode 100644 index 7743fec..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V2/ApiController.php.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V2/ApiController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiController
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 ping
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V2;
4
5use App\Http\Controllers\Controller;
6use Illuminate\Http\JsonResponse;
7
8class ApiController extends Controller
9{
10    /**
11     * Just returns HTTP 200 response.
12     *
13     * @return \Illuminate\Http\JsonResponse
14     */
15    public function ping(): JsonResponse
16    {
17        return response()->json();
18    }
19}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V2/ArcadiaController.php.html b/tests/coverage/app/Http/Controllers/Api/V2/ArcadiaController.php.html deleted file mode 100644 index 480a052..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V2/ArcadiaController.php.html +++ /dev/null @@ -1,362 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V2/ArcadiaController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
40 / 40
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ArcadiaController
-
- 100.00% covered (success) -
-
-
100.00%
40 / 40
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 outgoingMailDefault
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 outgoingMailGame
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 handleArcadiaMail
-
- 100.00% covered (success) -
-
-
100.00%
30 / 30
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 makeXml
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V2;
4
5use App\Enums\ArcadiaMailType;
6use App\Enums\ArcadiaOrderType;
7use App\Http\Controllers\Controller;
8use App\Http\Requests\Api\V2\BaseApiRequest;
9use App\Http\Requests\Api\V2\SendArchadiaDefaultMailRequest;
10use App\Http\Requests\Api\V2\SendArchadiaGameMailRequest;
11use App\Mail\CourrierArcadiaError;
12use DOMDocument;
13use Illuminate\Http\JsonResponse;
14use Illuminate\Support\Facades\Log;
15use Illuminate\Support\Facades\Mail;
16use Illuminate\Support\Facades\Storage;
17use Illuminate\Support\Str;
18
19/**
20 * ! Ici c'est du sale à cause d'arcadia
21 * Ils ont fait le choix de rajouter une fonctionnalité
22 * sur une methode existante en rajoutant des conditions
23 * sales. Ils ont donc une seule méthode pour envoyer plusieurs
24 * types de réclas avec des champs différents...
25 *
26 * Donc une séparation est faite sur les endpoints CRM et dans le client
27 * pour éviter une confusion de nos utilisateurs
28 */
29class ArcadiaController extends Controller
30{
31    /**
32     * Send arcadia default mail (reclamations).
33     *
34     * @param \App\Http\Requests\Api\V2\SendArchadiaDefaultMailRequest $request
35     * @return \Illuminate\Http\JsonResponse
36     */
37    public function outgoingMailDefault(SendArchadiaDefaultMailRequest $request): JsonResponse
38    {
39        return $this->handleArcadiaMail($request, ArcadiaMailType::default);
40    }
41
42    /**
43     * Send arcadia game mail (games).
44     *
45     * @param \App\Http\Requests\Api\V2\SendArchadiaGameMailRequest $request
46     * @return \Illuminate\Http\JsonResponse
47     */
48    public function outgoingMailGame(SendArchadiaGameMailRequest $request): JsonResponse
49    {
50        return $this->handleArcadiaMail($request, ArcadiaMailType::game);
51    }
52
53    /**
54     * Form xml message and save it in the apropriate storage location
55     * to be picked up by the arcadia job.
56     *
57     * @param \App\Http\Requests\Api\V2\BaseApiRequest $request
58     * @param \App\Enums\ArcadiaMailType               $type
59     * @return \Illuminate\Http\JsonResponse
60     * @throws \Exception If an error occurs while generating and saving the xml file.
61     */
62    private function handleArcadiaMail(BaseApiRequest $request, ArcadiaMailType $type): JsonResponse
63    {
64        $request = $request->merge([
65            'order_num' => str_pad(\intval($request->order_num), 9, '0', STR_PAD_LEFT)
66        ]);
67        $xml     = 'none';
68        try {
69            $customerInfo = \array_intersect_key($request->all()['deliver'], [
70                'email'     => '',
71                'firstname' => '',
72                'lastname'  => '',
73                'address'   => '',
74                'address2'  => '',
75                'city'      => '',
76                'postcode'  => '',
77                'phone'     => ''
78            ]);
79            $orderType    = ArcadiaOrderType::make(intval($request->state_order));
80            $xml          = $this->makeXml($request, $type, $orderType, $customerInfo);
81
82            // * Format xml.
83            $doc                     = new DOMDocument('1.0', 'utf-8');
84            $doc->xmlStandalone      = true;
85            $doc->preserveWhiteSpace = false;
86            $doc->formatOutput       = true;
87            $doc->loadXML($xml);
88            $xml = $doc->saveXML();
89
90            Storage::disk('arcadia')->put(Str::slug(sprintf(
91                'v2_order_%s_%s_%s%s',
92                $request->order_num,
93                $type->label(),
94                date('Ymd_His'),
95                \microtime(true)
96            )) . '.xml', $xml);
97            return response()->json();
98            // @codeCoverageIgnoreStart
99        } catch (\Exception $e) {
100            Log::critical("ARCADIA XML CREATION FAILED FOR $request->order_num : " . $e->getMessage());
101            if (!config('app.debug')) {
102                dispatch(function () use ($xml, $e, $request) {
103                    Mail::to(config('mail.MAIL_ADMIN'))->send(new CourrierArcadiaError(
104                        "ARCADIA XML CREATION FAILED FOR $request->order_num",
105                        "Une erreur est survenue lors de la création du fichier XML : " . $e->getMessage(),
106                        $xml ?: ''
107                    ));
108                })->afterResponse();
109            }
110            throw $e;
111            // @codeCoverageIgnoreEnd
112        } //end try
113    }
114
115    /**
116     * Render Arcadia xml for order.
117     *
118     * @param \App\Http\Requests\Api\V2\BaseApiRequest $request
119     * @param \App\Enums\ArcadiaMailType               $type
120     * @param \App\Enums\ArcadiaOrderType              $orderType
121     * @param array                                    $customerInfo
122     * @return string
123     */
124    private function makeXml(
125        BaseApiRequest $request,
126        ArcadiaMailType $type,
127        ArcadiaOrderType $orderType,
128        array $customerInfo
129    ): string {
130        $arcadiaMailType = $type->equals(ArcadiaMailType::default) ?
131            'mail.arcadiaOrders.default' : 'mail.arcadiaOrders.game';
132        return view($arcadiaMailType, [
133            'request'      => $request,
134            'type'         => $type,
135            'orderType'    => $orderType,
136            'customerInfo' => $customerInfo
137        ])->render();
138    }
139}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V2/CustomerController.php.html b/tests/coverage/app/Http/Controllers/Api/V2/CustomerController.php.html deleted file mode 100644 index 251de5f..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V2/CustomerController.php.html +++ /dev/null @@ -1,528 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V2/CustomerController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
80 / 80
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerController
-
- 100.00% covered (success) -
-
-
100.00%
80 / 80
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
26
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 store
-
- 100.00% covered (success) -
-
-
100.00%
28 / 28
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
7
 show
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 update
-
- 100.00% covered (success) -
-
-
100.00%
15 / 15
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
5
 destroy
-
- 100.00% covered (success) -
-
-
100.00%
17 / 17
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
6
 authenticate
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 activateAccount
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V2;
4
5use App\Enums\ApiError;
6use App\Exceptions\Api\V2\ApiErrorException;
7use App\Exceptions\Api\V2\CrmException;
8use App\Http\Controllers\Controller;
9use App\Http\Requests\Api\V2\AuthenticateRequest;
10use App\Http\Requests\Api\V2\StoreCustomerRequest;
11use App\Http\Requests\Api\V2\UpdateCustomerRequest;
12use App\Http\Resources\Api\V2\CustomerResource;
13use App\Jobs\UpdateCustomerLastConnection;
14use App\Models\Customer;
15use App\Models\Service;
16use App\Models\SingleOptin;
17use Illuminate\Database\Eloquent\Builder;
18use Illuminate\Database\Eloquent\ModelNotFoundException;
19use Illuminate\Http\JsonResponse;
20use Illuminate\Http\Resources\Json\JsonResource;
21use Illuminate\Support\Facades\DB;
22
23class CustomerController extends Controller
24{
25    /**
26     * Creates a new customer for the specified service.
27     *
28     * @param \App\Http\Requests\Api\V2\StoreCustomerRequest $request
29     * @param \App\Models\Service                            $service
30     * @return \Illuminate\Http\Resources\Json\JsonResource
31     * @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::customerExists if
32     *                                                  the customer with this email already exists.
33     * @throws \App\Exceptions\Api\V2\CrmException If saving the customer to DB failed.
34     */
35    public function store(StoreCustomerRequest $request, Service $service): JsonResource
36    {
37        $data = (object)$request->validated();
38
39        /** @var \App\Models\Customer */
40        $customer = Customer::query()->where('email', $data->email)->firstOrCreate([
41            'email' => $data->email
42        ]);
43
44        DB::transaction(function () use (&$customer, $data, $request, $service) {
45
46            $saved = $customer->save();
47            $customer->setOptIn($service->brand, $data->opt_in);
48
49            // * Delete Single optin if exists.
50            /** @var \App\Models\SingleOptin|null $singleOptin */
51            $singleOptin = SingleOptin::query()->where('email', $data->email)
52                ->whereHas('brand', function (Builder $q) use ($service) {
53                    $q->where('id', $service->brand->id);
54                })->first();
55            if ($singleOptin) {
56                $saved = $singleOptin->delete() && $saved;
57            }
58
59            /** @var \App\Models\CustomerInfo */
60            $customerInfo = $customer->info($service->brand, Customer::FIRST_OR_NEW);
61            if ($customerInfo->exists) {
62                throw new ApiErrorException(ApiError::customerExists);
63            }
64            $customerInfo->fill($request->validated());
65            $customerInfo->brand()->associate($service->brand);
66            $customerInfo->customer()->associate($customer);
67            $saved = $customerInfo->save() && $saved;
68
69            /** @var \App\Models\CustomerLogin */
70            $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_NEW);
71            $customerLogin->fill($request->validated());
72            $customerLogin->brand()->associate($service->brand);
73            $customerLogin->customer()->associate($customer);
74            $saved = $customerLogin->save() && $saved;
75
76            if (!$saved) {
77                // @codeCoverageIgnoreStart
78                throw new CrmException('Api failed to store customer.');
79                // @codeCoverageIgnoreEnd
80            }
81        });
82
83        return new CustomerResource($service->brand, $customer);
84    }
85
86    /**
87     * Renders the specific customer infos.
88     *
89     * @param  \App\Models\Service  $service
90     * @param  \App\Models\Customer $customer
91     * @return \Illuminate\Http\Resources\Json\JsonResource
92     */
93    public function show(Service $service, Customer $customer): JsonResource
94    {
95        // * Make sure we are accessing a customer that belongs to our service.
96        $this->authorize('customerBelongsToService', $customer);
97
98        return new CustomerResource($service->brand, $customer);
99    }
100
101    /**
102     * Updates information for a specific customer.
103     *
104     * @param \App\Http\Requests\Api\V2\UpdateCustomerRequest $request
105     * @param \App\Models\Service                             $service
106     * @param \App\Models\Customer                            $customer
107     * @return \Illuminate\Http\Resources\Json\JsonResource
108     * @throws \App\Exceptions\Api\V2\CrmException If saving the customer to DB failed.
109     */
110    public function update(UpdateCustomerRequest $request, Service $service, Customer $customer): JsonResource
111    {
112        // * Make sure we are accessing a customer that belongs to our service.
113        $this->authorize('customerBelongsToService', $customer);
114
115        DB::transaction(function () use ($request, $customer, $service) {
116            // To correct with create.
117            $customer->fill($request->validated());
118            $saved = $customer->save();
119            if ($request->has('opt_in')) {
120                $customer->setOptIn($service->brand, $request->opt_in);
121            }
122
123            /** @var \App\Models\CustomerInfo */
124            $customerInfo = $customer->info($service->brand, Customer::FIRST_OR_FAIL);
125            $customerInfo->fill($request->validated());
126            $saved = $customerInfo->save() && $saved;
127
128            /** @var \App\Models\CustomerLogin */
129            $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
130            $customerLogin->fill($request->validated());
131            $saved = $customerLogin->save() && $saved;
132
133            if (!$saved) {
134                // @codeCoverageIgnoreStart
135                throw new CrmException('Api failed to update customer.');
136                // @codeCoverageIgnoreEnd
137            }
138        });
139
140        return new CustomerResource($service->brand, $customer);
141    }
142
143    /**
144     * Deletes customer information for a specific service.
145     *
146     * @param \App\Models\Service  $service
147     * @param \App\Models\Customer $customer
148     * @return \Illuminate\Http\JsonResponse
149     * @throws \App\Exceptions\Api\V2\CrmException If removing the customer off the DB failed.
150     */
151    public function destroy(Service $service, Customer $customer): JsonResponse
152    {
153        // * Make sure we are accessing a customer that belongs to our service.
154        $this->authorize('customerBelongsToService', $customer);
155
156        // TODO: Gestion avec mesBR.
157        /** @var \App\Models\CustomerInfo */
158        $customerInfo = $customer->info($service->brand, Customer::FIRST_OR_FAIL);
159        /** @var \App\Models\CustomerLogin */
160        $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
161
162        DB::transaction(function () use ($service, $customer, $customerLogin, $customerInfo) {
163            if (
164                $customerInfo->delete() === false ||
165                $customerLogin->delete() === false
166            ) {
167                // @codeCoverageIgnoreStart
168                throw new CrmException('Api failed to delete customer.');
169                // @codeCoverageIgnoreEnd
170            };
171
172            $customer->optInHistory()->whereHas('brand', function ($q) use ($service) {
173                $q->where('id', $service->brand_id);
174            })->delete();
175
176            // * Force loading real relation counts.
177            $customer->unsetRelation('logins');
178            $customer->unsetRelation('infos');
179            $logins = $customer->logins()->count();
180            $infos  = $customer->infos()->count();
181
182            // If customer is not associated with any brand then delete.
183            if (!$logins and !$infos) {
184                if ($customer->delete() === false) {
185                    // @codeCoverageIgnoreStart
186                    throw new CrmException('Api failed to update customer.');
187                    // @codeCoverageIgnoreEnd
188                }
189            }
190        });
191
192        return response()->json();
193    }
194
195    /**
196     * Authenticate the user.
197     *
198     * @param \App\Http\Requests\Api\V2\AuthenticateRequest $request
199     * @param \App\Models\Service                           $service
200     * @return \Illuminate\Http\Resources\Json\JsonResource
201     * @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::authFailed in case
202     *                                                  of wrong credentials.
203     * @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::customerNotActivated if
204     *                                                  customer account is not activated.
205     */
206    public function authenticate(AuthenticateRequest $request, Service $service): JsonResource
207    {
208        try {
209            /** @var \App\Models\Customer */
210            $customer = Customer::query()->where('email', $request->email)->firstOrFail();
211
212            /** @var \App\Models\CustomerLogin $customerLogin */
213            $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
214            if (!$customerLogin->passwordMatch($request->password)) {
215                throw new ApiErrorException(ApiError::authFailed);
216            }
217
218            if (!$customerLogin->status) {
219                throw new ApiErrorException(ApiError::customerNotActivated);
220            }
221
222            UpdateCustomerLastConnection::dispatch($customer, $customerLogin, now())
223                ->onConnection('database')->afterResponse();
224
225            return new CustomerResource($service->brand, $customer);
226        } catch (ModelNotFoundException $e) {
227            throw new ApiErrorException(ApiError::authFailed);
228        } //end try
229    }
230
231    /**
232     * Activate the account of the user.
233     *
234     * @param \App\Models\Customer $customer
235     * @param \App\Models\Service  $service
236     * @return \Illuminate\Http\JsonResponse
237     * @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::customerAlreadyActive
238     *                                                  if customer account is already active.
239     * @throws \App\Exceptions\Api\V2\CrmException If saving the customer to DB failed.
240     */
241    public function activateAccount(Customer $customer, Service $service): JsonResponse
242    {
243        // * Make sure we are accessing a customer that belongs to our service.
244        $this->authorize('customerBelongsToService', $customer);
245
246        /** @var \App\Models\CustomerLogin $login */
247        $login = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
248
249        if ($login->status) {
250            throw new ApiErrorException(ApiError::customerAlreadyActive);
251        }
252
253        $login->status = true;
254        if (!$login->save()) {
255            // @codeCoverageIgnoreStart
256            throw new CrmException('Failed to save login');
257            // @codeCoverageIgnoreEnd
258        }
259        return response()->json();
260    }
261}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V2/OptinController.php.html b/tests/coverage/app/Http/Controllers/Api/V2/OptinController.php.html deleted file mode 100644 index d2d9fbb..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V2/OptinController.php.html +++ /dev/null @@ -1,294 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V2/OptinController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
19 / 19
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
OptinController
-
- 100.00% covered (success) -
-
-
100.00%
19 / 19
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 optin
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
 optoutWithHashcode
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
 changeOptin
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V2;
4
5use App\Enums\ApiError;
6use App\Exceptions\Api\V2\ApiErrorException;
7use App\Exceptions\Api\V2\CrmException;
8use App\Http\Controllers\Controller;
9use App\Http\Requests\Api\V2\BaseApiRequest;
10use App\Http\Requests\Api\V2\SingleOptinRequest;
11use App\Http\Requests\Api\V2\SingleOptinRemoveWithHashcodeRequest;
12use App\Models\CustomerInfo;
13use App\Models\Service;
14use Illuminate\Http\JsonResponse;
15use App\Models\SingleOptin;
16
17class OptinController extends Controller
18{
19    /**
20     * Creates a new Single optin or destroys it if exists.
21     *
22     * @param \App\Http\Requests\Api\V2\SingleOptinRequest $request
23     * @param \App\Models\Service                          $service
24     * @return \Illuminate\Http\JsonResponse
25     * @throws \App\Exceptions\Api\V2\ApiErrorException With ApiError::singleOptinCustomerExists
26     *                                                  if this email already has a full account.
27     * @throws \App\Exceptions\Api\V2\CrmException If the single optin could not be added or removed.
28     */
29    public function optin(SingleOptinRequest $request, Service $service): JsonResponse
30    {
31        if (CustomerInfo::getFromEmail($service->brand, $request->email)->exists()) {
32            throw new ApiErrorException(ApiError::singleOptinCustomerExists);
33        }
34
35        /** @var \App\Models\SingleOptin */
36        $singleOptin = SingleOptin::query()->where('email', $request->email)
37            ->whereHas('brand', function ($q) use ($service) {
38                $q->where('id', $service->brand->id);
39            })->firstOrNew();
40
41        if (!$this->changeOptin($service, $request, \boolval($request->opt_in), $singleOptin)) {
42            // @codeCoverageIgnoreStart
43            throw new CrmException('Api failed to update single optin.');
44            // @codeCoverageIgnoreEnd
45        }
46
47        return response()->json();
48    }
49
50    /**
51     * Creates a new Single optin or destroys it if exists using hashcode.
52     *
53     * @param \App\Http\Requests\Api\V2\SingleOptinRemoveWithHashcodeRequest $request
54     * @param \App\Models\Service                                            $service
55     * @return \Illuminate\Http\JsonResponse
56     * @throws \App\Exceptions\Api\V2\CrmException If the single optin could not be removed.
57     */
58    public function optoutWithHashcode(SingleOptinRemoveWithHashcodeRequest $request, Service $service): JsonResponse
59    {
60        /** @var \App\Models\SingleOptin */
61        $singleOptin = SingleOptin::query()->where('hashcode', $request->hashcode)
62            ->whereHas('brand', function ($q) use ($service) {
63                $q->whereId($service->brand->id);
64            })->firstOrFail();
65
66        if ($singleOptin and !$this->changeOptin($service, $request, \boolval($request->opt_in), $singleOptin)) {
67            // @codeCoverageIgnoreStart
68            throw new CrmException('Api failed to update single optin.');
69            // @codeCoverageIgnoreEnd
70        }
71
72        return response()->json();
73    }
74
75    /**
76     * Changes the optin state.
77     *
78     * @param \App\Models\Service                      $service
79     * @param \App\Http\Requests\Api\V2\BaseApiRequest $request
80     * @param boolean                                  $optin
81     * @param \App\Models\SingleOptin                  $singleOptin
82     * @return boolean Returns false in case of failure.
83     */
84    private function changeOptin(Service $service, BaseApiRequest $request, bool $optin, SingleOptin $singleOptin): bool
85    {
86        if ($optin) {
87            $singleOptin->fill($request->validated());
88            $singleOptin->brand()->associate($service->brand);
89            return $singleOptin->save();
90        }
91        return $singleOptin->delete() !== false;
92    }
93}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V2/QuestionController.php.html b/tests/coverage/app/Http/Controllers/Api/V2/QuestionController.php.html deleted file mode 100644 index b84aff2..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V2/QuestionController.php.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V2/QuestionController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionController
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 index
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 indexWithResponse
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 unAnsweredBy
-
- 100.00% covered (success) -
-
-
100.00%
9 / 9
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V2;
4
5use App\Http\Controllers\Controller;
6use App\Http\Resources\Api\V2\QuestionsResource;
7use App\Models\Answer;
8use App\Models\Customer;
9use App\Models\Question;
10use App\Models\Service;
11use Illuminate\Http\Resources\Json\JsonResource;
12use Illuminate\Http\Resources\Json\ResourceCollection;
13
14class QuestionController extends Controller
15{
16    /**
17     * Returns all service questions.
18     *
19     * @param \App\Models\Service $service
20     * @return \Illuminate\Http\Resources\Json\ResourceCollection
21     */
22    public function index(Service $service): ResourceCollection
23    {
24        return new QuestionsResource($service->brand->questions);
25    }
26
27    /**
28     * Returns all service questions with user answers for all of them.
29     *
30     * @param \App\Models\Service  $service
31     * @param \App\Models\Customer $customer
32     * @return \Illuminate\Http\Resources\Json\ResourceCollection
33     */
34    public function indexWithResponse(Service $service, Customer $customer): ResourceCollection
35    {
36        // * Make sure we are accessing a customer that belongs to our service.
37        $this->authorize('customerBelongsToService', $customer);
38
39        $customerAnswers = $customer->getAnswers($service);
40        return new QuestionsResource($service->brand->questions, $customerAnswers);
41    }
42
43    /**
44     * Returns all service questions that was not answered by a user.
45     *
46     * @param \App\Models\Service  $service
47     * @param \App\Models\Customer $customer
48     * @return \Illuminate\Http\Resources\Json\JsonResource
49     */
50    public function unAnsweredBy(Service $service, Customer $customer): JsonResource
51    {
52        // * Make sure we are accessing a customer that belongs to our service.
53        $this->authorize('customerBelongsToService', $customer);
54
55        $questions = Question::query()->whereHas('brand', function ($q) use ($service) {
56            $q->where('id', $service->brand->id);
57        })->whereDoesntHave('answers', function ($q) use ($customer) {
58            $q->whereIn('id', Answer::query()->whereHas('customers', function ($q) use ($customer) {
59                $q->where('id', $customer->id);
60            })->pluck('id'));
61        })->with('answers')->get();
62        return new QuestionsResource($questions);
63    }
64}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V2/StatsController.php.html b/tests/coverage/app/Http/Controllers/Api/V2/StatsController.php.html deleted file mode 100644 index 22b7f29..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V2/StatsController.php.html +++ /dev/null @@ -1,310 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V2/StatsController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
45 / 45
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
StatsController
-
- 100.00% covered (success) -
-
-
100.00%
45 / 45
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 brandStats
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 questionStats
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 answersByDays
-
- 100.00% covered (success) -
-
-
100.00%
33 / 33
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V2;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Api\V2\GetBrandStatsRequest;
7use App\Http\Requests\Api\V2\GetQuestionStatsRequest;
8use App\Http\Resources\Api\V2\BrandStatsResource;
9use App\Http\Resources\Api\V2\QuestionStatsResource;
10use App\Models\BrandStat;
11use App\Models\CustomerAnswer;
12use App\Models\Question;
13use App\Models\Service;
14use Illuminate\Http\Resources\Json\ResourceCollection;
15use Illuminate\Support\Carbon;
16use Illuminate\Support\Collection;
17
18class StatsController extends Controller
19{
20    /**
21     * Get specific brand statistics.
22     *
23     * @param \App\Http\Requests\Api\V2\GetBrandStatsRequest $request
24     * @param \App\Models\Service                            $service
25     * @return \Illuminate\Http\Resources\Json\ResourceCollection
26     */
27    public function brandStats(GetBrandStatsRequest $request, Service $service): ResourceCollection
28    {
29        $stats = BrandStat::query()->whereDate('created_at', '>=', $request->start)
30            ->whereDate('created_at', '<=', $request->end)
31            ->whereBrandId($service->brand->id)->get();
32        return new BrandStatsResource($stats);
33    }
34
35    /**
36     * Get statistics for a specific question.
37     *
38     * @param \App\Http\Requests\Api\V2\GetQuestionStatsRequest $request
39     * @param \App\Models\Question                              $question
40     * @return \App\Http\Resources\Api\V2\QuestionStatsResource
41     */
42    public function questionStats(GetQuestionStatsRequest $request, Question $question): QuestionStatsResource
43    {
44        // * Make sure we are accessing a customer that belongs to our service.
45        $this->authorize('questionBelongsToService', $question);
46
47        $answers = $question->answers;
48        $start   = Carbon::parse($request->start);
49        $end     = Carbon::parse($request->end);
50
51        return new QuestionStatsResource(
52            $this->answersByDays($answers, $start, $end),
53            $question
54        );
55    }
56
57    /**
58     * Total réponses par dates.
59     *
60     * @param \Illuminate\Support\Collection $answers
61     * @param \Illuminate\Support\Carbon     $start
62     * @param \Illuminate\Support\Carbon     $end
63     * @return \Illuminate\Support\Collection
64     */
65    private function answersByDays(Collection $answers, Carbon $start, Carbon $end): Collection
66    {
67        // * Totalize by date all answers.
68        $answersByDays = CustomerAnswer::query()->whereDate('created_at', '>=', $start)
69            ->whereDate('created_at', '<=', $end)
70            ->whereIn('answer_id', $answers->pluck('id'))
71            ->get()->map(function ($custAnswer) {
72                return [
73                    'answer_id' => $custAnswer->answer_id,
74                    'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
75                ];
76            })->groupBy(['created_at', 'answer_id'])->map(function ($day) {
77                return $day->map(function ($custAnswers) {
78                    return $custAnswers->count();
79                });
80            });
81
82        do {
83            $currentDate = $start->isoFormat('YYYY-MM-DD');
84            /** @var \Illuminate\Support\Collection $answersByDays */
85            if (!$answersByDays->has($currentDate)) {
86                $answersByDays->put(
87                    $currentDate,
88                    $answers->mapWithKeys(function ($answer) {
89                        return [$answer->id => 0];
90                    })
91                );
92            } else {
93                $curentAnswers = $answersByDays->pull($currentDate);
94                $answersByDays->put(
95                    $currentDate,
96                    $answers->mapWithKeys(function ($answer) use ($curentAnswers) {
97                        return [$answer->id =>
98                        $curentAnswers->has($answer->id) ?
99                            $curentAnswers->get($answer->id) : 0];
100                    })
101                );
102            }
103
104            $start = $start->addDay();
105        } while ($start->lessThanOrEqualTo($end));
106
107        return $answersByDays;
108    }
109}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V2/dashboard.html b/tests/coverage/app/Http/Controllers/Api/V2/dashboard.html deleted file mode 100644 index 12ea181..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V2/dashboard.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Controllers/Api/V2 - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V2/index.html b/tests/coverage/app/Http/Controllers/Api/V2/index.html deleted file mode 100644 index 21f5e40..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V2/index.html +++ /dev/null @@ -1,291 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V2 - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
203 / 203
-
- 100.00% covered (success) -
-
-
100.00%
21 / 21
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
AnswerController.php
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiController.php
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ArcadiaController.php
-
- 100.00% covered (success) -
-
-
100.00%
40 / 40
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerController.php
-
- 100.00% covered (success) -
-
-
100.00%
80 / 80
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
OptinController.php
-
- 100.00% covered (success) -
-
-
100.00%
19 / 19
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionController.php
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
StatsController.php
-
- 100.00% covered (success) -
-
-
100.00%
45 / 45
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Controllers/Api/V4/AnswerController.php.html b/tests/coverage/app/Http/Controllers/Api/V4/AnswerController.php.html deleted file mode 100644 index af734ac..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V4/AnswerController.php.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V4/AnswerController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
AnswerController
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 storeCustomerAnswers
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V4;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Api\V4\StoreCustomerAnswers;
7use App\Models\Answer;
8use App\Models\Customer;
9use App\Models\Service;
10use Illuminate\Http\JsonResponse;
11
12class AnswerController extends Controller
13{
14    /**
15     * Store the customer answers.
16     *
17     * @param \App\Http\Requests\Api\V4\StoreCustomerAnswers $request
18     * @param \App\Models\Service                            $service
19     * @param \App\Models\Customer                           $customer
20     * @return \Illuminate\Http\JsonResponse
21     */
22    public function storeCustomerAnswers(
23        StoreCustomerAnswers $request,
24        Service $service,
25        Customer $customer
26    ): JsonResponse {
27        // * Make sure we are accessing a customer that belongs to our service.
28        $this->authorize('customerBelongsToService', $customer);
29
30        $existingAnswerIds = $customer->getAnswers($service)->pluck('id');
31        $answersID         = Answer::query()->whereIn('id', $request->answers)->pluck('id');
32        $customer->answers()->sync($answersID->merge($existingAnswerIds));
33        return response()->json();
34    }
35}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V4/ApiController.php.html b/tests/coverage/app/Http/Controllers/Api/V4/ApiController.php.html deleted file mode 100644 index edd82de..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V4/ApiController.php.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V4/ApiController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiController
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 ping
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V4;
4
5use App\Http\Controllers\Controller;
6use Illuminate\Http\JsonResponse;
7
8class ApiController extends Controller
9{
10    /**
11     * Just returns HTTP 200 response.
12     *
13     * @return \Illuminate\Http\JsonResponse
14     */
15    public function ping(): JsonResponse
16    {
17        return response()->json();
18    }
19}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V4/ArcadiaController.php.html b/tests/coverage/app/Http/Controllers/Api/V4/ArcadiaController.php.html deleted file mode 100644 index 9456882..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V4/ArcadiaController.php.html +++ /dev/null @@ -1,362 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V4/ArcadiaController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
40 / 40
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ArcadiaController
-
- 100.00% covered (success) -
-
-
100.00%
40 / 40
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 outgoingMailDefault
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 outgoingMailGame
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 handleArcadiaMail
-
- 100.00% covered (success) -
-
-
100.00%
30 / 30
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 makeXml
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V4;
4
5use App\Enums\ArcadiaMailType;
6use App\Enums\ArcadiaOrderType;
7use App\Http\Controllers\Controller;
8use App\Http\Requests\Api\V4\BaseApiRequest;
9use App\Http\Requests\Api\V4\SendArchadiaDefaultMailRequest;
10use App\Http\Requests\Api\V4\SendArchadiaGameMailRequest;
11use App\Mail\CourrierArcadiaError;
12use DOMDocument;
13use Illuminate\Http\JsonResponse;
14use Illuminate\Support\Facades\Log;
15use Illuminate\Support\Facades\Mail;
16use Illuminate\Support\Facades\Storage;
17use Illuminate\Support\Str;
18
19/**
20 * ! Ici c'est du sale à cause d'arcadia
21 * Ils ont fait le choix de rajouter une fonctionnalité
22 * sur une methode existante en rajoutant des conditions
23 * sales. Ils ont donc une seule méthode pour envoyer plusieurs
24 * types de réclas avec des champs différents...
25 *
26 * Donc une séparation est faite sur les endpoints CRM et dans le client
27 * pour éviter une confusion de nos utilisateurs
28 */
29class ArcadiaController extends Controller
30{
31    /**
32     * Send arcadia default mail (reclamations).
33     *
34     * @param \App\Http\Requests\Api\V4\SendArchadiaDefaultMailRequest $request
35     * @return \Illuminate\Http\JsonResponse
36     */
37    public function outgoingMailDefault(SendArchadiaDefaultMailRequest $request): JsonResponse
38    {
39        return $this->handleArcadiaMail($request, ArcadiaMailType::default);
40    }
41
42    /**
43     * Send arcadia game mail (games).
44     *
45     * @param \App\Http\Requests\Api\V4\SendArchadiaGameMailRequest $request
46     * @return \Illuminate\Http\JsonResponse
47     */
48    public function outgoingMailGame(SendArchadiaGameMailRequest $request): JsonResponse
49    {
50        return $this->handleArcadiaMail($request, ArcadiaMailType::game);
51    }
52
53    /**
54     * Form xml message and save it in the apropriate storage location
55     * to be picked up by the arcadia job.
56     *
57     * @param \App\Http\Requests\Api\V4\BaseApiRequest $request
58     * @param \App\Enums\ArcadiaMailType               $type
59     * @return \Illuminate\Http\JsonResponse
60     * @throws \Exception If an error occurs while generating and saving the xml file.
61     */
62    private function handleArcadiaMail(BaseApiRequest $request, ArcadiaMailType $type): JsonResponse
63    {
64        $request = $request->merge([
65            'order_num' => str_pad(\intval($request->order_num), 9, '0', STR_PAD_LEFT)
66        ]);
67        $xml     = 'none';
68        try {
69            $customerInfo = \array_intersect_key($request->all()['deliver'], [
70                'email'     => '',
71                'firstname' => '',
72                'lastname'  => '',
73                'address'   => '',
74                'address2'  => '',
75                'city'      => '',
76                'postcode'  => '',
77                'phone'     => ''
78            ]);
79            $orderType    = ArcadiaOrderType::make(intval($request->state_order));
80            $xml          = $this->makeXml($request, $type, $orderType, $customerInfo);
81
82            // * Format xml.
83            $doc                     = new DOMDocument('1.0', 'utf-8');
84            $doc->xmlStandalone      = true;
85            $doc->preserveWhiteSpace = false;
86            $doc->formatOutput       = true;
87            $doc->loadXML($xml);
88            $xml = $doc->saveXML();
89
90            Storage::disk('arcadia')->put(Str::slug(sprintf(
91                'v4_order_%s_%s_%s%s',
92                $request->order_num,
93                $type->label(),
94                date('Ymd_His'),
95                \microtime(true)
96            )) . '.xml', $xml);
97            return response()->json();
98            // @codeCoverageIgnoreStart
99        } catch (\Exception $e) {
100            Log::critical("ARCADIA XML CREATION FAILED FOR $request->order_num : " . $e->getMessage());
101            if (!config('app.debug')) {
102                dispatch(function () use ($xml, $e, $request) {
103                    Mail::to(config('mail.MAIL_ADMIN'))->send(new CourrierArcadiaError(
104                        "ARCADIA XML CREATION FAILED FOR $request->order_num",
105                        "Une erreur est survenue lors de la création du fichier XML : " . $e->getMessage(),
106                        $xml ?: ''
107                    ));
108                })->afterResponse();
109            }
110            throw $e;
111            // @codeCoverageIgnoreEnd
112        } //end try
113    }
114
115    /**
116     * Render Arcadia xml for order.
117     *
118     * @param \App\Http\Requests\Api\V4\BaseApiRequest $request
119     * @param \App\Enums\ArcadiaMailType               $type
120     * @param \App\Enums\ArcadiaOrderType              $orderType
121     * @param array                                    $customerInfo
122     * @return string
123     */
124    private function makeXml(
125        BaseApiRequest $request,
126        ArcadiaMailType $type,
127        ArcadiaOrderType $orderType,
128        array $customerInfo
129    ): string {
130        $arcadiaMailType = $type->equals(ArcadiaMailType::default) ?
131            'mail.arcadiaOrders.default' : 'mail.arcadiaOrders.game';
132        return view($arcadiaMailType, [
133            'request' => $request,
134            'type' => $type,
135            'orderType' => $orderType,
136            'customerInfo' => $customerInfo
137        ])->render();
138    }
139}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V4/CustomerController.php.html b/tests/coverage/app/Http/Controllers/Api/V4/CustomerController.php.html deleted file mode 100644 index 48909b3..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V4/CustomerController.php.html +++ /dev/null @@ -1,528 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V4/CustomerController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
80 / 80
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerController
-
- 100.00% covered (success) -
-
-
100.00%
80 / 80
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
26
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 store
-
- 100.00% covered (success) -
-
-
100.00%
28 / 28
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
7
 show
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 update
-
- 100.00% covered (success) -
-
-
100.00%
15 / 15
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
5
 destroy
-
- 100.00% covered (success) -
-
-
100.00%
17 / 17
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
6
 authenticate
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 activateAccount
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V4;
4
5use App\Enums\ApiError;
6use App\Exceptions\Api\V4\ApiErrorException;
7use App\Exceptions\Api\V4\CrmException;
8use App\Http\Controllers\Controller;
9use App\Http\Requests\Api\V4\AuthenticateRequest;
10use App\Http\Requests\Api\V4\StoreCustomerRequest;
11use App\Http\Requests\Api\V4\UpdateCustomerRequest;
12use App\Http\Resources\Api\V4\CustomerResource;
13use App\Jobs\UpdateCustomerLastConnection;
14use App\Models\Customer;
15use App\Models\Service;
16use App\Models\SingleOptin;
17use Illuminate\Database\Eloquent\Builder;
18use Illuminate\Database\Eloquent\ModelNotFoundException;
19use Illuminate\Http\JsonResponse;
20use Illuminate\Http\Resources\Json\JsonResource;
21use Illuminate\Support\Facades\DB;
22
23class CustomerController extends Controller
24{
25    /**
26     * Creates a new customer for the specified service.
27     *
28     * @param \App\Http\Requests\Api\V4\StoreCustomerRequest $request
29     * @param \App\Models\Service                            $service
30     * @return \Illuminate\Http\Resources\Json\JsonResource
31     * @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::customerExists if
32     *                                                  the customer with this email already exists.
33     * @throws \App\Exceptions\Api\V4\CrmException If saving the customer to DB failed.
34     */
35    public function store(StoreCustomerRequest $request, Service $service): JsonResource
36    {
37        $data = (object)$request->validated();
38
39        /** @var \App\Models\Customer */
40        $customer = Customer::query()->where('email', $data->email)->firstOrCreate([
41            'email' => $data->email
42        ]);
43
44        DB::transaction(function () use (&$customer, $data, $request, $service) {
45
46            $saved = $customer->save();
47            $customer->setOptIn($service->brand, $data->opt_in);
48
49            // * Delete Single optin if exists.
50            /** @var \App\Models\SingleOptin|null $singleOptin */
51            $singleOptin = SingleOptin::query()->where('email', $data->email)
52                ->whereHas('brand', function (Builder $q) use ($service) {
53                    $q->where('id', $service->brand->id);
54                })->first();
55            if ($singleOptin) {
56                $saved = $singleOptin->delete() && $saved;
57            }
58
59            /** @var \App\Models\CustomerInfo */
60            $customerInfo = $customer->info($service->brand, Customer::FIRST_OR_NEW);
61            if ($customerInfo->exists) {
62                throw new ApiErrorException(ApiError::customerExists);
63            }
64            $customerInfo->fill($request->validated());
65            $customerInfo->brand()->associate($service->brand);
66            $customerInfo->customer()->associate($customer);
67            $saved = $customerInfo->save() && $saved;
68
69            /** @var \App\Models\CustomerLogin */
70            $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_NEW);
71            $customerLogin->fill($request->validated());
72            $customerLogin->brand()->associate($service->brand);
73            $customerLogin->customer()->associate($customer);
74            $saved = $customerLogin->save() && $saved;
75
76            if (!$saved) {
77                // @codeCoverageIgnoreStart
78                throw new CrmException('Api failed to store customer.');
79                // @codeCoverageIgnoreEnd
80            }
81        });
82
83        return new CustomerResource($service->brand, $customer);
84    }
85
86    /**
87     * Renders the specific customer infos.
88     *
89     * @param  \App\Models\Service  $service
90     * @param  \App\Models\Customer $customer
91     * @return \Illuminate\Http\Resources\Json\JsonResource
92     */
93    public function show(Service $service, Customer $customer): JsonResource
94    {
95        // * Make sure we are accessing a customer that belongs to our service.
96        $this->authorize('customerBelongsToService', $customer);
97
98        return new CustomerResource($service->brand, $customer);
99    }
100
101    /**
102     * Updates information for a specific customer.
103     *
104     * @param \App\Http\Requests\Api\V4\UpdateCustomerRequest $request
105     * @param \App\Models\Service                             $service
106     * @param \App\Models\Customer                            $customer
107     * @return \Illuminate\Http\Resources\Json\JsonResource
108     * @throws \App\Exceptions\Api\V4\CrmException If saving the customer to DB failed.
109     */
110    public function update(UpdateCustomerRequest $request, Service $service, Customer $customer): JsonResource
111    {
112        // * Make sure we are accessing a customer that belongs to our service.
113        $this->authorize('customerBelongsToService', $customer);
114
115        DB::transaction(function () use ($request, $customer, $service) {
116            // To correct with create.
117            $customer->fill($request->validated());
118            $saved = $customer->save();
119            if ($request->has('opt_in')) {
120                $customer->setOptIn($service->brand, $request->opt_in);
121            }
122
123            /** @var \App\Models\CustomerInfo */
124            $customerInfo = $customer->info($service->brand, Customer::FIRST_OR_FAIL);
125            $customerInfo->fill($request->validated());
126            $saved = $customerInfo->save() && $saved;
127
128            /** @var \App\Models\CustomerLogin */
129            $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
130            $customerLogin->fill($request->validated());
131            $saved = $customerLogin->save() && $saved;
132
133            if (!$saved) {
134                // @codeCoverageIgnoreStart
135                throw new CrmException('Api failed to update customer.');
136                // @codeCoverageIgnoreEnd
137            }
138        });
139
140        return new CustomerResource($service->brand, $customer);
141    }
142
143    /**
144     * Deletes customer information for a specific service.
145     *
146     * @param \App\Models\Service  $service
147     * @param \App\Models\Customer $customer
148     * @return \Illuminate\Http\JsonResponse
149     * @throws \App\Exceptions\Api\V4\CrmException If removing the customer off the DB failed.
150     */
151    public function destroy(Service $service, Customer $customer): JsonResponse
152    {
153        // * Make sure we are accessing a customer that belongs to our service.
154        $this->authorize('customerBelongsToService', $customer);
155
156        // TODO: Gestion avec mesBR.
157        /** @var \App\Models\CustomerInfo */
158        $customerInfo = $customer->info($service->brand, Customer::FIRST_OR_FAIL);
159        /** @var \App\Models\CustomerLogin */
160        $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
161
162        DB::transaction(function () use ($service, $customer, $customerLogin, $customerInfo) {
163            if (
164                $customerInfo->delete() === false ||
165                $customerLogin->delete() === false
166            ) {
167                // @codeCoverageIgnoreStart
168                throw new CrmException('Api failed to delete customer.');
169                // @codeCoverageIgnoreEnd
170            };
171
172            $customer->optInHistory()->whereHas('brand', function ($q) use ($service) {
173                $q->where('id', $service->brand_id);
174            })->delete();
175
176            // * Force loading real relation counts.
177            $customer->unsetRelation('logins');
178            $customer->unsetRelation('infos');
179            $logins = $customer->logins()->count();
180            $infos  = $customer->infos()->count();
181
182            // If customer is not associated with any brand then delete.
183            if (!$logins and !$infos) {
184                if ($customer->delete() === false) {
185                    // @codeCoverageIgnoreStart
186                    throw new CrmException('Api failed to update customer.');
187                    // @codeCoverageIgnoreEnd
188                }
189            }
190        });
191
192        return response()->json();
193    }
194
195    /**
196     * Authenticate the user.
197     *
198     * @param \App\Http\Requests\Api\V4\AuthenticateRequest $request
199     * @param \App\Models\Service                           $service
200     * @return \Illuminate\Http\Resources\Json\JsonResource
201     * @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::authFailed in case
202     *                                                  of wrong credentials.
203     * @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::customerNotActivated if
204     *                                                  customer account is not activated.
205     */
206    public function authenticate(AuthenticateRequest $request, Service $service): JsonResource
207    {
208        try {
209            /** @var \App\Models\Customer */
210            $customer = Customer::query()->where('email', $request->email)->firstOrFail();
211
212            /** @var \App\Models\CustomerLogin $customerLogin */
213            $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
214            if (!$customerLogin->passwordMatch($request->password)) {
215                throw new ApiErrorException(ApiError::authFailed);
216            }
217
218            if (!$customerLogin->status) {
219                throw new ApiErrorException(ApiError::customerNotActivated);
220            }
221
222            UpdateCustomerLastConnection::dispatch($customer, $customerLogin, now())
223                ->onConnection('database')->afterResponse();
224
225            return new CustomerResource($service->brand, $customer);
226        } catch (ModelNotFoundException $e) {
227            throw new ApiErrorException(ApiError::authFailed);
228        } //end try
229    }
230
231    /**
232     * Activate the account of the user.
233     *
234     * @param \App\Models\Customer $customer
235     * @param \App\Models\Service  $service
236     * @return \Illuminate\Http\JsonResponse
237     * @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::customerAlreadyActive
238     *                                                  if customer account is already active.
239     * @throws \App\Exceptions\Api\V4\CrmException If saving the customer to DB failed.
240     */
241    public function activateAccount(Customer $customer, Service $service): JsonResponse
242    {
243        // * Make sure we are accessing a customer that belongs to our service.
244        $this->authorize('customerBelongsToService', $customer);
245
246        /** @var \App\Models\CustomerLogin $login */
247        $login = $customer->login($service->brand, Customer::FIRST_OR_FAIL);
248
249        if ($login->status) {
250            throw new ApiErrorException(ApiError::customerAlreadyActive);
251        }
252
253        $login->status = true;
254        if (!$login->save()) {
255            // @codeCoverageIgnoreStart
256            throw new CrmException('Failed to save login');
257            // @codeCoverageIgnoreEnd
258        }
259        return response()->json();
260    }
261}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V4/OptinController.php.html b/tests/coverage/app/Http/Controllers/Api/V4/OptinController.php.html deleted file mode 100644 index 098ca94..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V4/OptinController.php.html +++ /dev/null @@ -1,294 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V4/OptinController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
19 / 19
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
OptinController
-
- 100.00% covered (success) -
-
-
100.00%
19 / 19
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 optin
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
 optoutWithHashcode
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
 changeOptin
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V4;
4
5use App\Enums\ApiError;
6use App\Exceptions\Api\V4\ApiErrorException;
7use App\Exceptions\Api\V4\CrmException;
8use App\Http\Controllers\Controller;
9use App\Http\Requests\Api\V4\BaseApiRequest;
10use App\Http\Requests\Api\V4\SingleOptinRequest;
11use App\Http\Requests\Api\V4\SingleOptinRemoveWithHashcodeRequest;
12use App\Models\CustomerInfo;
13use App\Models\Service;
14use Illuminate\Http\JsonResponse;
15use App\Models\SingleOptin;
16
17class OptinController extends Controller
18{
19    /**
20     * Creates a new Single optin or destroys it if exists.
21     *
22     * @param \App\Http\Requests\Api\V4\SingleOptinRequest $request
23     * @param \App\Models\Service                          $service
24     * @return \Illuminate\Http\JsonResponse
25     * @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::singleOptinCustomerExists
26     *                                                  if this email already has a full account.
27     * @throws \App\Exceptions\Api\V4\CrmException If the single optin could not be added or removed.
28     */
29    public function optin(SingleOptinRequest $request, Service $service): JsonResponse
30    {
31        if (CustomerInfo::getFromEmail($service->brand, $request->email)->exists()) {
32            throw new ApiErrorException(ApiError::singleOptinCustomerExists);
33        }
34
35        /** @var \App\Models\SingleOptin */
36        $singleOptin = SingleOptin::query()->where('email', $request->email)
37            ->whereHas('brand', function ($q) use ($service) {
38                $q->where('id', $service->brand->id);
39            })->firstOrNew();
40
41        if (!$this->changeOptin($service, $request, \boolval($request->opt_in), $singleOptin)) {
42            // @codeCoverageIgnoreStart
43            throw new CrmException('Api failed to update single optin.');
44            // @codeCoverageIgnoreEnd
45        }
46
47        return response()->json();
48    }
49
50    /**
51     * Creates a new Single optin or destroys it if exists using hashcode.
52     *
53     * @param \App\Http\Requests\Api\V4\SingleOptinRemoveWithHashcodeRequest $request
54     * @param \App\Models\Service                                            $service
55     * @return \Illuminate\Http\JsonResponse
56     * @throws \App\Exceptions\Api\V4\CrmException If the single optin could not be removed.
57     */
58    public function optoutWithHashcode(SingleOptinRemoveWithHashcodeRequest $request, Service $service): JsonResponse
59    {
60        /** @var \App\Models\SingleOptin */
61        $singleOptin = SingleOptin::query()->where('hashcode', $request->hashcode)
62            ->whereHas('brand', function ($q) use ($service) {
63                $q->whereId($service->brand->id);
64            })->firstOrFail();
65
66        if ($singleOptin and !$this->changeOptin($service, $request, \boolval($request->opt_in), $singleOptin)) {
67            // @codeCoverageIgnoreStart
68            throw new CrmException('Api failed to update single optin.');
69            // @codeCoverageIgnoreEnd
70        }
71
72        return response()->json();
73    }
74
75    /**
76     * Changes the optin state.
77     *
78     * @param \App\Models\Service                      $service
79     * @param \App\Http\Requests\Api\V4\BaseApiRequest $request
80     * @param boolean                                  $optin
81     * @param \App\Models\SingleOptin                  $singleOptin
82     * @return boolean Returns false in case of failure.
83     */
84    private function changeOptin(Service $service, BaseApiRequest $request, bool $optin, SingleOptin $singleOptin): bool
85    {
86        if ($optin) {
87            $singleOptin->fill($request->validated());
88            $singleOptin->brand()->associate($service->brand);
89            return $singleOptin->save();
90        }
91        return $singleOptin->delete() !== false;
92    }
93}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V4/QuestionController.php.html b/tests/coverage/app/Http/Controllers/Api/V4/QuestionController.php.html deleted file mode 100644 index 551feb3..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V4/QuestionController.php.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V4/QuestionController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionController
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 index
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 indexWithResponse
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 unAnsweredBy
-
- 100.00% covered (success) -
-
-
100.00%
9 / 9
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V4;
4
5use App\Http\Controllers\Controller;
6use App\Http\Resources\Api\V4\QuestionsResource;
7use App\Models\Answer;
8use App\Models\Customer;
9use App\Models\Question;
10use App\Models\Service;
11use Illuminate\Http\Resources\Json\JsonResource;
12use Illuminate\Http\Resources\Json\ResourceCollection;
13
14class QuestionController extends Controller
15{
16    /**
17     * Returns all service questions.
18     *
19     * @param \App\Models\Service $service
20     * @return \Illuminate\Http\Resources\Json\ResourceCollection
21     */
22    public function index(Service $service): ResourceCollection
23    {
24        return new QuestionsResource($service->brand->questions);
25    }
26
27    /**
28     * Returns all service questions with user answers for all of them.
29     *
30     * @param \App\Models\Service  $service
31     * @param \App\Models\Customer $customer
32     * @return \Illuminate\Http\Resources\Json\ResourceCollection
33     */
34    public function indexWithResponse(Service $service, Customer $customer): ResourceCollection
35    {
36        // * Make sure we are accessing a customer that belongs to our service.
37        $this->authorize('customerBelongsToService', $customer);
38
39        $customerAnswers = $customer->getAnswers($service);
40        return new QuestionsResource($service->brand->questions, $customerAnswers);
41    }
42
43    /**
44     * Returns all service questions that was not answered by a user.
45     *
46     * @param \App\Models\Service  $service
47     * @param \App\Models\Customer $customer
48     * @return \Illuminate\Http\Resources\Json\JsonResource
49     */
50    public function unAnsweredBy(Service $service, Customer $customer): JsonResource
51    {
52        // * Make sure we are accessing a customer that belongs to our service.
53        $this->authorize('customerBelongsToService', $customer);
54
55        $questions = Question::query()->whereHas('brand', function ($q) use ($service) {
56            $q->where('id', $service->brand->id);
57        })->whereDoesntHave('answers', function ($q) use ($customer) {
58            $q->whereIn('id', Answer::query()->whereHas('customers', function ($q) use ($customer) {
59                $q->where('id', $customer->id);
60            })->pluck('id'));
61        })->with('answers')->get();
62        return new QuestionsResource($questions);
63    }
64}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V4/StatsController.php.html b/tests/coverage/app/Http/Controllers/Api/V4/StatsController.php.html deleted file mode 100644 index 7990915..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V4/StatsController.php.html +++ /dev/null @@ -1,310 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V4/StatsController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
45 / 45
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
StatsController
-
- 100.00% covered (success) -
-
-
100.00%
45 / 45
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 brandStats
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 questionStats
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 answersByDays
-
- 100.00% covered (success) -
-
-
100.00%
33 / 33
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Api\V4;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Api\V4\GetBrandStatsRequest;
7use App\Http\Requests\Api\V4\GetQuestionStatsRequest;
8use App\Http\Resources\Api\V4\BrandStatsResource;
9use App\Http\Resources\Api\V4\QuestionStatsResource;
10use App\Models\BrandStat;
11use App\Models\CustomerAnswer;
12use App\Models\Question;
13use App\Models\Service;
14use Illuminate\Http\Resources\Json\ResourceCollection;
15use Illuminate\Support\Carbon;
16use Illuminate\Support\Collection;
17
18class StatsController extends Controller
19{
20    /**
21     * Get specific brand statistics.
22     *
23     * @param \App\Http\Requests\Api\V4\GetBrandStatsRequest $request
24     * @param \App\Models\Service                            $service
25     * @return \Illuminate\Http\Resources\Json\ResourceCollection
26     */
27    public function brandStats(GetBrandStatsRequest $request, Service $service): ResourceCollection
28    {
29        $stats = BrandStat::query()->whereDate('created_at', '>=', $request->start)
30            ->whereDate('created_at', '<=', $request->end)
31            ->whereBrandId($service->brand->id)->get();
32        return new BrandStatsResource($stats);
33    }
34
35    /**
36     * Get statistics for a specific question.
37     *
38     * @param \App\Http\Requests\Api\V4\GetQuestionStatsRequest $request
39     * @param \App\Models\Question                              $question
40     * @return \App\Http\Resources\Api\V4\QuestionStatsResource
41     */
42    public function questionStats(GetQuestionStatsRequest $request, Question $question): QuestionStatsResource
43    {
44        // * Make sure we are accessing a customer that belongs to our service.
45        $this->authorize('questionBelongsToService', $question);
46
47        $answers = $question->answers;
48        $start   = Carbon::parse($request->start);
49        $end     = Carbon::parse($request->end);
50
51        return new QuestionStatsResource(
52            $this->answersByDays($answers, $start, $end),
53            $question
54        );
55    }
56
57    /**
58     * Total réponses par dates.
59     *
60     * @param \Illuminate\Support\Collection $answers
61     * @param \Illuminate\Support\Carbon     $start
62     * @param \Illuminate\Support\Carbon     $end
63     * @return \Illuminate\Support\Collection
64     */
65    private function answersByDays(Collection $answers, Carbon $start, Carbon $end): Collection
66    {
67        // * Totalize by date all answers.
68        $answersByDays = CustomerAnswer::query()->whereDate('created_at', '>=', $start)
69            ->whereDate('created_at', '<=', $end)
70            ->whereIn('answer_id', $answers->pluck('id'))
71            ->get()->map(function ($custAnswer) {
72                return [
73                    'answer_id' => $custAnswer->answer_id,
74                    'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
75                ];
76            })->groupBy(['created_at', 'answer_id'])->map(function ($day) {
77                return $day->map(function ($custAnswers) {
78                    return $custAnswers->count();
79                });
80            });
81
82        do {
83            $currentDate = $start->isoFormat('YYYY-MM-DD');
84            /** @var \Illuminate\Support\Collection $answersByDays */
85            if (!$answersByDays->has($currentDate)) {
86                $answersByDays->put(
87                    $currentDate,
88                    $answers->mapWithKeys(function ($answer) {
89                        return [$answer->id => 0];
90                    })
91                );
92            } else {
93                $curentAnswers = $answersByDays->pull($currentDate);
94                $answersByDays->put(
95                    $currentDate,
96                    $answers->mapWithKeys(function ($answer) use ($curentAnswers) {
97                        return [$answer->id =>
98                        $curentAnswers->has($answer->id) ?
99                            $curentAnswers->get($answer->id) : 0];
100                    })
101                );
102            }
103
104            $start = $start->addDay();
105        } while ($start->lessThanOrEqualTo($end));
106
107        return $answersByDays;
108    }
109}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V4/dashboard.html b/tests/coverage/app/Http/Controllers/Api/V4/dashboard.html deleted file mode 100644 index a572a02..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V4/dashboard.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Controllers/Api/V4 - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/V4/index.html b/tests/coverage/app/Http/Controllers/Api/V4/index.html deleted file mode 100644 index 6d0df0a..0000000 --- a/tests/coverage/app/Http/Controllers/Api/V4/index.html +++ /dev/null @@ -1,291 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api/V4 - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
203 / 203
-
- 100.00% covered (success) -
-
-
100.00%
21 / 21
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
AnswerController.php
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiController.php
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ArcadiaController.php
-
- 100.00% covered (success) -
-
-
100.00%
40 / 40
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerController.php
-
- 100.00% covered (success) -
-
-
100.00%
80 / 80
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
OptinController.php
-
- 100.00% covered (success) -
-
-
100.00%
19 / 19
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionController.php
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
StatsController.php
-
- 100.00% covered (success) -
-
-
100.00%
45 / 45
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Controllers/Api/dashboard.html b/tests/coverage/app/Http/Controllers/Api/dashboard.html deleted file mode 100644 index 258973b..0000000 --- a/tests/coverage/app/Http/Controllers/Api/dashboard.html +++ /dev/null @@ -1,287 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Controllers/Api - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Api/index.html b/tests/coverage/app/Http/Controllers/Api/index.html deleted file mode 100644 index 6fd5e31..0000000 --- a/tests/coverage/app/Http/Controllers/Api/index.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Api - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
406 / 406
-
- 100.00% covered (success) -
-
-
100.00%
42 / 42
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
V2
-
- 100.00% covered (success) -
-
-
100.00%
203 / 203
-
- 100.00% covered (success) -
-
-
100.00%
21 / 21
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
V4
-
- 100.00% covered (success) -
-
-
100.00%
203 / 203
-
- 100.00% covered (success) -
-
-
100.00%
21 / 21
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- -
- - diff --git a/tests/coverage/app/Http/Controllers/Bo/ActivityLogsController.php.html b/tests/coverage/app/Http/Controllers/Bo/ActivityLogsController.php.html deleted file mode 100644 index 5a4e07e..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/ActivityLogsController.php.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/ActivityLogsController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 26
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ActivityLogsController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 26
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 show
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo;
4
5use App\Http\Controllers\Controller;
6use App\Models\ActivityLog;
7use App\Traits\Controllers\ChangesModelOrder;
8use App\Traits\Controllers\UpdateModelPublished;
9use Illuminate\Http\Request;
10
11class ActivityLogsController extends Controller
12{
13    use ChangesModelOrder;
14    use UpdateModelPublished;
15
16    /**
17     * Display a listing of the resource.
18     *
19     * @param \Illuminate\Http\Request $request
20     * @return \Illuminate\Contracts\View\View
21     */
22    public function index(Request $request): \Illuminate\Contracts\View\View
23    {
24        $this->authorize('isConceptor');
25        /** @var \Illuminate\Database\Eloquent\Builder $query */
26        $query = ActivityLog::query()->with('user');
27
28        /** @var string $search Search field */
29        $search = $request->search;
30        if ($search) {
31            $this->searchQuery(
32                $query,
33                $search,
34                null,
35                'model_class',
36            );
37        }
38        $searchFields = \implode(', ', [
39            trans('validation.custom.target'),
40        ]);
41
42        /** Sort columns with a query */
43        $this->sortQuery($query);
44
45        /** Custom pagination */
46        $activitylogModels = $this->paginate($query);
47
48        return view('bo.pages.activity_logs.index', compact('activitylogModels', 'search', 'searchFields'));
49    }
50
51    /**
52     * Show the form for editing the specified resource.
53     *
54     * @param App\Models\ActivityLog $activity_log
55     * @return \Illuminate\Contracts\View\View
56     */
57    public function show(ActivityLog $activity_log): \Illuminate\Contracts\View\View
58    {
59        $this->authorize('isConceptor');
60        $targetModelClass = $activity_log->model_class;
61        $targetModel      = $activity_log->model_class::where(
62            (new $targetModelClass())->getRouteKeyName(),
63            $activity_log->model_id
64        )->first();
65
66        return view('bo.pages.activity_logs.show', [
67            'activitylogModel' => $activity_log,
68            'targetModel'      => $targetModel,
69        ]);
70    }
71}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/AnswerController.php.html b/tests/coverage/app/Http/Controllers/Bo/AnswerController.php.html deleted file mode 100644 index 69df6ea..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/AnswerController.php.html +++ /dev/null @@ -1,428 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/AnswerController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 66
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
AnswerController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 66
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
110
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 store
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 edit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 destroy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Bo\Answers\StoreAnswerRequest;
7use App\Http\Requests\Bo\Answers\UpdateAnswerRequest;
8use App\Models\Answer;
9use App\Models\Question;
10use Illuminate\Http\Request;
11use Illuminate\Support\Facades\DB;
12use Illuminate\Support\Str;
13
14class AnswerController extends Controller
15{
16    /**
17     * Display a listing of the resource.
18     *
19     * @param \Illuminate\Http\Request $request
20     * @return \Illuminate\Contracts\View\View
21     */
22    public function index(Request $request): \Illuminate\Contracts\View\View
23    {
24        /** @var \App\Models\Question $questionModel */
25        $questionModel = $request->question;
26
27        /** @var \Illuminate\Database\Eloquent\Builder $answers */
28        $answers = Answer::query()->where('question_id', $questionModel->id);
29
30        if ($request->search) {
31            $this->searchQuery(
32                $answers,
33                $request->search,
34                null,
35                'answer',
36            );
37        }
38
39        $this->sortQuery($answers);
40        $searchFields = trans('Réponse');
41
42        $answerModels = $this->paginate($answers);
43
44        return view('bo.pages.answers.index', compact('answerModels', 'questionModel', 'searchFields'));
45    }
46
47    /**
48     * Show the form for creating a new resource.
49     *
50     * @param \Illuminate\Http\Request $request
51     * @param \App\Models\Answer       $answer
52     * @return \Illuminate\Contracts\View\View
53     */
54    public function create(Request $request, Answer $answer): \Illuminate\Contracts\View\View
55    {
56        /** @var \App\Models\Question $questionModel */
57        $questionModel = $request->question;
58
59        return view('bo.pages.answers.create', [
60            'answerModel' => $answer,
61            'questionModel' => $questionModel
62        ]);
63    }
64
65    /**
66     * Store a newly created resource in storage.
67     *
68     * @param \App\Http\Requests\Bo\Answers\StoreAnswerRequest $request
69     * @return \Illuminate\Http\RedirectResponse
70     */
71    public function store(StoreAnswerRequest $request): \Illuminate\Http\RedirectResponse
72    {
73        return DB::transaction(function () use ($request) {
74            $answer = new Answer();
75            $answer->fill($request->validated());
76            if ($answer->saveOrFail()) {
77                return redirect()
78                    ->route('bo.answers.edit', $answer)
79                    ->with('success', trans(
80                        ':model a été créé.',
81                        ['model' => Str::singular(trans('models.classes.answers'))]
82                    ));
83            }
84            return redirect()
85                ->back()
86                ->with('error', trans(
87                    ':model n\'a pas été créé.',
88                    ['model' => Str::singular(trans('models.classes.answers'))]
89                ));
90        });
91    }
92
93    /**
94     * Show the form for editing the specified resource.
95     *
96     * @param \App\Models\Question $question
97     * @param \App\Models\Answer   $answers
98     * @return \Illuminate\Contracts\View\View
99     */
100    public function edit(Question $question, Answer $answers): \Illuminate\Contracts\View\View
101    {
102        return view('bo.pages.answers.edit', [
103            'answerModel' => $answers,
104            'questionModel' => $question
105        ]);
106    }
107
108    /**
109     * Update a spacific resource in storage.
110     *
111     * @param \App\Http\Requests\Bo\Answers\UpdateAnswerRequest $request
112     * @param \App\Models\Question                              $question
113     * @param \App\Models\Answer                                $answer
114     * @return \Illuminate\Http\RedirectResponse
115     */
116    public function update(
117        UpdateAnswerRequest $request,
118        Question $question,
119        Answer $answer
120    ): \Illuminate\Http\RedirectResponse {
121        return DB::transaction(function () use ($request, $question, $answer) {
122            $answer->fill($request->validated());
123            if ($answer->saveOrFail()) {
124                return redirect()
125                    ->route('bo.questions.answers.edit', ['question' => $question, 'answer' => $answer])
126                    ->with('success', trans(
127                        ':model a été mis à jour.',
128                        ['model' => Str::singular(trans('models.classes.answers'))]
129                    ));
130            }
131            return redirect()
132                ->back()
133                ->with('error', trans(
134                    ':model n\'a pas été mis à jour.',
135                    ['model' => Str::singular(trans('models.classes.answers'))]
136                ));
137        });
138    }
139
140    /**
141     * Remove the specified resource from storage.
142     *
143     * @param \App\Models\Question $question
144     * @param \App\Models\Answer   $answer
145     * @return \Illuminate\Http\RedirectResponse
146     */
147    public function destroy(Question $question, Answer $answer): \Illuminate\Http\RedirectResponse
148    {
149        if ($answer->deleteOrFail()) {
150            return redirect()->route('bo.questions.answers.index', $question)
151                ->with('success', trans(
152                    ':model a été supprimé.',
153                    ['model' => Str::singular(trans('models.classes.answers'))]
154                ));
155        }
156        return redirect()->back()
157            ->with('error', trans(
158                ':model n\'a pas pu être supprimé.',
159                ['model' => Str::singular(trans('models.classes.answers'))]
160            ));
161    }
162}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/Auth/LoginController.php.html b/tests/coverage/app/Http/Controllers/Bo/Auth/LoginController.php.html deleted file mode 100644 index 1ba50bf..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/Auth/LoginController.php.html +++ /dev/null @@ -1,317 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/Auth/LoginController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
LoginController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 guard
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 showLoginForm
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 redirectTo
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 attemptLogin
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo\Auth;
4
5use App\Http\Controllers\Controller;
6use Illuminate\Contracts\Auth\StatefulGuard;
7use Illuminate\Contracts\View\View;
8use Illuminate\Foundation\Auth\AuthenticatesUsers;
9use Illuminate\Http\Request;
10use Illuminate\Support\Facades\Auth;
11
12class LoginController extends Controller
13{
14    use AuthenticatesUsers;
15
16    /**
17     * Create a new controller instance.
18     *
19     * @return void
20     */
21    public function __construct()
22    {
23        $this->middleware('guest:backend')->except('logout');
24    }
25
26    /**
27     * Get the guard to be used during authentication.
28     *
29     * @return \Illuminate\Contracts\Auth\StatefulGuard
30     */
31    protected function guard(): StatefulGuard
32    {
33        return Auth::guard('backend');
34    }
35
36    /**
37     * Show the application's login form.
38     *
39     * @return \Illuminate\Contracts\View\View
40     */
41    public function showLoginForm(): View
42    {
43        return view('bo.auth.login');
44    }
45
46    /**
47     * Where to redirect users after login.
48     *
49     * @return string
50     */
51    protected function redirectTo(): string
52    {
53        return response()->redirectToIntended()->getTargetUrl();
54    }
55
56    /**
57     * Attempt to log the user into the application.
58     *
59     * @param \Illuminate\Http\Request $request
60     * @return boolean
61     */
62    protected function attemptLogin(Request $request)
63    {
64        $credentials = $this->credentials($request);
65        // * Attempt login only using published users.
66        $credentials['published'] = true;
67        return $this->guard()->attempt(
68            $credentials,
69            $request->boolean('remember')
70        );
71    }
72}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/Auth/ResetPasswordController.php.html b/tests/coverage/app/Http/Controllers/Bo/Auth/ResetPasswordController.php.html deleted file mode 100644 index c120943..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/Auth/ResetPasswordController.php.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/Auth/ResetPasswordController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ResetPasswordController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 guard
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 redirectTo
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo\Auth;
4
5use App\Http\Controllers\Controller;
6use Illuminate\Contracts\Auth\StatefulGuard;
7use Illuminate\Foundation\Auth\ResetsPasswords;
8use Illuminate\Support\Facades\Auth;
9
10class ResetPasswordController extends Controller
11{
12    use ResetsPasswords;
13
14    /**
15     * Get the guard to be used during authentication.
16     *
17     * @return \Illuminate\Contracts\Auth\StatefulGuard
18     */
19    protected function guard(): StatefulGuard
20    {
21        return Auth::guard('backend');
22    }
23
24    /**
25     * Where to redirect users after login.
26     *
27     * @return string
28     */
29    protected function redirectTo(): string
30    {
31        return \route('bo.login');
32    }
33}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/Auth/dashboard.html b/tests/coverage/app/Http/Controllers/Bo/Auth/dashboard.html deleted file mode 100644 index a5dbf03..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/Auth/dashboard.html +++ /dev/null @@ -1,297 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Controllers/Bo/Auth - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

- -
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - -
MethodCoverage
__construct0%
guard0%
showLoginForm0%
redirectTo0%
attemptLogin0%
guard0%
redirectTo0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/Auth/index.html b/tests/coverage/app/Http/Controllers/Bo/Auth/index.html deleted file mode 100644 index 1b7abac..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/Auth/index.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/Auth - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
LoginController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ResetPasswordController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Controllers/Bo/BrandController.php.html b/tests/coverage/app/Http/Controllers/Bo/BrandController.php.html deleted file mode 100644 index fa39a3a..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/BrandController.php.html +++ /dev/null @@ -1,409 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/BrandController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 58
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BrandController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 58
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
90
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 store
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 edit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 jsonPaginate
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Bo\Brands\StoreBrandRequest;
7use App\Http\Requests\Bo\Brands\UpdateBrandRequest;
8use App\Models\Brand;
9use Illuminate\Database\Eloquent\Builder;
10use Illuminate\Http\Request;
11use Illuminate\Support\Facades\DB;
12use Illuminate\Support\Str;
13
14class BrandController extends Controller
15{
16    /**
17     * Display a listing of the resource.
18     *
19     * @param \Illuminate\Http\Request $request
20     * @return \Illuminate\Contracts\View\View
21     */
22    public function index(Request $request): \Illuminate\Contracts\View\View
23    {
24        /** @var \Illuminate\Database\Eloquent\Builder $query */
25        $query = Brand::query();
26
27        if ($request->search) {
28            $this->searchQuery(
29                $query,
30                $request->search,
31                null,
32                'name',
33            );
34        }
35
36        $this->sortQuery($query);
37        $searchFields = trans('Nom');
38
39        $query->withCount(['customerInfos', 'customerInfos as customer_infos_optin_count' => function (Builder $q) {
40            $q->where('opt_in', true);
41        }]);
42
43        $brandModels = $this->paginate($query);
44
45        return view('bo.pages.brands.index', compact('brandModels', 'searchFields'));
46    }
47
48    /**
49     * Show the form for creating a new resource.
50     *
51     * @param \App\Models\Brand $brands
52     * @return \Illuminate\Contracts\View\View
53     */
54    public function create(Brand $brands): \Illuminate\Contracts\View\View
55    {
56        return view('bo.pages.brands.create', [
57            'brandModel' => $brands
58        ]);
59    }
60
61    /**
62     * Store a newly created resource in storage.
63     *
64     * @param \App\Http\Requests\Brands\Bo\StoreBrandRequest $request
65     * @return \Illuminate\Http\RedirectResponse
66     */
67    public function store(StoreBrandRequest $request): \Illuminate\Http\RedirectResponse
68    {
69        return DB::transaction(function () use ($request) {
70            $brand = new Brand();
71            $brand->fill($request->validated());
72            if ($brand->saveOrFail()) {
73                return redirect()
74                    ->route('bo.brands.edit', $brand)
75                    ->with('success', trans(
76                        ':model a été créé.',
77                        ['model' => Str::singular(trans('models.classes.brands'))]
78                    ));
79            }
80            return redirect()
81                ->back()
82                ->with('error', trans(
83                    ':model n\'a pas été créé.',
84                    ['model' => Str::singular(trans('models.classes.brands'))]
85                ));
86        });
87    }
88
89    /**
90     * Show the form for editing the specified resource.
91     *
92     * @param \App\Models\Brand $brands
93     * @return \Illuminate\Contracts\View\View
94     */
95    public function edit(Brand $brands): \Illuminate\Contracts\View\View
96    {
97        return view('bo.pages.brands.edit', [
98            'brandModel' => $brands
99        ]);
100    }
101
102    /**
103     * Update a spacific resource in storage.
104     *
105     * @param \App\Http\Requests\Brands\Bo\UpdateBrandRequest $request
106     * @param \App\Models\Brand                               $brand
107     * @return \Illuminate\Http\RedirectResponse
108     */
109    public function update(UpdateBrandRequest $request, Brand $brand): \Illuminate\Http\RedirectResponse
110    {
111        return DB::transaction(function () use ($request, $brand) {
112            $brand->fill($request->validated());
113            if ($brand->saveOrFail()) {
114                return redirect()
115                    ->route('bo.brands.edit', $brand)
116                    ->with('success', trans(
117                        ':model a été mis à jour.',
118                        ['model' => Str::singular(trans('models.classes.brands'))]
119                    ));
120            }
121            return redirect()
122                ->back()
123                ->with('error', trans(
124                    ':model n\'a pas été mis à jour.',
125                    ['model' => Str::singular(trans('models.classes.brands'))]
126                ));
127        });
128    }
129
130    /**
131     * Store a newly created resource in storage.
132     *
133     * @return \Illuminate\Http\JsonResponse
134     */
135    public function jsonPaginate(): \Illuminate\Http\JsonResponse
136    {
137        return DB::transaction(function () {
138            /** @var \App\Models\Brand */
139            $brandModels = Brand::paginate(12);
140            return \response()->json($brandModels ?? 500);
141        });
142    }
143}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/CustomerController.php.html b/tests/coverage/app/Http/Controllers/Bo/CustomerController.php.html deleted file mode 100644 index 68bc5f1..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/CustomerController.php.html +++ /dev/null @@ -1,551 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/CustomerController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 164
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 164
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
992
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 60
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
182
 show
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 delete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
72
 export
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 exportSubmit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 67
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
72
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo;
4
5use App\Enums\CustomerExportType;
6use App\Http\Controllers\Controller;
7use App\Http\Requests\Bo\CustomerExport;
8use App\Models\Brand;
9use App\Models\Customer;
10use App\Models\CustomerInfo;
11use App\Models\CustomerLogin;
12use App\Models\SingleOptin;
13use Illuminate\Database\Eloquent\Builder;
14use Illuminate\Database\Query\JoinClause;
15use Illuminate\Http\Request;
16use Illuminate\Support\Carbon;
17use Illuminate\Support\Facades\DB;
18use Illuminate\Support\Facades\Schema;
19use Illuminate\Support\Facades\Session;
20use Illuminate\Support\Str;
21use League\Csv\Writer;
22use Symfony\Component\HttpFoundation\StreamedResponse;
23
24class CustomerController extends Controller
25{
26    /**
27     * View all customers.
28     *
29     * @param \Illuminate\Http\Request $request
30     * @return \Illuminate\Contracts\View\View
31     */
32    public function index(Request $request): \Illuminate\Contracts\View\View
33    {
34        $modelTable = (new Customer())->getTable();
35        $modelClass = Customer::class;
36        $brands     = Brand::query()->select('id', 'name')->get();
37        $columns    = ['customer_infos.lastname', 'customer_infos.firstname'];
38
39        // * Jointure pour pouvoir trier les colonnes.
40        /** @var \Illuminate\Database\Eloquent\Builder */
41        $query = CustomerInfo::query()->join('customer_logins', function (JoinClause $join) {
42            $join->on('customer_logins.brand_id', '=', 'customer_infos.brand_id')
43                ->on('customer_logins.customer_id', '=', 'customer_infos.customer_id');
44        })->join('customers', function (JoinClause $join) {
45            $join->on('customers.id', '=', 'customer_infos.customer_id');
46        })->join('brands', function (JoinClause $join) {
47            $join->on('brands.id', '=', 'customer_infos.brand_id');
48        });
49
50        if ($request->rst) {
51            Session::remove("crud.$modelTable.brand");
52            Session::remove("crud.$modelTable.search");
53            Session::remove("crud.$modelTable.sort_way");
54            Session::remove("crud.$modelTable.sort_col");
55        }
56
57        if (request()->brand or Session::has("crud.$modelTable.brand")) {
58            $brand = $request->brand ?? Session::get("crud.$modelTable.brand");
59            Session::put("crud.$modelTable.brand", $brand);
60            $query = $query->where('customer_infos.brand_id', $brand);
61        }
62
63        // * Search on crud Label column.
64        if ($request->search or Session::has("crud.$modelTable.search")) {
65            $search = $request->search ?? Session::get("crud.$modelTable.search");
66            Session::put("crud.$modelTable.search", $search);
67            $query->where(function ($q) use ($columns, $search) {
68                foreach ($columns as $column) {
69                    $q = $q->orWhere($column, 'LIKE', "%$search%");
70                }
71                $q = $q->orWhere('customers.email', 'LIKE', "%$search%");
72                $q = $q->orWhere('customer_logins.last_connection', 'LIKE', "%$search%");
73            });
74        }
75
76        // * Sort columns.
77        if ($request->sort_col) {
78            Session::put("crud.$modelTable.sort_col", $request->sort_col);
79        }
80        if ($request->sort_way) {
81            Session::put("crud.$modelTable.sort_way", $request->sort_way);
82        }
83
84        if (
85            Session::has("crud.$modelTable.sort_col") and
86            Session::has("crud.$modelTable.sort_way") and
87            (Schema::hasColumn($modelTable, Session::get("crud.$modelTable.sort_col")) or
88                in_array(Session::get("crud.$modelTable.sort_col"), [
89                    'brands.name',
90                    'customers.email',
91                    'customer_infos.firstname',
92                    'customer_infos.lastname',
93                    'customer_infos.opt_in',
94                    'customer_logins.last_connection',
95                    'customer_logins.status'
96                ]))
97        ) {
98            $query = $query->orderBy(
99                Session::get("crud.$modelTable.sort_col"),
100                Session::get("crud.$modelTable.sort_way")
101            );
102        }
103
104        $searchFields = trans('Email, Prénom, Nom');
105
106        $query->with(['customer', 'brand']);
107
108        /** @var \Illuminate\Pagination\AbstractPaginator */
109        $customerModels = $this->paginate($query);
110
111        return view('bo.pages.customers.index', compact(
112            'modelClass',
113            'modelTable',
114            'customerModels',
115            'brands',
116            'searchFields'
117        ));
118    }
119
120    /**
121     * Show a specific custmer.
122     *
123     * @param \App\Models\Customer $customer
124     * @param \App\Models\Brand    $brand
125     * @return \Illuminate\Contracts\View\View
126     */
127    public function show(Customer $customer, Brand $brand): \Illuminate\Contracts\View\View
128    {
129        $customerInfos = CustomerInfo::query()->where('customer_id', $customer->id)
130            ->where('brand_id', $brand->id)->firstOrFail();
131        $customerLogin = CustomerLogin::query()->where('customer_id', $customer->id)
132            ->where('brand_id', $brand->id)->first();
133
134        return view('bo.pages.customers.show', compact(
135            'customerInfos',
136            'customerLogin'
137        ));
138    }
139
140    /**
141     * Delete a specific customer info.
142     *
143     * @param \App\Models\Customer $customer
144     * @param \App\Models\Brand    $brand
145     * @return \Illuminate\Http\RedirectResponse
146     */
147    public function delete(Customer $customer, Brand $brand): \Illuminate\Http\RedirectResponse
148    {
149        try {
150            // TODO: Gestion avec mesBR.
151            /** @var \App\Models\CustomerInfo */
152            $customerInfo = $customer->info($brand, Customer::FIRST_OR_FAIL);
153            /** @var \App\Models\CustomerLogin */
154            $customerLogin = $customer->login($brand, Customer::FIRST_OR_FAIL);
155
156            DB::transaction(function () use (
157                $brand,
158                $customer,
159                $customerLogin,
160                $customerInfo
161            ) {
162                if (
163                    $customerInfo->delete() === false ||
164                    $customerLogin->delete() === false
165                ) {
166                    throw new \ErrorException('Api failed to delete customer.');
167                };
168
169                $customer->optInHistory()->whereHas('brand', function ($q) use ($brand) {
170                    $q->where('id', $brand->id);
171                })->delete();
172
173                $logins  = $customer->logins()->count();
174                $infos   = $customer->infos()->count();
175                $history = $customer->optInHistory()->count();
176
177                // If customer is not associated with any brand then delete.
178                if (!$logins and !$infos and !$history) {
179                    if ($customer->delete() === false) {
180                        throw new \ErrorException('Api failed to update customer.');
181                    }
182                }
183            });
184        } catch (\ErrorException $e) {
185            return redirect()->route('bo.customers.index')
186                ->with('error', trans('Le compte n\'a pas pu être supprimé.'));
187        } //end try
188
189        return redirect()->route('bo.customers.index')->with('warning', trans('Compte supprimé.'));
190    }
191
192    /**
193     * Show export the customers form.
194     *
195     * @return \Illuminate\Contracts\View\View
196     */
197    public function export(): \Illuminate\Contracts\View\View
198    {
199        $brands = Brand::all();
200        return view('bo.pages.customers.export', compact(
201            'brands'
202        ));
203    }
204
205    /**
206     * Exports customers following the requested export type.
207     *
208     * @param \App\Http\Requests\Bo\CustomerExport $request
209     * @return \Symfony\Component\HttpFoundation\StreamedResponse
210     * @throws \Exception If the request export type in not handled.
211     */
212    public function exportSubmit(CustomerExport $request): \Symfony\Component\HttpFoundation\StreamedResponse
213    {
214        $pagination = 2000;
215        $header     = '"lastname";"firstname";"email";"hashcode"';
216
217        $w = Writer::createFromString($header . PHP_EOL);
218        $w->setDelimiter(';');
219        $w->setEnclosure('"');
220        $w->setOutputBOM(Writer::BOM_UTF8);
221
222        $exportType = CustomerExportType::make(\intval($request->export_type));
223
224        // * We send the CSV using Symfony StreamedResponse.
225        $response = new StreamedResponse();
226        $response->headers->set('Content-Encoding', 'none');
227        $response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
228        $response->headers->set('Description', 'File Transfer');
229        $response->headers->set(
230            'Content-Disposition',
231            sprintf(
232                'attachment; filename="Export pour newsletter %s %s.csv"',
233                Carbon::now()->isoFormat('DD-MM-YYYY_HH-mm'),
234                Str::slug($exportType->label())
235            )
236        );
237
238        switch ($exportType) {
239            case CustomerExportType::both:
240                $continue = true;
241                // ! Continue
242            case CustomerExportType::customer:
243                $page = 1;
244                /** @var \Illuminate\Database\Eloquent\Builder $req */
245                $req   = CustomerInfo::query()->where('brand_id', $request->brand)
246                    ->where('opt_in', true);
247                $total = $req->count();
248                $pages = \ceil($total / $pagination);
249                do {
250                    /** @var \Illuminate\Pagination\LengthAwarePaginator $items */
251                    $items = $req->with('customer', function ($q) {
252                        $q->select(['id', 'email']);
253                    })->paginate(
254                        $pagination,
255                        ['lastname', 'firstname', 'hashcode', 'customer_id'],
256                        'page',
257                        $page
258                    );
259                    $items->map(function (CustomerInfo $customerInfo) use ($w) {
260                        $w->insertOne([
261                            'lastname' => $customerInfo->lastname,
262                            'firstname' => $customerInfo->firstname,
263                            'email' => $customerInfo->customer->email,
264                            'hashcode' => $customerInfo->hashcode
265                        ]);
266                    });
267                } while ($page++ <= $pages);
268                if (!isset($continue)) {
269                    break;
270                }
271                // ! Continue
272            case CustomerExportType::singleOptin:
273                SingleOptin::query()->whereHas('brand', function (Builder $q) use ($request) {
274                    $q->where('id', $request->brand);
275                })->get()->map(function (SingleOptin $singleOptin) use ($w) {
276                    $w->insertOne([
277                        'lastname' => '',
278                        'firstname' => '',
279                        'email' => $singleOptin->email,
280                        'hashcode' => $singleOptin->hashcode
281                    ]);
282                });
283                break;
284            default:
285                throw new \Exception(sprintf('Unhandled CustomerExportType %s', $exportType->label()));
286        } //end switch
287
288        /*
289            We create a callable to output the CSV in chunk
290            with Symfony StreamResponse you can flush the body content if necessary
291            see Symfony documentation for more information
292        */
293
294        // * The flush value should depend on your CSV size.
295        $flush_threshold = 1000;
296
297        $response->setCallback(function () use ($w, $flush_threshold) {
298            foreach ($w->chunk(1024) as $offset => $chunk) {
299                echo $chunk;
300                if ($offset % $flush_threshold === 0) {
301                    flush();
302                }
303            }
304        });
305        return $response;
306    }
307}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/DashboardController.php.html b/tests/coverage/app/Http/Controllers/Bo/DashboardController.php.html deleted file mode 100644 index a1e6e62..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/DashboardController.php.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/DashboardController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
DashboardController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo;
4
5use App\Http\Controllers\Controller;
6use Illuminate\Contracts\View\View;
7
8class DashboardController extends Controller
9{
10    /**
11     * Dashboard Page
12     *
13     * @return \Illuminate\Contracts\View\View
14     */
15    public function index(): View
16    {
17        return view('bo.pages.dashboard');
18    }
19}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/QuestionController.php.html b/tests/coverage/app/Http/Controllers/Bo/QuestionController.php.html deleted file mode 100644 index 48cb2df..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/QuestionController.php.html +++ /dev/null @@ -1,610 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/QuestionController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 130
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
QuestionController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 130
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
462
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 store
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 edit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 show
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 destroy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 export
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 exportSubmit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 55
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
72
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Bo\QuestionExport;
7use App\Http\Requests\Bo\Questions\StoreQuestionRequest;
8use App\Http\Requests\Bo\Questions\UpdateQuestionRequest;
9use App\Models\Brand;
10use App\Models\Question;
11use Carbon\Carbon;
12use Illuminate\Http\Request;
13use Illuminate\Support\Facades\DB;
14use Illuminate\Support\Str;
15use League\Csv\Writer;
16use Symfony\Component\HttpFoundation\StreamedResponse;
17
18class QuestionController extends Controller
19{
20    /**
21     * Display a listing of the resource.
22     *
23     * @param \Illuminate\Http\Request $request
24     * @return \Illuminate\Contracts\View\View
25     */
26    public function index(Request $request): \Illuminate\Contracts\View\View
27    {
28        /** @var \Illuminate\Database\Eloquent\Builder $query */
29        $query = Question::query();
30
31        if ($request->brand) {
32            $query = $query->where('brand_id', '=', $request->brand);
33        }
34        if ($request->search) {
35            $this->searchQuery(
36                $query,
37                $request->search,
38                null,
39                'question',
40            );
41        }
42
43        $this->sortQuery($query);
44        $searchFields = trans('Question');
45
46        $query->with(['brand', 'answers']);
47
48        /** @var \Illuminate\Pagination\AbstractPaginator */
49        $questionModels = $this->paginate($query);
50
51        return view('bo.pages.questions.index', compact('questionModels', 'searchFields'));
52    }
53
54    /**
55     * Show the form for creating a new resource.
56     *
57     * @param \App\Models\Question $question
58     * @return \Illuminate\Contracts\View\View
59     */
60    public function create(Question $question): \Illuminate\Contracts\View\View
61    {
62        $brandModels = Brand::all();
63
64        return view('bo.pages.questions.create', [
65            'questionModel' => $question,
66            'brandModels' => $brandModels
67        ]);
68    }
69
70    /**
71     * Store a newly created resource in storage.
72     *
73     * @param \App\Http\Requests\Questions\StoreQuestionRequest $request
74     * @return \Illuminate\Http\RedirectResponse
75     */
76    public function store(StoreQuestionRequest $request): \Illuminate\Http\RedirectResponse
77    {
78        return DB::transaction(function () use ($request) {
79            $question = new Question();
80            $question->fill($request->validated());
81            if ($question->saveOrFail()) {
82                return redirect()
83                    ->route('bo.questions.edit', $question)
84                    ->with('success', trans(
85                        ':model a été créé.',
86                        ['model' => Str::singular(trans('models.classes.questions'))]
87                    ));
88            }
89            return redirect()
90                ->back()
91                ->with('error', trans(
92                    ':model n\'a pas été créé.',
93                    ['model' => Str::singular(trans('models.classes.questions'))]
94                ));
95        });
96    }
97
98    /**
99     * Show the form for editing the specified resource.
100     *
101     * @param \App\Models\Question $question
102     * @return \Illuminate\Contracts\View\View
103     */
104    public function edit(Question $question): \Illuminate\Contracts\View\View
105    {
106        $brandModels = Brand::all();
107        $question->load('brand');
108
109        return view('bo.pages.questions.edit', [
110            'questionModel' => $question,
111            'brandModels' => $brandModels
112        ]);
113    }
114
115    /**
116     * Update a spacific resource in storage.
117     *
118     * @param \App\Http\Requests\Questions\UpdateQuestionRequest $request
119     * @param \App\Models\Question                               $question
120     * @return \Illuminate\Http\RedirectResponse
121     */
122    public function update(UpdateQuestionRequest $request, Question $question): \Illuminate\Http\RedirectResponse
123    {
124        return DB::transaction(function () use ($request, $question) {
125            $question->fill($request->validated());
126            if ($question->saveOrFail()) {
127                return redirect()
128                    ->route('bo.questions.edit', $question)
129                    ->with('success', trans(
130                        ':model a été mis à jour.',
131                        ['model' => Str::singular(trans('models.classes.questions'))]
132                    ));
133            }
134            return redirect()
135                ->back()
136                ->with('error', trans(
137                    ':model n\'a pas été mis à jour.',
138                    ['model' => Str::singular(trans('models.classes.questions'))]
139                ));
140        });
141    }
142
143    /**
144     * Show the specified resource.
145     *
146     * @param \App\Models\Question $question
147     * @return \Illuminate\Contracts\View\View
148     */
149    public function show(Question $question): \Illuminate\Contracts\View\View
150    {
151        return view('bo.pages.questions.show', [
152            'questionModel' => $question
153        ]);
154    }
155
156    /**
157     * Remove the specified resource from storage.
158     *
159     * @param \App\Models\Question $question
160     * @return \Illuminate\Http\RedirectResponse
161     */
162    public function destroy(Question $question): \Illuminate\Http\RedirectResponse
163    {
164        if ($question->deleteOrFail()) {
165            return redirect()->route('bo.questions.index')
166                ->with('success', trans(
167                    ':model a été supprimé.',
168                    ['model' => Str::singular(trans('models.classes.questions'))]
169                ));
170        }
171        return redirect()->back()
172            ->with('error', trans(
173                ':model n\'a pas pu être supprimé.',
174                ['model' => Str::singular(trans('models.classes.questions'))]
175            ));
176    }
177
178    /**
179     * Shows the question export form
180     *
181     * @return \Illuminate\Contracts\View\View
182     */
183    public function export(): \Illuminate\Contracts\View\View
184    {
185        $brands = Brand::all();
186        return view('bo.pages.questions.export', compact('brands'));
187    }
188
189    /**
190     * Exports questions as csv the requested export type
191     *
192     * @param \App\Http\Requests\QuestionExport $request
193     * @return \Symfony\Component\HttpFoundation\StreamedResponse
194     */
195    public function exportSubmit(QuestionExport $request): \Symfony\Component\HttpFoundation\StreamedResponse
196    {
197        $results = [];
198        /** @var \App\Models\Brand $brand */
199        $brand     = Brand::query()->where('id', $request->brand)->firstOrFail();
200        $questions = $brand->questions->load('answers');
201
202        foreach ($questions as $question) {
203            $answersCounts = DB::query()
204                ->selectRaw('count(*) as total, answer_id')
205                ->from('customer_answer')
206                ->whereIn('answer_id', $question->answers->pluck('id'))
207                ->groupBy('answer_id')
208                ->get()->keyBy('answer_id');
209
210            $results[$question->id] = [
211                'question' => $question->question,
212                'answers' => []
213            ];
214            foreach ($question->answers as $answer) {
215                $results[$question->id]['answers'][] =
216                    [
217                        "$answer->answer ",
218                        $answersCounts[$answer->id]->total ?? 0
219                    ];
220            }
221        }
222
223        $w = Writer::createFromString('');
224        $w->setDelimiter(';');
225        $w->setEnclosure('"');
226        $w->setOutputBOM(Writer::BOM_UTF8);
227
228        // * We send the CSV using Symfony StreamedResponse.
229        $response = new StreamedResponse();
230        $response->headers->set('Content-Encoding', 'none');
231        $response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
232        $response->headers->set('Description', 'File Transfer');
233        $response->headers->set(
234            'Content-Disposition',
235            sprintf(
236                'attachment; filename="Export pour newsletter %s %s.csv"',
237                Carbon::now()->isoFormat('DD-MM-YYYY_HH-mm'),
238                Str::slug($brand->name)
239            )
240        );
241
242        foreach ($results as $result) {
243            $w->insertOne([
244                'question' => $result['question'],
245            ]);
246            foreach ($result['answers'] as $answer) {
247                $w->insertOne($answer);
248            }
249            $w->insertOne([]);
250        }
251
252        // * Push empty line if nothing to export
253        if (empty($results)) {
254            $w->insertOne([
255                'Aucune question pour cette marque'
256            ]);
257        }
258
259        /*
260            We create a callable to output the CSV in chunk
261            with Symfony StreamResponse you can flush the body content if necessary
262            see Symfony documentation for more information
263        */
264
265        // * The flush value should depend on your CSV size.
266        $flush_threshold = 1000;
267
268        $response->setCallback(function () use ($w, $flush_threshold) {
269            foreach ($w->chunk(1024) as $offset => $chunk) {
270                echo $chunk;
271                if ($offset % $flush_threshold === 0) {
272                    flush();
273                }
274            }
275        });
276        return $response;
277    }
278}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/ServiceController.php.html b/tests/coverage/app/Http/Controllers/Bo/ServiceController.php.html deleted file mode 100644 index fc2ac42..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/ServiceController.php.html +++ /dev/null @@ -1,514 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/ServiceController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 83
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ServiceController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 83
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
210
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 store
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 19
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 edit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 show
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 destroy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 generateServicePassword
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Bo\GenerateServiceToken;
7use App\Http\Requests\Bo\Services\StoreServiceRequest;
8use App\Http\Requests\Bo\Services\UpdateServiceRequest;
9use App\Mail\ServiceCredentialRenewed;
10use App\Models\Brand;
11use App\Models\Service;
12use Illuminate\Http\Request;
13use Illuminate\Support\Facades\DB;
14use Illuminate\Support\Facades\Hash;
15use Illuminate\Support\Facades\Mail;
16use Illuminate\Support\Str;
17
18class ServiceController extends Controller
19{
20    /**
21     * Display a listing of the resource.
22     *
23     * @param \Illuminate\Http\Request $request
24     * @return \Illuminate\Contracts\View\View
25     */
26    public function index(Request $request): \Illuminate\Contracts\View\View
27    {
28        /** @var \Illuminate\Database\Eloquent\Builder $query */
29        $query = Service::query();
30
31        if ($request->brand) {
32            $query = $query->where('brand_id', '=', $request->brand);
33        }
34        if ($request->search) {
35            $this->searchQuery(
36                $query,
37                $request->search,
38                null,
39                'name',
40            );
41        }
42
43        $this->sortQuery($query);
44        $searchFields = trans('Nom');
45
46        $query->with(['brand']);
47
48        $serviceModels = $this->paginate($query);
49
50        return view('bo.pages.services.index', compact('serviceModels', 'searchFields'));
51    }
52
53    /**
54     * Show the form for creating a new resource.
55     *
56     * @param \App\Models\Service $service
57     * @return \Illuminate\Contracts\View\View
58     */
59    public function create(Service $service): \Illuminate\Contracts\View\View
60    {
61        $brandModels = Brand::all();
62
63        return view('bo.pages.services.create', [
64            'serviceModel' => $service,
65            'brandModels' => $brandModels
66        ]);
67    }
68
69    /**
70     * Store a newly created resource in storage.
71     *
72     * @param \App\Http\Requests\Bo\Services\StoreServiceRequest $request
73     * @return \Illuminate\Http\RedirectResponse
74     */
75    public function store(StoreServiceRequest $request): \Illuminate\Http\RedirectResponse
76    {
77        return DB::transaction(function () use ($request) {
78            $service = new Service();
79            $service->fill($request->validated());
80            $service->generateBearerToken();
81            $this->generateServicePassword($service);
82            if ($service->saveOrFail()) {
83                return redirect()
84                    ->route('bo.services.edit', $service)
85                    ->with('success', trans(
86                        ':model a été créé.',
87                        ['model' => Str::singular(trans('models.classes.services'))]
88                    ));
89            }
90            return redirect()
91                ->back()
92                ->with('error', trans(
93                    ':model n\'a pas été créé.',
94                    ['model' => Str::singular(trans('models.classes.services'))]
95                ));
96        });
97    }
98
99    /**
100     * Show the form for editing the specified resource.
101     *
102     * @param \App\Models\Service $service
103     * @return \Illuminate\Contracts\View\View
104     */
105    public function edit(Service $service): \Illuminate\Contracts\View\View
106    {
107        $brandModels = Brand::all();
108
109        return view('bo.pages.services.edit', [
110            'serviceModel' => $service,
111            'brandModels' => $brandModels
112        ]);
113    }
114
115    /**
116     * Update a spacific resource in storage.
117     *
118     * @param \App\Http\Requests\Services\Bo\UpdateServiceRequest $request
119     * @param \App\Models\Service                                 $service
120     * @return \Illuminate\Http\RedirectResponse
121     */
122    public function update(UpdateServiceRequest $request, Service $service): \Illuminate\Http\RedirectResponse
123    {
124        return DB::transaction(function () use ($request, $service) {
125            $service->fill($request->validated());
126            if ($service->saveOrFail()) {
127                return redirect()
128                    ->route('bo.services.edit', $service)
129                    ->with('success', trans(
130                        ':model a été mis à jour.',
131                        ['model' => Str::singular(trans('models.classes.services'))]
132                    ));
133            }
134            return redirect()
135                ->back()
136                ->with('error', trans(
137                    ':model n\'a pas été mis à jour.',
138                    ['model' => Str::singular(trans('models.classes.services'))]
139                ));
140        });
141    }
142
143    /**
144     * Show the specified resource.
145     *
146     * @param \App\Models\Service $service
147     * @return \Illuminate\Contracts\View\View
148     */
149    public function show(Service $service): \Illuminate\Contracts\View\View
150    {
151        return view('bo.pages.services.show', [
152            'serviceModel' => $service
153        ]);
154    }
155
156    /**
157     * Remove the specified resource from storage.
158     *
159     * @param \App\Models\Service $service
160     * @return \Illuminate\Http\RedirectResponse
161     */
162    public function destroy(Service $service): \Illuminate\Http\RedirectResponse
163    {
164        if ($service->deleteOrFail()) {
165            return redirect()->route('bo.services.index')
166                ->with('success', trans(
167                    ':model a été supprimé.',
168                    ['model' => Str::singular(trans('models.classes.services'))]
169                ));
170        }
171        return redirect()->back()
172            ->with('error', trans(
173                ':model n\'a pas pu être supprimé.',
174                ['model' => Str::singular(trans('models.classes.services'))]
175            ));
176    }
177
178    /**
179     * Regen service credentials.
180     *
181     * @param \App\Http\Requests\Bo\GenerateServiceToken $request
182     * @param \App\Models\Service                        $service
183     * @return \Illuminate\Http\RedirectResponse
184     */
185    // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed, Squiz.Commenting.FunctionComment.Missing
186    public function generateServicePassword(
187        Service $service,
188        GenerateServiceToken $request = null
189    ): \Illuminate\Http\RedirectResponse {
190        /** @var \App\Models\User $user */
191        $user = auth('backend')->user();
192
193        // * Special Condition for migration from v2 to v3.
194        $service->bearer_token = !Hash::needsRehash($service->bearer_token) ?
195            $service->generateBearerToken() : $service->bearer_token;
196
197        $bearerPwd = $service->generateBearerPassword();
198        $service->saveOrFail();
199        Mail::send(new ServiceCredentialRenewed($service, $user));
200        return back()
201            // phpcs:ignore Generic.Files.LineLength.TooLong
202            ->with('error', "ATTENTION : METTEZ À JOUR LE SITE ! \nNouveau token d'API de $service->name : '$service->bearer_token' et mot de passe '$bearerPwd'");
203    }
204}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/SingleOptinController.php.html b/tests/coverage/app/Http/Controllers/Bo/SingleOptinController.php.html deleted file mode 100644 index b0a44b5..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/SingleOptinController.php.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/SingleOptinController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
SingleOptinController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 destroy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo;
4
5use App\Http\Controllers\Controller;
6use App\Models\SingleOptin;
7use Illuminate\Database\Eloquent\Builder;
8use Illuminate\Http\Request;
9use Illuminate\Support\Str;
10
11class SingleOptinController extends Controller
12{
13    /**
14     * Display a listing of the resource.
15     *
16     * @param \Illuminate\Http\Request $request
17     * @return \Illuminate\Contracts\View\View
18     */
19    public function index(Request $request): \Illuminate\Contracts\View\View
20    {
21        /** @var \Illuminate\Database\Eloquent\Builder $query */
22        $query = SingleOptin::query();
23
24        if ($request->brand) {
25            $query = $query->whereHas('brand', function (Builder $q) use ($request) {
26                $q->where('id', $request->brand);
27            });
28        }
29        if ($request->search) {
30            $this->searchQuery(
31                $query,
32                $request->search,
33                null,
34                'email',
35            );
36        }
37
38        $this->sortQuery($query);
39        $searchFields = trans('E-mail');
40
41        $query->with(['brand']);
42
43        /** @var \Illuminate\Pagination\AbstractPaginator */
44        $singleoptinModels = $this->paginate($query);
45
46        return view('bo.pages.singleoptins.index', compact('singleoptinModels', 'searchFields'));
47    }
48
49    /**
50     * Remove the specified resource from storage.
51     *
52     * @param \App\Models\SingleOptin $singleoptin
53     * @return \Illuminate\Http\RedirectResponse
54     */
55    public function destroy(SingleOptin $singleoptin): \Illuminate\Http\RedirectResponse
56    {
57        if ($singleoptin->deleteOrFail()) {
58            return redirect()->route('bo.single_optins.index')
59                ->with('success', trans(
60                    ':model a été supprimé.',
61                    ['model' => Str::singular(trans('models.classes.singleoptins'))]
62                ));
63        }
64        return redirect()->back()
65            ->with('error', trans(
66                ':model n\'a pas pu être supprimé.',
67                ['model' => Str::singular(trans('models.classes.singleoptins'))]
68            ));
69    }
70}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/StatsController.php.html b/tests/coverage/app/Http/Controllers/Bo/StatsController.php.html deleted file mode 100644 index 2cf718d..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/StatsController.php.html +++ /dev/null @@ -1,441 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/StatsController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 101
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatsController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 101
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
156
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 viewStatsByBrand
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 exportByBrandCsv
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 27
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 viewByQuestion
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 exportByQuestionCsv
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 answersByDays
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 33
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Bo\StatsByBrandRequest;
7use App\Http\Requests\Bo\StatsByQuestionRequest;
8use App\Models\Brand;
9use App\Models\BrandStat;
10use App\Models\CustomerAnswer;
11use App\Models\Question;
12use Illuminate\Support\Carbon;
13use Illuminate\Support\Collection;
14use Illuminate\Support\Facades\Schema;
15use League\Csv\Writer;
16
17class StatsController extends Controller
18{
19    /**
20     * Shows stats by brand.
21     *
22     * @param \App\Http\Requests\Bo\StatsByBrandRequest $request
23     * @return \Illuminate\Http\Response
24     */
25    public function viewStatsByBrand(StatsByBrandRequest $request)
26    {
27        $stats = null;
28        if ($request->post()) {
29            $stats = BrandStat::query()->whereDate('created_at', '>=', $request->start)
30                ->whereDate('created_at', '<=', $request->end)
31                ->whereBrandId($request->brand)->get();
32        }
33        return view('bo.pages.stats.view-stats-by-brands', \compact('stats'));
34    }
35
36    /**
37     * Exports stats by brand as a csv file.
38     *
39     * @param \App\Http\Requests\Bo\StatsByBrandRequest $request
40     * @return \Illuminate\Http\Response
41     */
42    public function exportByBrandCsv(StatsByBrandRequest $request): \Illuminate\Http\Response
43    {
44        $brand = Brand::query()->findOrFail($request->brand);
45        $stats = BrandStat::query()->with('brand')->whereDate('created_at', '>=', $request->start)
46            ->whereDate('created_at', '<=', $request->end)
47            ->whereBrandId($request->brand)->get();
48
49        $columns = collect(Schema::getColumnListing((new BrandStat())->getTable()))
50            ->filter(function ($value) {
51                return !in_array($value, ['created_at', 'brand_id']);
52            })->all();
53
54        $header = '"date";"marque";' . implode(';', $columns);
55
56        $w = Writer::createFromString($header . PHP_EOL);
57        $w->setDelimiter(';');
58        $w->setEnclosure('"');
59        $w->setOutputBOM(Writer::BOM_UTF8);
60
61        foreach ($stats as $stat) {
62            $cols = [
63                $stat->created_at->isoFormat('YYYY-MM-DD'),
64                $stat->brand->name
65            ];
66            foreach ($columns as $colname) {
67                $cols[] = $stat->{$colname};
68            }
69            $w->insertOne($cols);
70        }
71        return response((string)$w, 200, [
72            'Content-Encoding' => 'none',
73            'Content-Type' => 'text/csv; charset=UTF-8',
74            // phpcs:ignore Generic.Files.LineLength.TooLong
75            'Content-Disposition' => "attachment; filename=\"Statistiques du $request->start au $request->end pour $brand->name.csv\"",
76            'Content-Description' => 'File Transfer',
77        ]);
78    }
79
80    /**
81     * Views stats for a specific question.
82     *
83     * @param \App\Http\Requests\Bo\StatsByQuestionRequest $request
84     * @return \Illuminate\Contracts\View\View
85     */
86    public function viewByQuestion(StatsByQuestionRequest $request): \Illuminate\Contracts\View\View
87    {
88        $question      = null;
89        $answers       = null;
90        $answersByDays = null;
91        if ($request->post()) {
92            $question = Question::query()->findOrFail($request->question);
93            $answers  = $question->answers;
94            $start    = Carbon::parse($request->start);
95            $end      = Carbon::parse($request->end);
96
97            $answersByDays = $this->answersByDays($answers, $start, $end);
98        }
99
100        return view('bo.pages.stats.view-stats-by-questions', \compact('question', 'answers', 'answersByDays'));
101    }
102
103    /**
104     * Exports stats for a specific question as csv.
105     *
106     * @param \App\Http\Requests\Bo\StatsByQuestionRequest $request
107     * @return \Illuminate\Http\Response
108     */
109    public function exportByQuestionCsv(StatsByQuestionRequest $request): \Illuminate\Http\Response
110    {
111        $question = Question::query()->findOrFail($request->question);
112        $answers  = $question->answers;
113        $start    = Carbon::parse($request->start);
114        $end      = Carbon::parse($request->end);
115
116        $answersByDays = $this->answersByDays($answers, $start, $end);
117
118        $header = '"date";' . implode(';', $answers->map(function ($answer) {
119            return "\"$answer->answer\"";
120        })->all());
121
122        $w = Writer::createFromString($header . PHP_EOL);
123        $w->setDelimiter(';');
124        $w->setEnclosure('"');
125        $w->setOutputBOM(Writer::BOM_UTF8);
126
127        foreach ($answersByDays as $day => $dayAnswers) {
128            $w->insertOne(array_merge(
129                [
130                    $day
131                ],
132                $dayAnswers->values()->all()
133            ));
134        }
135        return response((string)$w, 200, [
136            'Content-Encoding' => 'none',
137            'Content-Type' => 'text/csv; charset=UTF-8',
138            // phpcs:ignore Generic.Files.LineLength.TooLong
139            'Content-Disposition' => "attachment; filename=\"Statistiques du $request->start au $request->end pour $question->question.csv\"",
140            'Content-Description' => 'File Transfer',
141        ]);
142    }
143
144    /**
145     * Makes a collection of total users answers by day.
146     *
147     * @param \Illuminate\Support\Collection $answers A collection of Answer.
148     * @param \Illuminate\Support\Carbon     $start   The wanted start period.
149     * @param \Illuminate\Support\Carbon     $end     The wanted end period.
150     * @return \Illuminate\Support\Collection A collection with date as Y_m_d index
151     *                                        with array of answers and their total.
152     */
153    private function answersByDays(Collection $answers, Carbon $start, Carbon $end): \Illuminate\Support\Collection
154    {
155        // * Totalize by date all answers.
156        $answersByDays = CustomerAnswer::query()->whereDate('created_at', '>=', $start)
157            ->whereDate('created_at', '<=', $end)
158            ->whereIn('answer_id', $answers->pluck('id'))
159            ->get()->map(function ($custAnswer) {
160                return [
161                    'answer_id' => $custAnswer->answer_id,
162                    'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
163                ];
164            })->groupBy(['created_at', 'answer_id'])->map(function ($day) {
165                return $day->map(function ($custAnswers) {
166                    return $custAnswers->count();
167                });
168            });
169
170        do {
171            $currentDate = $start->isoFormat('YYYY-MM-DD');
172            /** @var \Illuminate\Support\Collection $answersByDays */
173            if (!$answersByDays->has($currentDate)) {
174                $answersByDays->put(
175                    $currentDate,
176                    $answers->mapWithKeys(function ($answer) {
177                        return [$answer->answer => 0];
178                    })
179                );
180            } else {
181                $curentAnswers = $answersByDays->pull($currentDate);
182                $answersByDays->put(
183                    $currentDate,
184                    $answers->mapWithKeys(function ($answer) use ($curentAnswers) {
185                        return [$answer->answer =>
186                        $curentAnswers->has($answer->id) ?
187                            $curentAnswers->get($answer->id) : 0];
188                    })
189                );
190            }
191
192            $start = $start->addDay();
193        } while ($start->lessThanOrEqualTo($end));
194
195        return $answersByDays;
196    }
197}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/UsersController.php.html b/tests/coverage/app/Http/Controllers/Bo/UsersController.php.html deleted file mode 100644 index 435ff3b..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/UsersController.php.html +++ /dev/null @@ -1,479 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo/UsersController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 59
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UsersController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 59
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
156
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 21
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 store
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 edit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 destroy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 duplicate
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers\Bo;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Bo\Users\StoreUserRequest;
7use App\Http\Requests\Bo\Users\UpdateUserRequest;
8use App\Models\User;
9use App\Traits\Controllers\UpdateModelPublished;
10use Illuminate\Http\Request;
11use Illuminate\Support\Facades\DB;
12use Illuminate\Support\Str;
13
14class UsersController extends Controller
15{
16    use UpdateModelPublished;
17
18    /**
19     * Create the controller instance.
20     */
21    public function __construct()
22    {
23        $this->authorizeResource(User::class);
24    }
25
26    /**
27     * Display a listing of the resource.
28     *
29     * @param \Illuminate\Http\Request $request
30     * @return \Illuminate\Contracts\View\View
31     */
32    public function index(Request $request): \Illuminate\Contracts\View\View
33    {
34        /** @var \Illuminate\Database\Eloquent\Builder $userModels */
35        $userModels = User::query();
36
37        /** @var string $search Search field */
38        $search = $request->search;
39        if ($search) {
40            $this->searchQuery(
41                $userModels,
42                $search,
43                null,
44                'first_name',
45                'last_name',
46                'email',
47                'role',
48            );
49        }
50        $searchFields = \implode(', ', [
51            trans('validation.attributes.first_name'),
52            trans('validation.attributes.last_name'),
53            trans('validation.attributes.email'),
54            trans('validation.attributes.role'),
55        ]);
56
57        /** Sort columns with a query */
58        $this->sortQuery($userModels);
59
60        /** Custom pagination */
61        $userModels = $this->paginate($userModels);
62
63        return view('bo.pages.users.index', compact('userModels', 'search', 'searchFields'));
64    }
65
66
67    /**
68     * Show the form for creating a new resource.
69     *
70     * @param \App\Models\User $user
71     * @return \Illuminate\Contracts\View\View
72     */
73    public function create(User $user): \Illuminate\Contracts\View\View
74    {
75        return view('bo.pages.users.create', ['userModel' => $user]);
76    }
77
78    /**
79     * Store a newly created resource in storage.
80     *
81     * @param \App\Http\Requests\Bo\Users\StoreUserRequest $request
82     * @return \Illuminate\Http\RedirectResponse
83     */
84    public function store(StoreUserRequest $request): \Illuminate\Http\RedirectResponse
85    {
86        return DB::transaction(function () use ($request) {
87            $user = new User();
88            $user->fill($request->validated());
89
90            if ($user->saveOrFail()) {
91                return redirect()->route('bo.users.edit', $user)
92                    ->with('success', __('crud.messages.has_been_created', [
93                        'model' => Str::ucfirst(__('models.classes.user'))
94                    ]));
95            }
96            return redirect()->back()
97                ->with('error', __('crud.messages.cannot_be_created', [
98                    'model' => Str::ucfirst(__('models.classes.user'))
99                ]));
100        });
101    }
102
103    /**
104     * Show the form for editing the specified resource.
105     *
106     * @param App\Models\User $user
107     * @return \Illuminate\Contracts\View\View
108     */
109    public function edit(User $user): \Illuminate\Contracts\View\View
110    {
111        return view('bo.pages.users.edit', ['userModel' => $user]);
112    }
113
114    /**
115     * Update the specified resource in storage.
116     *
117     * @param \App\Http\Requests\Bo\Users\UpdateUserRequest $request
118     * @param \App\Models\User                              $user
119     * @return \Illuminate\Http\RedirectResponse
120     */
121    public function update(UpdateUserRequest $request, User $user): \Illuminate\Http\RedirectResponse
122    {
123        return DB::transaction(function () use ($request, $user) {
124            $user->fill($request->validated());
125
126            if ($user->saveOrFail()) {
127                return redirect()->route('bo.users.edit', $user)
128                    ->with('success', __('crud.messages.has_been_updated', [
129                        'model' => Str::ucfirst(__('models.classes.user'))
130                    ]));
131            }
132            return redirect()->route('bo.users.edit', $user)
133                ->with('error', __('crud.messages.cannot_be_updated', [
134                    'model' => Str::ucfirst(__('models.classes.user'))
135                ]));
136        });
137    }
138
139    /**
140     * Remove the specified resource from storage.
141     *
142     * @param \App\Models\User $user
143     * @return \Illuminate\Http\RedirectResponse
144     */
145    public function destroy(User $user): \Illuminate\Http\RedirectResponse
146    {
147        if ($user->deleteOrFail()) {
148            return redirect()->route('bo.users.index')
149                ->with('success', __('crud.messages.has_been_deleted', [
150                    'model' => Str::ucfirst(__('models.classes.user'))
151                ]));
152        }
153        return redirect()->back()
154            ->with('error', __('crud.messages.cannot_be_deleted', [
155                'model' => Str::ucfirst(__('models.classes.user'))
156            ]));
157    }
158
159    /**
160     * Duplicate the specified resource.
161     *
162     * @param \App\Models\User $user
163     * @return \Illuminate\Contracts\View\View
164     */
165    public function duplicate(User $user): \Illuminate\Contracts\View\View
166    {
167        return $this->create($user->replicate());
168    }
169}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/dashboard.html b/tests/coverage/app/Http/Controllers/Bo/dashboard.html deleted file mode 100644 index 6210948..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/dashboard.html +++ /dev/null @@ -1,399 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Controllers/Bo - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- -
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

- -
- -
- -
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Bo/index.html b/tests/coverage/app/Http/Controllers/Bo/index.html deleted file mode 100644 index c9664e7..0000000 --- a/tests/coverage/app/Http/Controllers/Bo/index.html +++ /dev/null @@ -1,402 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Bo - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 728
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 59
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
Auth
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
ActivityLogsController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 26
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
AnswerController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 66
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BrandController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 58
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 164
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
DashboardController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
QuestionController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 130
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ServiceController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 83
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
SingleOptinController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatsController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 101
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UsersController.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 59
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Controllers/BrandController.php.html b/tests/coverage/app/Http/Controllers/BrandController.php.html deleted file mode 100644 index fc0f95a..0000000 --- a/tests/coverage/app/Http/Controllers/BrandController.php.html +++ /dev/null @@ -1,408 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/BrandController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 58
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BrandController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 58
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
90
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 store
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 edit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 jsonPaginate
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\Brands\StoreBrandRequest;
7use App\Http\Requests\Brands\UpdateBrandRequest;
8use App\Models\Brand;
9use Illuminate\Database\Eloquent\Builder;
10use Illuminate\Http\Request;
11use Illuminate\Support\Facades\DB;
12use Illuminate\Support\Str;
13
14class BrandController extends Controller
15{
16    /**
17     * Display a listing of the resource.
18     *
19     * @param \Illuminate\Http\Request $request
20     * @return \Illuminate\Contracts\View\View
21     */
22    public function index(Request $request): \Illuminate\Contracts\View\View
23    {
24        /** @var \Illuminate\Database\Eloquent\Builder $query */
25        $query = Brand::query();
26
27        if ($request->search) {
28            $this->searchQuery(
29                $query,
30                $request->search,
31                null,
32                'name',
33            );
34        }
35
36        $this->sortQuery($query);
37        $searchFields = trans('Nom');
38
39        $query->withCount(['customerInfos', 'customerInfos as customer_infos_optin_count' => function (Builder $q) {
40            $q->where('opt_in', true);
41        }]);
42
43        $brandModels = $query->paginate(12);
44
45        return view('brands.index', compact('brandModels', 'searchFields'));
46    }
47
48    /**
49     * Show the form for creating a new resource.
50     *
51     * @param \App\Models\Brand $brands
52     * @return \Illuminate\Contracts\View\View
53     */
54    public function create(Brand $brands): \Illuminate\Contracts\View\View
55    {
56        return view('brands.create', [
57            'brandModel' => $brands
58        ]);
59    }
60
61    /**
62     * Store a newly created resource in storage.
63     *
64     * @param \App\Http\Requests\Brands\StoreBrandRequest $request
65     * @return \Illuminate\Http\RedirectResponse
66     */
67    public function store(StoreBrandRequest $request): \Illuminate\Http\RedirectResponse
68    {
69        return DB::transaction(function () use ($request) {
70            $brand = new Brand();
71            $brand->fill($request->validated());
72            if ($brand->saveOrFail()) {
73                return redirect()
74                    ->route('brands.edit', $brand)
75                    ->with('success', trans(
76                        ':model a été créé.',
77                        ['model' => Str::singular(trans('models.classes.brands'))]
78                    ));
79            }
80            return redirect()
81                ->back()
82                ->with('error', trans(
83                    ':model n\'a pas été créé.',
84                    ['model' => Str::singular(trans('models.classes.brands'))]
85                ));
86        });
87    }
88
89    /**
90     * Show the form for editing the specified resource.
91     *
92     * @param \App\Models\Brand $brands
93     * @return \Illuminate\Contracts\View\View
94     */
95    public function edit(Brand $brands): \Illuminate\Contracts\View\View
96    {
97        return view('brands.edit', [
98            'brandModel' => $brands
99        ]);
100    }
101
102    /**
103     * Update a spacific resource in storage.
104     *
105     * @param \App\Http\Requests\Brands\UpdateBrandRequest $request
106     * @param \App\Models\Brand                            $brand
107     * @return \Illuminate\Http\RedirectResponse
108     */
109    public function update(UpdateBrandRequest $request, Brand $brand): \Illuminate\Http\RedirectResponse
110    {
111        return DB::transaction(function () use ($request, $brand) {
112            $brand->fill($request->validated());
113            if ($brand->saveOrFail()) {
114                return redirect()
115                    ->route('brands.edit', $brand)
116                    ->with('success', trans(
117                        ':model a été mis à jour.',
118                        ['model' => Str::singular(trans('models.classes.brands'))]
119                    ));
120            }
121            return redirect()
122                ->back()
123                ->with('error', trans(
124                    ':model n\'a pas été mis à jour.',
125                    ['model' => Str::singular(trans('models.classes.brands'))]
126                ));
127        });
128    }
129
130    /**
131     * Store a newly created resource in storage.
132     *
133     * @return \Illuminate\Http\JsonResponse
134     */
135    public function jsonPaginate(): \Illuminate\Http\JsonResponse
136    {
137        return DB::transaction(function () {
138            /** @var \App\Models\Brand */
139            $brandModels = Brand::paginate(12);
140            return \response()->json($brandModels ?? 500);
141        });
142    }
143}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/Controller.php.html b/tests/coverage/app/Http/Controllers/Controller.php.html deleted file mode 100644 index d81fe49..0000000 --- a/tests/coverage/app/Http/Controllers/Controller.php.html +++ /dev/null @@ -1,496 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/Controller.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 101
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Controller
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 101
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
1332
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 searchQuery
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
 searchOnFields
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 31
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
90
 getSearchValue
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 sortQuery
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 29
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
182
 paginate
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 setTheme
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Enums\Pagination\ItemsPerPaginationEnum;
6use App\Enums\Theme\BootstrapThemeEnum;
7use App\Lib\Helpers\ToolboxHelper;
8use Illuminate\Database\Eloquent\Builder;
9use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
10use Illuminate\Foundation\Validation\ValidatesRequests;
11use Illuminate\Http\Request;
12use Illuminate\Routing\Controller as BaseController;
13use Illuminate\Support\Facades\Cache;
14use Illuminate\Support\Facades\Schema;
15use Illuminate\Support\Facades\Session;
16use Illuminate\Support\Str;
17
18class Controller extends BaseController
19{
20    use AuthorizesRequests;
21    use ValidatesRequests;
22
23    /**
24     * Build Search query on specified fields
25     * splitting search into words or using whole sentence
26     *
27     * @param \Illuminate\Database\Eloquent\Builder $query       The eloquent query builder.
28     * @param string                                $search      The query string.
29     * @param callable                              $searchQuery The query string.
30     * @param string                                ...$fields   Either a simple array or a string
31     *                                                           in case of a string the two fields
32     *                                                           would be concatenate to make the search.
33     * @return \Illuminate\Database\Eloquent\Builder
34     */
35    protected function searchQuery(
36        Builder $query,
37        string $search,
38        callable $searchQuery = null,
39        string ...$fields
40    ): \Illuminate\Database\Eloquent\Builder {
41        if (count($fields)) {
42            // Search using words.
43            $words = explode(' ', $search);
44            $query->where(function ($query) use ($searchQuery, $words, $search, $fields) {
45                foreach ($words as $word) {
46                    if (!strlen($word)) {
47                        continue;
48                    }
49                    $this->searchOnFields($query, $word, $fields);
50                } //end foreach
51                // Search whole using whole sentence.
52                $this->searchOnFields($query, $search, $fields);
53                if ($searchQuery) {
54                    $searchQuery($query);
55                }
56            });
57        } //end if
58        return $query;
59    }
60
61    /**
62     * Build query search on all fields
63     *
64     * @param \Illuminate\Database\Eloquent\Builder $query
65     * @param string                                $search
66     * @param array                                 $fields
67     * @return \Illuminate\Database\Eloquent\Builder
68     */
69    private function searchOnFields(
70        Builder $query,
71        string $search,
72        array $fields
73    ): \Illuminate\Database\Eloquent\Builder {
74        $table = $query->getModel()->getTable();
75        foreach ($fields as $field) {
76            $field = str_replace('?', '\?', $field);
77            if (is_array($field)) {
78                $query->orWhereRaw(
79                    sprintf("UPPER(CONCAT(%s)) LIKE UPPER(?)", collect($field)->map(function ($q) use ($table) {
80                        return "`$table`.`$q`";
81                    })->implode(', \' \', ')),
82                    ['%' . htmlspecialchars($search) . '%']
83                );
84                return $query;
85            }
86            // Get models woth enum's label.
87            if (is_array($this->getSearchValue($query, $search, $field))) {
88                foreach ($this->getSearchValue($query, $search, $field) as $array) {
89                    $query->orWhereRaw(
90                        "UPPER(`$table`.`$field`) LIKE UPPER(?)",
91                        ['%' . htmlspecialchars($array->value) . '%']
92                    );
93                }
94                return $query;
95            }
96            // Get models with relation's name/label.
97            if (Str::endsWith($field, '_id') && $query->getModel()->has(Str::remove('_id', $field))) {
98                $query->orWhereHas(Str::remove('_id', $field), function ($queryRelation) use ($field, $search) {
99                    if (Schema::hasColumn(Str::remove('_id', $field) . 's', 'name')) {
100                        $queryRelation->where('name', 'like', '%' . $search . '%');
101                    } elseif (Schema::hasColumn(Str::remove('_id', $field) . 's', 'label')) {
102                        $queryRelation->where('label', 'like', '%' . $search . '%');
103                    }
104                });
105                return $query;
106            }
107            $query->orWhereRaw(
108                "UPPER(`$table`.`$field`) LIKE UPPER(?)",
109                ['%' . htmlspecialchars($this->getSearchValue($query, $search, $field)) . '%']
110            );
111        } //end foreach
112        return $query;
113    }
114
115    /**
116     * Get the search value (on string or Enum).
117     *
118     * @param \Illuminate\Database\Eloquent\Builder $query
119     * @param string                                $search
120     * @param string                                $field
121     * @return string|array
122     */
123    protected function getSearchValue(Builder $query, string $search, string $field): string|array
124    {
125        if (
126            count($query->getModel()->getCasts()) and // Check if the model has casts.
127            isset($query->getModel()->getCasts()[$field]) and // Check if there is cast about specific field.
128            enum_exists($query->getModel()->getCasts()[$field]) // Check if the cast is an enum.
129        ) {
130            $cases = collect($query->getModel()->getCasts()[$field]::toArray());
131            $enum  = $cases->filter(function ($item) use ($search) {
132                return preg_match('/' . Str::lower($search) . '/', Str::lower($item->label));
133            });
134            return $enum->toArray();
135        } else {
136            return $search;
137        }
138    }
139
140    /**
141     * Sort columns with a query.
142     *
143     * @param \Illuminate\Database\Eloquent\Builder $query
144     * @param array                                 $ignore
145     * @return \Illuminate\Database\Eloquent\Builder
146     */
147    protected function sortQuery(Builder $query, array $ignore = []): \Illuminate\Database\Eloquent\Builder
148    {
149        $rName = request()->route()->getName();
150        $table = $query->getModel()->getTable();
151        if (request()->sort_col) {
152            Session::put("$rName.sort_col", request()->sort_col);
153            Session::put("$rName.sorted", true);
154        }
155        if (request()->sort_way) {
156            Session::put("$rName.sort_way", request()->sort_way);
157            Session::put("$rName.sorted", true);
158        }
159        if (request()->rst) {
160            Session::remove("$rName.sorted");
161            Session::remove("$rName.sort_col");
162            Session::remove("$rName.sort_way");
163        }
164        if (request()->sort_col and request()->sort_way and Schema::hasColumn($table, request()->sort_col)) {
165            if (
166                !isset($ignore) or
167                (isset($ignore) and !in_array(request()->sort_col, $ignore))
168            ) {
169                $query = $query->orderBy(\sprintf("$table.%s", request()->sort_col), request()->sort_way);
170            }
171        } elseif (Schema::hasColumn($table, 'order')) {
172            $query = $query->orderBy('order', 'ASC');
173            Session::put("$rName.sort_col", 'order');
174            Session::put("$rName.sort_way", 'asc');
175        } elseif (Schema::hasColumn($table, 'updated_at')) {
176            $query = $query->orderBy('updated_at', 'DESC');
177            Session::put("$rName.sort_col", 'updated_at');
178            Session::put("$rName.sort_way", 'desc');
179        } elseif (Schema::hasColumn($table, 'created_at')) {
180            $query = $query->orderBy('created_at', 'DESC');
181            Session::put("$rName.sort_col", 'created_at');
182            Session::put("$rName.sort_way", 'desc');
183        }
184        return $query;
185    }
186
187    /**
188     * Customize pagination with cache or config (default).
189     *
190     * @param \Illuminate\Database\Eloquent\Builder             $query
191     * @param \App\Enums\Pagination\ItemsPerPaginationEnum|null $pagination
192     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
193     */
194    protected function paginate(
195        Builder $query,
196        ItemsPerPaginationEnum $pagination = null
197    ): \Illuminate\Contracts\Pagination\LengthAwarePaginator {
198        $currentRoutePath = Str::slug(request()->route()->getName());
199        $cacheKey         = "pagination.{$currentRoutePath}";
200        $pagination       = $pagination ?? ItemsPerPaginationEnum::twelve;
201        $pagination       = ToolboxHelper::getValidatedEnum(
202            Cache::get($cacheKey, $pagination->value()),
203            'pagination',
204            '\App\Enums\Pagination\ItemsPerPaginationEnum',
205        );
206        if (Cache::get($cacheKey) !== $pagination) {
207            Cache::put($cacheKey, $pagination);
208        }
209        $query = $query->paginate($pagination);
210        return $query;
211    }
212
213    /**
214     * Set the bootstrap theme or light (default).
215     *
216     * @param \Illuminate\Http\Request $request
217     * @return \Illuminate\Http\RedirectResponse
218     */
219    protected function setTheme(Request $request): \Illuminate\Http\RedirectResponse
220    {
221        $theme = ToolboxHelper::getValidatedEnum(
222            $request->theme ?: Cache::get('theme', BootstrapThemeEnum::light->value()),
223            'theme',
224            '\App\Http\Controllers\BootstrapThemeEnum',
225        );
226        if (Cache::get("theme") !== $theme) {
227            Cache::put("theme", $theme);
228        }
229        return redirect()->back()->with('success', __('crud.messages.theme_updated'));
230    }
231}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/CustomerController.php.html b/tests/coverage/app/Http/Controllers/CustomerController.php.html deleted file mode 100644 index df7ddb7..0000000 --- a/tests/coverage/app/Http/Controllers/CustomerController.php.html +++ /dev/null @@ -1,547 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/CustomerController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 163
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 163
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
992
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 59
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
182
 show
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 delete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
72
 export
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 exportSubmit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 67
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
72
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Enums\CustomerExportType;
6use App\Http\Requests\CustomerExport;
7use App\Models\Brand;
8use App\Models\Customer;
9use App\Models\CustomerInfo;
10use App\Models\CustomerLogin;
11use App\Models\SingleOptin;
12use Illuminate\Database\Eloquent\Builder;
13use Illuminate\Database\Query\JoinClause;
14use Illuminate\Http\Request;
15use Illuminate\Support\Carbon;
16use Illuminate\Support\Facades\DB;
17use Illuminate\Support\Facades\Schema;
18use Illuminate\Support\Facades\Session;
19use Illuminate\Support\Str;
20use League\Csv\Writer;
21use Symfony\Component\HttpFoundation\StreamedResponse;
22
23class CustomerController extends Controller
24{
25    /**
26     * View all customers.
27     *
28     * @param \Illuminate\Http\Request $request
29     * @return \Illuminate\Contracts\View\View
30     */
31    public function index(Request $request): \Illuminate\Contracts\View\View
32    {
33        $modelTable = (new Customer())->getTable();
34        $modelClass = Customer::class;
35        $brands     = Brand::query()->select('id', 'name')->get();
36        $columns    = ['customer_infos.lastname', 'customer_infos.firstname'];
37
38        // * Jointure pour pouvoir trier les colonnes.
39        /** @var \Illuminate\Database\Eloquent\Builder */
40        $query = CustomerInfo::query()->join('customer_logins', function (JoinClause $join) {
41            $join->on('customer_logins.brand_id', '=', 'customer_infos.brand_id')
42                ->on('customer_logins.customer_id', '=', 'customer_infos.customer_id');
43        })->join('customers', function (JoinClause $join) {
44            $join->on('customers.id', '=', 'customer_infos.customer_id');
45        })->join('brands', function (JoinClause $join) {
46            $join->on('brands.id', '=', 'customer_infos.brand_id');
47        });
48
49        if ($request->rst) {
50            Session::remove("crud.$modelTable.brand");
51            Session::remove("crud.$modelTable.search");
52            Session::remove("crud.$modelTable.sort_way");
53            Session::remove("crud.$modelTable.sort_col");
54        }
55
56        if (request()->brand or Session::has("crud.$modelTable.brand")) {
57            $brand = $request->brand ?? Session::get("crud.$modelTable.brand");
58            Session::put("crud.$modelTable.brand", $brand);
59            $query = $query->where('customer_infos.brand_id', $brand);
60        }
61
62        // * Search on crud Label column.
63        if ($request->search or Session::has("crud.$modelTable.search")) {
64            $search = $request->search ?? Session::get("crud.$modelTable.search");
65            Session::put("crud.$modelTable.search", $search);
66            $query->where(function ($q) use ($columns, $search) {
67                foreach ($columns as $column) {
68                    $q = $q->orWhere($column, 'LIKE', "%$search%");
69                }
70                $q = $q->orWhere('customers.email', 'LIKE', "%$search%");
71                $q = $q->orWhere('customer_logins.last_connection', 'LIKE', "%$search%");
72            });
73        }
74
75        // * Sort columns.
76        if ($request->sort_col) {
77            Session::put("crud.$modelTable.sort_col", $request->sort_col);
78        }
79        if ($request->sort_way) {
80            Session::put("crud.$modelTable.sort_way", $request->sort_way);
81        }
82
83        if (
84            Session::has("crud.$modelTable.sort_col") and
85            Session::has("crud.$modelTable.sort_way") and
86            (Schema::hasColumn($modelTable, Session::get("crud.$modelTable.sort_col")) or
87                in_array(Session::get("crud.$modelTable.sort_col"), [
88                    'brands.name',
89                    'customers.email',
90                    'customer_infos.firstname',
91                    'customer_infos.lastname',
92                    'customer_infos.opt_in',
93                    'customer_logins.last_connection',
94                    'customer_logins.status'
95                ]))
96        ) {
97            $query = $query->orderBy(
98                Session::get("crud.$modelTable.sort_col"),
99                Session::get("crud.$modelTable.sort_way")
100            );
101        }
102
103        $searchFields = trans('Email, Prénom, Nom');
104
105        /** @var \Illuminate\Pagination\AbstractPaginator */
106        $customerModels = $query->paginate(50);
107
108        return view('customers.index', compact(
109            'modelClass',
110            'modelTable',
111            'customerModels',
112            'brands',
113            'searchFields'
114        ));
115    }
116
117    /**
118     * Show a specific custmer.
119     *
120     * @param \App\Models\Customer $customer
121     * @param \App\Models\Brand    $brand
122     * @return \Illuminate\Contracts\View\View
123     */
124    public function show(Customer $customer, Brand $brand): \Illuminate\Contracts\View\View
125    {
126        $customerInfos = CustomerInfo::query()->where('customer_id', $customer->id)
127            ->where('brand_id', $brand->id)->firstOrFail();
128        $customerLogin = CustomerLogin::query()->where('customer_id', $customer->id)
129            ->where('brand_id', $brand->id)->first();
130
131        return view('customers.show', compact(
132            'customerInfos',
133            'customerLogin'
134        ));
135    }
136
137    /**
138     * Delete a specific customer info.
139     *
140     * @param \App\Models\Customer $customer
141     * @param \App\Models\Brand    $brand
142     * @return \Illuminate\Http\RedirectResponse
143     */
144    public function delete(Customer $customer, Brand $brand): \Illuminate\Http\RedirectResponse
145    {
146        try {
147            // TODO: Gestion avec mesBR.
148            /** @var \App\Models\CustomerInfo */
149            $customerInfo = $customer->info($brand, Customer::FIRST_OR_FAIL);
150            /** @var \App\Models\CustomerLogin */
151            $customerLogin = $customer->login($brand, Customer::FIRST_OR_FAIL);
152
153            DB::transaction(function () use (
154                $brand,
155                $customer,
156                $customerLogin,
157                $customerInfo
158            ) {
159                if (
160                    $customerInfo->delete() === false ||
161                    $customerLogin->delete() === false
162                ) {
163                    throw new \ErrorException('Api failed to delete customer.');
164                };
165
166                $customer->optInHistory()->whereHas('brand', function ($q) use ($brand) {
167                    $q->where('id', $brand->id);
168                })->delete();
169
170                $logins  = $customer->logins()->count();
171                $infos   = $customer->infos()->count();
172                $history = $customer->optInHistory()->count();
173
174                // If customer is not associated with any brand then delete.
175                if (!$logins and !$infos and !$history) {
176                    if ($customer->delete() === false) {
177                        throw new \ErrorException('Api failed to update customer.');
178                    }
179                }
180            });
181        } catch (\ErrorException $e) {
182            return redirect()->route('customers.index')
183                ->with('error', trans('Le compte n\'a pas pu être supprimé.'));
184        } //end try
185
186        return redirect()->route('customers.index')->with('warning', trans('Compte supprimé.'));
187    }
188
189    /**
190     * Show export the customers form.
191     *
192     * @return \Illuminate\Contracts\View\View
193     */
194    public function export(): \Illuminate\Contracts\View\View
195    {
196        $brands = Brand::all();
197        return view('customers.export', compact(
198            'brands'
199        ));
200    }
201
202    /**
203     * Exports customers following the requested export type.
204     *
205     * @param \App\Http\Requests\CustomerExport $request
206     * @return \Symfony\Component\HttpFoundation\StreamedResponse
207     * @throws \Exception If the request export type in not handled.
208     */
209    public function exportSubmit(CustomerExport $request): \Symfony\Component\HttpFoundation\StreamedResponse
210    {
211        $pagination = 2000;
212        $header     = '"lastname";"firstname";"email";"hashcode"';
213
214        $w = Writer::createFromString($header . PHP_EOL);
215        $w->setDelimiter(';');
216        $w->setEnclosure('"');
217        $w->setOutputBOM(Writer::BOM_UTF8);
218
219        $exportType = CustomerExportType::make(\intval($request->export_type));
220
221        // * We send the CSV using Symfony StreamedResponse.
222        $response = new StreamedResponse();
223        $response->headers->set('Content-Encoding', 'none');
224        $response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
225        $response->headers->set('Description', 'File Transfer');
226        $response->headers->set(
227            'Content-Disposition',
228            sprintf(
229                'attachment; filename="Export pour newsletter %s %s.csv"',
230                Carbon::now()->isoFormat('DD-MM-YYYY_HH-mm'),
231                Str::slug($exportType->label())
232            )
233        );
234
235        switch ($exportType) {
236            case CustomerExportType::both:
237                $continue = true;
238                // ! Continue
239            case CustomerExportType::customer:
240                $page = 1;
241                /** @var \Illuminate\Database\Eloquent\Builder $req */
242                $req   = CustomerInfo::query()->where('brand_id', $request->brand)
243                    ->where('opt_in', true);
244                $total = $req->count();
245                $pages = \ceil($total / $pagination);
246                do {
247                    /** @var \Illuminate\Pagination\LengthAwarePaginator $items */
248                    $items = $req->with('customer', function ($q) {
249                        $q->select(['id', 'email']);
250                    })->paginate(
251                        $pagination,
252                        ['lastname', 'firstname', 'hashcode', 'customer_id'],
253                        'page',
254                        $page
255                    );
256                    $items->map(function (CustomerInfo $customerInfo) use ($w) {
257                        $w->insertOne([
258                            'lastname' => $customerInfo->lastname,
259                            'firstname' => $customerInfo->firstname,
260                            'email' => $customerInfo->customer->email,
261                            'hashcode' => $customerInfo->hashcode
262                        ]);
263                    });
264                } while ($page++ <= $pages);
265                if (!isset($continue)) {
266                    break;
267                }
268                // ! Continue
269            case CustomerExportType::singleOptin:
270                SingleOptin::query()->whereHas('brand', function (Builder $q) use ($request) {
271                    $q->where('id', $request->brand);
272                })->get()->map(function (SingleOptin $singleOptin) use ($w) {
273                    $w->insertOne([
274                        'lastname' => '',
275                        'firstname' => '',
276                        'email' => $singleOptin->email,
277                        'hashcode' => $singleOptin->hashcode
278                    ]);
279                });
280                break;
281            default:
282                throw new \Exception(sprintf('Unhandled CustomerExportType %s', $exportType->label()));
283        } //end switch
284
285        /*
286            We create a callable to output the CSV in chunk
287            with Symfony StreamResponse you can flush the body content if necessary
288            see Symfony documentation for more information
289        */
290
291        // * The flush value should depend on your CSV size.
292        $flush_threshold = 1000;
293
294        $response->setCallback(function () use ($w, $flush_threshold) {
295            foreach ($w->chunk(1024) as $offset => $chunk) {
296                echo $chunk;
297                if ($offset % $flush_threshold === 0) {
298                    flush();
299                }
300            }
301        });
302        return $response;
303    }
304}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/LoginController.php.html b/tests/coverage/app/Http/Controllers/LoginController.php.html deleted file mode 100644 index 0d969e9..0000000 --- a/tests/coverage/app/Http/Controllers/LoginController.php.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/LoginController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
LoginController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 authenticate
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 logout
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers;
4
5use Illuminate\Http\Request;
6use Illuminate\Support\Facades\Auth;
7
8class LoginController extends Controller
9{
10    /**
11     * Shows the login view.
12     *
13     * @return \Illuminate\Contracts\View\View
14     */
15    public function index(): \Illuminate\Contracts\View\View
16    {
17        return view('login');
18    }
19
20    /**
21     * Authenticate specific user.
22     *
23     * @param \Illuminate\Http\Request $request
24     * @return \Illuminate\Http\RedirectResponse
25     */
26    public function authenticate(Request $request): \Illuminate\Http\RedirectResponse
27    {
28        if (
29            Auth::attempt(
30                ["email" => $request->email, "password" => $request->password],
31                $request->remember !== null ? true : false
32            )
33        ) {
34            return redirect()->route('customers.index');
35        } else {
36            return redirect()->back()->withInput($request->except("password"))
37                ->withErrors("Les identifiants entrés sont incorrects, veuillez réessayer.");
38        }
39    }
40
41    /**
42     * Logout user connected.
43     *
44     * @return \Illuminate\Http\RedirectResponse
45     */
46    public function logout(): \Illuminate\Http\RedirectResponse
47    {
48        Auth::logout();
49        return redirect()->route('login');
50    }
51}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/QuestionController.php.html b/tests/coverage/app/Http/Controllers/QuestionController.php.html deleted file mode 100644 index 7af73ec..0000000 --- a/tests/coverage/app/Http/Controllers/QuestionController.php.html +++ /dev/null @@ -1,606 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/QuestionController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 128
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
QuestionController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 128
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
462
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 store
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 edit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 show
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 destroy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 export
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 exportSubmit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 55
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
72
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Http\Controllers\Controller;
6use App\Http\Requests\QuestionExport;
7use App\Http\Requests\Questions\StoreQuestionRequest;
8use App\Http\Requests\Questions\UpdateQuestionRequest;
9use App\Models\Brand;
10use App\Models\Question;
11use Carbon\Carbon;
12use Illuminate\Http\Request;
13use Illuminate\Support\Facades\DB;
14use Illuminate\Support\Str;
15use League\Csv\Writer;
16use Symfony\Component\HttpFoundation\StreamedResponse;
17
18class QuestionController extends Controller
19{
20    /**
21     * Display a listing of the resource.
22     *
23     * @param \Illuminate\Http\Request $request
24     * @return \Illuminate\Contracts\View\View
25     */
26    public function index(Request $request): \Illuminate\Contracts\View\View
27    {
28        /** @var \Illuminate\Database\Eloquent\Builder $query */
29        $query = Question::query();
30
31        if ($request->brand) {
32            $query = $query->where('brand_id', '=', $request->brand);
33        }
34        if ($request->search) {
35            $this->searchQuery(
36                $query,
37                $request->search,
38                null,
39                'question',
40            );
41        }
42
43        $this->sortQuery($query);
44        $searchFields = trans('Question');
45
46        /** @var \Illuminate\Pagination\AbstractPaginator */
47        $questionModels = $query->paginate(12);
48
49        return view('questions.index', compact('questionModels', 'searchFields'));
50    }
51
52    /**
53     * Show the form for creating a new resource.
54     *
55     * @param \App\Models\Question $question
56     * @return \Illuminate\Contracts\View\View
57     */
58    public function create(Question $question): \Illuminate\Contracts\View\View
59    {
60        $brandModels = Brand::all();
61
62        return view('questions.create', [
63            'questionModel' => $question,
64            'brandModels' => $brandModels
65        ]);
66    }
67
68    /**
69     * Store a newly created resource in storage.
70     *
71     * @param \App\Http\Requests\Questions\StoreQuestionRequest $request
72     * @return \Illuminate\Http\RedirectResponse
73     */
74    public function store(StoreQuestionRequest $request): \Illuminate\Http\RedirectResponse
75    {
76        return DB::transaction(function () use ($request) {
77            $question = new Question();
78            $question->fill($request->validated());
79            if ($question->saveOrFail()) {
80                return redirect()
81                    ->route('questions.edit', $question)
82                    ->with('success', trans(
83                        ':model a été créé.',
84                        ['model' => Str::singular(trans('models.classes.questions'))]
85                    ));
86            }
87            return redirect()
88                ->back()
89                ->with('error', trans(
90                    ':model n\'a pas été créé.',
91                    ['model' => Str::singular(trans('models.classes.questions'))]
92                ));
93        });
94    }
95
96    /**
97     * Show the form for editing the specified resource.
98     *
99     * @param \App\Models\Question $question
100     * @return \Illuminate\Contracts\View\View
101     */
102    public function edit(Question $question): \Illuminate\Contracts\View\View
103    {
104        $brandModels = Brand::all();
105
106        return view('questions.edit', [
107            'questionModel' => $question,
108            'brandModels' => $brandModels
109        ]);
110    }
111
112    /**
113     * Update a spacific resource in storage.
114     *
115     * @param \App\Http\Requests\Questions\UpdateQuestionRequest $request
116     * @param \App\Models\Question                               $question
117     * @return \Illuminate\Http\RedirectResponse
118     */
119    public function update(UpdateQuestionRequest $request, Question $question): \Illuminate\Http\RedirectResponse
120    {
121        return DB::transaction(function () use ($request, $question) {
122            $question->fill($request->validated());
123            if ($question->saveOrFail()) {
124                return redirect()
125                    ->route('questions.edit', $question)
126                    ->with('success', trans(
127                        ':model a été mis à jour.',
128                        ['model' => Str::singular(trans('models.classes.questions'))]
129                    ));
130            }
131            return redirect()
132                ->back()
133                ->with('error', trans(
134                    ':model n\'a pas été mis à jour.',
135                    ['model' => Str::singular(trans('models.classes.questions'))]
136                ));
137        });
138    }
139
140    /**
141     * Show the specified resource.
142     *
143     * @param \App\Models\Question $question
144     * @return \Illuminate\Contracts\View\View
145     */
146    public function show(Question $question): \Illuminate\Contracts\View\View
147    {
148        return view('questions.show', [
149            'questionModel' => $question
150        ]);
151    }
152
153    /**
154     * Remove the specified resource from storage.
155     *
156     * @param \App\Models\Question $question
157     * @return \Illuminate\Http\RedirectResponse
158     */
159    public function destroy(Question $question): \Illuminate\Http\RedirectResponse
160    {
161        if ($question->deleteOrFail()) {
162            return redirect()->route('questions.index')
163                ->with('success', trans(
164                    ':model a été supprimé.',
165                    ['model' => Str::singular(trans('models.classes.questions'))]
166                ));
167        }
168        return redirect()->back()
169            ->with('error', trans(
170                ':model n\'a pas pu être supprimé.',
171                ['model' => Str::singular(trans('models.classes.questions'))]
172            ));
173    }
174
175    /**
176     * Shows the question export form
177     *
178     * @return \Illuminate\Contracts\View\View
179     */
180    public function export(): \Illuminate\Contracts\View\View
181    {
182        $brands = Brand::all();
183        return view('questions.export', compact('brands'));
184    }
185
186    /**
187     * Exports questions as csv the requested export type
188     *
189     * @param \App\Http\Requests\QuestionExport $request
190     * @return \Symfony\Component\HttpFoundation\StreamedResponse
191     */
192    public function exportSubmit(QuestionExport $request): \Symfony\Component\HttpFoundation\StreamedResponse
193    {
194        $results = [];
195        /** @var \App\Models\Brand $brand */
196        $brand     = Brand::query()->where('id', $request->brand)->firstOrFail();
197        $questions = $brand->questions->load('answers');
198
199        foreach ($questions as $question) {
200            $answersCounts = DB::query()
201                ->selectRaw('count(*) as total, answer_id')
202                ->from('customer_answer')
203                ->whereIn('answer_id', $question->answers->pluck('id'))
204                ->groupBy('answer_id')
205                ->get()->keyBy('answer_id');
206
207            $results[$question->id] = [
208                'question' => $question->question,
209                'answers' => []
210            ];
211            foreach ($question->answers as $answer) {
212                $results[$question->id]['answers'][] =
213                    [
214                        "$answer->answer ",
215                        $answersCounts[$answer->id]->total ?? 0
216                    ];
217            }
218        }
219
220        $w = Writer::createFromString('');
221        $w->setDelimiter(';');
222        $w->setEnclosure('"');
223        $w->setOutputBOM(Writer::BOM_UTF8);
224
225        // * We send the CSV using Symfony StreamedResponse.
226        $response = new StreamedResponse();
227        $response->headers->set('Content-Encoding', 'none');
228        $response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
229        $response->headers->set('Description', 'File Transfer');
230        $response->headers->set(
231            'Content-Disposition',
232            sprintf(
233                'attachment; filename="Export pour newsletter %s %s.csv"',
234                Carbon::now()->isoFormat('DD-MM-YYYY_HH-mm'),
235                Str::slug($brand->name)
236            )
237        );
238
239        foreach ($results as $result) {
240            $w->insertOne([
241                'question' => $result['question'],
242            ]);
243            foreach ($result['answers'] as $answer) {
244                $w->insertOne($answer);
245            }
246            $w->insertOne([]);
247        }
248
249        // * Push empty line if nothing to export
250        if (empty($results)) {
251            $w->insertOne([
252                'Aucune question pour cette marque'
253            ]);
254        }
255
256        /*
257            We create a callable to output the CSV in chunk
258            with Symfony StreamResponse you can flush the body content if necessary
259            see Symfony documentation for more information
260        */
261
262        // * The flush value should depend on your CSV size.
263        $flush_threshold = 1000;
264
265        $response->setCallback(function () use ($w, $flush_threshold) {
266            foreach ($w->chunk(1024) as $offset => $chunk) {
267                echo $chunk;
268                if ($offset % $flush_threshold === 0) {
269                    flush();
270                }
271            }
272        });
273        return $response;
274    }
275}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/ServiceController.php.html b/tests/coverage/app/Http/Controllers/ServiceController.php.html deleted file mode 100644 index 8009d3e..0000000 --- a/tests/coverage/app/Http/Controllers/ServiceController.php.html +++ /dev/null @@ -1,510 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/ServiceController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 82
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ServiceController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 82
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
210
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 store
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 19
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 edit
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 show
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 destroy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 generateServicePassword
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Http\Requests\GenerateServiceToken;
6use App\Http\Requests\Services\StoreServiceRequest;
7use App\Http\Requests\Services\UpdateServiceRequest;
8use App\Mail\ServiceCredentialRenewed;
9use App\Models\Brand;
10use App\Models\Service;
11use Illuminate\Http\Request;
12use Illuminate\Support\Facades\DB;
13use Illuminate\Support\Facades\Hash;
14use Illuminate\Support\Facades\Mail;
15use Illuminate\Support\Str;
16
17class ServiceController extends Controller
18{
19    /**
20     * Display a listing of the resource.
21     *
22     * @param \Illuminate\Http\Request $request
23     * @return \Illuminate\Contracts\View\View
24     */
25    public function index(Request $request): \Illuminate\Contracts\View\View
26    {
27        /** @var \Illuminate\Database\Eloquent\Builder $query */
28        $query = Service::query();
29
30        if ($request->brand) {
31            $query = $query->where('brand_id', '=', $request->brand);
32        }
33        if ($request->search) {
34            $this->searchQuery(
35                $query,
36                $request->search,
37                null,
38                'name',
39            );
40        }
41
42        $this->sortQuery($query);
43        $searchFields = trans('Nom');
44
45        $serviceModels = $query->paginate(12);
46
47        return view('services.index', compact('serviceModels', 'searchFields'));
48    }
49
50    /**
51     * Show the form for creating a new resource.
52     *
53     * @param \App\Models\Service $service
54     * @return \Illuminate\Contracts\View\View
55     */
56    public function create(Service $service): \Illuminate\Contracts\View\View
57    {
58        $brandModels = Brand::all();
59
60        return view('services.create', [
61            'serviceModel' => $service,
62            'brandModels' => $brandModels
63        ]);
64    }
65
66    /**
67     * Store a newly created resource in storage.
68     *
69     * @param \App\Http\Requests\Services\StoreServiceRequest $request
70     * @return \Illuminate\Http\RedirectResponse
71     */
72    public function store(StoreServiceRequest $request): \Illuminate\Http\RedirectResponse
73    {
74        return DB::transaction(function () use ($request) {
75            $service = new Service();
76            $service->fill($request->validated());
77            $service->generateBearerToken();
78            $this->generateServicePassword($service);
79            if ($service->saveOrFail()) {
80                return redirect()
81                    ->route('services.edit', $service)
82                    ->with('success', trans(
83                        ':model a été créé.',
84                        ['model' => Str::singular(trans('models.classes.services'))]
85                    ));
86            }
87            return redirect()
88                ->back()
89                ->with('error', trans(
90                    ':model n\'a pas été créé.',
91                    ['model' => Str::singular(trans('models.classes.services'))]
92                ));
93        });
94    }
95
96    /**
97     * Show the form for editing the specified resource.
98     *
99     * @param \App\Models\Service $service
100     * @return \Illuminate\Contracts\View\View
101     */
102    public function edit(Service $service): \Illuminate\Contracts\View\View
103    {
104        $brandModels = Brand::all();
105
106        return view('services.edit', [
107            'serviceModel' => $service,
108            'brandModels' => $brandModels
109        ]);
110    }
111
112    /**
113     * Update a spacific resource in storage.
114     *
115     * @param \App\Http\Requests\Services\UpdateServiceRequest $request
116     * @param \App\Models\Service                              $service
117     * @return \Illuminate\Contracts\View\View
118     */
119    public function update(UpdateServiceRequest $request, Service $service): \Illuminate\Contracts\View\View
120    {
121        return DB::transaction(function () use ($request, $service) {
122            $service->fill($request->validated());
123            if ($service->saveOrFail()) {
124                return redirect()
125                    ->route('services.edit', $service)
126                    ->with('success', trans(
127                        ':model a été mis à jour.',
128                        ['model' => Str::singular(trans('models.classes.services'))]
129                    ));
130            }
131            return redirect()
132                ->back()
133                ->with('error', trans(
134                    ':model n\'a pas été mis à jour.',
135                    ['model' => Str::singular(trans('models.classes.services'))]
136                ));
137        });
138    }
139
140    /**
141     * Show the specified resource.
142     *
143     * @param \App\Models\Service $service
144     * @return \Illuminate\Contracts\View\View
145     */
146    public function show(Service $service): \Illuminate\Contracts\View\View
147    {
148        return view('services.show', [
149            'serviceModel' => $service
150        ]);
151    }
152
153    /**
154     * Remove the specified resource from storage.
155     *
156     * @param \App\Models\Service $service
157     * @return \Illuminate\Http\RedirectResponse
158     */
159    public function destroy(Service $service): \Illuminate\Http\RedirectResponse
160    {
161        if ($service->deleteOrFail()) {
162            return redirect()->route('services.index')
163                ->with('success', trans(
164                    ':model a été supprimé.',
165                    ['model' => Str::singular(trans('models.classes.services'))]
166                ));
167        }
168        return redirect()->back()
169            ->with('error', trans(
170                ':model n\'a pas pu être supprimé.',
171                ['model' => Str::singular(trans('models.classes.services'))]
172            ));
173    }
174
175    /**
176     * Regen service credentials.
177     *
178     * @param \App\Http\Requests\GenerateServiceToken $request
179     * @param \App\Models\Service                     $service
180     * @return \Illuminate\Http\RedirectResponse
181     */
182    // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed, Squiz.Commenting.FunctionComment.Missing
183    public function generateServicePassword(
184        Service $service,
185        GenerateServiceToken $request = null
186    ): \Illuminate\Http\RedirectResponse {
187        /** @var \App\Models\User $user */
188        $user = auth()->user();
189
190        // * Special Condition for migration from v2 to v3.
191        $service->bearer_token = !Hash::needsRehash($service->bearer_token) ?
192            $service->generateBearerToken() : $service->bearer_token;
193
194        $bearerPwd = $service->generateBearerPassword();
195        $service->saveOrFail();
196        Mail::send(new ServiceCredentialRenewed($service, $user));
197        return back()
198            // phpcs:ignore Generic.Files.LineLength.TooLong
199            ->with('error', "ATTENTION : METTEZ À JOUR LE SITE ! \nNouveau token d'API de $service->name : '$service->bearer_token' et mot de passe '$bearerPwd'");
200    }
201}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/SingleOptinController.php.html b/tests/coverage/app/Http/Controllers/SingleOptinController.php.html deleted file mode 100644 index 8b684bb..0000000 --- a/tests/coverage/app/Http/Controllers/SingleOptinController.php.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/SingleOptinController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 27
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
SingleOptinController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 27
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 index
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 destroy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Models\SingleOptin;
6use Illuminate\Database\Eloquent\Builder;
7use Illuminate\Http\Request;
8use Illuminate\Support\Str;
9
10class SingleOptinController extends Controller
11{
12    /**
13     * Display a listing of the resource.
14     *
15     * @param \Illuminate\Http\Request $request
16     * @return \Illuminate\Contracts\View\View
17     */
18    public function index(Request $request): \Illuminate\Contracts\View\View
19    {
20        /** @var \Illuminate\Database\Eloquent\Builder $query */
21        $query = SingleOptin::query();
22
23        if ($request->brand) {
24            $query = $query->whereHas('brand', function (Builder $q) use ($request) {
25                $q->where('id', $request->brand);
26            });
27        }
28        if ($request->search) {
29            $this->searchQuery(
30                $query,
31                $request->search,
32                null,
33                'email',
34            );
35        }
36
37        $this->sortQuery($query);
38        $searchFields = trans('E-mail');
39
40        /** @var \Illuminate\Pagination\AbstractPaginator */
41        $singleoptinModels = $query->paginate(12);
42
43        return view('singleoptins.index', compact('singleoptinModels', 'searchFields'));
44    }
45
46    /**
47     * Remove the specified resource from storage.
48     *
49     * @param \App\Models\SingleOptin $singleoptin
50     * @return \Illuminate\Http\RedirectResponse
51     */
52    public function destroy(SingleOptin $singleoptin): \Illuminate\Http\RedirectResponse
53    {
54        if ($singleoptin->deleteOrFail()) {
55            return redirect()->route('single_optins.index')
56                ->with('success', trans(
57                    ':model a été supprimé.',
58                    ['model' => Str::singular(trans('models.classes.singleoptins'))]
59                ));
60        }
61        return redirect()->back()
62            ->with('error', trans(
63                ':model n\'a pas pu être supprimé.',
64                ['model' => Str::singular(trans('models.classes.singleoptins'))]
65            ));
66    }
67}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/StatsController.php.html b/tests/coverage/app/Http/Controllers/StatsController.php.html deleted file mode 100644 index e9aa13c..0000000 --- a/tests/coverage/app/Http/Controllers/StatsController.php.html +++ /dev/null @@ -1,439 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers/StatsController.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 101
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatsController
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 101
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
156
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 viewStatsByBrand
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 exportByBrandCsv
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 27
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 viewByQuestion
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 exportByQuestionCsv
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 answersByDays
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 33
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Http\Requests\StatsByBrandRequest;
6use App\Http\Requests\StatsByQuestionRequest;
7use App\Models\Brand;
8use App\Models\BrandStat;
9use App\Models\CustomerAnswer;
10use App\Models\Question;
11use Illuminate\Support\Carbon;
12use Illuminate\Support\Collection;
13use Illuminate\Support\Facades\Schema;
14use League\Csv\Writer;
15
16class StatsController extends Controller
17{
18    /**
19     * Shows stats by brand.
20     *
21     * @param \App\Http\Requests\StatsByBrandRequest $request
22     * @return \Illuminate\Http\Response
23     */
24    public function viewStatsByBrand(StatsByBrandRequest $request)
25    {
26        $stats = null;
27        if ($request->post()) {
28            $stats = BrandStat::query()->whereDate('created_at', '>=', $request->start)
29                ->whereDate('created_at', '<=', $request->end)
30                ->whereBrandId($request->brand)->get();
31        }
32        return view('stats.view-stats-by-brands', \compact('stats'));
33    }
34
35    /**
36     * Exports stats by brand as a csv file.
37     *
38     * @param \App\Http\Requests\StatsByBrandRequest $request
39     * @return \Illuminate\Http\Response
40     */
41    public function exportByBrandCsv(StatsByBrandRequest $request): \Illuminate\Http\Response
42    {
43        $brand = Brand::query()->findOrFail($request->brand);
44        $stats = BrandStat::query()->with('brand')->whereDate('created_at', '>=', $request->start)
45            ->whereDate('created_at', '<=', $request->end)
46            ->whereBrandId($request->brand)->get();
47
48        $columns = collect(Schema::getColumnListing((new BrandStat())->getTable()))
49            ->filter(function ($value) {
50                return !in_array($value, ['created_at', 'brand_id']);
51            })->all();
52
53        $header = '"date";"marque";' . implode(';', $columns);
54
55        $w = Writer::createFromString($header . PHP_EOL);
56        $w->setDelimiter(';');
57        $w->setEnclosure('"');
58        $w->setOutputBOM(Writer::BOM_UTF8);
59
60        foreach ($stats as $stat) {
61            $cols = [
62                $stat->created_at->isoFormat('YYYY-MM-DD'),
63                $stat->brand->name
64            ];
65            foreach ($columns as $colname) {
66                $cols[] = $stat->{$colname};
67            }
68            $w->insertOne($cols);
69        }
70        return response((string)$w, 200, [
71            'Content-Encoding' => 'none',
72            'Content-Type' => 'text/csv; charset=UTF-8',
73            // phpcs:ignore Generic.Files.LineLength.TooLong
74            'Content-Disposition' => "attachment; filename=\"Statistiques du $request->start au $request->end pour $brand->name.csv\"",
75            'Content-Description' => 'File Transfer',
76        ]);
77    }
78
79    /**
80     * Views stats for a specific question.
81     *
82     * @param \App\Http\Requests\StatsByQuestionRequest $request
83     * @return \Illuminate\Contracts\View\View
84     */
85    public function viewByQuestion(StatsByQuestionRequest $request): \Illuminate\Contracts\View\View
86    {
87        $question      = null;
88        $answers       = null;
89        $answersByDays = null;
90        if ($request->post()) {
91            $question = Question::query()->findOrFail($request->question);
92            $answers  = $question->answers;
93            $start    = Carbon::parse($request->start);
94            $end      = Carbon::parse($request->end);
95
96            $answersByDays = $this->answersByDays($answers, $start, $end);
97        }
98
99        return view('stats.view-stats-by-questions', \compact('question', 'answers', 'answersByDays'));
100    }
101
102    /**
103     * Exports stats for a specific question as csv.
104     *
105     * @param \App\Http\Requests\StatsByQuestionRequest $request
106     * @return \Illuminate\Http\Response
107     */
108    public function exportByQuestionCsv(StatsByQuestionRequest $request): \Illuminate\Http\Response
109    {
110        $question = Question::query()->findOrFail($request->question);
111        $answers  = $question->answers;
112        $start    = Carbon::parse($request->start);
113        $end      = Carbon::parse($request->end);
114
115        $answersByDays = $this->answersByDays($answers, $start, $end);
116
117        $header = '"date";' . implode(';', $answers->map(function ($answer) {
118            return "\"$answer->answer\"";
119        })->all());
120
121        $w = Writer::createFromString($header . PHP_EOL);
122        $w->setDelimiter(';');
123        $w->setEnclosure('"');
124        $w->setOutputBOM(Writer::BOM_UTF8);
125
126        foreach ($answersByDays as $day => $dayAnswers) {
127            $w->insertOne(array_merge(
128                [
129                    $day
130                ],
131                $dayAnswers->values()->all()
132            ));
133        }
134        return response((string)$w, 200, [
135            'Content-Encoding' => 'none',
136            'Content-Type' => 'text/csv; charset=UTF-8',
137            // phpcs:ignore Generic.Files.LineLength.TooLong
138            'Content-Disposition' => "attachment; filename=\"Statistiques du $request->start au $request->end pour $question->question.csv\"",
139            'Content-Description' => 'File Transfer',
140        ]);
141    }
142
143    /**
144     * Makes a collection of total users answers by day.
145     *
146     * @param \Illuminate\Support\Collection $answers A collection of Answer.
147     * @param \Illuminate\Support\Carbon     $start   The wanted start period.
148     * @param \Illuminate\Support\Carbon     $end     The wanted end period.
149     * @return \Illuminate\Support\Collection A collection with date as Y_m_d index
150     *                                        with array of answers and their total.
151     */
152    private function answersByDays(Collection $answers, Carbon $start, Carbon $end): \Illuminate\Support\Collection
153    {
154        // * Totalize by date all answers.
155        $answersByDays = CustomerAnswer::query()->whereDate('created_at', '>=', $start)
156            ->whereDate('created_at', '<=', $end)
157            ->whereIn('answer_id', $answers->pluck('id'))
158            ->get()->map(function ($custAnswer) {
159                return [
160                    'answer_id' => $custAnswer->answer_id,
161                    'created_at' => $custAnswer->created_at->isoFormat('YYYY-MM-DD'),
162                ];
163            })->groupBy(['created_at', 'answer_id'])->map(function ($day) {
164                return $day->map(function ($custAnswers) {
165                    return $custAnswers->count();
166                });
167            });
168
169        do {
170            $currentDate = $start->isoFormat('YYYY-MM-DD');
171            /** @var \Illuminate\Support\Collection $answersByDays */
172            if (!$answersByDays->has($currentDate)) {
173                $answersByDays->put(
174                    $currentDate,
175                    $answers->mapWithKeys(function ($answer) {
176                        return [$answer->answer => 0];
177                    })
178                );
179            } else {
180                $curentAnswers = $answersByDays->pull($currentDate);
181                $answersByDays->put(
182                    $currentDate,
183                    $answers->mapWithKeys(function ($answer) use ($curentAnswers) {
184                        return [$answer->answer =>
185                        $curentAnswers->has($answer->id) ?
186                            $curentAnswers->get($answer->id) : 0];
187                    })
188                );
189            }
190
191            $start = $start->addDay();
192        } while ($start->lessThanOrEqualTo($end));
193
194        return $answersByDays;
195    }
196}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/dashboard.html b/tests/coverage/app/Http/Controllers/dashboard.html deleted file mode 100644 index 38123bb..0000000 --- a/tests/coverage/app/Http/Controllers/dashboard.html +++ /dev/null @@ -1,412 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Controllers - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- -
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- - -
- - - - - - diff --git a/tests/coverage/app/Http/Controllers/index.html b/tests/coverage/app/Http/Controllers/index.html deleted file mode 100644 index d635c96..0000000 --- a/tests/coverage/app/Http/Controllers/index.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Controllers - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 32.87% covered (danger) -
-
-
32.87%
406 / 1235
-
- 39.25% covered (danger) -
-
-
39.25%
42 / 107
-
- 51.85% covered (warning) -
-
-
51.85%
14 / 27
Api
-
- 100.00% covered (success) -
-
-
100.00%
406 / 406
-
- 100.00% covered (success) -
-
-
100.00%
42 / 42
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
Bo
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 728
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 59
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
Controller.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 101
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Kernel.php.html b/tests/coverage/app/Http/Kernel.php.html deleted file mode 100644 index 30aca73..0000000 --- a/tests/coverage/app/Http/Kernel.php.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Kernel.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
Kernel
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http;
4
5use Illuminate\Foundation\Http\Kernel as HttpKernel;
6
7class Kernel extends HttpKernel
8{
9    /**
10     * The application's global HTTP middleware stack.
11     *
12     * These middleware are run during every request to your application.
13     *
14     * @var array
15     */
16    protected $middleware = [
17        \App\Http\Middleware\TrustHosts::class,
18        \App\Http\Middleware\TrustProxies::class,
19        \Illuminate\Http\Middleware\HandleCors::class,
20        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
21        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
22        \App\Http\Middleware\TrimStrings::class,
23        \App\Http\Middleware\HtmlSanitizer::class
24    ];
25
26    /**
27     * The application's route middleware groups.
28     *
29     * @var array
30     */
31    protected $middlewareGroups = [
32        'web' => [
33            \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
34            \App\Http\Middleware\EncryptCookies::class,
35            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
36            \Illuminate\Session\Middleware\StartSession::class,
37            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
38            \App\Http\Middleware\VerifyCsrfToken::class,
39            \Illuminate\Routing\Middleware\SubstituteBindings::class,
40            \App\Http\Middleware\SecureHeaders::class
41        ],
42
43        'api' => [
44            \Illuminate\Routing\Middleware\ThrottleRequests::class . ':api',
45            \App\Http\Middleware\JsonOnly::class,
46            \App\Http\Middleware\ApiResponse::class,
47            \App\Http\Middleware\ApiCheckTimeStamps::class,
48            \Illuminate\Routing\Middleware\SubstituteBindings::class
49        ],
50    ];
51
52    /**
53     * The application's route middleware.
54     *
55     * These middleware may be assigned to groups or used individually.
56     *
57     * @var array
58     */
59    protected $routeMiddleware = [
60        'auth' => \App\Http\Middleware\Authenticate::class,
61        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
62        'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
63        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
64        'can' => \Illuminate\Auth\Middleware\Authorize::class,
65        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
66        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
67        'signed' => \App\Http\Middleware\ValidateSignature::class,
68        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
69        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
70        'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
71    ];
72}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/ApiCheckTimeStamps.php.html b/tests/coverage/app/Http/Middleware/ApiCheckTimeStamps.php.html deleted file mode 100644 index ec6393f..0000000 --- a/tests/coverage/app/Http/Middleware/ApiCheckTimeStamps.php.html +++ /dev/null @@ -1,198 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/ApiCheckTimeStamps.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiCheckTimeStamps
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 handle
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use App\Enums\ApiError;
6use App\Exceptions\Api\V4\ApiErrorException;
7use App\Lib\Helper;
8use Illuminate\Http\Request;
9use Illuminate\Support\Carbon;
10
11/**
12 * Check Http Header Timestamp with request timestamp
13 * to prevent replay attacks
14 * https://restfulapi.net/security-essentials/
15 */
16class ApiCheckTimeStamps
17{
18    /**
19     * Handle an incoming request.
20     *
21     * @param \Illuminate\Http\Request $request
22     * @param \Closure                 $next
23     * @return mixed
24     * @throws \App\Exceptions\Api\V4\ApiErrorException With ApiError::wrongTimeStamp
25     *                                                  if timestamp has an incorrect
26     *                                                  format or is timed out.
27     */
28    public function handle(Request $request, \Closure $next): mixed
29    {
30        if (Helper::isRequestForApiV2($request) || Helper::isRequestForApiV4($request)) {
31            if (!\is_string($request->timestamp) or !Carbon::hasFormat($request->timestamp, 'Y-m-d H:i:s')) {
32                throw new ApiErrorException(ApiError::wrongTimeStamp);
33            }
34            if (
35                Carbon::parse($request->timestamp, 'utc')
36                ->isBefore(Carbon::now('UTC')->subSeconds(config('api.timestampTimeout', 10)))
37            ) {
38                throw new ApiErrorException(ApiError::wrongTimeStamp);
39            }
40        }
41        return $next($request);
42    }
43}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/ApiResponse.php.html b/tests/coverage/app/Http/Middleware/ApiResponse.php.html deleted file mode 100644 index bc3b4ef..0000000 --- a/tests/coverage/app/Http/Middleware/ApiResponse.php.html +++ /dev/null @@ -1,220 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/ApiResponse.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiResponse
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 handle
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
10
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use App\Enums\ApiStatus;
6use App\Http\Resources\Api\V2\ApiResponse as V2ApiResponse;
7use App\Http\Resources\Api\V4\ApiResponse as V4ApiResponse;
8use App\Lib\Helper;
9use App\Models\Service;
10use Illuminate\Http\JsonResponse;
11use Illuminate\Http\Request;
12
13class ApiResponse
14{
15    /**
16     * Handle an incoming request.
17     *
18     * @param  \Illuminate\Http\Request $request
19     * @param  \Closure                 $next
20     * @return mixed
21     * @throws \ErrorException If the received response is not a JsonResponse.
22     */
23    public function handle(Request $request, \Closure $next): mixed
24    {
25        /** @var \Illuminate\Http\JsonResponse $response */
26        $response = $next($request);
27
28        if (\get_class($response) !== JsonResponse::class) {
29            // @codeCoverageIgnoreStart
30            throw new \ErrorException('All api responses should be json.');
31            // @codeCoverageIgnoreEnd
32        }
33
34        // Set no cache header.
35        $response->header('Cache-Control', 'No-Store');
36
37        /** @var \App\Models\Service|null */
38        if (\optional($service = app(Service::class))->id) {
39            $service->incrementStat();
40        }
41
42        /** @var object $data */
43        $data = $response->getData();
44
45        /** Check if it's V2 or V4 response. */
46        if (
47            gettype($data) === "object" and
48            isset($data->status) and
49            isset($data->data) and
50            isset($data->version) and
51            in_array($data->status, [ApiStatus::OK->value(), ApiStatus::KO->value()])
52        ) {
53            /** Return direct ApiResponse */
54            return $response;
55        }
56
57        $status = intval($response->getStatusCode() / 100) == 2 ? ApiStatus::OK : ApiStatus::KO;
58
59        if (Helper::isRequestForApiV2($request)) {
60            return $response->setData(new V2ApiResponse((object)$data, $status));
61        }
62
63        return $response->setData(new V4ApiResponse((object)$data, $status));
64    }
65}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/Authenticate.php.html b/tests/coverage/app/Http/Middleware/Authenticate.php.html deleted file mode 100644 index d42f762..0000000 --- a/tests/coverage/app/Http/Middleware/Authenticate.php.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/Authenticate.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 41.67% covered (danger) -
-
-
41.67%
5 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Authenticate
-
- 41.67% covered (danger) -
-
-
41.67%
5 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
13.15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 redirectTo
-
- 41.67% covered (danger) -
-
-
41.67%
5 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
13.15
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Illuminate\Auth\Middleware\Authenticate as Middleware;
6use Illuminate\Http\Request;
7use Illuminate\Support\Facades\Session;
8
9class Authenticate extends Middleware
10{
11    /**
12     * Get the path the user should be redirected to when they are not authenticated.
13     *
14     * @param  \Illuminate\Http\Request $request
15     * @return string|null
16     */
17    protected function redirectTo(Request $request): ?string
18    {
19        $logins = [
20            'backend' => route('bo.login')
21        ];
22        if (!$request->expectsJson()) {
23            // * Notify must login
24            Session::flash('warning', trans('Veuillez vous connecter pour continuer'));
25
26            foreach ($request->route()->gatherMiddleware() as $middleware) {
27                if (\is_string($middleware) and strpos($middleware, 'auth:') !== false) {
28                    $route = $logins[str_replace('auth:', '', $middleware)] ?? null;
29                    if ($route) {
30                        return $route;
31                    }
32                }
33            }
34            return route('login');
35        }
36
37        return null;
38    }
39}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/EncryptCookies.php.html b/tests/coverage/app/Http/Middleware/EncryptCookies.php.html deleted file mode 100644 index 8fbd779..0000000 --- a/tests/coverage/app/Http/Middleware/EncryptCookies.php.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/EncryptCookies.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
EncryptCookies
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
6
7class EncryptCookies extends Middleware
8{
9    /**
10     * The names of the cookies that should not be encrypted.
11     *
12     * @var array
13     */
14    protected $except = [];
15}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/HtmlSanitizer.php.html b/tests/coverage/app/Http/Middleware/HtmlSanitizer.php.html deleted file mode 100644 index 7257328..0000000 --- a/tests/coverage/app/Http/Middleware/HtmlSanitizer.php.html +++ /dev/null @@ -1,216 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/HtmlSanitizer.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 71.43% covered (warning) -
-
-
71.43%
20 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
HtmlSanitizer
-
- 71.43% covered (warning) -
-
-
71.43%
20 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
9.49
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 handle
-
- 71.43% covered (warning) -
-
-
71.43%
20 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
9.49
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use App\Lib\Helpers\ToolboxHelper;
6use Illuminate\Http\Request;
7use Symfony\Component\HttpFoundation\Response;
8
9class HtmlSanitizer
10{
11    /**
12     * Handle an incoming request.
13     *
14     * @param  \Illuminate\Http\Request $request
15     * @param  \Closure                 $next
16     * @param  string|array             ...$params
17     * @return \Symfony\Component\HttpFoundation\Response
18     */
19    public function handle(Request $request, \Closure $next, string|array ...$params): Response
20    {
21        $inputs = $request->all();
22        /** @var callable|null */
23        $cleanInput = null;
24        $cleanInput = function (
25            null|string|array &$input,
26            string $name,
27            ?string $rootName = null
28        ) use (
29            $params,
30            &$cleanInput
31        ): void {
32            // * Nested element array
33            if (is_array($input)) {
34                array_walk_recursive($input, $cleanInput, $name);
35            }
36            if (!is_string($input)) {
37                return;
38            }
39            if (in_array($name, $params) or in_array($rootName ?? $name, $params)) {
40                // ? Is a json input ?
41                if ($isJson = \json_decode($input, true) and is_array($isJson)) {
42                    // ! Decode each json field recursive.
43                    \array_walk_recursive($isJson, function (string|array &$item) {
44                        if (\is_string($item)) {
45                            $item = clean($item);
46                            $item = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($item);
47                        }
48                    });
49                } else {
50                    $input = clean($input);
51                    $input = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($input);
52                }
53            } else {
54                $input = strip_tags($input);
55            }
56        };
57        \array_walk($inputs, $cleanInput);
58        $request->merge($inputs);
59        return $next($request);
60    }
61}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/JsonOnly.php.html b/tests/coverage/app/Http/Middleware/JsonOnly.php.html deleted file mode 100644 index 96dd0f7..0000000 --- a/tests/coverage/app/Http/Middleware/JsonOnly.php.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/JsonOnly.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
JsonOnly
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 handle
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Illuminate\Http\Request;
6
7class JsonOnly
8{
9    /**
10     * Handle an incoming request.
11     *
12     * @param  \Illuminate\Http\Request $request
13     * @param  \Closure                 $next
14     * @return mixed
15     */
16    public function handle(Request $request, \Closure $next): mixed
17    {
18        if (
19            (!$request->isJson() or
20                !$request->expectsJson() or
21                is_null(json_decode($request->getContent())))
22        ) {
23            abort(400, 'Invalid JSON');
24        }
25
26        return $next($request);
27    }
28}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/PreventRequestsDuringMaintenance.php.html b/tests/coverage/app/Http/Middleware/PreventRequestsDuringMaintenance.php.html deleted file mode 100644 index 0181750..0000000 --- a/tests/coverage/app/Http/Middleware/PreventRequestsDuringMaintenance.php.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/PreventRequestsDuringMaintenance.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
PreventRequestsDuringMaintenance
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
6
7class PreventRequestsDuringMaintenance extends Middleware
8{
9    /**
10     * The URIs that should be reachable while maintenance mode is enabled.
11     *
12     * @var array<int, string>
13     */
14    protected $except = [];
15}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/RedirectIfAuthenticated.php.html b/tests/coverage/app/Http/Middleware/RedirectIfAuthenticated.php.html deleted file mode 100644 index 530e482..0000000 --- a/tests/coverage/app/Http/Middleware/RedirectIfAuthenticated.php.html +++ /dev/null @@ -1,198 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/RedirectIfAuthenticated.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
RedirectIfAuthenticated
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
72
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 handle
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
72
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Illuminate\Http\Request;
6use Symfony\Component\HttpFoundation\Response;
7
8class RedirectIfAuthenticated
9{
10    /**
11     * Handle an incoming request.
12     *
13     * @param  \Illuminate\Http\Request                                                         $request
14     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
15     * @param  string|null                                                                      ...$guards
16     * @return \Symfony\Component\HttpFoundation\Response
17     * @throws \RuntimeException If guard is unhandled.
18     * @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
19     */
20    public function handle(Request $request, \Closure $next, ...$guards): Response
21    {
22        // phpcs:enable phpcs:disable
23        $guards = empty($guards) ? [null] : $guards;
24
25        foreach ($guards as $guard) {
26            if (auth($guard)->check()) {
27                switch ($guard) {
28                    case 'frontend':
29                        return \redirect()->route('fo.homepage');
30                    case 'backend':
31                        if (!$request->routeIs('bo.*')) {
32                            continue;
33                        }
34                        return \redirect()->route('bo.dashboard');
35                    default:
36                        throw new \RuntimeException("Unhandled guard `{$guard}` .");
37                }
38            }
39        }
40
41        return $next($request);
42    }
43}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/SecureHeaders.php.html b/tests/coverage/app/Http/Middleware/SecureHeaders.php.html deleted file mode 100644 index f53a7f2..0000000 --- a/tests/coverage/app/Http/Middleware/SecureHeaders.php.html +++ /dev/null @@ -1,259 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/SecureHeaders.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 31
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
SecureHeaders
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 31
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 handle
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 29
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 removeUnwantedHeaders
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Closure;
6use Illuminate\Http\Request;
7use Illuminate\Support\Facades\Route;
8use Illuminate\Support\Facades\View;
9use Illuminate\Support\Facades\Vite;
10use Symfony\Component\HttpFoundation\Response;
11
12class SecureHeaders
13{
14    /**
15     * Enumerate headers which you do not want in your application's responses.
16     * Great starting point would be to go check out @Scott_Helme's:
17     * https://securityheaders.com/
18     *
19     * @var array
20     */
21    private $unwantedHeaderList = [
22        'X-Powered-By',
23        'Server',
24    ];
25
26    /**
27     * Handle an incoming request.
28     *
29     * @param  \Illuminate\Http\Request                                                         $request
30     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
31     * @return \Symfony\Component\HttpFoundation\Response
32     * @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
33     */
34    public function handle(Request $request, Closure $next): Response
35    {
36        // phpcs:enable
37        View::share('nonce', $nonce = Vite::useCspNonce());
38        // * For VueJS dev tool to execute
39        $jsDev     = config('app.debug') ? "'unsafe-eval' 'unsafe-inline'" : "'nonce-{$nonce}' 'strict-dynamic'";
40        $scheme    = config('app.env') === 'local' ? 'http' : 'https';
41        $reportUri = Route::has('cspReportUri') ?
42            \sprintf(' report-uri %s ;', \parse_url(route('cspReportUri'), \PHP_URL_PATH)) : '';
43        $this->removeUnwantedHeaders($this->unwantedHeaderList);
44        $response = $next($request);
45        $response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade');
46        $response->headers->set('X-Content-Type-Options', 'nosniff');
47        $response->headers->set('X-XSS-Protection', '1; mode=block');
48        $response->headers->set('X-Frame-Options', 'SAMEORIGIN');
49        $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains;');
50        $cspPolicies = [
51            "default-src 'none';",
52            "manifest-src 'self';",
53            "connect-src 'self' blob:;",
54            "img-src * data: blob:;",
55            "font-src 'self' data: https://fonts.gstatic.com;",
56            "style-src 'self' 'unsafe-inline' " . \implode(' ', []) . ';',
57            "script-src 'self' {$jsDev} " . \implode(' ', [
58                'https:  blob:',
59            ]) . ';'
60        ];
61
62        $response->headers->set(
63            'Content-Security-Policy',
64            implode(' ', $cspPolicies) . $reportUri
65        );
66        $response->headers->set('Feature-Policy', 'fullscreen \'self\';');
67        return $response;
68    }
69
70    /**
71     * Remove unwanted headers
72     *
73     * @param array $headerList
74     * @return void
75     */
76    private function removeUnwantedHeaders(array $headerList): void
77    {
78        foreach ($headerList as $header) {
79            header_remove($header);
80        }
81    }
82}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/TrimStrings.php.html b/tests/coverage/app/Http/Middleware/TrimStrings.php.html deleted file mode 100644 index 4642bcd..0000000 --- a/tests/coverage/app/Http/Middleware/TrimStrings.php.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/TrimStrings.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
TrimStrings
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
6
7class TrimStrings extends Middleware
8{
9    /**
10     * The names of the attributes that should not be trimmed.
11     *
12     * @var array<int, string>
13     */
14    protected $except = [
15        'current_password',
16        'password',
17        'password_confirmation',
18    ];
19}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/TrustHosts.php.html b/tests/coverage/app/Http/Middleware/TrustHosts.php.html deleted file mode 100644 index d02288d..0000000 --- a/tests/coverage/app/Http/Middleware/TrustHosts.php.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/TrustHosts.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
TrustHosts
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 hosts
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Illuminate\Http\Middleware\TrustHosts as Middleware;
6
7class TrustHosts extends Middleware
8{
9    /**
10     * Get the host patterns that should be trusted.
11     *
12     * @return array<int, string|null>
13     */
14    public function hosts()
15    {
16        return [
17            $this->allSubdomainsOfApplicationUrl(),
18        ];
19    }
20}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/TrustProxies.php.html b/tests/coverage/app/Http/Middleware/TrustProxies.php.html deleted file mode 100644 index 5e6c2f5..0000000 --- a/tests/coverage/app/Http/Middleware/TrustProxies.php.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/TrustProxies.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
TrustProxies
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Illuminate\Http\Middleware\TrustProxies as Middleware;
6use Illuminate\Http\Request;
7
8class TrustProxies extends Middleware
9{
10    /**
11     * The trusted proxies for this application.
12     *
13     * @var array<int, string>|string|null
14     */
15    protected $proxies;
16
17    /**
18     * The headers that should be used to detect proxies.
19     *
20     * @var integer
21     */
22    protected $headers =
23    Request::HEADER_X_FORWARDED_FOR |
24        Request::HEADER_X_FORWARDED_HOST |
25        Request::HEADER_X_FORWARDED_PORT |
26        Request::HEADER_X_FORWARDED_PROTO |
27        Request::HEADER_X_FORWARDED_AWS_ELB;
28}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/ValidateSignature.php.html b/tests/coverage/app/Http/Middleware/ValidateSignature.php.html deleted file mode 100644 index 82f0753..0000000 --- a/tests/coverage/app/Http/Middleware/ValidateSignature.php.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/ValidateSignature.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
ValidateSignature
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
6
7class ValidateSignature extends Middleware
8{
9    /**
10     * The names of the query string parameters that should be ignored.
11     *
12     * @var array<int, string>
13     */
14    protected $except = [];
15}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/VerifyCsrfToken.php.html b/tests/coverage/app/Http/Middleware/VerifyCsrfToken.php.html deleted file mode 100644 index 17c3383..0000000 --- a/tests/coverage/app/Http/Middleware/VerifyCsrfToken.php.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/VerifyCsrfToken.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
VerifyCsrfToken
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
6
7class VerifyCsrfToken extends Middleware
8{
9    /**
10     * The URIs that should be excluded from CSRF verification.
11     *
12     * @var array<int, string>
13     */
14    protected $except = [
15        '/csp-report'
16    ];
17}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/XssSanitizer.php.html b/tests/coverage/app/Http/Middleware/XssSanitizer.php.html deleted file mode 100644 index 882aeb4..0000000 --- a/tests/coverage/app/Http/Middleware/XssSanitizer.php.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware/XssSanitizer.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
XssSanitizer
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 handle
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Middleware;
4
5use Closure;
6
7class XssSanitizer
8{
9    /**
10     * Handle an incoming request.
11     *
12     * @param  mixed    $request
13     * @param  \Closure $next
14     * @return mixed
15     */
16    public function handle(mixed $request, Closure $next): mixed
17    {
18        $input = $request->all();
19        array_walk_recursive($input, function (&$input) {
20            $input = strip_tags($input);
21        });
22        $request->merge($input);
23        return $next($request);
24    }
25}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/dashboard.html b/tests/coverage/app/Http/Middleware/dashboard.html deleted file mode 100644 index 5e49526..0000000 --- a/tests/coverage/app/Http/Middleware/dashboard.html +++ /dev/null @@ -1,306 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Middleware - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- -
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - -
MethodCoverage
handle0%
handle0%
removeUnwantedHeaders0%
hosts0%
redirectTo41%
handle71%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - -
MethodCRAP
handle72
handle20
redirectTo13
handle9
removeUnwantedHeaders6
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Middleware/index.html b/tests/coverage/app/Http/Middleware/index.html deleted file mode 100644 index 865e21a..0000000 --- a/tests/coverage/app/Http/Middleware/index.html +++ /dev/null @@ -1,395 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Middleware - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 46.90% covered (danger) -
-
-
46.90%
53 / 113
-
- 33.33% covered (danger) -
-
-
33.33%
3 / 9
-
- 37.50% covered (danger) -
-
-
37.50%
3 / 8
ApiCheckTimeStamps.php
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiResponse.php
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
Authenticate.php
-
- 41.67% covered (danger) -
-
-
41.67%
5 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
EncryptCookies.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
HtmlSanitizer.php
-
- 71.43% covered (warning) -
-
-
71.43%
20 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
JsonOnly.php
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
PreventRequestsDuringMaintenance.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
RedirectIfAuthenticated.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
SecureHeaders.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 31
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
TrimStrings.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
TrustHosts.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
TrustProxies.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ValidateSignature.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
VerifyCsrfToken.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Answers/StoreAnswerRequest.php.html b/tests/coverage/app/Http/Requests/Answers/StoreAnswerRequest.php.html deleted file mode 100644 index 02a7700..0000000 --- a/tests/coverage/app/Http/Requests/Answers/StoreAnswerRequest.php.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Answers/StoreAnswerRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreAnswerRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 attributes
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Answers;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class StoreAnswerRequest extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth()->check();
17    }
18
19    /**
20     * Get the validation rules that apply to the request.
21     *
22     * @return array
23     */
24    public function rules(): array
25    {
26        return [
27            'answer' => 'required|string|min:1|max:255',
28        ];
29    }
30
31    /**
32     * Get custom attributes for validator errors.
33     *
34     * @return array
35     */
36    public function attributes(): array
37    {
38        return [
39            'answer' => trans('Réponse à une question'),
40        ];
41    }
42}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Answers/UpdateAnswerRequest.php.html b/tests/coverage/app/Http/Requests/Answers/UpdateAnswerRequest.php.html deleted file mode 100644 index c07f204..0000000 --- a/tests/coverage/app/Http/Requests/Answers/UpdateAnswerRequest.php.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Answers/UpdateAnswerRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
UpdateAnswerRequest
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Answers;
4
5class UpdateAnswerRequest extends StoreAnswerRequest
6{
7}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Answers/dashboard.html b/tests/coverage/app/Http/Requests/Answers/dashboard.html deleted file mode 100644 index 0f2f4f3..0000000 --- a/tests/coverage/app/Http/Requests/Answers/dashboard.html +++ /dev/null @@ -1,291 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Answers - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Http\Requests\Answers\StoreAnswerRequest0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - -
MethodCoverage
authorize0%
rules0%
attributes0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Answers/index.html b/tests/coverage/app/Http/Requests/Answers/index.html deleted file mode 100644 index e1ef640..0000000 --- a/tests/coverage/app/Http/Requests/Answers/index.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Answers - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreAnswerRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateAnswerRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Api/V2/AuthenticateRequest.php.html b/tests/coverage/app/Http/Requests/Api/V2/AuthenticateRequest.php.html deleted file mode 100644 index 75a2960..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/AuthenticateRequest.php.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/AuthenticateRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
AuthenticateRequest
n/a
0 / 0
n/a
0 / 0
2
n/a
0 / 0
 authorize
n/a
0 / 0
n/a
0 / 0
1
 rules
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5/**
6 * @codeCoverageIgnore
7 */
8class AuthenticateRequest extends BaseApiRequest
9{
10    /**
11     * Determine if the user is authorized to make this request.
12     *
13     * @return boolean
14     */
15    public function authorize(): bool
16    {
17        return true;
18    }
19
20    /**
21     * Get the validation rules that apply to the request.
22     *
23     * @return array
24     */
25    public function rules(): array
26    {
27        return [
28            'email'    => 'required|email:rfc',
29            'password' => 'required'
30        ];
31    }
32}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/BaseApiRequest.php.html b/tests/coverage/app/Http/Requests/Api/V2/BaseApiRequest.php.html deleted file mode 100644 index 4145faa..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/BaseApiRequest.php.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/BaseApiRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
BaseApiRequest
n/a
0 / 0
n/a
0 / 0
1
n/a
0 / 0
 authorize
n/a
0 / 0
n/a
0 / 0
1
 rules
n/a
0 / 0
n/a
0 / 0
0
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5use App\Http\Sanitizers\RemoveSpaces;
6use ArondeParon\RequestSanitizer\Sanitizers\Capitalize;
7use ArondeParon\RequestSanitizer\Sanitizers\Lowercase;
8use ArondeParon\RequestSanitizer\Sanitizers\RemoveNonNumeric;
9use ArondeParon\RequestSanitizer\Sanitizers\Trim;
10use ArondeParon\RequestSanitizer\Sanitizers\TrimDuplicateSpaces;
11use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
12use Illuminate\Foundation\Http\FormRequest;
13
14/**
15 * @codeCoverageIgnore
16 */
17abstract class BaseApiRequest extends FormRequest
18{
19    use SanitizesInputs;
20
21    /**
22     * Using these sanitizers before proceeding the request.
23     *
24     * @var array
25     */
26    protected $sanitizers = [
27        'firstname' => [Trim::class, TrimDuplicateSpaces::class, Capitalize::class],
28        'lastname'  => [Trim::class, TrimDuplicateSpaces::class, Capitalize::class],
29        'address'   => [Trim::class, TrimDuplicateSpaces::class],
30        'address2'  => [Trim::class, TrimDuplicateSpaces::class],
31        'city'      => [Trim::class, TrimDuplicateSpaces::class],
32        'password'  => Trim::class,
33        'phone'     => [Trim::class, RemoveSpaces::class],
34        'email'     => [Lowercase::class, Trim::class, RemoveSpaces::class],
35        'postcode'  => [RemoveNonNumeric::class, Trim::class]
36    ];
37
38    /**
39     * Determine if the user is authorized to make this request.
40     *
41     * @return boolean
42     */
43    public function authorize(): bool
44    {
45        return auth('api')->check();
46    }
47
48    /**
49     * Get the validation rules that apply to the request.
50     *
51     * @return array
52     */
53    abstract public function rules(): array;
54}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/GetBrandStatsRequest.php.html b/tests/coverage/app/Http/Requests/Api/V2/GetBrandStatsRequest.php.html deleted file mode 100644 index 014bc42..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/GetBrandStatsRequest.php.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/GetBrandStatsRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
GetBrandStatsRequest
n/a
0 / 0
n/a
0 / 0
4
n/a
0 / 0
 rules
n/a
0 / 0
n/a
0 / 0
4
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5use App\Http\Requests\Api\V2\BaseApiRequest;
6use Illuminate\Support\Carbon;
7use Illuminate\Validation\ValidationException;
8
9/**
10 * @codeCoverageIgnore
11 */
12class GetBrandStatsRequest extends BaseApiRequest
13{
14    /**
15     * Get the validation rules that apply to the request.
16     *
17     * @return array
18     * @throws \Illuminate\Validation\ValidationException If given dates are unparsable of
19     *                                                    period is bigger than 3 months.
20     * @throws \Exception If carbon date processing failed.
21     */
22    public function rules(): array
23    {
24        try {
25            if (Carbon::parse($this->end)->floatDiffInMonths(Carbon::parse($this->start)) > 3) {
26                throw ValidationException::withMessages([
27                    'Vous devez sélectionner une période de maximum 3 mois'
28                ]);
29            }
30        } catch (\Exception $e) {
31            if (\get_class($e) !== ValidationException::class) {
32                throw ValidationException::withMessages([
33                    'Les dates séléectionnées ne sembles pas être valides'
34                ]);
35            }
36            throw $e;
37        }
38        return [
39            'start' => 'required|date|date_format:Y-m-d',
40            'end'   => 'required|date|date_format:Y-m-d|after_or_equal:start',
41        ];
42    }
43}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/GetQuestionStatsRequest.php.html b/tests/coverage/app/Http/Requests/Api/V2/GetQuestionStatsRequest.php.html deleted file mode 100644 index 30a51bb..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/GetQuestionStatsRequest.php.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/GetQuestionStatsRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
GetQuestionStatsRequest
n/a
0 / 0
n/a
0 / 0
4
n/a
0 / 0
 rules
n/a
0 / 0
n/a
0 / 0
4
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5use App\Http\Requests\Api\V2\BaseApiRequest;
6use Exception;
7use Illuminate\Support\Carbon;
8use Illuminate\Validation\ValidationException;
9
10/**
11 * @codeCoverageIgnore
12 */
13class GetQuestionStatsRequest extends BaseApiRequest
14{
15    /**
16     * Get the validation rules that apply to the request.
17     *
18     * @return array
19     * @throws \Illuminate\Validation\ValidationException If given dates are unparsable of
20     *                                                    period is bigger than 3 months.
21     * @throws \Exception If carbon date processing failed.
22     */
23    public function rules(): array
24    {
25        try {
26            if (Carbon::parse($this->end)->floatDiffInMonths(Carbon::parse($this->start)) > 3) {
27                throw ValidationException::withMessages([
28                    'Vous devez sélectionner une période de maximum 3 mois'
29                ]);
30            }
31        } catch (Exception $e) {
32            if (\get_class($e) !== ValidationException::class) {
33                throw ValidationException::withMessages([
34                    'Les dates sélectionnées ne sembles pas être valides'
35                ]);
36            }
37            throw $e;
38        }
39        return [
40            'start' => 'required|date|date_format:Y-m-d',
41            'end'   => 'required|date|date_format:Y-m-d|after_or_equal:start',
42        ];
43    }
44}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/SendArchadiaDefaultMailRequest.php.html b/tests/coverage/app/Http/Requests/Api/V2/SendArchadiaDefaultMailRequest.php.html deleted file mode 100644 index ae4e566..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/SendArchadiaDefaultMailRequest.php.html +++ /dev/null @@ -1,253 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/SendArchadiaDefaultMailRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
SendArchadiaDefaultMailRequest
n/a
0 / 0
n/a
0 / 0
3
n/a
0 / 0
 rules
n/a
0 / 0
n/a
0 / 0
1
 attributes
n/a
0 / 0
n/a
0 / 0
1
 messages
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5use App\Enums\ArcadiaOrderType;
6use App\Http\Sanitizers\RemoveSpaces;
7use ArondeParon\RequestSanitizer\Sanitizers\RemoveNonNumeric;
8use ArondeParon\RequestSanitizer\Sanitizers\Trim;
9use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
10use Illuminate\Validation\Rules\Enum;
11
12/**
13 * @codeCoverageIgnore
14 */
15class SendArchadiaDefaultMailRequest extends BaseApiRequest
16{
17    use SanitizesInputs;
18
19    /**
20     * Using these sanitizers before proceeding the request.
21     *
22     * @var array
23     */
24    protected $sanitizers = [
25        'label_type_support'  => Trim::class,
26        'operation'           => Trim::class,
27        'order_date'          => Trim::class,
28        'order_num'           => RemoveNonNumeric::class,
29        'package_unit_weight' => RemoveNonNumeric::class,
30        'support_code'        => Trim::class,
31        'deliver.firstname'   => Trim::class,
32        'deliver.lastname'    => Trim::class,
33        'deliver.email'       => Trim::class,
34        'deliver.address'     => Trim::class,
35        'deliver.address2'    => Trim::class,
36        'deliver.city'        => Trim::class,
37        'deliver.postcode'    => Trim::class,
38        'deliver.phone'       => [Trim::class, RemoveSpaces::class]
39    ];
40
41    /**
42     * Get the validation rules that apply to the request.
43     *
44     * @return array
45     */
46    public function rules(): array
47    {
48        return [
49            'label_type_support'  => 'required|string',
50            'operation'           => 'required|int',
51            'order_date'          => 'required|date',
52            'order_num'           => 'required|numeric',
53            'package_unit_weight' => 'required|integer',
54            'state_order'         => [
55                'required',
56                new Enum(ArcadiaOrderType::class)
57            ],
58            'support_code'        => 'required|int',
59            'deliver'             => 'required|array',
60            'deliver.firstname'   => 'required|string|min:1|max:255',
61            'deliver.lastname'    => 'required|string|min:1|max:255',
62            'deliver.email'       => 'required|email:rfc,dns,spoof,filter|max:255',
63            'deliver.address'     => 'required|string|min:2|max:255',
64            'deliver.address2'    => 'sometimes|string|min:2|max:255',
65            'deliver.city'        => 'required|string|min:2|max:255',
66            'deliver.postcode'    => 'required|string|postal_code:FR|max:255',
67            'deliver.phone'       => 'present|string|nullable|phone:FR|max:255',
68        ];
69    }
70
71    /**
72     * Attributes.
73     *
74     * @return array
75     */
76    public function attributes(): array
77    {
78        return [
79            'label_type_support'  => trans('label type support'),
80            'operation'           => trans('code opération'),
81            'order_date'          => trans('date de la commande'),
82            'order_num'           => trans('numero de commande'),
83            'package_unit_weight' => trans('poids unitaire du paquet'),
84            'state_order'         => trans('type de commande arcadia'),
85            'support_code'        => trans('code de support'),
86            'deliver'             => trans('coordonées de livraison'),
87            'deliver.civility'    => trans('civilitée dans coordonées de livraison'),
88            'deliver.firstname'   => trans('prénom dans coordonées de livraison'),
89            'deliver.lastname'    => trans('nom dans coordonées de livraison'),
90            'deliver.address'     => trans('adresse dans coordonées de livraison'),
91            'deliver.postcode'    => trans('code postal dans coordonées de livraison'),
92            'deliver.phone'       => trans('téléphone dans coordonées de livraison'),
93            'deliver.city'        => trans('ville dans coordonées de livraison'),
94            'deliver.email'       => trans('e-mail dans coordonées de livraison'),
95        ];
96    }
97
98    /**
99     * Messages.
100     *
101     * @return array
102     */
103    public function messages(): array
104    {
105        return [
106            'deliver.phone.phone'          => trans('Le champ :attribute est invalide, il accepte les numéros
107                des pays suivants: France.'),
108            'deliver.postcode.postal_code' => trans('Le champ :attribute accepte les codes postaux des pays
109                suivants :countries comme par exemple :examples.'),
110        ];
111    }
112}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/SendArchadiaGameMailRequest.php.html b/tests/coverage/app/Http/Requests/Api/V2/SendArchadiaGameMailRequest.php.html deleted file mode 100644 index 2bfaa6c..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/SendArchadiaGameMailRequest.php.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/SendArchadiaGameMailRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
SendArchadiaGameMailRequest
n/a
0 / 0
n/a
0 / 0
3
n/a
0 / 0
 rules
n/a
0 / 0
n/a
0 / 0
1
 attributes
n/a
0 / 0
n/a
0 / 0
1
 messages
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5use App\Http\Sanitizers\RemoveSpaces;
6use ArondeParon\RequestSanitizer\Sanitizers\Trim;
7use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
8
9/**
10 * @codeCoverageIgnore
11 */
12class SendArchadiaGameMailRequest extends BaseApiRequest
13{
14    use SanitizesInputs;
15
16    /**
17     * Using these sanitizers before proceeding the request.
18     *
19     * @var array
20     */
21    protected $sanitizers = [
22        'code_on_pack'       => Trim::class,
23        'code_unique'        => Trim::class,
24        'label_type_support' => Trim::class,
25        'operation'          => Trim::class,
26        'order_date'         => Trim::class,
27        'support_code'       => Trim::class,
28        'type'               => Trim::class,
29        'deliver.firstname'  => Trim::class,
30        'deliver.lastname'   => Trim::class,
31        'deliver.email'      => Trim::class,
32        'deliver.address'    => Trim::class,
33        'deliver.address2'   => Trim::class,
34        'deliver.city'       => Trim::class,
35        'deliver.postcode'   => Trim::class,
36        'deliver.phone'      => [Trim::class, RemoveSpaces::class]
37    ];
38
39    /**
40     * Get the validation rules that apply to the request.
41     *
42     * @return array
43     */
44    public function rules(): array
45    {
46        return [
47            'code_on_pack'       => 'sometimes|string|max:50',
48            'code_unique'        => 'required|string',
49            'label_type_support' => 'required|string',
50            'operation'          => 'required|int',
51            'order_date'         => 'required|date',
52            'support_code'       => 'required|int',
53            'deliver'            => 'required|array',
54            'deliver.firstname'  => 'required|string|min:1|max:255',
55            'deliver.lastname'   => 'required|string|min:1|max:255',
56            'deliver.email'      => 'required|email:rfc,dns,spoof,filter|max:255',
57            'deliver.address'    => 'required|string|min:2|max:255',
58            'deliver.address2'   => 'sometimes|string|min:2|max:255',
59            'deliver.city'       => 'required|string|min:2|max:255',
60            'deliver.postcode'   => 'required|string|postal_code:FR|max:255',
61            'deliver.phone'      => 'present|string|nullable|phone:FR|max:255',
62        ];
63    }
64
65    /**
66     * Attributes.
67     *
68     * @return array
69     */
70    public function attributes(): array
71    {
72        return [
73            'code_on_pack'       => trans('code ean emballage'),
74            'code_unique'        => trans('code unique'),
75            'label_type_support' => trans('label type support'),
76            'operation'          => trans('code opération'),
77            'order_date'         => trans('date de la commande'),
78            'support_code'       => trans('code de support'),
79            'deliver'            => trans('coordonées de livraison'),
80            'deliver.civility'   => trans('civilitée dans coordonées de livraison'),
81            'deliver.firstname'  => trans('prénom dans coordonées de livraison'),
82            'deliver.lastname'   => trans('nom dans coordonées de livraison'),
83            'deliver.address'    => trans('adresse dans coordonées de livraison'),
84            'deliver.postcode'   => trans('code postal dans coordonées de livraison'),
85            'deliver.phone'      => trans('téléphone dans coordonées de livraison'),
86            'deliver.city'       => trans('ville dans coordonées de livraison'),
87            'deliver.email'      => trans('e-mail dans coordonées de livraison'),
88        ];
89    }
90
91    /**
92     * Messages.
93     *
94     * @return array
95     */
96    public function messages(): array
97    {
98        return [
99            'deliver.phone.phone'          => trans('Le champ :attribute est invalide, il accepte
100                les numéros des pays suivants: France.'),
101            'deliver.postcode.postal_code' => trans('Le champ :attribute accepte les codes postaux
102                des pays suivants :countries comme par exemple :examples.'),
103        ];
104    }
105}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/SingleOptinRemoveWithHashcodeRequest.php.html b/tests/coverage/app/Http/Requests/Api/V2/SingleOptinRemoveWithHashcodeRequest.php.html deleted file mode 100644 index 7a01d91..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/SingleOptinRemoveWithHashcodeRequest.php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/SingleOptinRemoveWithHashcodeRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
SingleOptinRemoveWithHashcodeRequest
n/a
0 / 0
n/a
0 / 0
1
n/a
0 / 0
 rules
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5/**
6 * @codeCoverageIgnore
7 */
8class SingleOptinRemoveWithHashcodeRequest extends BaseApiRequest
9{
10    /**
11     * Get the validation rules that apply to the request.
12     *
13     * @return array
14     */
15    public function rules(): array
16    {
17        return [
18            'hashcode' => 'required|string|size:36'
19        ];
20    }
21}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/SingleOptinRequest.php.html b/tests/coverage/app/Http/Requests/Api/V2/SingleOptinRequest.php.html deleted file mode 100644 index 8992c4f..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/SingleOptinRequest.php.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/SingleOptinRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
SingleOptinRequest
n/a
0 / 0
n/a
0 / 0
1
n/a
0 / 0
 rules
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5/**
6 * @codeCoverageIgnore
7 */
8class SingleOptinRequest extends BaseApiRequest
9{
10    /**
11     * Get the validation rules that apply to the request.
12     *
13     * @return array
14     */
15    public function rules(): array
16    {
17        return [
18            'email'  => 'required|email:rfc,dns,spoof,filter',
19            'opt_in' => 'required|boolean'
20        ];
21    }
22}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/StoreCustomerAnswers.php.html b/tests/coverage/app/Http/Requests/Api/V2/StoreCustomerAnswers.php.html deleted file mode 100644 index afca597..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/StoreCustomerAnswers.php.html +++ /dev/null @@ -1,168 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/StoreCustomerAnswers.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
StoreCustomerAnswers
n/a
0 / 0
n/a
0 / 0
3
n/a
0 / 0
 rules
n/a
0 / 0
n/a
0 / 0
3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5use App\Models\Answer;
6use App\Models\Question;
7use App\Models\Service;
8
9/**
10 * @codeCoverageIgnore
11 */
12class StoreCustomerAnswers extends BaseApiRequest
13{
14    /**
15     * Get the validation rules that apply to the request.
16     *
17     * @return array
18     */
19    public function rules(): array
20    {
21        // * Resolve Service.
22        $service           = app()->make(Service::class);
23        $brandId           = $service->brand->id;
24        $question          = Question::query()->findOrFail($this->question);
25        $questionTableName = (new Question())->getTable();
26        $answerTableName   = (new Answer())->getTable();
27        return [
28            'question'  => [
29                'required',
30                "exists:$questionTableName,id",
31                // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
32                function ($attribute, $value, $fail) use ($question, $brandId) {
33                    if ($question->brand->id !== $brandId) {
34                        $fail("$attribute does not belong to brand $brandId");
35                    }
36                }
37            ],
38            'answers'   => 'required|array',
39            'answers.*' => [
40                'int',
41                'distinct',
42                "exists:$answerTableName,id",
43                function ($attribute, $value, $fail) use ($question) {
44                    if (Answer::query()->findOrFail($value)->question->id !== $question->id) {
45                        $fail("$attribute does not belong to question $question->id");
46                    }
47                }
48            ]
49        ];
50    }
51}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/StoreCustomerRequest.php.html b/tests/coverage/app/Http/Requests/Api/V2/StoreCustomerRequest.php.html deleted file mode 100644 index 0f155f7..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/StoreCustomerRequest.php.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/StoreCustomerRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
StoreCustomerRequest
n/a
0 / 0
n/a
0 / 0
6
n/a
0 / 0
 prepareForValidation
n/a
0 / 0
n/a
0 / 0
2
 rules
n/a
0 / 0
n/a
0 / 0
3
 messages
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5use App\Enums\Country;
6use Illuminate\Validation\Rules\Enum;
7use Illuminate\Validation\Rules\Password;
8
9/**
10 * @codeCoverageIgnore
11 */
12class StoreCustomerRequest extends BaseApiRequest
13{
14    /**
15     * Current country
16     *
17     * @var \App\Enums\Country|null
18     */
19    protected $currentCountry = null;
20
21    /**
22     * Prepare the data for validation.
23     *
24     * @return void
25     */
26    protected function prepareForValidation(): void
27    {
28        try {
29            $this->currentCountry = Country::make(\intval($this->country));
30        } catch (\TypeError | \BadMethodCallException $e) {
31            $this->currentCountry = null;
32        }
33        parent::prepareForValidation();
34    }
35
36    /**
37     * Get the validation rules that apply to the request.
38     *
39     * @return array
40     */
41    public function rules(): array
42    {
43        $countryList = ($this->currentCountry && $this->currentCountry->get('iso')) ?
44            $this->currentCountry->get('iso') : implode(',', Country::getValidIsoAplha2Codes());
45        return [
46            'firstname'  => 'required|string|min:1|max:255',
47            'lastname'   => 'required|string|min:1|max:255',
48            'email'      => 'required|email:rfc,dns,spoof,filter|max:255',
49            'password'   => [
50                'required',
51                'max:255',
52                Password::min(8)
53                    ->mixedCase()
54                    ->letters()
55                    ->numbers()
56                    ->symbols()
57                    ->uncompromised()
58            ],
59            'birth_date' => 'required|date_format:Y-m-d|max:255',
60            'address'    => 'sometimes|required_with:address2|string|max:255',
61            'address2'   => 'sometimes|string|max:255',
62            'phone'      => ['sometimes', 'string',  "phone:{$countryList}"],
63            'country'    => [
64                'sometimes',
65                'numeric',
66                new Enum(Country::class),
67                sprintf(
68                    'in:%s',
69                    implode(',', Country::getValidCountriesValues())
70                )
71            ],
72            'city'       => 'sometimes|string|min:2|max:255',
73            'postcode'   => ['sometimes', 'string',  "postal_code:{$countryList}"],
74            'opt_in'     => 'required|boolean',
75        ];
76    }
77
78    /**
79     * Messages.
80     *
81     * @return array
82     */
83    public function messages(): array
84    {
85        return [
86            'phone.phone' => trans(
87                'Le champ :attribute est invalide, il accepte les numéros des pays
88                suivants :countries.',
89                ['countries' => implode(',', Country::getValidCountriesLabel())]
90            ),
91            'country.in'  => trans(
92                'Le champ :attribute est invalide, il accepte les pays suivants
93                :countries.',
94                ['countries' => implode(',', Country::getValidCountriesLabel())]
95            )
96        ];
97    }
98}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/UpdateCustomerRequest.php.html b/tests/coverage/app/Http/Requests/Api/V2/UpdateCustomerRequest.php.html deleted file mode 100644 index 95ea81f..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/UpdateCustomerRequest.php.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2/UpdateCustomerRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
UpdateCustomerRequest
n/a
0 / 0
n/a
0 / 0
5
n/a
0 / 0
 rules
n/a
0 / 0
n/a
0 / 0
5
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V2;
4
5use App\Enums\Country;
6use Illuminate\Validation\Rules\Enum;
7use Illuminate\Validation\Rules\Password;
8
9/**
10 * @codeCoverageIgnore
11 */
12class UpdateCustomerRequest extends StoreCustomerRequest
13{
14    /**
15     * Get the validation rules that apply to the request.
16     *
17     * @return array
18     */
19    public function rules(): array
20    {
21        $fields  = [
22            'firstname', 'lastname', 'email', 'password',
23            'birth_date', 'address', 'phone', 'country',
24            'city', 'postcode', 'opt_in'
25        ];
26        $atLeast = function ($attribute) use ($fields) {
27            return 'required_without_all:' . collect($fields)
28                ->filter(function ($fieldName) use ($attribute) {
29                    return $fieldName !== $attribute;
30                })->implode(',');
31        };
32        return [
33            'firstname'  => [$atLeast('firstname'), 'string', 'min:1', 'max:255'],
34            'lastname'   => [$atLeast('lastname'), 'string', 'min:1', 'max:255'],
35            'email'      => [$atLeast('email'), 'email:rfc,dns,spoof,filter', 'max:255'],
36            'password'   => [
37                $atLeast('password'), 'max:255', Password::min(8)
38                    ->mixedCase()
39                    ->letters()
40                    ->numbers()
41                    ->symbols()
42                    ->uncompromised()
43            ],
44            'birth_date' => [$atLeast('birth_date'), 'date_format:Y-m-d', 'max:255'],
45            'address'    => [$atLeast('address'), 'required_with:address2', 'string', 'max:255'],
46            'address2'   => ['sometimes', 'string', 'max:255'],
47            'phone'      => [$atLeast('phone'), 'string', 'phone:' . (
48                ($this->currentCountry && $this->currentCountry->get('iso')) ?
49                $this->currentCountry->get('iso') : implode(',', Country::getValidIsoAplha2Codes())
50            ), 'max:255'],
51            'country'    => [
52                $atLeast('country'),
53                'numeric',
54                new Enum(Country::class),
55                sprintf(
56                    'in:%s',
57                    implode(',', Country::getValidCountriesValues())
58                )
59            ],
60            'city'       => [$atLeast('city'), 'string', 'min:2', 'max:255'],
61            'postcode'   => [$atLeast('postcode'), 'string', 'postal_code:' . (
62                ($this->currentCountry && $this->currentCountry->get('iso')) ?
63                $this->currentCountry->get('iso') : implode(',', Country::getValidIsoAplha2Codes())
64            ), 'max:255'],
65            'opt_in'     => [$atLeast('opt_in'), 'boolean'],
66        ];
67    }
68}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/dashboard.html b/tests/coverage/app/Http/Requests/Api/V2/dashboard.html deleted file mode 100644 index 4432109..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/dashboard.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Api/V2 - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V2/index.html b/tests/coverage/app/Http/Requests/Api/V2/index.html deleted file mode 100644 index 88682bf..0000000 --- a/tests/coverage/app/Http/Requests/Api/V2/index.html +++ /dev/null @@ -1,223 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V2 - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
AuthenticateRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
BaseApiRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
GetBrandStatsRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
GetQuestionStatsRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
SendArchadiaDefaultMailRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
SendArchadiaGameMailRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
SingleOptinRemoveWithHashcodeRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
SingleOptinRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
StoreCustomerAnswers.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
StoreCustomerRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
UpdateCustomerRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Api/V4/AuthenticateRequest.php.html b/tests/coverage/app/Http/Requests/Api/V4/AuthenticateRequest.php.html deleted file mode 100644 index 6fa3be7..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/AuthenticateRequest.php.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/AuthenticateRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
AuthenticateRequest
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 authorize
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 rules
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5class AuthenticateRequest extends BaseApiRequest
6{
7    /**
8     * Determine if the user is authorized to make this request.
9     *
10     * @return boolean
11     */
12    public function authorize(): bool
13    {
14        return true;
15    }
16
17    /**
18     * Get the validation rules that apply to the request.
19     *
20     * @return array
21     */
22    public function rules(): array
23    {
24        return [
25            'email'    => 'required|email:rfc',
26            'password' => 'required'
27        ];
28    }
29}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/BaseApiRequest.php.html b/tests/coverage/app/Http/Requests/Api/V4/BaseApiRequest.php.html deleted file mode 100644 index 14af469..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/BaseApiRequest.php.html +++ /dev/null @@ -1,220 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/BaseApiRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
BaseApiRequest
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 authorize
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 rules
n/a
0 / 0
n/a
0 / 0
0
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5use App\Http\Sanitizers\RemoveSpaces;
6use ArondeParon\RequestSanitizer\Sanitizers\Capitalize;
7use ArondeParon\RequestSanitizer\Sanitizers\Lowercase;
8use ArondeParon\RequestSanitizer\Sanitizers\RemoveNonNumeric;
9use ArondeParon\RequestSanitizer\Sanitizers\Trim;
10use ArondeParon\RequestSanitizer\Sanitizers\TrimDuplicateSpaces;
11use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
12use Illuminate\Foundation\Http\FormRequest;
13
14abstract class BaseApiRequest extends FormRequest
15{
16    use SanitizesInputs;
17
18    /**
19     * Using these sanitizers before proceeding the request.
20     *
21     * @var array
22     */
23    protected $sanitizers = [
24        'firstname' => [Trim::class, TrimDuplicateSpaces::class, Capitalize::class],
25        'lastname'  => [Trim::class, TrimDuplicateSpaces::class, Capitalize::class],
26        'address'   => [Trim::class, TrimDuplicateSpaces::class],
27        'address2'  => [Trim::class, TrimDuplicateSpaces::class],
28        'city'      => [Trim::class, TrimDuplicateSpaces::class],
29        'password'  => Trim::class,
30        'phone'     => [Trim::class, RemoveSpaces::class],
31        'email'     => [Lowercase::class, Trim::class, RemoveSpaces::class],
32        'postcode'  => [RemoveNonNumeric::class, Trim::class]
33    ];
34
35    /**
36     * Determine if the user is authorized to make this request.
37     *
38     * @return boolean
39     */
40    public function authorize(): bool
41    {
42        return auth('api')->check();
43    }
44
45    /**
46     * Get the validation rules that apply to the request.
47     *
48     * @return array
49     */
50    abstract public function rules(): array;
51}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/GetBrandStatsRequest.php.html b/tests/coverage/app/Http/Requests/Api/V4/GetBrandStatsRequest.php.html deleted file mode 100644 index 8ec5d44..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/GetBrandStatsRequest.php.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/GetBrandStatsRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
GetBrandStatsRequest
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 rules
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5use App\Http\Requests\Api\V4\BaseApiRequest;
6use Illuminate\Support\Carbon;
7use Illuminate\Validation\ValidationException;
8
9class GetBrandStatsRequest extends BaseApiRequest
10{
11    /**
12     * Get the validation rules that apply to the request.
13     *
14     * @return array
15     * @throws \Illuminate\Validation\ValidationException If given dates are unparsable of
16     *                                                    period is bigger than 3 months.
17     * @throws \Exception If carbon date processing failed.
18     */
19    public function rules(): array
20    {
21        try {
22            if (Carbon::parse($this->end)->floatDiffInMonths(Carbon::parse($this->start)) > 3) {
23                throw ValidationException::withMessages([
24                    'Vous devez sélectionner une période de maximum 3 mois'
25                ]);
26            }
27        } catch (\Exception $e) {
28            if (\get_class($e) !== ValidationException::class) {
29                throw ValidationException::withMessages([
30                    'Les dates séléectionnées ne sembles pas être valides'
31                ]);
32            }
33            throw $e;
34        }
35        return [
36            'start' => 'required|date|date_format:Y-m-d',
37            'end'   => 'required|date|date_format:Y-m-d|after_or_equal:start',
38        ];
39    }
40}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/GetQuestionStatsRequest.php.html b/tests/coverage/app/Http/Requests/Api/V4/GetQuestionStatsRequest.php.html deleted file mode 100644 index 687fe6e..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/GetQuestionStatsRequest.php.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/GetQuestionStatsRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
GetQuestionStatsRequest
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 rules
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5use App\Http\Requests\Api\V4\BaseApiRequest;
6use Illuminate\Support\Carbon;
7use Illuminate\Validation\ValidationException;
8
9class GetQuestionStatsRequest extends BaseApiRequest
10{
11    /**
12     * Get the validation rules that apply to the request.
13     *
14     * @return array
15     * @throws \Illuminate\Validation\ValidationException If given dates are unparsable of
16     *                                                    period is bigger than 3 months.
17     * @throws \Exception If carbon date processing failed.
18     */
19    public function rules(): array
20    {
21        try {
22            if (Carbon::parse($this->end)->floatDiffInMonths(Carbon::parse($this->start)) > 3) {
23                throw ValidationException::withMessages([
24                    'Vous devez sélectionner une période de maximum 3 mois'
25                ]);
26            }
27        } catch (\Exception $e) {
28            if (\get_class($e) !== ValidationException::class) {
29                throw ValidationException::withMessages([
30                    'Les dates sélectionnées ne sembles pas être valides'
31                ]);
32            }
33            throw $e;
34        }
35        return [
36            'start' => 'required|date|date_format:Y-m-d',
37            'end'   => 'required|date|date_format:Y-m-d|after_or_equal:start',
38        ];
39    }
40}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/SendArchadiaDefaultMailRequest.php.html b/tests/coverage/app/Http/Requests/Api/V4/SendArchadiaDefaultMailRequest.php.html deleted file mode 100644 index 40c24d3..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/SendArchadiaDefaultMailRequest.php.html +++ /dev/null @@ -1,310 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/SendArchadiaDefaultMailRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
45 / 45
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SendArchadiaDefaultMailRequest
-
- 100.00% covered (success) -
-
-
100.00%
45 / 45
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 rules
-
- 100.00% covered (success) -
-
-
100.00%
21 / 21
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 attributes
-
- 100.00% covered (success) -
-
-
100.00%
18 / 18
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 messages
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5use App\Enums\ArcadiaOrderType;
6use App\Http\Sanitizers\RemoveSpaces;
7use ArondeParon\RequestSanitizer\Sanitizers\RemoveNonNumeric;
8use ArondeParon\RequestSanitizer\Sanitizers\Trim;
9use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
10use Illuminate\Validation\Rules\Enum;
11
12class SendArchadiaDefaultMailRequest extends BaseApiRequest
13{
14    use SanitizesInputs;
15
16    /**
17     * Using these sanitizers before proceeding the request.
18     *
19     * @var array
20     */
21    protected $sanitizers = [
22        'label_type_support'  => Trim::class,
23        'operation'           => Trim::class,
24        'order_date'          => Trim::class,
25        'order_num'           => RemoveNonNumeric::class,
26        'package_unit_weight' => RemoveNonNumeric::class,
27        'support_code'        => Trim::class,
28        'deliver.firstname'   => Trim::class,
29        'deliver.lastname'    => Trim::class,
30        'deliver.email'       => Trim::class,
31        'deliver.address'     => Trim::class,
32        'deliver.address2'    => Trim::class,
33        'deliver.city'        => Trim::class,
34        'deliver.postcode'    => Trim::class,
35        'deliver.phone'       => [Trim::class, RemoveSpaces::class]
36    ];
37
38    /**
39     * Get the validation rules that apply to the request.
40     *
41     * @return array
42     */
43    public function rules(): array
44    {
45        return [
46            'label_type_support'  => 'required|string',
47            'operation'           => 'required|int',
48            'order_date'          => 'required|date',
49            'order_num'           => 'required|numeric',
50            'package_unit_weight' => 'required|integer',
51            'state_order'         => [
52                'required',
53                new Enum(ArcadiaOrderType::class)
54            ],
55            'support_code'        => 'required|int',
56            'deliver'             => 'required|array',
57            'deliver.firstname'   => 'required|string|min:1|max:255',
58            'deliver.lastname'    => 'required|string|min:1|max:255',
59            'deliver.email'       => 'required|email:rfc,dns,spoof,filter|max:255',
60            'deliver.address'     => 'required|string|min:2|max:255',
61            'deliver.address2'    => 'sometimes|string|min:2|max:255',
62            'deliver.city'        => 'required|string|min:2|max:255',
63            'deliver.postcode'    => 'required|string|postal_code:FR|max:255',
64            'deliver.phone'       => 'present|string|nullable|phone:FR|max:255',
65        ];
66    }
67
68    /**
69     * Attributes.
70     *
71     * @return array
72     */
73    public function attributes(): array
74    {
75        return [
76            'label_type_support'  => trans('label type support'),
77            'operation'           => trans('code opération'),
78            'order_date'          => trans('date de la commande'),
79            'order_num'           => trans('numero de commande'),
80            'package_unit_weight' => trans('poids unitaire du paquet'),
81            'state_order'         => trans('type de commande arcadia'),
82            'support_code'        => trans('code de support'),
83            'deliver'             => trans('coordonées de livraison'),
84            'deliver.civility'    => trans('civilitée dans coordonées de livraison'),
85            'deliver.firstname'   => trans('prénom dans coordonées de livraison'),
86            'deliver.lastname'    => trans('nom dans coordonées de livraison'),
87            'deliver.address'     => trans('adresse dans coordonées de livraison'),
88            'deliver.postcode'    => trans('code postal dans coordonées de livraison'),
89            'deliver.phone'       => trans('téléphone dans coordonées de livraison'),
90            'deliver.city'        => trans('ville dans coordonées de livraison'),
91            'deliver.email'       => trans('e-mail dans coordonées de livraison'),
92        ];
93    }
94
95    /**
96     * Messages.
97     *
98     * @return array
99     */
100    public function messages(): array
101    {
102        return [
103            'deliver.phone.phone'          => trans('Le champ :attribute est invalide, il accepte les numéros
104                des pays suivants: France.'),
105            'deliver.postcode.postal_code' => trans('Le champ :attribute accepte les codes postaux des pays
106                suivants :countries comme par exemple :examples.'),
107        ];
108    }
109}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/SendArchadiaGameMailRequest.php.html b/tests/coverage/app/Http/Requests/Api/V4/SendArchadiaGameMailRequest.php.html deleted file mode 100644 index 8a6dfe4..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/SendArchadiaGameMailRequest.php.html +++ /dev/null @@ -1,303 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/SendArchadiaGameMailRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
40 / 40
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SendArchadiaGameMailRequest
-
- 100.00% covered (success) -
-
-
100.00%
40 / 40
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 rules
-
- 100.00% covered (success) -
-
-
100.00%
17 / 17
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 attributes
-
- 100.00% covered (success) -
-
-
100.00%
17 / 17
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 messages
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5use App\Http\Sanitizers\RemoveSpaces;
6use ArondeParon\RequestSanitizer\Sanitizers\Trim;
7use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
8
9class SendArchadiaGameMailRequest extends BaseApiRequest
10{
11    use SanitizesInputs;
12
13    /**
14     * Using these sanitizers before proceeding the request.
15     *
16     * @var array
17     */
18    protected $sanitizers = [
19        'code_on_pack'       => Trim::class,
20        'code_unique'        => Trim::class,
21        'label_type_support' => Trim::class,
22        'operation'          => Trim::class,
23        'order_date'         => Trim::class,
24        'support_code'       => Trim::class,
25        'type'               => Trim::class,
26        'deliver.firstname'  => Trim::class,
27        'deliver.lastname'   => Trim::class,
28        'deliver.email'      => Trim::class,
29        'deliver.address'    => Trim::class,
30        'deliver.address2'   => Trim::class,
31        'deliver.city'       => Trim::class,
32        'deliver.postcode'   => Trim::class,
33        'deliver.phone'      => [Trim::class, RemoveSpaces::class]
34    ];
35
36    /**
37     * Get the validation rules that apply to the request.
38     *
39     * @return array
40     */
41    public function rules(): array
42    {
43        return [
44            'code_on_pack'       => 'sometimes|string|max:50',
45            'code_unique'        => 'required|string',
46            'label_type_support' => 'required|string',
47            'operation'          => 'required|int',
48            'order_date'         => 'required|date',
49            'support_code'       => 'required|int',
50            'deliver'            => 'required|array',
51            'deliver.firstname'  => 'required|string|min:1|max:255',
52            'deliver.lastname'   => 'required|string|min:1|max:255',
53            'deliver.email'      => 'required|email:rfc,dns,spoof,filter|max:255',
54            'deliver.address'    => 'required|string|min:2|max:255',
55            'deliver.address2'   => 'sometimes|string|min:2|max:255',
56            'deliver.city'       => 'required|string|min:2|max:255',
57            'deliver.postcode'   => 'required|string|postal_code:FR|max:255',
58            'deliver.phone'      => 'present|string|nullable|phone:FR|max:255',
59        ];
60    }
61
62    /**
63     * Attributes.
64     *
65     * @return array
66     */
67    public function attributes(): array
68    {
69        return [
70            'code_on_pack'       => trans('code ean emballage'),
71            'code_unique'        => trans('code unique'),
72            'label_type_support' => trans('label type support'),
73            'operation'          => trans('code opération'),
74            'order_date'         => trans('date de la commande'),
75            'support_code'       => trans('code de support'),
76            'deliver'            => trans('coordonées de livraison'),
77            'deliver.civility'   => trans('civilitée dans coordonées de livraison'),
78            'deliver.firstname'  => trans('prénom dans coordonées de livraison'),
79            'deliver.lastname'   => trans('nom dans coordonées de livraison'),
80            'deliver.address'    => trans('adresse dans coordonées de livraison'),
81            'deliver.postcode'   => trans('code postal dans coordonées de livraison'),
82            'deliver.phone'      => trans('téléphone dans coordonées de livraison'),
83            'deliver.city'       => trans('ville dans coordonées de livraison'),
84            'deliver.email'      => trans('e-mail dans coordonées de livraison'),
85        ];
86    }
87
88    /**
89     * Messages.
90     *
91     * @return array
92     */
93    public function messages(): array
94    {
95        return [
96            'deliver.phone.phone'          => trans('Le champ :attribute est invalide, il accepte
97                les numéros des pays suivants: France.'),
98            'deliver.postcode.postal_code' => trans('Le champ :attribute accepte les codes postaux
99                des pays suivants :countries comme par exemple :examples.'),
100        ];
101    }
102}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/SingleOptinRemoveWithHashcodeRequest.php.html b/tests/coverage/app/Http/Requests/Api/V4/SingleOptinRemoveWithHashcodeRequest.php.html deleted file mode 100644 index 54c1d66..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/SingleOptinRemoveWithHashcodeRequest.php.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/SingleOptinRemoveWithHashcodeRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SingleOptinRemoveWithHashcodeRequest
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 rules
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5class SingleOptinRemoveWithHashcodeRequest extends BaseApiRequest
6{
7    /**
8     * Get the validation rules that apply to the request.
9     *
10     * @return array
11     */
12    public function rules(): array
13    {
14        return [
15            'hashcode' => 'required|string|size:36'
16        ];
17    }
18}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/SingleOptinRequest.php.html b/tests/coverage/app/Http/Requests/Api/V4/SingleOptinRequest.php.html deleted file mode 100644 index e38ced2..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/SingleOptinRequest.php.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/SingleOptinRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SingleOptinRequest
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 rules
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5class SingleOptinRequest extends BaseApiRequest
6{
7    /**
8     * Get the validation rules that apply to the request.
9     *
10     * @return array
11     */
12    public function rules(): array
13    {
14        return [
15            'email'  => 'required|email:rfc,dns,spoof,filter',
16            'opt_in' => 'required|boolean'
17        ];
18    }
19}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/StoreCustomerAnswers.php.html b/tests/coverage/app/Http/Requests/Api/V4/StoreCustomerAnswers.php.html deleted file mode 100644 index b0a1257..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/StoreCustomerAnswers.php.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/StoreCustomerAnswers.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 92.00% covered (success) -
-
-
92.00%
23 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreCustomerAnswers
-
- 92.00% covered (success) -
-
-
92.00%
23 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.00
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 rules
-
- 92.00% covered (success) -
-
-
92.00%
23 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.00
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5use App\Models\Answer;
6use App\Models\Question;
7use App\Models\Service;
8
9class StoreCustomerAnswers extends BaseApiRequest
10{
11    /**
12     * Get the validation rules that apply to the request.
13     *
14     * @return array
15     */
16    public function rules(): array
17    {
18        // * Resolve Service.
19        $service           = app()->make(Service::class);
20        $brandId           = $service->brand->id;
21        $question          = Question::query()->findOrFail($this->question);
22        $questionTableName = (new Question())->getTable();
23        $answerTableName   = (new Answer())->getTable();
24        return [
25            'question'  => [
26                'required',
27                "exists:$questionTableName,id",
28                // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
29                function ($attribute, $value, $fail) use ($question, $brandId) {
30                    if ($question->brand->id !== $brandId) {
31                        $fail("$attribute does not belong to brand $brandId");
32                    }
33                }
34            ],
35            'answers'   => 'required|array',
36            'answers.*' => [
37                'int',
38                'distinct',
39                "exists:$answerTableName,id",
40                function ($attribute, $value, $fail) use ($question) {
41                    if (Answer::query()->findOrFail($value)->question->id !== $question->id) {
42                        $fail("$attribute does not belong to question $question->id");
43                    }
44                }
45            ]
46        ];
47    }
48}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/StoreCustomerRequest.php.html b/tests/coverage/app/Http/Requests/Api/V4/StoreCustomerRequest.php.html deleted file mode 100644 index 0f2eacc..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/StoreCustomerRequest.php.html +++ /dev/null @@ -1,296 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/StoreCustomerRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 95.92% covered (success) -
-
-
95.92%
47 / 49
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreCustomerRequest
-
- 95.92% covered (success) -
-
-
95.92%
47 / 49
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 prepareForValidation
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.50
 rules
-
- 100.00% covered (success) -
-
-
100.00%
33 / 33
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
 messages
-
- 100.00% covered (success) -
-
-
100.00%
12 / 12
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5use App\Enums\Country;
6use Illuminate\Validation\Rules\Enum;
7use Illuminate\Validation\Rules\Password;
8
9class StoreCustomerRequest extends BaseApiRequest
10{
11    /**
12     * Current country
13     *
14     * @var \App\Enums\Country|null
15     */
16    protected $currentCountry = null;
17
18    /**
19     * Prepare the data for validation.
20     *
21     * @return void
22     */
23    protected function prepareForValidation(): void
24    {
25        try {
26            $this->currentCountry = Country::make(\intval($this->country));
27        } catch (\TypeError | \BadMethodCallException $e) {
28            $this->currentCountry = null;
29        }
30        parent::prepareForValidation();
31    }
32
33    /**
34     * Get the validation rules that apply to the request.
35     *
36     * @return array
37     */
38    public function rules(): array
39    {
40        $countryList = ($this->currentCountry && $this->currentCountry->get('iso')) ?
41            $this->currentCountry->get('iso') : implode(',', Country::getValidIsoAplha2Codes());
42        return [
43            'firstname'  => 'required|string|min:1|max:255',
44            'lastname'   => 'required|string|min:1|max:255',
45            'email'      => 'required|email:rfc,dns,spoof,filter|max:255',
46            'password'   => [
47                'required',
48                'max:255',
49                Password::min(8)
50                    ->mixedCase()
51                    ->letters()
52                    ->numbers()
53                    ->symbols()
54                    ->uncompromised()
55            ],
56            'birth_date' => 'required|date_format:Y-m-d|max:255',
57            'address'    => 'sometimes|required_with:address2|string|max:255',
58            'address2'   => 'sometimes|string|max:255',
59            'phone'      => ['sometimes', 'string',  "phone:{$countryList}"],
60            'country'    => [
61                'sometimes',
62                'numeric',
63                new Enum(Country::class),
64                sprintf(
65                    'in:%s',
66                    implode(',', Country::getValidCountriesValues())
67                )
68            ],
69            'city'       => 'sometimes|string|min:2|max:255',
70            'postcode'   => ['sometimes', 'string',  "postal_code:{$countryList}"],
71            'opt_in'     => 'required|boolean',
72        ];
73    }
74
75    /**
76     * Messages.
77     *
78     * @return array
79     */
80    public function messages(): array
81    {
82        return [
83            'phone.phone' => trans(
84                'Le champ :attribute est invalide, il accepte les numéros des pays
85                suivants :countries.',
86                ['countries' => implode(',', Country::getValidCountriesLabel())]
87            ),
88            'country.in'  => trans(
89                'Le champ :attribute est invalide, il accepte les pays suivants
90                :countries.',
91                ['countries' => implode(',', Country::getValidCountriesLabel())]
92            )
93        ];
94    }
95}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/UpdateCustomerRequest.php.html b/tests/coverage/app/Http/Requests/Api/V4/UpdateCustomerRequest.php.html deleted file mode 100644 index d6ce883..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/UpdateCustomerRequest.php.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4/UpdateCustomerRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
46 / 46
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
UpdateCustomerRequest
-
- 100.00% covered (success) -
-
-
100.00%
46 / 46
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 rules
-
- 100.00% covered (success) -
-
-
100.00%
46 / 46
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
5
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Api\V4;
4
5use App\Enums\Country;
6use Illuminate\Validation\Rules\Enum;
7use Illuminate\Validation\Rules\Password;
8
9class UpdateCustomerRequest extends StoreCustomerRequest
10{
11    /**
12     * Get the validation rules that apply to the request.
13     *
14     * @return array
15     */
16    public function rules(): array
17    {
18        $fields  = [
19            'firstname', 'lastname', 'email', 'password',
20            'birth_date', 'address', 'phone', 'country',
21            'city', 'postcode', 'opt_in'
22        ];
23        $atLeast = function ($attribute) use ($fields) {
24            return 'required_without_all:' . collect($fields)
25                ->filter(function ($fieldName) use ($attribute) {
26                    return $fieldName !== $attribute;
27                })->implode(',');
28        };
29        return [
30            'firstname'  => [$atLeast('firstname'), 'string', 'min:1', 'max:255'],
31            'lastname'   => [$atLeast('lastname'), 'string', 'min:1', 'max:255'],
32            'email'      => [$atLeast('email'), 'email:rfc,dns,spoof,filter', 'max:255'],
33            'password'   => [
34                $atLeast('password'), 'max:255', Password::min(8)
35                    ->mixedCase()
36                    ->letters()
37                    ->numbers()
38                    ->symbols()
39                    ->uncompromised()
40            ],
41            'birth_date' => [$atLeast('birth_date'), 'date_format:Y-m-d', 'max:255'],
42            'address'    => [$atLeast('address'), 'required_with:address2', 'string', 'max:255'],
43            'address2'   => ['sometimes', 'string', 'max:255'],
44            'phone'      => [$atLeast('phone'), 'string', 'phone:' . (
45                ($this->currentCountry && $this->currentCountry->get('iso')) ?
46                $this->currentCountry->get('iso') : implode(',', Country::getValidIsoAplha2Codes())
47            ), 'max:255'],
48            'country'    => [
49                $atLeast('country'),
50                'numeric',
51                new Enum(Country::class),
52                sprintf(
53                    'in:%s',
54                    implode(',', Country::getValidCountriesValues())
55                )
56            ],
57            'city'       => [$atLeast('city'), 'string', 'min:2', 'max:255'],
58            'postcode'   => [$atLeast('postcode'), 'string', 'postal_code:' . (
59                ($this->currentCountry && $this->currentCountry->get('iso')) ?
60                $this->currentCountry->get('iso') : implode(',', Country::getValidIsoAplha2Codes())
61            ), 'max:255'],
62            'opt_in'     => [$atLeast('opt_in'), 'boolean'],
63        ];
64    }
65}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/dashboard.html b/tests/coverage/app/Http/Requests/Api/V4/dashboard.html deleted file mode 100644 index 7fb1162..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/dashboard.html +++ /dev/null @@ -1,290 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Api/V4 - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
MethodCoverage
prepareForValidation50%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
MethodCRAP
prepareForValidation2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/V4/index.html b/tests/coverage/app/Http/Requests/Api/V4/index.html deleted file mode 100644 index a3b3907..0000000 --- a/tests/coverage/app/Http/Requests/Api/V4/index.html +++ /dev/null @@ -1,403 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api/V4 - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 98.37% covered (success) -
-
-
98.37%
242 / 246
-
- 88.89% covered (warning) -
-
-
88.89%
16 / 18
-
- 81.82% covered (warning) -
-
-
81.82%
9 / 11
AuthenticateRequest.php
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
BaseApiRequest.php
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
GetBrandStatsRequest.php
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
GetQuestionStatsRequest.php
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SendArchadiaDefaultMailRequest.php
-
- 100.00% covered (success) -
-
-
100.00%
45 / 45
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SendArchadiaGameMailRequest.php
-
- 100.00% covered (success) -
-
-
100.00%
40 / 40
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SingleOptinRemoveWithHashcodeRequest.php
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SingleOptinRequest.php
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
StoreCustomerAnswers.php
-
- 92.00% covered (success) -
-
-
92.00%
23 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreCustomerRequest.php
-
- 95.92% covered (success) -
-
-
95.92%
47 / 49
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateCustomerRequest.php
-
- 100.00% covered (success) -
-
-
100.00%
46 / 46
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Api/dashboard.html b/tests/coverage/app/Http/Requests/Api/dashboard.html deleted file mode 100644 index 3d8d0fe..0000000 --- a/tests/coverage/app/Http/Requests/Api/dashboard.html +++ /dev/null @@ -1,289 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Api - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
MethodCoverage
prepareForValidation50%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
MethodCRAP
prepareForValidation2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Api/index.html b/tests/coverage/app/Http/Requests/Api/index.html deleted file mode 100644 index 9639872..0000000 --- a/tests/coverage/app/Http/Requests/Api/index.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Api - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 98.37% covered (success) -
-
-
98.37%
242 / 246
-
- 88.89% covered (warning) -
-
-
88.89%
16 / 18
-
- 81.82% covered (warning) -
-
-
81.82%
9 / 11
V2
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
V4
-
- 98.37% covered (success) -
-
-
98.37%
242 / 246
-
- 88.89% covered (warning) -
-
-
88.89%
16 / 18
-
- 81.82% covered (warning) -
-
-
81.82%
9 / 11
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Bo/Answers/StoreAnswerRequest.php.html b/tests/coverage/app/Http/Requests/Bo/Answers/StoreAnswerRequest.php.html deleted file mode 100644 index 00fd099..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Answers/StoreAnswerRequest.php.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Answers/StoreAnswerRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreAnswerRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 attributes
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo\Answers;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class StoreAnswerRequest extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth('backend')->check();
17    }
18
19    /**
20     * Get the validation rules that apply to the request.
21     *
22     * @return array
23     */
24    public function rules(): array
25    {
26        return [
27            'answer' => 'required|string|min:1|max:255',
28        ];
29    }
30
31    /**
32     * Get custom attributes for validator errors.
33     *
34     * @return array
35     */
36    public function attributes(): array
37    {
38        return [
39            'answer' => trans('Réponse à une question'),
40        ];
41    }
42}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Answers/UpdateAnswerRequest.php.html b/tests/coverage/app/Http/Requests/Bo/Answers/UpdateAnswerRequest.php.html deleted file mode 100644 index fc02feb..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Answers/UpdateAnswerRequest.php.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Answers/UpdateAnswerRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
UpdateAnswerRequest
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo\Answers;
4
5class UpdateAnswerRequest extends StoreAnswerRequest
6{
7}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Answers/dashboard.html b/tests/coverage/app/Http/Requests/Bo/Answers/dashboard.html deleted file mode 100644 index b37b810..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Answers/dashboard.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Bo/Answers - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Http\Requests\Bo\Answers\StoreAnswerRequest0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - -
MethodCoverage
authorize0%
rules0%
attributes0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Answers/index.html b/tests/coverage/app/Http/Requests/Bo/Answers/index.html deleted file mode 100644 index f0a1333..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Answers/index.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Answers - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreAnswerRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateAnswerRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Bo/Brands/StoreBrandRequest.php.html b/tests/coverage/app/Http/Requests/Bo/Brands/StoreBrandRequest.php.html deleted file mode 100644 index f8b05f4..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Brands/StoreBrandRequest.php.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Brands/StoreBrandRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreBrandRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 attributes
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo\Brands;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class StoreBrandRequest extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth('backend')->check();
17    }
18
19    /**
20     * Get the validation rules that apply to the request.
21     *
22     * @return array
23     */
24    public function rules(): array
25    {
26        return [
27            'name' => 'required|string|min:5|max:255',
28        ];
29    }
30
31    /**
32     * Get custom attributes for validator errors.
33     *
34     * @return array
35     */
36    public function attributes(): array
37    {
38        return [
39            'name' => trans('Nom de la marque'),
40        ];
41    }
42}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Brands/UpdateBrandRequest.php.html b/tests/coverage/app/Http/Requests/Bo/Brands/UpdateBrandRequest.php.html deleted file mode 100644 index c99d86a..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Brands/UpdateBrandRequest.php.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Brands/UpdateBrandRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
UpdateBrandRequest
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo\Brands;
4
5class UpdateBrandRequest extends StoreBrandRequest
6{
7}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Brands/dashboard.html b/tests/coverage/app/Http/Requests/Bo/Brands/dashboard.html deleted file mode 100644 index e6ee8b2..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Brands/dashboard.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Bo/Brands - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Http\Requests\Bo\Brands\StoreBrandRequest0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - -
MethodCoverage
authorize0%
rules0%
attributes0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Brands/index.html b/tests/coverage/app/Http/Requests/Bo/Brands/index.html deleted file mode 100644 index 1c968d0..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Brands/index.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Brands - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreBrandRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateBrandRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Bo/CustomerExport.php.html b/tests/coverage/app/Http/Requests/Bo/CustomerExport.php.html deleted file mode 100644 index d432b1a..0000000 --- a/tests/coverage/app/Http/Requests/Bo/CustomerExport.php.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/CustomerExport.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerExport
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo;
4
5use App\Enums\CustomerExportType;
6use Illuminate\Foundation\Http\FormRequest;
7
8class CustomerExport extends FormRequest
9{
10    /**
11     * Determine if the user is authorized to make this request.
12     *
13     * @return boolean
14     */
15    public function authorize(): bool
16    {
17        return auth('backend')->check();
18    }
19
20    /**
21     * Get the validation rules that apply to the request.
22     *
23     * @return array
24     */
25    public function rules(): array
26    {
27        return [
28            'brand'       => 'required|numeric|exists:brands,id',
29            'export_type' => [
30                'required',
31                'numeric',
32                // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
33                function ($attribute, $value, $fail) {
34                    if (!\in_array($value, CustomerExportType::toValues())) {
35                        $fail(trans('Le type d\'export invalide'));
36                    }
37                }
38            ]
39        ];
40    }
41}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/GenerateServiceToken.php.html b/tests/coverage/app/Http/Requests/Bo/GenerateServiceToken.php.html deleted file mode 100644 index 197e9b1..0000000 --- a/tests/coverage/app/Http/Requests/Bo/GenerateServiceToken.php.html +++ /dev/null @@ -1,206 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/GenerateServiceToken.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
GenerateServiceToken
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class GenerateServiceToken extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth('backend')->check();
17    }
18
19    /**
20     * Get the validation rules that apply to the request.
21     *
22     * @return array
23     */
24    public function rules(): array
25    {
26        return [];
27    }
28}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/ManageBrandRequest.php.html b/tests/coverage/app/Http/Requests/Bo/ManageBrandRequest.php.html deleted file mode 100644 index e18b702..0000000 --- a/tests/coverage/app/Http/Requests/Bo/ManageBrandRequest.php.html +++ /dev/null @@ -1,228 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/ManageBrandRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ManageBrandRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo;
4
5use ArondeParon\RequestSanitizer\Sanitizers\FilterVars;
6use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
7use Illuminate\Foundation\Http\FormRequest;
8
9class ManageBrandRequest extends FormRequest
10{
11    use SanitizesInputs;
12
13    /**
14     * Using these sanitizers before proceeding the request
15     *
16     * @var array
17     */
18    protected $sanitizers = [
19        'name' => [
20            FilterVars::class => [
21                'filter' => FILTER_SANITIZE_STRING
22            ]
23        ],
24    ];
25
26    /**
27     * Determine if the user is authorized to make this request.
28     *
29     * @return boolean
30     */
31    public function authorize(): bool
32    {
33        return auth('backend')->check();
34    }
35
36    /**
37     * Get the validation rules that apply to the request.
38     *
39     * @return array
40     */
41    public function rules(): array
42    {
43        if ($this->isMethod('post')) {
44            return [
45                'name' => 'required|string|min:5|max:255'
46            ];
47        }
48        return [];
49    }
50}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/ManageServiceRequest.php.html b/tests/coverage/app/Http/Requests/Bo/ManageServiceRequest.php.html deleted file mode 100644 index 3bea47a..0000000 --- a/tests/coverage/app/Http/Requests/Bo/ManageServiceRequest.php.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/ManageServiceRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ManageServiceRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo;
4
5use ArondeParon\RequestSanitizer\Sanitizers\FilterVars;
6use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
7use Illuminate\Foundation\Http\FormRequest;
8
9class ManageServiceRequest extends FormRequest
10{
11    use SanitizesInputs;
12
13    /**
14     * Using these sanitizers before proceeding the request
15     *
16     * @var array
17     */
18    protected $sanitizers = [
19        'name' => [
20            FilterVars::class => [
21                'filter' => FILTER_SANITIZE_STRING
22            ]
23        ],
24    ];
25
26    /**
27     * Determine if the user is authorized to make this request.
28     *
29     * @return boolean
30     */
31    public function authorize(): bool
32    {
33        return auth('backend')->check();
34    }
35
36    /**
37     * Get the validation rules that apply to the request.
38     *
39     * @return array
40     */
41    public function rules(): array
42    {
43        if ($this->isMethod('post')) {
44            return [
45                'name'     => 'required|string|min:5|max:255',
46                'brand_id' => 'required|exists:brands,id'
47            ];
48        }
49        return [];
50    }
51}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/QuestionExport.php.html b/tests/coverage/app/Http/Requests/Bo/QuestionExport.php.html deleted file mode 100644 index 509bbf0..0000000 --- a/tests/coverage/app/Http/Requests/Bo/QuestionExport.php.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/QuestionExport.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
QuestionExport
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class QuestionExport extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth('backend')->check();
17    }
18
19    /**
20     * Get the validation rules that apply to the request.
21     *
22     * @return array
23     */
24    public function rules(): array
25    {
26        return [
27            'brand' => 'required|numeric|exists:brands,id'
28        ];
29    }
30}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Questions/StoreQuestionRequest.php.html b/tests/coverage/app/Http/Requests/Bo/Questions/StoreQuestionRequest.php.html deleted file mode 100644 index 9528be1..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Questions/StoreQuestionRequest.php.html +++ /dev/null @@ -1,283 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Questions/StoreQuestionRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreQuestionRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
20
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 prepareForValidation
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 attributes
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo\Questions;
4
5use App\Enums\QuestionType;
6use Illuminate\Foundation\Http\FormRequest;
7use Illuminate\Validation\Rules\Enum;
8
9class StoreQuestionRequest extends FormRequest
10{
11    /**
12     * Determine if the user is authorized to make this request.
13     *
14     * @return boolean
15     */
16    public function authorize(): bool
17    {
18        return auth('backend')->check();
19    }
20
21    /**
22     * Prepare the data for validation.
23     *
24     * @return void
25     */
26    protected function prepareForValidation(): void
27    {
28        $this->merge([
29            'brand_id' => collect($this->brand)->pluck('id')->first()
30        ]);
31    }
32
33    /**
34     * Get the validation rules that apply to the request.
35     *
36     * @return array
37     */
38    public function rules(): array
39    {
40        return [
41            'question' => 'required|string|min:10|max:255',
42            'type'     => ['required', new Enum(QuestionType::class)],
43            'brand_id' => 'required|integer|min:0|exists:brands,id',
44        ];
45    }
46
47    /**
48     * Get custom attributes for validator errors.
49     *
50     * @return array
51     */
52    public function attributes(): array
53    {
54        return [
55            'question' => trans('Texte de la question'),
56            'type'     => trans('Type de question'),
57            'brand_id' => trans('Id de la marque'),
58        ];
59    }
60}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Questions/UpdateQuestionRequest.php.html b/tests/coverage/app/Http/Requests/Bo/Questions/UpdateQuestionRequest.php.html deleted file mode 100644 index b5c5b85..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Questions/UpdateQuestionRequest.php.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Questions/UpdateQuestionRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
UpdateQuestionRequest
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo\Questions;
4
5class UpdateQuestionRequest extends StoreQuestionRequest
6{
7}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Questions/dashboard.html b/tests/coverage/app/Http/Requests/Bo/Questions/dashboard.html deleted file mode 100644 index b945eaf..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Questions/dashboard.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Bo/Questions - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Http\Requests\Bo\Questions\StoreQuestionRequest0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - -
MethodCoverage
authorize0%
prepareForValidation0%
rules0%
attributes0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Questions/index.html b/tests/coverage/app/Http/Requests/Bo/Questions/index.html deleted file mode 100644 index 6d67b02..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Questions/index.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Questions - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreQuestionRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateQuestionRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Bo/Services/StoreServiceRequest.php.html b/tests/coverage/app/Http/Requests/Bo/Services/StoreServiceRequest.php.html deleted file mode 100644 index 86cce6d..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Services/StoreServiceRequest.php.html +++ /dev/null @@ -1,279 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Services/StoreServiceRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreServiceRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
20
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 prepareForValidation
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 attributes
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo\Services;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class StoreServiceRequest extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth('backend')->check();
17    }
18
19    /**
20     * Prepare the data for validation.
21     *
22     * @return void
23     */
24    protected function prepareForValidation(): void
25    {
26        $this->merge([
27            'brand_id' => collect($this->brand)->pluck('id')->first()
28        ]);
29    }
30
31    /**
32     * Get the validation rules that apply to the request.
33     *
34     * @return array
35     */
36    public function rules(): array
37    {
38        return [
39            'name'     => 'required|string|min:5|max:255',
40            'brand_id' => 'required|integer|min:0|exists:brands,id',
41        ];
42    }
43
44    /**
45     * Get custom attributes for validator errors.
46     *
47     * @return array
48     */
49    public function attributes(): array
50    {
51        return [
52            'name'     => trans('Nom du service'),
53            'brand_id' => trans('Id de la marque'),
54        ];
55    }
56}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Services/UpdateServiceRequest.php.html b/tests/coverage/app/Http/Requests/Bo/Services/UpdateServiceRequest.php.html deleted file mode 100644 index efb68af..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Services/UpdateServiceRequest.php.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Services/UpdateServiceRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
UpdateServiceRequest
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo\Services;
4
5class UpdateServiceRequest extends StoreServiceRequest
6{
7}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Services/dashboard.html b/tests/coverage/app/Http/Requests/Bo/Services/dashboard.html deleted file mode 100644 index ab72138..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Services/dashboard.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Bo/Services - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Http\Requests\Bo\Services\StoreServiceRequest0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - -
MethodCoverage
authorize0%
prepareForValidation0%
rules0%
attributes0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Services/index.html b/tests/coverage/app/Http/Requests/Bo/Services/index.html deleted file mode 100644 index 2d14e58..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Services/index.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Services - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreServiceRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateServiceRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Bo/StatsByBrandRequest.php.html b/tests/coverage/app/Http/Requests/Bo/StatsByBrandRequest.php.html deleted file mode 100644 index 878d9c5..0000000 --- a/tests/coverage/app/Http/Requests/Bo/StatsByBrandRequest.php.html +++ /dev/null @@ -1,232 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/StatsByBrandRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatsByBrandRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo;
4
5use Illuminate\Foundation\Http\FormRequest;
6use Illuminate\Support\Carbon;
7use Illuminate\Validation\ValidationException;
8
9class StatsByBrandRequest extends FormRequest
10{
11    /**
12     * Determine if the user is authorized to make this request.
13     *
14     * @return boolean
15     */
16    public function authorize(): bool
17    {
18        return auth('backend')->check();
19    }
20
21    /**
22     * Get the validation rules that apply to the request.
23     *
24     * @return array
25     * @throws \Illuminate\Validation\ValidationException If given dates are unparsable of period
26     *                                                    is bigger than 1 year.
27     * @throws \Exception If carbon date processing failed.
28     */
29    public function rules(): array
30    {
31        if ($this->post()) {
32            try {
33                if ((Carbon::parse($this->end)->diffInDays(Carbon::parse($this->start)) + 1) > 365) {
34                    throw ValidationException::withMessages([
35                        'Vous devez sélectionner une période de maximum 1 ans'
36                    ]);
37                }
38            } catch (\Exception $e) {
39                if (\get_class($e) !== ValidationException::class) {
40                    throw ValidationException::withMessages([
41                        'Les dates séléectionnées ne sembles pas être valides'
42                    ]);
43                }
44                throw $e;
45            }
46            return [
47                'brand' => 'required|exists:brands,id',
48                'start' => 'required|date|date_format:Y-m-d',
49                'end'   => 'required|date|date_format:Y-m-d|after_or_equal:start',
50            ];
51        } //end if
52        return [];
53    }
54}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/StatsByQuestionRequest.php.html b/tests/coverage/app/Http/Requests/Bo/StatsByQuestionRequest.php.html deleted file mode 100644 index 8020f36..0000000 --- a/tests/coverage/app/Http/Requests/Bo/StatsByQuestionRequest.php.html +++ /dev/null @@ -1,232 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/StatsByQuestionRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatsByQuestionRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo;
4
5use Illuminate\Foundation\Http\FormRequest;
6use Illuminate\Support\Carbon;
7use Illuminate\Validation\ValidationException;
8
9class StatsByQuestionRequest extends FormRequest
10{
11    /**
12     * Determine if the user is authorized to make this request.
13     *
14     * @return boolean
15     */
16    public function authorize(): bool
17    {
18        return auth('backend')->check();
19    }
20
21    /**
22     * Get the validation rules that apply to the request.
23     *
24     * @return array
25     * @throws \Illuminate\Validation\ValidationException If given dates are unparsable of period
26     *                                                    is bigger than 1 year.
27     * @throws \Exception If carbon date processing failed.
28     */
29    public function rules(): array
30    {
31        if ($this->post()) {
32            try {
33                if ((Carbon::parse($this->end)->diffInDays(Carbon::parse($this->start)) + 1) > 365) {
34                    throw ValidationException::withMessages([
35                        'Vous devez sélectionner une période de maximum 1 ans'
36                    ]);
37                }
38            } catch (\Exception $e) {
39                if (\get_class($e) !== ValidationException::class) {
40                    throw ValidationException::withMessages([
41                        'Les dates sélectionnées ne sembles pas être valides'
42                    ]);
43                }
44                throw $e;
45            }
46            return [
47                'question' => 'required|exists:questions,id',
48                'start'    => 'required|date|date_format:Y-m-d',
49                'end'      => 'required|date|date_format:Y-m-d|after_or_equal:start',
50            ];
51        } //end if
52        return [];
53    }
54}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/UpdateChangeOrderRequest.php.html b/tests/coverage/app/Http/Requests/Bo/UpdateChangeOrderRequest.php.html deleted file mode 100644 index 3597567..0000000 --- a/tests/coverage/app/Http/Requests/Bo/UpdateChangeOrderRequest.php.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/UpdateChangeOrderRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateChangeOrderRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
20
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 prepareForValidation
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class UpdateChangeOrderRequest extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth('backend')->check();
17    }
18
19    /**
20     * Prepare the data for validation.
21     *
22     * @return void
23     */
24    protected function prepareForValidation(): void
25    {
26        $this->merge([
27            'direction' => $this->direction === 'up' ? true : false
28        ]);
29    }
30
31    /**
32     * Get the validation rules that apply to the request.
33     *
34     * @return array
35     */
36    public function rules(): array
37    {
38        return [
39            'direction' => 'required|boolean',
40        ];
41    }
42}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/UpdateMiniCrudRequest.php.html b/tests/coverage/app/Http/Requests/Bo/UpdateMiniCrudRequest.php.html deleted file mode 100644 index eff5864..0000000 --- a/tests/coverage/app/Http/Requests/Bo/UpdateMiniCrudRequest.php.html +++ /dev/null @@ -1,473 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/UpdateMiniCrudRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 144
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateMiniCrudRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 144
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
1190
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 116
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
462
 compileValidate
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
90
 ruleHasToComeFirst
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 isUpdate
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo;
4
5use App\Enums\InputType;
6use App\Lib\Helpers\ToolboxHelper;
7use Illuminate\Foundation\Http\FormRequest;
8use Illuminate\Validation\ValidationException;
9
10abstract class UpdateMiniCrudRequest extends FormRequest
11{
12    /**
13     * The model parameter name
14     *
15     * @var string
16     */
17    protected $modelName = null;
18
19    /**
20     * Determine if the user is authorized to make this request.
21     *
22     * @return boolean
23     */
24    public function authorize()
25    {
26        return auth('backend')->check();
27    }
28
29    /**
30     * Get the validation rules that apply to the request.
31     *
32     * @return array
33     * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
34     * @phpcs:disable Generic.Metrics.NestingLevel.TooHigh
35     */
36    public function rules()
37    {
38        // phpcs:enable
39        $rules = [];
40        foreach ($this->{$this->modelName}->data as $iptName => $input) {
41            $input = \json_decode(\json_encode($input), true);
42            switch ($input['inputType']) {
43                case InputType::number->value:
44                    $rules = array_merge($rules, [
45                        "data.$iptName.value" => $this->compileValidate('required|numeric', $input)
46                    ]);
47                    break;
48                case InputType::videoYoutube->value:
49                    $rules = array_merge($rules, [
50                        "data.$iptName.value" => $this->compileValidate('regex:%([^"&?\/\s]{11})%i', $input)
51                    ]);
52                    break;
53                case InputType::videoVimeo->value:
54                    $rules = array_merge($rules, [
55                        "data.$iptName.value" => $this->compileValidate('regex:%([0-9]{8,10})%i', $input)
56                    ]);
57                    break;
58                case InputType::video->value:
59                    $rules = array_merge($rules, [
60                        "data.$iptName.value" => $this->compileValidate([
61                            'regex:%([0-9]{8,10}|[^"&?\/\s]{11})%i'
62                        ], $input)
63                    ]);
64                    break;
65                case InputType::string->value:
66                    $rules = array_merge($rules, [
67                        "data.$iptName.value" => $this->compileValidate('required|string|min:3', $input)
68                    ]);
69                    break;
70                case InputType::text->value:
71                    $mergeRules = $this->compileValidate('required|string|min:15', $input);
72                    $mergeRules = collect($mergeRules)
73                        ->map(function ($rule) {
74                            if (\strpos($rule, 'max:') !== false) {
75                                $max = \intval(str_replace('max:', '', $rule));
76                                return function ($attribute, $value, $fail) use ($max) {
77                                    if (\strlen(\strip_tags($value)) > $max) {
78                                        $fail("$attribute ne doit pas excéder $max caractères");
79                                    }
80                                };
81                            }
82                            return $rule;
83                        });
84                    $rules      = array_merge($rules, [
85                        "data.$iptName.value" => $mergeRules
86                    ]);
87                    break;
88                case InputType::image->value:
89                    $required = $this->isUpdate() ? 'sometimes' : 'required';
90
91                    $ipt = $this->data[$iptName];
92                    $max = isset($ipt['dimensionsMax']);
93                    $dim = \is_string($input['dimensions']) ? collect(explode(
94                        ',',
95                        (isset($ipt['dimensionsMax']) and is_string($ipt['dimensionsMax'])) ?
96                            $ipt['dimensionsMax'] : $input['dimensions']
97                    ))->mapWithKeys(function ($v) {
98                        $v = explode(' ', $v);
99                        return [$v[0] => $v[1]];
100                    }) : $input['dimensions'];
101
102                    // * Adapt dimensions
103                    $sizes = (object)[
104                        'minHeight' => $dim['height'],
105                        'maxHeight' => $dim['height'],
106                        'minWith' => $dim['width'],
107                        'maxWith' => $dim['width'],
108                    ];
109                    $rules = array_merge($rules, [
110                        "data.$iptName.value" => [
111                            function (string $attribute, $value, callable $fail) use ($sizes) {
112                                return ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
113                            }
114                        ],
115                        $this->compileValidate(
116                            implode('|', [
117                                $required,
118                                'image',
119                                'mimes:png,jpg,jpeg',
120                                sprintf(
121                                    'dimensions:%s=%d,%s=%d',
122                                    $max ? 'max_height' : 'height',
123                                    $dim['height'],
124                                    $max ? 'max_width' : 'width',
125                                    $dim['width']
126                                )
127                            ]),
128                            $input
129                        ),
130                        "data.$iptName.alt" => $this->compileValidate("$required|string|min:5", $input),
131                        "data.$iptName.title" => $this->compileValidate("$required|string|min:5", $input)
132                    ]);
133                    break;
134                case InputType::url->value:
135                    $rules = array_merge($rules, [
136                        "data.$iptName.value" => [
137                            'required', 'url',
138                            // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
139                            function ($attribute, $value, $fail) {
140                                try {
141                                    ToolboxHelper::assertNoInternalUrls($attribute, $value);
142                                    ToolboxHelper::assertNoInternalBoUrls($attribute, $value);
143                                } catch (ValidationException $e) {
144                                    $fail(collect($e->errors())->first()[0]);
145                                }
146                            }
147                        ]
148                    ]);
149                    break;
150                case InputType::boolean->value:
151                    $all    = $this->all();
152                    $nested = ToolboxHelper::dotStringToNestedArray(
153                        "data.$iptName.value",
154                        $this->input("data.$iptName.value") ? true : false
155                    );
156                    $all    = ToolboxHelper::arrayMergeRecursiveDistinct($all, $nested);
157                    $this->merge($all);
158                    $rules = array_merge($rules, [
159                        "data.$iptName.value" => 'boolean'
160                    ]);
161                    break;
162            } //end switch
163        } //end foreach
164        return $rules;
165    }
166
167    /**
168     * Undocumented function
169     *
170     * @param string|array $inputTypeValidate
171     * @param array        $input
172     * @return array
173     */
174    public function compileValidate(string|array $inputTypeValidate, array $input): array
175    {
176        if (\is_string($inputTypeValidate)) {
177            $inputTypeValidate = explode('|', $inputTypeValidate);
178        }
179        /** @var array|string */
180        $inputValidate = \collect($input)->get('validate', $input);
181        $inputValidate = \is_string($inputValidate) ? explode('|', $inputValidate) : $inputValidate;
182        foreach ($inputValidate as $validate) {
183            if (!\in_array($validate, $inputTypeValidate)) {
184                $inputTypeValidate[] = $validate;
185            }
186        }
187
188        $test = \collect($inputTypeValidate)->all();
189        $test = \collect($inputTypeValidate)->sort(function ($valueA, $valueB) {
190            $valueA = $this->ruleHasToComeFirst($valueA) ? 0 : 2;
191            $valueB = $this->ruleHasToComeFirst($valueB) ? 1 : 2;
192            return $valueA - $valueB;
193        })->unique()->all();
194
195        return \collect($inputTypeValidate)->unique()->sort(function ($valueA, $valueB) {
196            $valueA = $this->ruleHasToComeFirst($valueA) ? 0 : 2;
197            $valueB = $this->ruleHasToComeFirst($valueB) ? 1 : 2;
198            return $valueA - $valueB;
199        })->all();
200    }
201
202    /**
203     * Does the rulle need to come first ?
204     *
205     * @param string $rule
206     * @return boolean
207     */
208    private function ruleHasToComeFirst(string $rule): bool
209    {
210        $rule = \collect(\explode(':', $rule, 1))->filter()->first(null, '');
211        return \collect([
212            'nullable', 'present', 'required', 'required_if',
213            'required_unless', 'required_with', 'required_with_all',
214            'required_without', 'required_without_all', 'required_with_all',
215            'missing', 'missing_if', 'missing_unless',
216            'missing_with', 'missing_with_all',
217        ])->first(fn (string $firstRule) =>  \strpos($rule, $firstRule) === 0) ? true : false;
218    }
219
220    /**
221     * Is this request an update request ?
222     *
223     * @return boolean
224     */
225    private function isUpdate(): bool
226    {
227        return $this->isMethod('PUT');
228    }
229}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Users/StoreUserRequest.php.html b/tests/coverage/app/Http/Requests/Bo/Users/StoreUserRequest.php.html deleted file mode 100644 index 7df932a..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Users/StoreUserRequest.php.html +++ /dev/null @@ -1,297 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Users/StoreUserRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 27
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreUserRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 27
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 prepareForValidation
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 attributes
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo\Users;
4
5use App\Enums\Users\RoleEnum;
6use Illuminate\Foundation\Http\FormRequest;
7use Illuminate\Validation\Rules\Enum;
8use Illuminate\Validation\Rules\Password;
9
10class StoreUserRequest extends FormRequest
11{
12    /**
13     * Determine if the user is authorized to make this request.
14     *
15     * @return boolean
16     */
17    public function authorize(): bool
18    {
19        return auth('backend')->check();
20    }
21
22    /**
23     * Prepare the data for validation.
24     *
25     * @return void
26     */
27    protected function prepareForValidation()
28    {
29        $this->merge([
30            'published' => $this->published ? true : false
31        ]);
32    }
33
34    /**
35     * Get the validation rules that apply to the request.
36     *
37     * @return array
38     */
39    public function rules(): array
40    {
41        return [
42            'first_name' => 'required|string|min:3|max:255',
43            'last_name' => 'required|string|min:3|max:255',
44            'email' => 'required|email:rfc,strict,dns,spoof,filter|unique:users,email',
45            'password' => [
46                'required', 'required_with:password_confirmation', 'confirmed', 'max:255', Password::min(8)
47                    ->letters()
48                    ->mixedCase()
49                    ->numbers()
50                    ->symbols()
51                    ->uncompromised()
52            ],
53            'role' => ['required', new Enum(RoleEnum::class)],
54            'published' => 'required|boolean',
55        ];
56    }
57
58    /**
59     * Get custom attributes for validator errors.
60     *
61     * @return array
62     */
63    public function attributes(): array
64    {
65        return [
66            'first_name' => trans('validation.attributes.first_name'),
67            'last_name' => trans('validation.attributes.last_name'),
68            'email' => trans('validation.attributes.email'),
69            'password' => trans('validation.attributes.password'),
70            'role' => trans('validation.attributes.role'),
71            'published' => trans('validation.custom.publication')
72        ];
73    }
74}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Users/UpdateUserRequest.php.html b/tests/coverage/app/Http/Requests/Bo/Users/UpdateUserRequest.php.html deleted file mode 100644 index 6d92421..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Users/UpdateUserRequest.php.html +++ /dev/null @@ -1,227 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Users/UpdateUserRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 22
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateUserRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 22
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 prepareForValidation
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Bo\Users;
4
5use Illuminate\Validation\Rules\Password;
6
7class UpdateUserRequest extends StoreUserRequest
8{
9    /**
10     * Prepare the data for validation.
11     *
12     * @return void
13     */
14    protected function prepareForValidation()
15    {
16        $this->merge([
17            'published' => $this->published ? true : false,
18            'password' => $this->password ? $this->password : $this->route('user')->password,
19            'password_confirmation' => $this->password_confirmation ?
20                $this->password_confirmation :
21                $this->route('user')->password
22        ]);
23    }
24
25    /**
26     * Get the validation rules that apply to the request.
27     *
28     * @return array
29     */
30    public function rules(): array
31    {
32        return array_merge(parent::rules(), [
33            'email' => [
34                'required',
35                'email:rfc,strict,dns,spoof,filter',
36                'unique:users,email,' . $this->route('user')->id . ',id',
37            ],
38            'password' => [
39                'required', 'required_with:password_confirmation', 'confirmed', 'max:255', Password::min(8)
40                    ->letters()
41                    ->mixedCase()
42                    ->numbers()
43                    ->symbols()
44                    ->uncompromised()
45            ],
46        ]);
47    }
48}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Users/dashboard.html b/tests/coverage/app/Http/Requests/Bo/Users/dashboard.html deleted file mode 100644 index d1b2628..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Users/dashboard.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Bo/Users - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

- -
-
-

Project Risks

- -
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - -
MethodCoverage
authorize0%
prepareForValidation0%
rules0%
attributes0%
prepareForValidation0%
rules0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - -
MethodCRAP
prepareForValidation20
prepareForValidation6
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/Users/index.html b/tests/coverage/app/Http/Requests/Bo/Users/index.html deleted file mode 100644 index d1b8e76..0000000 --- a/tests/coverage/app/Http/Requests/Bo/Users/index.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo/Users - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 49
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
StoreUserRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 27
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateUserRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 22
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Bo/dashboard.html b/tests/coverage/app/Http/Requests/Bo/dashboard.html deleted file mode 100644 index b280f00..0000000 --- a/tests/coverage/app/Http/Requests/Bo/dashboard.html +++ /dev/null @@ -1,364 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Bo - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- -
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- - -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Bo/index.html b/tests/coverage/app/Http/Requests/Bo/index.html deleted file mode 100644 index 760e0b4..0000000 --- a/tests/coverage/app/Http/Requests/Bo/index.html +++ /dev/null @@ -1,486 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Bo - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 307
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 15
Answers
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Brands
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Questions
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Services
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Users
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 49
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CustomerExport.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
GenerateServiceToken.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ManageBrandRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ManageServiceRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
QuestionExport.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatsByBrandRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatsByQuestionRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateChangeOrderRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateMiniCrudRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 144
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Brands/StoreBrandRequest.php.html b/tests/coverage/app/Http/Requests/Brands/StoreBrandRequest.php.html deleted file mode 100644 index e29c852..0000000 --- a/tests/coverage/app/Http/Requests/Brands/StoreBrandRequest.php.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Brands/StoreBrandRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreBrandRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 attributes
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Brands;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class StoreBrandRequest extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth()->check();
17    }
18
19    /**
20     * Get the validation rules that apply to the request.
21     *
22     * @return array
23     */
24    public function rules(): array
25    {
26        return [
27            'name' => 'required|string|min:5|max:255',
28        ];
29    }
30
31    /**
32     * Get custom attributes for validator errors.
33     *
34     * @return array
35     */
36    public function attributes(): array
37    {
38        return [
39            'name' => trans('Nom de la marque'),
40        ];
41    }
42}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Brands/UpdateBrandRequest.php.html b/tests/coverage/app/Http/Requests/Brands/UpdateBrandRequest.php.html deleted file mode 100644 index 8918a27..0000000 --- a/tests/coverage/app/Http/Requests/Brands/UpdateBrandRequest.php.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Brands/UpdateBrandRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
UpdateBrandRequest
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Brands;
4
5class UpdateBrandRequest extends StoreBrandRequest
6{
7}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Brands/dashboard.html b/tests/coverage/app/Http/Requests/Brands/dashboard.html deleted file mode 100644 index e60aa8c..0000000 --- a/tests/coverage/app/Http/Requests/Brands/dashboard.html +++ /dev/null @@ -1,291 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Brands - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Http\Requests\Brands\StoreBrandRequest0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - -
MethodCoverage
authorize0%
rules0%
attributes0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Brands/index.html b/tests/coverage/app/Http/Requests/Brands/index.html deleted file mode 100644 index d39f381..0000000 --- a/tests/coverage/app/Http/Requests/Brands/index.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Brands - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreBrandRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateBrandRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/CustomerExport.php.html b/tests/coverage/app/Http/Requests/CustomerExport.php.html deleted file mode 100644 index e4b507d..0000000 --- a/tests/coverage/app/Http/Requests/CustomerExport.php.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/CustomerExport.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerExport
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests;
4
5use App\Enums\CustomerExportType;
6use Illuminate\Foundation\Http\FormRequest;
7
8class CustomerExport extends FormRequest
9{
10    /**
11     * Determine if the user is authorized to make this request.
12     *
13     * @return boolean
14     */
15    public function authorize(): bool
16    {
17        return auth()->check();
18    }
19
20    /**
21     * Get the validation rules that apply to the request.
22     *
23     * @return array
24     */
25    public function rules(): array
26    {
27        return [
28            'brand'       => 'required|numeric|exists:brands,id',
29            'export_type' => [
30                'required',
31                'numeric',
32                // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
33                function ($attribute, $value, $fail) {
34                    if (!\in_array($value, CustomerExportType::toValues())) {
35                        $fail(trans('Le type d\'export invalide'));
36                    }
37                }
38            ]
39        ];
40    }
41}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/GenerateServiceToken.php.html b/tests/coverage/app/Http/Requests/GenerateServiceToken.php.html deleted file mode 100644 index 6bd6b95..0000000 --- a/tests/coverage/app/Http/Requests/GenerateServiceToken.php.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/GenerateServiceToken.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
GenerateServiceToken
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class GenerateServiceToken extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth()->check();
17    }
18
19    /**
20     * Get the validation rules that apply to the request.
21     *
22     * @return array
23     */
24    public function rules(): array
25    {
26        return [];
27    }
28}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/ManageBrandRequest.php.html b/tests/coverage/app/Http/Requests/ManageBrandRequest.php.html deleted file mode 100644 index 516ba87..0000000 --- a/tests/coverage/app/Http/Requests/ManageBrandRequest.php.html +++ /dev/null @@ -1,227 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/ManageBrandRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ManageBrandRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests;
4
5use ArondeParon\RequestSanitizer\Sanitizers\FilterVars;
6use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
7use Illuminate\Foundation\Http\FormRequest;
8
9class ManageBrandRequest extends FormRequest
10{
11    use SanitizesInputs;
12
13    /**
14     * Using these sanitizers before proceeding the request
15     *
16     * @var array
17     */
18    protected $sanitizers = [
19        'name' => [
20            FilterVars::class => [
21                'filter' => FILTER_SANITIZE_STRING
22            ]
23        ],
24    ];
25
26    /**
27     * Determine if the user is authorized to make this request.
28     *
29     * @return boolean
30     */
31    public function authorize(): bool
32    {
33        return auth()->check();
34    }
35
36    /**
37     * Get the validation rules that apply to the request.
38     *
39     * @return array
40     */
41    public function rules(): array
42    {
43        if ($this->isMethod('post')) {
44            return [
45                'name' => 'required|string|min:5|max:255'
46            ];
47        }
48        return [];
49    }
50}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/ManageServiceRequest.php.html b/tests/coverage/app/Http/Requests/ManageServiceRequest.php.html deleted file mode 100644 index 70c4d9d..0000000 --- a/tests/coverage/app/Http/Requests/ManageServiceRequest.php.html +++ /dev/null @@ -1,228 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/ManageServiceRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ManageServiceRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests;
4
5use ArondeParon\RequestSanitizer\Sanitizers\FilterVars;
6use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
7use Illuminate\Foundation\Http\FormRequest;
8
9class ManageServiceRequest extends FormRequest
10{
11    use SanitizesInputs;
12
13    /**
14     * Using these sanitizers before proceeding the request
15     *
16     * @var array
17     */
18    protected $sanitizers = [
19        'name' => [
20            FilterVars::class => [
21                'filter' => FILTER_SANITIZE_STRING
22            ]
23        ],
24    ];
25
26    /**
27     * Determine if the user is authorized to make this request.
28     *
29     * @return boolean
30     */
31    public function authorize(): bool
32    {
33        return auth()->check();
34    }
35
36    /**
37     * Get the validation rules that apply to the request.
38     *
39     * @return array
40     */
41    public function rules(): array
42    {
43        if ($this->isMethod('post')) {
44            return [
45                'name'     => 'required|string|min:5|max:255',
46                'brand_id' => 'required|exists:brands,id'
47            ];
48        }
49        return [];
50    }
51}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/QuestionExport.php.html b/tests/coverage/app/Http/Requests/QuestionExport.php.html deleted file mode 100644 index 268afe7..0000000 --- a/tests/coverage/app/Http/Requests/QuestionExport.php.html +++ /dev/null @@ -1,207 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/QuestionExport.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
QuestionExport
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class QuestionExport extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth()->check();
17    }
18
19    /**
20     * Get the validation rules that apply to the request.
21     *
22     * @return array
23     */
24    public function rules(): array
25    {
26        return [
27            'brand' => 'required|numeric|exists:brands,id'
28        ];
29    }
30}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Questions/StoreQuestionRequest.php.html b/tests/coverage/app/Http/Requests/Questions/StoreQuestionRequest.php.html deleted file mode 100644 index 57ac68b..0000000 --- a/tests/coverage/app/Http/Requests/Questions/StoreQuestionRequest.php.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Questions/StoreQuestionRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreQuestionRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 attributes
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Questions;
4
5use App\Enums\QuestionType;
6use Illuminate\Foundation\Http\FormRequest;
7use Illuminate\Validation\Rules\Enum;
8
9class StoreQuestionRequest extends FormRequest
10{
11    /**
12     * Determine if the user is authorized to make this request.
13     *
14     * @return boolean
15     */
16    public function authorize(): bool
17    {
18        return auth()->check();
19    }
20
21    /**
22     * Get the validation rules that apply to the request.
23     *
24     * @return array
25     */
26    public function rules(): array
27    {
28        return [
29            'question' => 'required|string|min:10|max:255',
30            'type'     => ['required', new Enum(QuestionType::class)],
31            'brand_id' => 'required|integer|min:0|exists:brands,id',
32        ];
33    }
34
35    /**
36     * Get custom attributes for validator errors.
37     *
38     * @return array
39     */
40    public function attributes(): array
41    {
42        return [
43            'question' => trans('Texte de la question'),
44            'type'     => trans('Type de question'),
45            'brand_id' => trans('Id de la marque'),
46        ];
47    }
48}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Questions/UpdateQuestionRequest.php.html b/tests/coverage/app/Http/Requests/Questions/UpdateQuestionRequest.php.html deleted file mode 100644 index 7c79b51..0000000 --- a/tests/coverage/app/Http/Requests/Questions/UpdateQuestionRequest.php.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Questions/UpdateQuestionRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
UpdateQuestionRequest
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Questions;
4
5class UpdateQuestionRequest extends StoreQuestionRequest
6{
7}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Questions/dashboard.html b/tests/coverage/app/Http/Requests/Questions/dashboard.html deleted file mode 100644 index 21cb807..0000000 --- a/tests/coverage/app/Http/Requests/Questions/dashboard.html +++ /dev/null @@ -1,291 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Questions - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Http\Requests\Questions\StoreQuestionRequest0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - -
MethodCoverage
authorize0%
rules0%
attributes0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Questions/index.html b/tests/coverage/app/Http/Requests/Questions/index.html deleted file mode 100644 index 1a3b436..0000000 --- a/tests/coverage/app/Http/Requests/Questions/index.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Questions - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreQuestionRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateQuestionRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/Services/StoreServiceRequest.php.html b/tests/coverage/app/Http/Requests/Services/StoreServiceRequest.php.html deleted file mode 100644 index 27dc048..0000000 --- a/tests/coverage/app/Http/Requests/Services/StoreServiceRequest.php.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Services/StoreServiceRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreServiceRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 attributes
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Services;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7class StoreServiceRequest extends FormRequest
8{
9    /**
10     * Determine if the user is authorized to make this request.
11     *
12     * @return boolean
13     */
14    public function authorize(): bool
15    {
16        return auth()->check();
17    }
18
19    /**
20     * Get the validation rules that apply to the request.
21     *
22     * @return array
23     */
24    public function rules(): array
25    {
26        return [
27            'name'     => 'required|string|min:5|max:255',
28            'brand_id' => 'required|integer|min:0|exists:brands,id',
29        ];
30    }
31
32    /**
33     * Get custom attributes for validator errors.
34     *
35     * @return array
36     */
37    public function attributes(): array
38    {
39        return [
40            'name'     => trans('Nom du service'),
41            'brand_id' => trans('Id de la marque'),
42        ];
43    }
44}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Services/UpdateServiceRequest.php.html b/tests/coverage/app/Http/Requests/Services/UpdateServiceRequest.php.html deleted file mode 100644 index ee0925f..0000000 --- a/tests/coverage/app/Http/Requests/Services/UpdateServiceRequest.php.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Services/UpdateServiceRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
UpdateServiceRequest
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests\Services;
4
5class UpdateServiceRequest extends StoreServiceRequest
6{
7}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Services/dashboard.html b/tests/coverage/app/Http/Requests/Services/dashboard.html deleted file mode 100644 index ca05f21..0000000 --- a/tests/coverage/app/Http/Requests/Services/dashboard.html +++ /dev/null @@ -1,291 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests/Services - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Http\Requests\Services\StoreServiceRequest0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - -
MethodCoverage
authorize0%
rules0%
attributes0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/Services/index.html b/tests/coverage/app/Http/Requests/Services/index.html deleted file mode 100644 index 43460ca..0000000 --- a/tests/coverage/app/Http/Requests/Services/index.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/Services - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StoreServiceRequest.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateServiceRequest.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Requests/StatsByBrandRequest.php.html b/tests/coverage/app/Http/Requests/StatsByBrandRequest.php.html deleted file mode 100644 index 183f5e6..0000000 --- a/tests/coverage/app/Http/Requests/StatsByBrandRequest.php.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/StatsByBrandRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatsByBrandRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests;
4
5use Illuminate\Foundation\Http\FormRequest;
6use Illuminate\Support\Carbon;
7use Illuminate\Validation\ValidationException;
8
9class StatsByBrandRequest extends FormRequest
10{
11    /**
12     * Determine if the user is authorized to make this request.
13     *
14     * @return boolean
15     */
16    public function authorize(): bool
17    {
18        return auth()->check();
19    }
20
21    /**
22     * Get the validation rules that apply to the request.
23     *
24     * @return array
25     * @throws \Illuminate\Validation\ValidationException If given dates are unparsable of period
26     *                                                    is bigger than 1 year.
27     * @throws \Exception If carbon date processing failed.
28     */
29    public function rules(): array
30    {
31        if ($this->post()) {
32            try {
33                if ((Carbon::parse($this->end)->diffInDays(Carbon::parse($this->start)) + 1) > 365) {
34                    throw ValidationException::withMessages([
35                        'Vous devez sélectionner une période de maximum 1 ans'
36                    ]);
37                }
38            } catch (\Exception $e) {
39                if (\get_class($e) !== ValidationException::class) {
40                    throw ValidationException::withMessages([
41                        'Les dates séléectionnées ne sembles pas être valides'
42                    ]);
43                }
44                throw $e;
45            }
46            return [
47                'brand' => 'required|exists:brands,id',
48                'start' => 'required|date|date_format:Y-m-d',
49                'end'   => 'required|date|date_format:Y-m-d|after_or_equal:start',
50            ];
51        } //end if
52        return [];
53    }
54}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/StatsByQuestionRequest.php.html b/tests/coverage/app/Http/Requests/StatsByQuestionRequest.php.html deleted file mode 100644 index 1061c1f..0000000 --- a/tests/coverage/app/Http/Requests/StatsByQuestionRequest.php.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests/StatsByQuestionRequest.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatsByQuestionRequest
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 authorize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 rules
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Requests;
4
5use Illuminate\Foundation\Http\FormRequest;
6use Illuminate\Support\Carbon;
7use Illuminate\Validation\ValidationException;
8
9class StatsByQuestionRequest extends FormRequest
10{
11    /**
12     * Determine if the user is authorized to make this request.
13     *
14     * @return boolean
15     */
16    public function authorize(): bool
17    {
18        return auth()->check();
19    }
20
21    /**
22     * Get the validation rules that apply to the request.
23     *
24     * @return array
25     * @throws \Illuminate\Validation\ValidationException If given dates are unparsable of period
26     *                                                    is bigger than 1 year.
27     * @throws \Exception If carbon date processing failed.
28     */
29    public function rules(): array
30    {
31        if ($this->post()) {
32            try {
33                if ((Carbon::parse($this->end)->diffInDays(Carbon::parse($this->start)) + 1) > 365) {
34                    throw ValidationException::withMessages([
35                        'Vous devez sélectionner une période de maximum 1 ans'
36                    ]);
37                }
38            } catch (\Exception $e) {
39                if (\get_class($e) !== ValidationException::class) {
40                    throw ValidationException::withMessages([
41                        'Les dates sélectionnées ne sembles pas être valides'
42                    ]);
43                }
44                throw $e;
45            }
46            return [
47                'question' => 'required|exists:questions,id',
48                'start'    => 'required|date|date_format:Y-m-d',
49                'end'      => 'required|date|date_format:Y-m-d|after_or_equal:start',
50            ];
51        } //end if
52        return [];
53    }
54}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.3.5 at Thu Oct 5 13:16:08 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Requests/dashboard.html b/tests/coverage/app/Http/Requests/dashboard.html deleted file mode 100644 index 4c759db..0000000 --- a/tests/coverage/app/Http/Requests/dashboard.html +++ /dev/null @@ -1,365 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Requests - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- -
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- - -
- - - - - - diff --git a/tests/coverage/app/Http/Requests/index.html b/tests/coverage/app/Http/Requests/index.html deleted file mode 100644 index 584a633..0000000 --- a/tests/coverage/app/Http/Requests/index.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Requests - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 43.76% covered (danger) -
-
-
43.76%
242 / 553
-
- 26.67% covered (danger) -
-
-
26.67%
16 / 60
-
- 34.62% covered (danger) -
-
-
34.62%
9 / 26
Api
-
- 98.37% covered (success) -
-
-
98.37%
242 / 246
-
- 88.89% covered (warning) -
-
-
88.89%
16 / 18
-
- 81.82% covered (warning) -
-
-
81.82%
9 / 11
Bo
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 307
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 15
-
- -
- - diff --git a/tests/coverage/app/Http/Resources/Api/V2/AnswersResource.php.html b/tests/coverage/app/Http/Resources/Api/V2/AnswersResource.php.html deleted file mode 100644 index 49b01cc..0000000 --- a/tests/coverage/app/Http/Resources/Api/V2/AnswersResource.php.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V2/AnswersResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
AnswersResource
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V2;
4
5use App\Models\Answer;
6use Illuminate\Http\Request;
7use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
8
9class AnswersResource extends JsonResourceCollection
10{
11    /**
12     * Transform the resource into an array.
13     *
14     * @param \Illuminate\Http\Request $request
15     * @return \Illuminate\Support\Collection
16     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
17     */
18    public function toArray(Request $request): \Illuminate\Support\Collection
19    {
20        //phpcs:enable
21        return $this->collection->map(function (Answer $answer) {
22            return [
23                'id' => $answer->id,
24                'answer' => $answer->answer
25            ];
26        });
27    }
28}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V2/ApiResponse.php.html b/tests/coverage/app/Http/Resources/Api/V2/ApiResponse.php.html deleted file mode 100644 index d1f4dbb..0000000 --- a/tests/coverage/app/Http/Resources/Api/V2/ApiResponse.php.html +++ /dev/null @@ -1,223 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V2/ApiResponse.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiResponse
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V2;
4
5use App\Enums\ApiStatus;
6use Illuminate\Http\Request;
7use Illuminate\Http\Resources\Json\JsonResource;
8use stdClass;
9
10class ApiResponse extends JsonResource
11{
12    /** @var \stdClass|null */
13    protected $data;
14
15    /** @var \App\Enums\ApiStatus */
16    protected $status;
17
18    /**
19     * @param \stdClass|null       $data
20     * @param \App\Enums\ApiStatus $status
21     */
22    public function __construct(stdClass|null $data = null, ApiStatus $status)
23    {
24        $this->status = $status;
25        $this->data   = $data;
26    }
27
28    /**
29     * Transform the resource into an array.
30     *
31     * @param \Illuminate\Http\Request $request
32     * @return array
33     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
34     */
35    public function toArray(Request $request): array
36    {
37        //phpcs:enable
38        return [
39            'status' => $this->status->value(),
40            'data' => (array)($this->data ?? []),
41            'version' => '3.0.6'
42        ];
43    }
44}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V2/BrandStatsResource.php.html b/tests/coverage/app/Http/Resources/Api/V2/BrandStatsResource.php.html deleted file mode 100644 index 2629d2c..0000000 --- a/tests/coverage/app/Http/Resources/Api/V2/BrandStatsResource.php.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V2/BrandStatsResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
BrandStatsResource
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V2;
4
5use App\Models\BrandStat;
6use Illuminate\Http\Request;
7use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
8
9class BrandStatsResource extends JsonResourceCollection
10{
11    /**
12     * Transform the resource into an array.
13     *
14     * @param \Illuminate\Http\Request $request
15     * @return array
16     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
17     */
18    public function toArray(Request $request): array
19    {
20        //phpcs:enable
21        return [
22            'stats' => $this->collection->map(function (BrandStat $brandStat) {
23                return [
24                    'date'           => $brandStat->created_at->isoFormat('YYYY-MM-DD'),
25                    'active'         => $brandStat->active,
26                    'inactive'       => $brandStat->inactive,
27                    'old_accounts'   => $brandStat->old_accounts,
28                    'new_accounts'   => $brandStat->new_accounts,
29                    'total_accounts' => $brandStat->total_accounts,
30                    'total_opt_in'   => $brandStat->total_opt_in
31                ];
32            })
33        ];
34    }
35}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V2/CustomerResource.php.html b/tests/coverage/app/Http/Resources/Api/V2/CustomerResource.php.html deleted file mode 100644 index 47c5d60..0000000 --- a/tests/coverage/app/Http/Resources/Api/V2/CustomerResource.php.html +++ /dev/null @@ -1,302 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V2/CustomerResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
18 / 18
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerResource
-
- 100.00% covered (success) -
-
-
100.00%
18 / 18
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getSkeleton
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V2;
4
5use App\Models\Brand;
6use App\Models\Customer;
7use Illuminate\Http\Resources\Json\JsonResource;
8
9class CustomerResource extends JsonResource
10{
11    /** @var \App\Models\Customer */
12    private $customer;
13
14    /** @var \App\Models\CustomerInfo */
15    private $info;
16
17    /** @var \App\Models\CustomerLogin */
18    private $login;
19
20    /** @var array */
21    private static $skeleton = [
22        'hashcode'   => '',
23        'firstname'  => '',
24        'lastname'   => '',
25        'email'      => '',
26        'birth_date' => '',
27        'address'    => '',
28        'address2'   => '',
29        'phone'      => '',
30        'country'    => '',
31        'city'       => '',
32        'postcode'   => '',
33        'opt_in'     => '',
34        'status'     => '',
35        'last_connection' => ''
36    ];
37
38    /**
39     * CustomerResource.
40     *
41     * @param \App\Models\Brand    $brand
42     * @param \App\Models\Customer $customer
43     */
44    public function __construct(Brand $brand, Customer $customer)
45    {
46        $this->customer = $customer;
47        $this->info     = $customer->info($brand, Customer::FIRST_OR_FAIL);
48        $this->login    = $customer->login($brand, Customer::FIRST_OR_FAIL);
49    }
50
51    /**
52     * Transform the resource into an array.
53     *
54     * @param \Illuminate\Http\Request|null $request
55     * @return array
56     * + email string
57     * + firstname string
58     * + lastname string
59     * + birth_date datetime
60     * + address string
61     * + address2 string
62     * + phone string
63     * + country string
64     * + city string
65     * + postcode string
66     * + opt_in boolean
67     * + hashcode string
68     * + status boolean
69     * + last_connection date
70     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass, Squiz.Commenting.FunctionComment.Missing
71     */
72    public function toArray($request = null): array
73    {
74        //phpcs:enable
75        $data = array_intersect_key(
76            array_merge(
77                [
78                    'email' => $this->customer->email
79                ],
80                $this->login->toArray(),
81                $this->info->toArray(),
82                ['status' => $this->login->status]
83            ),
84            $this->getSkeleton()
85        );
86
87        $data['country']  = $this->info->country->value();
88        $data['address2'] = $this->info->address2 ?? '';
89        return $data;
90    }
91
92    /**
93     * Returns the resource skeletton
94     *
95     * @return array
96     */
97    public static function getSkeleton(): array
98    {
99        return self::$skeleton;
100    }
101}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V2/QuestionStatsResource.php.html b/tests/coverage/app/Http/Resources/Api/V2/QuestionStatsResource.php.html deleted file mode 100644 index 6c54df5..0000000 --- a/tests/coverage/app/Http/Resources/Api/V2/QuestionStatsResource.php.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V2/QuestionStatsResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionStatsResource
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V2;
4
5use App\Models\Question;
6use Illuminate\Http\Request;
7use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
8use Illuminate\Support\Collection;
9
10class QuestionStatsResource extends JsonResourceCollection
11{
12    /** @var \App\Models\Question */
13    protected $question = null;
14
15    /**
16     * Create a new resource instance.
17     *
18     * @param  \Illuminate\Support\Collection $questionStats
19     * @param  \App\Models\Question           $question
20     * @return void
21     */
22    public function __construct(Collection $questionStats = null, Question $question)
23    {
24        $this->question = $question;
25        parent::__construct($questionStats);
26    }
27
28    /**
29     * Transform the resource into an array.
30     *
31     * @param \Illuminate\Http\Request $request
32     * @return array
33     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
34     */
35    public function toArray(Request $request): array
36    {
37        //phpcs:enable
38        return [
39            'answers' => (new AnswersResource($this->question->answers))->toArray($request),
40            'stats' => $this->collection->toArray()
41        ];
42    }
43}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V2/QuestionsResource.php.html b/tests/coverage/app/Http/Resources/Api/V2/QuestionsResource.php.html deleted file mode 100644 index f21261e..0000000 --- a/tests/coverage/app/Http/Resources/Api/V2/QuestionsResource.php.html +++ /dev/null @@ -1,237 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V2/QuestionsResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionsResource
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V2;
4
5use App\Models\Answer;
6use App\Models\Question;
7use Illuminate\Http\Request;
8use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
9use Illuminate\Support\Collection;
10
11class QuestionsResource extends JsonResourceCollection
12{
13    /** @var \Illuminate\Support\Collection<\App\Models\CustomerAnswer> */
14    protected $userAnwsers = null;
15
16    /**
17     * Create a new resource instance.
18     *
19     * @param  mixed                                                      $resource
20     * @param  \Illuminate\Support\Collection<\App\Models\CustomerAnswer> $userAnwsers
21     * @return void
22     * @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
23     */
24    public function __construct(mixed $resource, Collection $userAnwsers = null)
25    {
26        //phpcs:enable
27        $this->userAnwsers = $userAnwsers;
28        parent::__construct($resource);
29    }
30
31    /**
32     * Transform the resource into an array.
33     *
34     * @param \Illuminate\Http\Request $request
35     * @return \Illuminate\Support\Collection
36     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
37     */
38    public function toArray(Request $request): \Illuminate\Support\Collection
39    {
40        //phpcs:enable
41        return $this->collection->map(function (Question $question) {
42            /** @var \Illuminate\Support\Collection */
43            $answers  = $question->answers;
44            $question = [
45                'id' => $question->id,
46                'type' => $question->type->value(),
47                'question' => $question->question,
48                'answers' => new AnswersResource($answers)
49            ];
50            if ($this->userAnwsers) {
51                $question['customerAnswers'] = new AnswersResource($answers->filter(function (Answer $answer) {
52                    return $this->userAnwsers->keyBy('id')->has($answer->id);
53                }));
54            }
55            return $question;
56        });
57    }
58}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V2/dashboard.html b/tests/coverage/app/Http/Resources/Api/V2/dashboard.html deleted file mode 100644 index 899ff27..0000000 --- a/tests/coverage/app/Http/Resources/Api/V2/dashboard.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Resources/Api/V2 - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V2/index.html b/tests/coverage/app/Http/Resources/Api/V2/index.html deleted file mode 100644 index a5e92ec..0000000 --- a/tests/coverage/app/Http/Resources/Api/V2/index.html +++ /dev/null @@ -1,263 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V2 - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
66 / 66
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
AnswersResource.php
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiResponse.php
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
BrandStatsResource.php
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerResource.php
-
- 100.00% covered (success) -
-
-
100.00%
18 / 18
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionStatsResource.php
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionsResource.php
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Resources/Api/V4/AnswersResource.php.html b/tests/coverage/app/Http/Resources/Api/V4/AnswersResource.php.html deleted file mode 100644 index 6b9c91a..0000000 --- a/tests/coverage/app/Http/Resources/Api/V4/AnswersResource.php.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V4/AnswersResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
AnswersResource
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V4;
4
5use App\Models\Answer;
6use Illuminate\Http\Request;
7use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
8
9class AnswersResource extends JsonResourceCollection
10{
11    /**
12     * Transform the resource into an array.
13     *
14     * @param \Illuminate\Http\Request $request
15     * @return \Illuminate\Support\Collection
16     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
17     */
18    public function toArray(Request $request): \Illuminate\Support\Collection
19    {
20        //phpcs:enable
21        return $this->collection->map(function (Answer $answer) {
22            return [
23                'id' => $answer->id,
24                'answer' => $answer->answer
25            ];
26        });
27    }
28}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V4/ApiResponse.php.html b/tests/coverage/app/Http/Resources/Api/V4/ApiResponse.php.html deleted file mode 100644 index c66d2d4..0000000 --- a/tests/coverage/app/Http/Resources/Api/V4/ApiResponse.php.html +++ /dev/null @@ -1,223 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V4/ApiResponse.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiResponse
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V4;
4
5use App\Enums\ApiStatus;
6use Illuminate\Http\Request;
7use Illuminate\Http\Resources\Json\JsonResource;
8use stdClass;
9
10class ApiResponse extends JsonResource
11{
12    /** @var \stdClass|null */
13    protected $data;
14
15    /** @var \App\Enums\ApiStatus */
16    protected $status;
17
18    /**
19     * @param \stdClass|null       $data
20     * @param \App\Enums\ApiStatus $status
21     */
22    public function __construct(stdClass|null $data = null, ApiStatus $status)
23    {
24        $this->status = $status;
25        $this->data   = $data;
26    }
27
28    /**
29     * Transform the resource into an array.
30     *
31     * @param \Illuminate\Http\Request $request
32     * @return array
33     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
34     */
35    public function toArray(Request $request): array
36    {
37        //phpcs:enable
38        return [
39            'status' => $this->status->value(),
40            'data' => (array)($this->data ?? []),
41            'version' => config('api.version')
42        ];
43    }
44}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V4/BrandStatsResource.php.html b/tests/coverage/app/Http/Resources/Api/V4/BrandStatsResource.php.html deleted file mode 100644 index 5434c53..0000000 --- a/tests/coverage/app/Http/Resources/Api/V4/BrandStatsResource.php.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V4/BrandStatsResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
BrandStatsResource
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V4;
4
5use App\Models\BrandStat;
6use Illuminate\Http\Request;
7use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
8
9class BrandStatsResource extends JsonResourceCollection
10{
11    /**
12     * Transform the resource into an array.
13     *
14     * @param \Illuminate\Http\Request $request
15     * @return array
16     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
17     */
18    public function toArray(Request $request)
19    {
20        //phpcs:enable
21        return [
22            'stats' => $this->collection->map(function (BrandStat $brandStat) {
23                return [
24                    'date'           => $brandStat->created_at->isoFormat('YYYY-MM-DD'),
25                    'active'         => $brandStat->active,
26                    'inactive'       => $brandStat->inactive,
27                    'old_accounts'   => $brandStat->old_accounts,
28                    'new_accounts'   => $brandStat->new_accounts,
29                    'total_accounts' => $brandStat->total_accounts,
30                    'total_opt_in'   => $brandStat->total_opt_in
31                ];
32            })
33        ];
34    }
35}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V4/CustomerResource.php.html b/tests/coverage/app/Http/Resources/Api/V4/CustomerResource.php.html deleted file mode 100644 index 96d12ce..0000000 --- a/tests/coverage/app/Http/Resources/Api/V4/CustomerResource.php.html +++ /dev/null @@ -1,302 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V4/CustomerResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
18 / 18
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerResource
-
- 100.00% covered (success) -
-
-
100.00%
18 / 18
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getSkeleton
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V4;
4
5use App\Models\Brand;
6use App\Models\Customer;
7use Illuminate\Http\Resources\Json\JsonResource;
8
9class CustomerResource extends JsonResource
10{
11    /** @var \App\Models\Customer */
12    private $customer;
13
14    /** @var \App\Models\CustomerInfo */
15    private $info;
16
17    /** @var \App\Models\CustomerLogin */
18    private $login;
19
20    /** @var array */
21    private static $skeleton = [
22        'hashcode'   => '',
23        'firstname'  => '',
24        'lastname'   => '',
25        'email'      => '',
26        'birth_date' => '',
27        'address'    => '',
28        'address2'   => '',
29        'phone'      => '',
30        'country'    => '',
31        'city'       => '',
32        'postcode'   => '',
33        'opt_in'     => '',
34        'status'     => '',
35        'last_connection' => ''
36    ];
37
38    /**
39     * CustomerResource.
40     *
41     * @param \App\Models\Brand    $brand
42     * @param \App\Models\Customer $customer
43     */
44    public function __construct(Brand $brand, Customer $customer)
45    {
46        $this->customer = $customer;
47        $this->info     = $customer->info($brand, Customer::FIRST_OR_FAIL);
48        $this->login    = $customer->login($brand, Customer::FIRST_OR_FAIL);
49    }
50
51    /**
52     * Transform the resource into an array.
53     *
54     * @param \Illuminate\Http\Request|null $request
55     * @return array
56     * + email string
57     * + firstname string
58     * + lastname string
59     * + birth_date datetime
60     * + address string
61     * + address2 string
62     * + phone string
63     * + country string
64     * + city string
65     * + postcode string
66     * + opt_in boolean
67     * + hashcode string
68     * + status boolean
69     * + last_connection date
70     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass, Squiz.Commenting.FunctionComment.Missing
71     */
72    public function toArray($request = null): array
73    {
74        //phpcs:enable
75        $data = array_intersect_key(
76            array_merge(
77                [
78                    'email' => $this->customer->email
79                ],
80                $this->login->toArray(),
81                $this->info->toArray(),
82                ['status' => $this->login->status]
83            ),
84            $this->getSkeleton()
85        );
86
87        $data['country']  = $this->info->country->value();
88        $data['address2'] = $this->info->address2 ?? '';
89        return $data;
90    }
91
92    /**
93     * Returns the resource skeletton
94     *
95     * @return array
96     */
97    public static function getSkeleton(): array
98    {
99        return self::$skeleton;
100    }
101}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V4/QuestionStatsResource.php.html b/tests/coverage/app/Http/Resources/Api/V4/QuestionStatsResource.php.html deleted file mode 100644 index 7a819ef..0000000 --- a/tests/coverage/app/Http/Resources/Api/V4/QuestionStatsResource.php.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V4/QuestionStatsResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionStatsResource
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V4;
4
5use App\Models\Question;
6use Illuminate\Http\Request;
7use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
8use Illuminate\Support\Collection;
9
10class QuestionStatsResource extends JsonResourceCollection
11{
12    /** @var \App\Models\Question */
13    protected $question = null;
14
15    /**
16     * Create a new resource instance.
17     *
18     * @param  \Illuminate\Support\Collection $questionStats
19     * @param  \App\Models\Question           $question
20     * @return void
21     */
22    public function __construct(Collection $questionStats = null, Question $question)
23    {
24        $this->question = $question;
25        parent::__construct($questionStats);
26    }
27
28    /**
29     * Transform the resource into an array.
30     *
31     * @param \Illuminate\Http\Request $request
32     * @return array
33     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
34     */
35    public function toArray(Request $request): array
36    {
37        //phpcs:enable
38        return [
39            'answers' => (new AnswersResource($this->question->answers))->toArray($request),
40            'stats' => $this->collection->toArray()
41        ];
42    }
43}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V4/QuestionsResource.php.html b/tests/coverage/app/Http/Resources/Api/V4/QuestionsResource.php.html deleted file mode 100644 index 94663b1..0000000 --- a/tests/coverage/app/Http/Resources/Api/V4/QuestionsResource.php.html +++ /dev/null @@ -1,237 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V4/QuestionsResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionsResource
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 toArray
-
- 100.00% covered (success) -
-
-
100.00%
14 / 14
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources\Api\V4;
4
5use App\Models\Answer;
6use App\Models\Question;
7use Illuminate\Http\Request;
8use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
9use Illuminate\Support\Collection;
10
11class QuestionsResource extends JsonResourceCollection
12{
13    /** @var \Illuminate\Support\Collection<\App\Models\CustomerAnswer> */
14    protected $userAnwsers = null;
15
16    /**
17     * Create a new resource instance.
18     *
19     * @param  mixed                                                      $resource
20     * @param  \Illuminate\Support\Collection<\App\Models\CustomerAnswer> $userAnwsers
21     * @return void
22     * @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
23     */
24    public function __construct(mixed $resource, Collection $userAnwsers = null)
25    {
26        //phpcs:enable
27        $this->userAnwsers = $userAnwsers;
28        parent::__construct($resource);
29    }
30
31    /**
32     * Transform the resource into an array.
33     *
34     * @param \Illuminate\Http\Request $request
35     * @return \Illuminate\Support\Collection
36     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
37     */
38    public function toArray(Request $request): \Illuminate\Support\Collection
39    {
40        //phpcs:enable
41        return $this->collection->map(function (Question $question) {
42            /** @var \Illuminate\Support\Collection */
43            $answers  = $question->answers;
44            $question = [
45                'id' => $question->id,
46                'type' => $question->type->value(),
47                'question' => $question->question,
48                'answers' => new AnswersResource($answers)
49            ];
50            if ($this->userAnwsers) {
51                $question['customerAnswers'] = new AnswersResource($answers->filter(function (Answer $answer) {
52                    return $this->userAnwsers->keyBy('id')->has($answer->id);
53                }));
54            }
55            return $question;
56        });
57    }
58}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V4/dashboard.html b/tests/coverage/app/Http/Resources/Api/V4/dashboard.html deleted file mode 100644 index 98ece9b..0000000 --- a/tests/coverage/app/Http/Resources/Api/V4/dashboard.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Resources/Api/V4 - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/V4/index.html b/tests/coverage/app/Http/Resources/Api/V4/index.html deleted file mode 100644 index 4f2849f..0000000 --- a/tests/coverage/app/Http/Resources/Api/V4/index.html +++ /dev/null @@ -1,263 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api/V4 - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
66 / 66
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
AnswersResource.php
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiResponse.php
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
BrandStatsResource.php
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerResource.php
-
- 100.00% covered (success) -
-
-
100.00%
18 / 18
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionStatsResource.php
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
QuestionsResource.php
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/Resources/Api/dashboard.html b/tests/coverage/app/Http/Resources/Api/dashboard.html deleted file mode 100644 index 7bf9210..0000000 --- a/tests/coverage/app/Http/Resources/Api/dashboard.html +++ /dev/null @@ -1,287 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Resources/Api - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Resources/Api/index.html b/tests/coverage/app/Http/Resources/Api/index.html deleted file mode 100644 index cfa399f..0000000 --- a/tests/coverage/app/Http/Resources/Api/index.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/Api - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
132 / 132
-
- 100.00% covered (success) -
-
-
100.00%
22 / 22
-
- 100.00% covered (success) -
-
-
100.00%
12 / 12
V2
-
- 100.00% covered (success) -
-
-
100.00%
66 / 66
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
V4
-
- 100.00% covered (success) -
-
-
100.00%
66 / 66
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- -
- - diff --git a/tests/coverage/app/Http/Resources/CustomerResource.php.html b/tests/coverage/app/Http/Resources/CustomerResource.php.html deleted file mode 100644 index 279946f..0000000 --- a/tests/coverage/app/Http/Resources/CustomerResource.php.html +++ /dev/null @@ -1,234 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/CustomerResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 23
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerResource
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 23
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 toArray
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 21
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources;
4
5use Illuminate\Http\Request;
6use Illuminate\Http\Resources\Json\JsonResource;
7
8class CustomerResource extends JsonResource
9{
10    /** @var integer */
11    private $brandId;
12
13    /**
14     * @param mixed   $resource
15     * @param integer $brandId
16     */
17    public function __construct(mixed $resource, int $brandId)
18    {
19        parent::__construct($resource);
20        $this->brandId = $brandId;
21    }
22
23    /**
24     * Transform the resource into an array.
25     *
26     * @param \Illuminate\Http\Request $request
27     * @return array
28     * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
29     */
30    public function toArray(Request $request): array
31    {
32        //phpcs:disable
33        /** @var \App\Models\CustomerInfo */
34        $infos = $this->infos()->where('brand_id', $this->brandId)->first();
35        /** @var \App\Models\CustomerLogin */
36        $login = $this->logins()->where('brand_id', $this->brandId)->first();
37        return [
38            'status' => 'OK',
39            'user' => [
40                'crm_id'     => $this->id,
41                'firstname'  => $infos->firstname,
42                'lastname'   => $infos->lastname,
43                'email'      => $this->email,
44                'birth_date' => $infos->birth_date,
45                'address'    => $infos->address,
46                'address2'   => $infos->address2,
47                'phone'      => $infos->phone,
48                'country'    => $infos->country->label(),
49                'city'       => $infos->city,
50                'postcode'   => $infos->postcode,
51                'opt_in'     => $infos->opt_in,
52                'hashcode'   => $infos->hashcode,
53                'status'     => $login->status,
54            ]
55        ];
56    }
57}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/StatusResource.php.html b/tests/coverage/app/Http/Resources/StatusResource.php.html deleted file mode 100644 index 2b75930..0000000 --- a/tests/coverage/app/Http/Resources/StatusResource.php.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources/StatusResource.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
StatusResource
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Resources;
4
5use Illuminate\Http\Resources\Json\JsonResource;
6
7class StatusResource extends JsonResource
8{
9}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Resources/dashboard.html b/tests/coverage/app/Http/Resources/dashboard.html deleted file mode 100644 index 01c9bf6..0000000 --- a/tests/coverage/app/Http/Resources/dashboard.html +++ /dev/null @@ -1,289 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Resources - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Http\Resources\CustomerResource0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
MethodCoverage
__construct0%
toArray0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Resources/index.html b/tests/coverage/app/Http/Resources/index.html deleted file mode 100644 index 3c0daf4..0000000 --- a/tests/coverage/app/Http/Resources/index.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Resources - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 85.16% covered (warning) -
-
-
85.16%
132 / 155
-
- 91.67% covered (success) -
-
-
91.67%
22 / 24
-
- 92.31% covered (success) -
-
-
92.31%
12 / 13
Api
-
- 100.00% covered (success) -
-
-
100.00%
132 / 132
-
- 100.00% covered (success) -
-
-
100.00%
22 / 22
-
- 100.00% covered (success) -
-
-
100.00%
12 / 12
CustomerResource.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 23
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatusResource.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Http/Sanitizers/RemoveSpaces.php.html b/tests/coverage/app/Http/Sanitizers/RemoveSpaces.php.html deleted file mode 100644 index e213763..0000000 --- a/tests/coverage/app/Http/Sanitizers/RemoveSpaces.php.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Sanitizers/RemoveSpaces.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
RemoveSpaces
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 sanitize
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Http\Sanitizers;
4
5use ArondeParon\RequestSanitizer\Contracts\Sanitizer;
6
7class RemoveSpaces implements Sanitizer
8{
9    /**
10     * @param mixed $input
11     * @return string
12     * @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing
13     */
14    public function sanitize($input): string
15    {
16        //phpcs:enable
17        return preg_replace('~\s{1,}~', '', $input);
18    }
19}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Http/Sanitizers/dashboard.html b/tests/coverage/app/Http/Sanitizers/dashboard.html deleted file mode 100644 index 030eb86..0000000 --- a/tests/coverage/app/Http/Sanitizers/dashboard.html +++ /dev/null @@ -1,286 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http/Sanitizers - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Http/Sanitizers/index.html b/tests/coverage/app/Http/Sanitizers/index.html deleted file mode 100644 index 2adb2cd..0000000 --- a/tests/coverage/app/Http/Sanitizers/index.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http/Sanitizers - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
RemoveSpaces.php
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- -
- - diff --git a/tests/coverage/app/Http/dashboard.html b/tests/coverage/app/Http/dashboard.html deleted file mode 100644 index 034c5d8..0000000 --- a/tests/coverage/app/Http/dashboard.html +++ /dev/null @@ -1,513 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Http - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ClassCoverage
App\Http\Controllers\Bo\ActivityLogsController0%
App\Http\Controllers\Bo\AnswerController0%
App\Http\Controllers\Bo\Auth\LoginController0%
App\Http\Controllers\Bo\Auth\ResetPasswordController0%
App\Http\Controllers\Bo\BrandController0%
App\Http\Controllers\Bo\CustomerController0%
App\Http\Controllers\Bo\DashboardController0%
App\Http\Controllers\Bo\QuestionController0%
App\Http\Controllers\Bo\ServiceController0%
App\Http\Controllers\Bo\SingleOptinController0%
App\Http\Controllers\Bo\StatsController0%
App\Http\Controllers\Bo\UsersController0%
App\Http\Controllers\Controller0%
App\Http\Middleware\RedirectIfAuthenticated0%
App\Http\Middleware\SecureHeaders0%
App\Http\Middleware\TrustHosts0%
App\Http\Requests\Bo\Answers\StoreAnswerRequest0%
App\Http\Requests\Bo\Brands\StoreBrandRequest0%
App\Http\Requests\Bo\CustomerExport0%
App\Http\Requests\Bo\GenerateServiceToken0%
App\Http\Requests\Bo\ManageBrandRequest0%
App\Http\Requests\Bo\ManageServiceRequest0%
App\Http\Requests\Bo\QuestionExport0%
App\Http\Requests\Bo\Questions\StoreQuestionRequest0%
App\Http\Requests\Bo\Services\StoreServiceRequest0%
App\Http\Requests\Bo\StatsByBrandRequest0%
App\Http\Requests\Bo\StatsByQuestionRequest0%
App\Http\Requests\Bo\UpdateChangeOrderRequest0%
App\Http\Requests\Bo\UpdateMiniCrudRequest0%
App\Http\Requests\Bo\Users\StoreUserRequest0%
App\Http\Requests\Bo\Users\UpdateUserRequest0%
App\Http\Resources\CustomerResource0%
App\Http\Middleware\Authenticate41%
App\Http\Middleware\HtmlSanitizer71%
-
-
- -
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

- -
- -
- -
- - - - - - diff --git a/tests/coverage/app/Http/index.html b/tests/coverage/app/Http/index.html deleted file mode 100644 index c40b260..0000000 --- a/tests/coverage/app/Http/index.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Http - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 40.54% covered (danger) -
-
-
40.54%
834 / 2057
-
- 41.79% covered (danger) -
-
-
41.79%
84 / 201
-
- 52.00% covered (warning) -
-
-
52.00%
39 / 75
Controllers
-
- 32.87% covered (danger) -
-
-
32.87%
406 / 1235
-
- 39.25% covered (danger) -
-
-
39.25%
42 / 107
-
- 51.85% covered (warning) -
-
-
51.85%
14 / 27
Middleware
-
- 46.90% covered (danger) -
-
-
46.90%
53 / 113
-
- 33.33% covered (danger) -
-
-
33.33%
3 / 9
-
- 37.50% covered (danger) -
-
-
37.50%
3 / 8
Requests
-
- 43.76% covered (danger) -
-
-
43.76%
242 / 553
-
- 26.67% covered (danger) -
-
-
26.67%
16 / 60
-
- 34.62% covered (danger) -
-
-
34.62%
9 / 26
Resources
-
- 85.16% covered (warning) -
-
-
85.16%
132 / 155
-
- 91.67% covered (success) -
-
-
91.67%
22 / 24
-
- 92.31% covered (success) -
-
-
92.31%
12 / 13
Sanitizers
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
Kernel.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Jobs/SetServiceStats.php.html b/tests/coverage/app/Jobs/SetServiceStats.php.html deleted file mode 100644 index 6859746..0000000 --- a/tests/coverage/app/Jobs/SetServiceStats.php.html +++ /dev/null @@ -1,299 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Jobs/SetServiceStats.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SetServiceStats
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 handle
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 retryUntil
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 middleware
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Jobs;
4
5use App\Models\Service;
6use App\Models\ServiceStat;
7use Illuminate\Bus\Queueable;
8use Illuminate\Contracts\Queue\ShouldQueue;
9use Illuminate\Foundation\Bus\Dispatchable;
10use Illuminate\Queue\InteractsWithQueue;
11use Illuminate\Queue\Middleware\WithoutOverlapping;
12use Illuminate\Queue\SerializesModels;
13
14class SetServiceStats implements ShouldQueue
15{
16    use Dispatchable;
17    use InteractsWithQueue;
18    use Queueable;
19    use SerializesModels;
20
21    private const KEY = '2202020';
22
23    /** @var \App\Models\Service */
24    protected $service;
25
26    /**
27     * Create a new job instance.
28     *
29     * @param \App\Models\Service $service
30     * @return void
31     */
32    public function __construct(Service $service)
33    {
34        $this->service = $service;
35    }
36
37    /**
38     * Execute the job.
39     *
40     * @return void
41     */
42    public function handle(): void
43    {
44        $serviceStat = ServiceStat::firstOrNew([
45            'date' => date('Y-m-d'),
46            'service_id' => $this->service->id,
47            'brand_id' => $this->service->brand->id,
48        ]);
49        if (!$serviceStat->exists) {
50            $serviceStat->service()->associate($this->service);
51            $serviceStat->brand()->associate($this->service->brand);
52        }
53        $serviceStat->nb_calls += 1;
54        $serviceStat->saveOrFail();
55    }
56
57    /**
58     * Determine the time at which the job should timeout.
59     *
60     * @return \DateTime
61     */
62    public function retryUntil(): \DateTime
63    {
64        return now()->addMinutes(rand(0, 360));
65    }
66
67    /**
68     * Get the middleware the job should pass through.
69     *
70     * @return array
71     */
72    public function middleware(): array
73    {
74        return [
75            (new WithoutOverlapping(self::KEY))
76                ->releaseAfter(rand(90, 180))
77        ];
78    }
79}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Jobs/StartStatJobs.php.html b/tests/coverage/app/Jobs/StartStatJobs.php.html deleted file mode 100644 index 9ed4923..0000000 --- a/tests/coverage/app/Jobs/StartStatJobs.php.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Jobs/StartStatJobs.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StartStatJobs
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 handle
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Jobs;
4
5use App\Models\Brand;
6use Illuminate\Bus\Queueable;
7use Illuminate\Contracts\Queue\ShouldQueue;
8use Illuminate\Foundation\Bus\Dispatchable;
9use Illuminate\Queue\InteractsWithQueue;
10
11class StartStatJobs implements ShouldQueue
12{
13    use Dispatchable;
14    use InteractsWithQueue;
15    use Queueable;
16
17    /**
18     * Execute the job.
19     *
20     * @return void
21     */
22    public function handle(): void
23    {
24        $brands = Brand::all();
25        foreach ($brands as $brand) {
26            \dispatch(new StatJob($brand))
27                ->delay(rand(0, 90));
28        }
29    }
30}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Jobs/StatJob.php.html b/tests/coverage/app/Jobs/StatJob.php.html deleted file mode 100644 index ac1b52c..0000000 --- a/tests/coverage/app/Jobs/StatJob.php.html +++ /dev/null @@ -1,294 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Jobs/StatJob.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 29
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatJob
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 29
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 handle
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 27
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 middleware
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Jobs;
4
5use App\Models\Brand;
6use App\Models\BrandStat;
7use App\Models\CustomerInfo;
8use App\Models\CustomerLogin;
9use App\Models\SingleOptin;
10use Illuminate\Bus\Queueable;
11use Illuminate\Contracts\Queue\ShouldQueue;
12use Illuminate\Database\Eloquent\Builder;
13use Illuminate\Foundation\Bus\Dispatchable;
14use Illuminate\Queue\InteractsWithQueue;
15use Illuminate\Queue\Middleware\WithoutOverlapping;
16use Illuminate\Queue\SerializesModels;
17use Illuminate\Support\Carbon;
18
19class StatJob implements ShouldQueue
20{
21    use Dispatchable;
22    use InteractsWithQueue;
23    use Queueable;
24    use SerializesModels;
25
26    /**
27     * Set high max tries as using prevent overlap
28     *
29     * @var integer
30     */
31    public $tries = 10;
32
33    /** Used to prevent overlaping */
34    private const JOBKEY = 32644296;
35
36    /** @var \App\Models\Brand */
37    private $brand;
38
39    /**
40     * Create a new job instance.
41     *
42     * @param \App\Models\Brand $brand
43     * @return void
44     */
45    public function __construct(Brand $brand)
46    {
47        $this->brand = $brand;
48    }
49
50    /**
51     * Execute the job.
52     *
53     * @return void
54     */
55    public function handle(): void
56    {
57        $stats = new BrandStat([
58            'active' => CustomerLogin::query()->whereHas('brand', function (Builder $q) {
59                $q->where('id', $this->brand->id);
60            })->whereDate('last_connection', '<', Carbon::now()->subMonths(6))->count(),
61            'inactive' => CustomerLogin::query()->whereHas('brand', function (Builder $q) {
62                $q->where('id', $this->brand->id);
63            })
64                ->whereDate('last_connection', '>', Carbon::now()->subMonths(6))->count(),
65            'new_accounts' => CustomerLogin::query()->whereHas('brand', function (Builder $q) {
66                $q->where('id', $this->brand->id);
67            })
68                ->whereDate('created_at', '<', Carbon::now()->subMonths(6))->count(),
69            'old_accounts' => CustomerLogin::query()->whereHas('brand', function (Builder $q) {
70                $q->where('id', $this->brand->id);
71            })
72                ->whereDate('created_at', '>', Carbon::now()->subMonths(6))->count(),
73            'total_accounts' => CustomerLogin::query()->whereHas('brand', function (Builder $q) {
74                $q->where('id', $this->brand->id);
75            })->count(),
76            'total_opt_in' => CustomerInfo::query()->whereHas('brand', function (Builder $q) {
77                $q->where('id', $this->brand->id);
78            })->whereOptIn(true)->count() + SingleOptin::query()->whereHas('brand', function (Builder $q) {
79                $q->where('id', $this->brand->id);
80            })->count()
81        ]);
82        $stats->brand()->associate($this->brand);
83        $stats->saveOrFail();
84    }
85
86    /**
87     * Get the middleware the job should pass through.
88     *
89     * @return array
90     */
91    public function middleware(): array
92    {
93        // * Dispatch randomly overlaping jobs if overlapping.
94        return [(new WithoutOverlapping(self::JOBKEY))->releaseAfter(rand(20, 90))];
95    }
96}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Jobs/UpdateCustomerLastConnection.php.html b/tests/coverage/app/Jobs/UpdateCustomerLastConnection.php.html deleted file mode 100644 index e6dd23d..0000000 --- a/tests/coverage/app/Jobs/UpdateCustomerLastConnection.php.html +++ /dev/null @@ -1,236 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Jobs/UpdateCustomerLastConnection.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
UpdateCustomerLastConnection
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 handle
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Jobs;
4
5use App\Models\Customer;
6use App\Models\CustomerLogin;
7use Illuminate\Bus\Queueable;
8use Illuminate\Contracts\Queue\ShouldQueue;
9use Illuminate\Foundation\Bus\Dispatchable;
10use Illuminate\Queue\InteractsWithQueue;
11use Illuminate\Queue\SerializesModels;
12use Illuminate\Support\Carbon;
13
14class UpdateCustomerLastConnection implements ShouldQueue
15{
16    use Dispatchable;
17    use InteractsWithQueue;
18    use Queueable;
19    use SerializesModels;
20
21    /** @var \Illuminate\Support\Carbon */
22    protected $date = null;
23
24    /** @var \App\Models\Customer */
25    protected $customer = null;
26
27    /** @var \App\Models\CustomerLogin */
28    protected $customerLogin = null;
29
30    /**
31     * Create a new job instance.
32     *
33     * @param \App\Models\Customer       $customer
34     * @param \App\Models\CustomerLogin  $customerLogin
35     * @param \Illuminate\Support\Carbon $date
36     * @return void
37     */
38    public function __construct(
39        Customer $customer,
40        CustomerLogin $customerLogin,
41        Carbon $date
42    ) {
43        $this->date          = $date;
44        $this->customer      = $customer;
45        $this->customerLogin = $customerLogin;
46    }
47
48    /**
49     * Execute the job.
50     *
51     * @return void
52     */
53    public function handle(): void
54    {
55        if ($this->customerLogin->last_connection < $this->date) {
56            $this->customerLogin->last_connection = $this->date;
57            $this->customer->logins()->save($this->customerLogin);
58        }
59    }
60}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Jobs/dashboard.html b/tests/coverage/app/Jobs/dashboard.html deleted file mode 100644 index 1ccd188..0000000 --- a/tests/coverage/app/Jobs/dashboard.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Jobs - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
ClassCoverage
App\Jobs\StartStatJobs0%
App\Jobs\StatJob0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
ClassCRAP
App\Jobs\StartStatJobs6
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - -
MethodCoverage
handle0%
__construct0%
handle0%
middleware0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
MethodCRAP
handle6
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Jobs/index.html b/tests/coverage/app/Jobs/index.html deleted file mode 100644 index 9a799ee..0000000 --- a/tests/coverage/app/Jobs/index.html +++ /dev/null @@ -1,204 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Jobs - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 40.00% covered (danger) -
-
-
40.00%
22 / 55
-
- 60.00% covered (warning) -
-
-
60.00%
6 / 10
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
SetServiceStats.php
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
StartStatJobs.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
StatJob.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 29
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateCustomerLastConnection.php
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- -
- - diff --git a/tests/coverage/app/Lib/Helper.php.html b/tests/coverage/app/Lib/Helper.php.html deleted file mode 100644 index e86f1f8..0000000 --- a/tests/coverage/app/Lib/Helper.php.html +++ /dev/null @@ -1,458 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Lib/Helper.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 91.07% covered (success) -
-
-
91.07%
51 / 56
-
- 85.71% covered (warning) -
-
-
85.71%
6 / 7
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Helper
-
- 91.07% covered (success) -
-
-
91.07%
51 / 56
-
- 85.71% covered (warning) -
-
-
85.71%
6 / 7
19.26
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 isRequestForApiV2
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 isRequestForApiV4
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 getRouteName
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 getRoutePrefix
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
 getRoute
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getPackageInfo
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 signRequest
-
- 88.37% covered (warning) -
-
-
88.37%
38 / 43
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
7.08
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Lib;
4
5use App\Exceptions\Api\V4\CrmException;
6use Illuminate\Contracts\Encryption\DecryptException;
7use Illuminate\Http\Request;
8use Illuminate\Support\Facades\Crypt;
9use Illuminate\Support\Facades\Route;
10
11/**
12 * Helper Class
13 */
14class Helper
15{
16    /**
17     * Package infos.
18     *
19     * @var array
20     */
21    private static $packageInfos;
22
23    /**
24     * Tells if the request is within apiV2 routes.
25     *
26     * @param \Illuminate\Http\Request $request
27     * @return boolean
28     */
29    public static function isRequestForApiV2(Request $request): bool
30    {
31        // * Small hack to ensure to know if route is From APIv2.
32        $routeName = static::getRouteName($request) ??
33            (strpos($request->path(), 'api/v2') === 0 ? 'apiV2.' : null) ?? 'none';
34        return strpos($routeName, 'apiV2.') === 0;
35    }
36
37    /**
38     * Tells if the request is within apiV4 routes.
39     *
40     * @param \Illuminate\Http\Request $request
41     * @return boolean
42     */
43    public static function isRequestForApiV4(Request $request): bool
44    {
45        // * Small hack to ensure to know if route is From APIv4.
46        $routeName = static::getRouteName($request) ??
47            (strpos($request->path(), 'api/v4') === 0 ? 'apiV4.' : null) ?? 'none';
48        return strpos($routeName, 'apiV4.') === 0;
49    }
50
51    /**
52     * Try to get current route name
53     *
54     * @param \Illuminate\Http\Request $request
55     * @return string|null
56     */
57    public static function getRouteName(Request $request): ?string
58    {
59        return Route::currentRouteName() ?? ($request->route() ? $request->route()->getName() : null);
60    }
61
62    /**
63     * Try to get current route prefix.
64     *
65     * @param \Illuminate\Http\Request $request
66     * @return string|null
67     */
68    public static function getRoutePrefix(Request $request): ?string
69    {
70        return (Route::getCurrentRoute() ? Route::getCurrentRoute()->getPrefix() : null) ??
71            ($request->route() ? $request->route()->getPrefix() : null);
72    }
73
74    /**
75     * Try to get route from request.
76     *
77     * @param \Illuminate\Http\Request $request
78     * @return \Illuminate\Routing\Route|null
79     */
80    public static function getRoute(Request $request): \Illuminate\Routing\Route|null
81    {
82        return Route::getRoutes()->getByName(static::getRouteName($request));
83    }
84
85    /**
86     * Get composer.json infos.
87     *
88     * @return array
89     */
90    public static function getPackageInfo(): array
91    {
92        if (!static::$packageInfos) {
93            static::$packageInfos = \json_decode(\file_get_contents(__DIR__ . '/../../composer.json'), true);
94        }
95        return static::$packageInfos;
96    }
97
98    /**
99     * Calculate the request signature.
100     *
101     * @param string $secret
102     * @param string $uri
103     * @param string $method
104     * @param array  $parameters
105     * @return string request signature
106     * @throws \App\Exceptions\Api\V4\CrmException If an error occurs.
107     */
108    public static function signRequest(string $secret, string $uri, string $method, array $parameters): string
109    {
110        try {
111            $uri    = collect(\parse_url($uri));
112            $method = \strtolower($method);
113
114            // * Remove signature from parameters to calculate the hashmac.
115            $signature = collect([
116                'uri' => sprintf(
117                    '%s://%s%s',
118                    $uri->get('scheme'),
119                    $uri->get('host'),
120                    $uri->get('path')
121                ),
122                'method' => $method
123            ]);
124
125            $flattenRequestArray = function (array $array) use (&$flattenRequestArray) {
126                $out = [];
127                foreach ($array as $key => $value) {
128                    if (is_array($value)) {
129                        $subArray = $flattenRequestArray($value);
130                        foreach ($subArray as $subKey => $subValue) {
131                            $out["$key.$subKey"] = $subValue;
132                        }
133                        continue;
134                    }
135                    $out[$key] = $value;
136                }
137                return $out;
138            };
139
140            $parameters = $flattenRequestArray($parameters);
141            $parameters = collect($parameters);
142
143            // * Remove signature from parameters.
144            $parameters->pull('signature');
145
146            // * Natural sort all parameters.
147            $parameters = $parameters->sortKeys(\SORT_NATURAL)
148                ->map(function ($value, $key) {
149                    return sprintf('%s=%s', \rawurlencode($key), \rawurlencode($value));
150                });
151
152            $signature->push($parameters->implode('&'));
153
154            $calculatedHash = base64_encode(hash_hmac(
155                'sha256',
156                $signature->implode('\n'),
157                Crypt::decryptString($secret),
158                true
159            ));
160
161            if (!$calculatedHash) {
162                throw new CrmException('Failed to calculate requests hash');
163            }
164
165            return $calculatedHash;
166        } catch (DecryptException $e) {
167            throw new CrmException('Failed to decrypt service credentials', 0, $e);
168        } catch (\Exception $e) {
169            throw new CrmException('An error occured when authenticating service', 0, $e);
170        } //end try
171    }
172}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Lib/Helpers/ExceptionsHelper.php.html b/tests/coverage/app/Lib/Helpers/ExceptionsHelper.php.html deleted file mode 100644 index 9d4c7e2..0000000 --- a/tests/coverage/app/Lib/Helpers/ExceptionsHelper.php.html +++ /dev/null @@ -1,379 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Lib/Helpers/ExceptionsHelper.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
ExceptionsHelper
n/a
0 / 0
n/a
0 / 0
33
n/a
0 / 0
 sentryEventHandler
n/a
0 / 0
n/a
0 / 0
2
 getAnonymizedSentryException
n/a
0 / 0
n/a
0 / 0
2
 getAnonymizedSentryStackTrace
n/a
0 / 0
n/a
0 / 0
4
 getAnonymizedSentryParams
n/a
0 / 0
n/a
0 / 0
10
 getAnonymizedMessage
n/a
0 / 0
n/a
0 / 0
2
 getAnonymizedStackTrace
n/a
0 / 0
n/a
0 / 0
6
 handleArgs
n/a
0 / 0
n/a
0 / 0
7
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Lib\Helpers;
4
5/**
6 * @codeCoverageIgnore
7 */
8class ExceptionsHelper
9{
10    /**
11     * Handle sentry event.
12     *
13     * @param \Sentry\Event $event
14     * @return null|\Sentry\Event
15     */
16    public static function sentryEventHandler(\Sentry\Event $event): ?\Sentry\Event
17    {
18        // Remove unwanted reports.
19        $event->setModules([]);
20        $event->setOsContext(null);
21
22        /** @var \Sentry\ExceptionDataBag[] */
23        $exceptionBag = [];
24        foreach ($event->getExceptions() as $exceptionDataBag) {
25            $exceptionBag[] = self::getAnonymizedSentryException($exceptionDataBag);
26        }
27        $event->setExceptions($exceptionBag);
28        return $event;
29    }
30
31    /**
32     * Anonimize Sentry Exception bag.
33     *
34     * @param \Sentry\ExceptionDataBag $exceptionDataBag
35     * @return \Sentry\ExceptionDataBag
36     */
37    private static function getAnonymizedSentryException(
38        \Sentry\ExceptionDataBag $exceptionDataBag
39    ): \Sentry\ExceptionDataBag {
40        $exceptionDataBag->setValue(self::getAnonymizedMessage($exceptionDataBag->getValue()));
41        if ($stackTrace = $exceptionDataBag->getStacktrace()) {
42            $exceptionDataBag->setStacktrace(self::getAnonymizedSentryStackTrace($stackTrace));
43        }
44        return $exceptionDataBag;
45    }
46
47    /**
48     * Anonymise sentry stacktrace.
49     *
50     * @param \Sentry\Stacktrace $stackTrace
51     * @return \Sentry\Stacktrace
52     */
53    private static function getAnonymizedSentryStackTrace(\Sentry\Stacktrace $stackTrace): \Sentry\Stacktrace
54    {
55        /** @var \Sentry\Frame[] */
56        $frames = \array_reverse($stackTrace->getFrames(), true);
57        $i      = \count($frames) - 1;
58        // * Remove all but keep first (index.php).
59        while ($i-- > 0) {
60            $stackTrace->removeFrame(count($stackTrace->getFrames()) - 1);
61        }
62        foreach ($frames as $index => $frame) {
63            $frame->setPostContext([]);
64            $frame->setPreContext([]);
65            $frame->setContextLine('');
66            $frame->setVars(self::getAnonymizedSentryParams($frame->getVars()));
67            $stackTrace->addFrame($frame);
68            if ($index === 0) {
69                $stackTrace->removeFrame(count($stackTrace->getFrames()) - 1);
70            }
71        }
72        return $stackTrace;
73    }
74
75    /**
76     * Get anonymized sentry params.
77     *
78     * @param mixed[] $params
79     * @return string[]
80     */
81    private static function getAnonymizedSentryParams(array $params): array
82    {
83        foreach ($params as &$param) {
84            $type = \strtolower(\gettype($param));
85            if (\is_string($param)) {
86                $type = \explode(' ', \trim(strtolower($param)))[0] ?? null;
87            }
88            switch (true) {
89                case $type === 'lambda':
90                case $type === 'object':
91                    continue 2;
92                case $type === 'array' and \is_array($param):
93                    $param = sprintf('Array(%d)', \count($param));
94                    continue 2;
95                default:
96                    if (\is_numeric($param)) {
97                        $param = \ucfirst($type);
98                        continue 2;
99                    }
100                    if (\is_string($param)) {
101                        $param = sprintf('String(%d)', \strlen($param));
102                        continue 2;
103                    }
104            } //end switch
105        } //end foreach
106        return $params;
107    }
108
109    /**
110     * Anonymize at least Sql queries.
111     *
112     * @param string $message
113     * @return string
114     */
115    public static function getAnonymizedMessage(string $message): string
116    {
117        $message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message;
118        if ($sqlPos = \strpos($message, 'to use near')) {
119            $message = \mb_strcut($message, 0, $sqlPos);
120        }
121        return $message;
122    }
123
124    /**
125     * Anonymize stack trace
126     *
127     * @param \Throwable $e
128     * @return string
129     */
130    public static function getAnonymizedStackTrace(\Throwable $e): string
131    {
132        $projectPath   = \realpath(\sprintf('%s/../', \app_path()));
133        $traceStack    = $e->getTrace();
134        $traceStr      = '';
135        $maxStackStage = 0;
136        foreach ($traceStack as $stackStage => $stack) {
137            $maxStackStage = $stackStage;
138            $traceStr     .= \sprintf(
139                '#%s %s(%d): ',
140                $stackStage,
141                str_replace($projectPath, '', $stack['file'] ?? ''),
142                $stack['line'] ?? ''
143            );
144            if (isset($stack['class'])) {
145                $traceStr .= "{$stack['class']}->{$stack['function']}(";
146                if (isset($stack['args'])) {
147                    $traceStr .= self::handleArgs($stack);
148                }
149                $traceStr .= ")\n";
150            } elseif (isset($stack['function'])) {
151                $traceStr .= "{$stack['function']}(";
152                if (isset($stack['args'])) {
153                    $traceStr .= self::handleArgs($stack);
154                }
155                $traceStr .= ")\n";
156            }
157        } //end foreach
158        $maxStackStage++;
159        $traceStr .= "#$maxStackStage {main}";
160        return $traceStr;
161    }
162
163    /**
164     * Handle Args.
165     *
166     * @param array $stack
167     * @return string
168     */
169    public static function handleArgs(array $stack): string
170    {
171        $traceArgs = '';
172        $argsCount = count($stack['args']);
173        for ($i = 0; $i < $argsCount; $i++) {
174            $type = \gettype($stack['args'][$i]);
175            switch ($type) {
176                case 'object':
177                    $traceArgs .= sprintf('Object(%s)', \get_class($stack['args'][$i]));
178                    break;
179                case 'array':
180                    $traceArgs .= sprintf('Array(%d)', \count($stack['args'][$i]));
181                    break;
182                case 'string':
183                    $traceArgs .= sprintf('String(%d)', \strlen($stack['args'][$i]));
184                    break;
185                default:
186                    $traceArgs .= \gettype($stack['args'][$i]);
187            }
188            $traceArgs .= ($i !== ($argsCount - 1) ? ',' : '');
189        }
190        return $traceArgs;
191    }
192}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Lib/Helpers/ToolboxHelper.php.html b/tests/coverage/app/Lib/Helpers/ToolboxHelper.php.html deleted file mode 100644 index 9da5356..0000000 --- a/tests/coverage/app/Lib/Helpers/ToolboxHelper.php.html +++ /dev/null @@ -1,1069 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Lib/Helpers/ToolboxHelper.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 209
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ToolboxHelper
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 209
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
6642
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 arrayMergeRecursiveDistinct
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
 validateRecaptcha
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 31
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
210
 stripCkEditorSchemesOnMediaInputs
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 assertNoInternalBoUrls
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 22
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 assertNoInternalUrls
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 23
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 mbReplace
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
90
 assertFieldIsUnique
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 getOriginal
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 queryColumnWithLocales
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 dotStringToNestedArray
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 objectToArray
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
42
 arrayToObject
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
42
 validatePicture
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 32
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
182
 getUploadedFileFullPath
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 getUploadedFileMimeType
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 getClassesUsingNamespace
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getClassesUsingInterface
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getValidatedEnum
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Lib\Helpers;
4
5use Carbon\Carbon;
6use Illuminate\Contracts\Database\Eloquent\Builder;
7use Illuminate\Database\Eloquent\Model;
8use Illuminate\Http\Request;
9use Illuminate\Support\Str;
10use Illuminate\Support\Arr;
11use Illuminate\Support\Facades\File;
12use Illuminate\Support\Facades\Http;
13use Illuminate\Support\Facades\Route;
14use Illuminate\Support\Facades\Storage;
15use Illuminate\Support\Facades\Validator;
16use Illuminate\Validation\Rule;
17use Illuminate\Validation\Rules\Enum;
18use Illuminate\Validation\ValidationException;
19use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
20use Symfony\Component\Finder\SplFileInfo;
21
22class ToolboxHelper
23{
24    /**
25     * @param array<int|string, mixed> $array1
26     * @param array<int|string, mixed> $array2
27     *
28     * @return array<int|string, mixed>
29     */
30    public static function arrayMergeRecursiveDistinct(array &$array1, array &$array2): array
31    {
32        $merged = $array1;
33        foreach ($array2 as $key => &$value) {
34            if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
35                $merged[$key] = self::arrayMergeRecursiveDistinct($merged[$key], $value);
36            } else {
37                $merged[$key] = $value;
38            }
39        }
40
41        return $merged;
42    }
43
44    /**
45     * Validate recaptcha
46     *
47     * @param \Illuminate\Http\Request $request
48     * @param boolean                  $isV3
49     * @return void
50     */
51    public static function validateRecaptcha(Request $request, bool $isV3 = true)
52    {
53        Validator::validate($request->all(), [
54            'g-recaptcha-response' => [
55                'required', 'string',
56                // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed, Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
57                function ($attribute, $value, $fail) use ($isV3) {
58                    try {
59                        $response = Http::asForm()->post('https://www.google.com/recaptcha/api/siteverify', [
60                            'secret' => config('services.google.recaptcha.private'),
61                            'response' => \strval($value),
62                            'remoteip' => app('clientIp')
63                        ]);
64                        if ($e = $response->toException()) {
65                            throw $e;
66                        }
67                        if ($isV3) {
68                            if (
69                                !$response->json('success') or
70                                !$response->json('challenge_ts') or
71                                Carbon::parse($response->json('challenge_ts'))->lessThan(\now('utc')->subMinutes(5)) or
72                                $response->json('hostname') !== \parse_url(config('app.url'), \PHP_URL_HOST) or
73                                !$response->json('score')
74                            ) {
75                                throw new \RuntimeException();
76                            }
77                            if (\floatval($response->json('score')) < 0.8) {
78                                $fail("Vous n'avez pas obtenu un score assez élevé lors de la validation du recaptcha");
79                            }
80                            return;
81                        }
82                        if (
83                            !$response->json('success') or
84                            !$response->json('challenge_ts') or
85                            Carbon::parse($response->json('challenge_ts'))->lessThan(\now('utc')->subMinutes(5)) or
86                            $response->json('hostname') !== \parse_url(config('app.url'), \PHP_URL_HOST)
87                        ) {
88                            throw new \RuntimeException();
89                        }
90                    } catch (\Exception $e) {
91                        $fail('Erreur lors de la validation du formulaire veuillez réssayer');
92                    } //end try
93                }
94            ]
95        ], [], ['g-recaptcha-response' => 'reCaptcha']);
96    }
97
98    /**
99     * Strip scheme (https) on oembed urls
100     * Only embed allowed are for MP4 self hosted videos right now
101     *
102     * https is force by ckeditor MediaElements which natively supports
103     * only cloud hosted medias (youtube, spotify etc..)
104     *
105     * @param string $input
106     * @return string
107     */
108    public static function stripCkEditorSchemesOnMediaInputs(string $input): string
109    {
110        $input = \preg_replace('/(?<=<oembed url=")(https:\/\/)(?=.*?">)/m', '', $input);
111        return $input;
112    }
113
114    /**
115     * Assert That no Back Office url is present on txt
116     *
117     * @param string $field
118     * @param string $text
119     * @return string
120     * @throws \Illuminate\Validation\ValidationException If url is a bo url.
121     */
122    public static function assertNoInternalBoUrls(string $field, string $text): string
123    {
124        $routes = Route::getRoutes();
125        // * Url replace and email replace.
126        $text = preg_replace_callback(
127            // phpcs:ignore Generic.Files.LineLength.TooLong
128            '/(?P<url>(?:http[s]?:\/\/.)?(?:www\.)?[-a-zA-Z0-9@%._\+~#=]{2,256}\.[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/\/=]*))/',
129            function ($matches) use ($routes, $field) {
130                $match = collect($matches)->first() ?? '';
131                $url   = $match;
132                try {
133                    $request = Request::create($url);
134                    // If a route is match then it do not throws exception.
135                    if (
136                        \parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST) &&
137                        trim($routes->match($request)->getPrefix() ?? '', '/') === 'bo'
138                    ) {
139                        // Removes the matched url.
140                        throw ValidationException::withMessages([
141                            $field => trans(
142                                'crud.libs.toolbox.assertNoInternalBoUrls',
143                                ['attribute' => $field]
144                            )
145                        ]);
146                    }
147                    return $match;
148                } catch (NotFoundHttpException $e) {
149                    return $match;
150                }
151            },
152            $text
153        );
154        return $text;
155    }
156
157    /**
158     * Assert That only external url is present on txt
159     *
160     * @param string $field
161     * @param string $text
162     * @return string
163     * @throws \Illuminate\Validation\ValidationException If url is a bo url.
164     */
165    public static function assertNoInternalUrls(string $field, string $text): string
166    {
167        self::assertNoInternalBoUrls($field, $text);
168        $routes = Route::getRoutes();
169        // * Url replace and email replace.
170        $text = preg_replace_callback(
171            // phpcs:ignore Generic.Files.LineLength.TooLong
172            '/(?P<url>(?:http[s]?:\/\/.)?(?:www\.)?[-a-zA-Z0-9@%._\+~#=]{2,256}\.[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/\/=]*))/',
173            function ($matches) use ($routes, $field) {
174                $match = collect($matches)->first() ?? '';
175                $url   = $match;
176                try {
177                    $request = Request::create($url);
178                    // If a route is match then it do not throws exception.
179                    if (
180                        \parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST) &&
181                        $routes->match($request)
182                    ) {
183                        // Removes the matched url.
184                        throw ValidationException::withMessages([
185                            $field => trans(
186                                'crud.libs.toolbox.assertNoInternalUrls',
187                                ['attribute' => $field, 'appname' => config('app.name')]
188                            )
189                        ]);
190                    }
191                    return $match;
192                } catch (NotFoundHttpException $e) {
193                    return $match;
194                }
195            },
196            $text
197        );
198        return $text;
199    }
200
201    /**
202     * Mutltibyte string replace
203     *
204     * @param array|string $search
205     * @param array|string $replace
206     * @param array|string $subject
207     * @param integer      $count
208     * @return array|string
209     */
210    public static function mbReplace(
211        array|string $search,
212        array|string $replace,
213        array|string $subject,
214        int &$count = 0
215    ): array|string {
216        if (!is_array($search) && is_array($replace)) {
217            return false;
218        }
219        if (is_array($subject)) {
220            // Call mb_replace for each single string in $subject .
221            foreach ($subject as &$string) {
222                $string = &self::mbReplace($search, $replace, $string, $count);
223            }
224        } elseif (is_array($search)) {
225            if (!is_array($replace)) {
226                foreach ($search as &$string) {
227                    $subject = self::mbReplace($string, $replace, $subject, $count);
228                }
229            } else {
230                $n = max(count($search), count($replace));
231                while ($n--) {
232                    $subject = self::mbReplace(current($search), current($replace), $subject, $count);
233                    next($search);
234                    next($replace);
235                }
236            }
237        } else {
238            $parts   = mb_split(preg_quote($search), $subject);
239            $count   = count($parts) - 1;
240            $subject = implode($replace, $parts);
241        } //end if
242        return $subject;
243    }
244
245    /**
246     * Asserts that the field is unique
247     *
248     * @param string                                  $table
249     * @param string                                  $field
250     * @param string|integer|float|boolean|null|array $value
251     * @param integer|null                            $id
252     * @param callable|null                           $query
253     * @return void
254     * @throws \Illuminate\Validation\ValidationException If the field is not unique.
255     */
256    public static function assertFieldIsUnique(
257        string $table,
258        string $field,
259        string|int|float|bool|null|array $value,
260        ?int $id = null,
261        ?callable $query = null
262    ) {
263        if (!$query) {
264            Validator::make([$field => $value], [
265                self::mbReplace('.', '\.', $field) => Rule::unique($table, $field)->ignore($id),
266            ], [
267                self::mbReplace('.', '\.', "{$field}.unique")
268                => trans('crud.libs.toolbox.assertFieldIsUnique', ['attribute' => $field, 'value' => $value])
269            ])->validate();
270            return;
271        }
272        Validator::make([$field => $value], [
273            $field => Rule::unique($table)->where($query)->ignore($id),
274        ], [
275            $field . '.unique' => trans(
276                'crud.libs.toolbox.assertFieldIsUnique',
277                ['attribute' => $field, 'value' => $value]
278            )
279        ])->validate();
280    }
281
282    /**
283     * Get original polyfill with autotranslate behavior
284     *
285     * @param \Illuminate\Database\Eloquent\Model $model
286     * @param string                              $attribute
287     * @return mixed
288     */
289    public static function getOriginal(Model $model, string $attribute): mixed
290    {
291        if (\in_array('Spatie\Translatable\HasTranslations', \class_uses_recursive($model))) {
292            return $model->getTranslation(
293                $attribute,
294                $model->getLocale(),
295                $model->useFallbackLocale()
296            );
297        }
298        return $model->getOriginal($attribute);
299    }
300
301    /**
302     * Dynamic model query
303     *
304     * @param string                                          $defaultLocale
305     * @param \Illuminate\Contracts\Database\Eloquent\Builder $q
306     * @param string                                          $column
307     * @param string                                          $value
308     * @return \Illuminate\Contracts\Database\Eloquent\Builder
309     */
310    public static function queryColumnWithLocales(
311        string $defaultLocale,
312        Builder $q,
313        string $column,
314        string $value
315    ): Builder {
316        $currentLocale = app()->currentLocale();
317        $locales       = collect(config('app.locales'))
318            ->mapWithKeys(fn (string $locale) => [$locale => $locale]);
319        if (!$locales->has($defaultLocale)) {
320            // * Remove default locale.
321            $locales->pull($defaultLocale);
322        }
323        if (!$locales->has($currentLocale)) {
324            // * Remove current locale.
325            $locales->pull($currentLocale);
326        }
327
328        return $q->where(function (Builder $q) use ($defaultLocale, $currentLocale, $locales, $column, $value) {
329            // * Query default locale
330            $q->whereRaw("JSON_EXTRACT({$column}, '$.{$defaultLocale}') = '{$value}'");
331            if ($defaultLocale !== $currentLocale) {
332                // * Query current locale
333                $q->whereRaw("JSON_EXTRACT({$column}, '$.{$currentLocale}') = '{$value}'");
334            }
335            // * Query any other locale
336            $locales->each(fn ($locale) => $q->orWhereRaw(
337                "JSON_EXTRACT({$column}, '$.{$locale}') = '{$value}'"
338            ));
339        });
340    }
341
342    /**
343     * Generates an array from a dot separated string
344     *
345     * @param string $path
346     * @param mixed  $value
347     * @param string $separator
348     * @return array
349     */
350    public static function dotStringToNestedArray(string $path, mixed $value, string $separator = '.'): array
351    {
352        $arr  = $value;
353        $keys = array_reverse(explode($separator, $path));
354
355        foreach ($keys as $key) {
356            $arr = [$key => $arr];
357        }
358        return $arr;
359    }
360
361    /**
362     * Convert deeply an object to array
363     *
364     * @param array|object $input
365     * @return array
366     * @throws \RuntimeException If $input var is a scalar value.
367     */
368    public static function objectToArray($input): array
369    {
370        // Only process if it's an object or array being passed to the function.
371        if (is_object($input) or is_array($input)) {
372            $ret = (array)$input;
373            foreach ($ret as &$item) {
374                // Recursively process EACH element only if not scalar.
375                $item = (is_object($item) or is_array($item)) ?
376                    self::objectToArray($item) : $item;
377            }
378            return $ret;
379        } else {
380            throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input));
381        }
382    }
383
384    /**
385     * Convert deeply an array to object
386     *
387     * @param array|object $input
388     * @return object
389     * @throws \RuntimeException If $input var is a scalar value.
390     */
391    public static function arrayToObject($input): object
392    {
393        // Only process if it's an object or array being passed to the function.
394        if (is_object($input) or is_array($input)) {
395            $ret = (object)$input;
396            foreach ($ret as &$item) {
397                // Recursively process EACH element only if not scalar.
398                $item = (is_object($item) or is_array($item)) ?
399                    self::arrayToObject($item) : $item;
400            }
401            return $ret;
402        } else {
403            throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input));
404        }
405    }
406
407    /**
408     * Validate picture
409     *
410     * @param string      $attribute
411     * @param string|null $value
412     * @param callback    $fail
413     * @param object      $sizes
414     * @return void
415     */
416    public static function validatePicture(string $attribute, string|null $value, callable $fail, object $sizes)
417    {
418        if (!($useStorage = Storage::exists($value)) and !File::exists($value)) {
419            $fail(trans(':attribute n\'existe pas dans le système de fichier', [
420                'attribute' => $attribute
421            ]));
422            return;
423        }
424        /** @var string */
425        $fileFullPath = self::getUploadedFileFullPath($value, $useStorage);
426        if (
427            !\in_array(self::getUploadedFileMimeType($value, $useStorage), [
428                'image/jpeg', 'image/jpg', 'image/png', 'image/gif'
429            ])
430        ) {
431            $fail(trans(':attribute doit être une image de type \'image/jpeg,image/jpg,image/png,image/gif\'', [
432                'attribute' => $attribute
433            ]));
434        }
435        if (!($dimensions = \getimagesize($fileFullPath)) or !isset($dimensions[0]) or !isset($dimensions[1])) {
436            $fail(trans(':attribute impossible de valider les dimensions', [
437                'attribute' => $attribute
438            ]));
439        } else {
440            $width  = intval($dimensions[0]);
441            $height = intval($dimensions[1]);
442
443            $xMessage = trans(
444                ":attribute la largeur doit être comprise entre {$sizes->minWith}px et {$sizes->maxWith}px"
445            );
446            if ($sizes->minWith === $sizes->maxWith) {
447                $xMessage = trans(":attribute la largeur doit être de {$sizes->minWith}px");
448            }
449            $yMessage = trans(
450                ":attribute la hauteur doit être comprise entre {$sizes->minWith}px et {$sizes->maxWith}px"
451            );
452            if ($sizes->minHeight === $sizes->maxHeight) {
453                $yMessage = trans(":attribute la hauteur doit être de {$sizes->minWith}px");
454            }
455
456            if (($width < $sizes->minWith) or ($width > $sizes->maxWith)) {
457                $fail($xMessage);
458            }
459            if (($height < $sizes->minHeight) or ($height > $sizes->maxHeight)) {
460                $fail($yMessage);
461            }
462        } //end if
463    }
464
465    /**
466     * Get the file full path
467     *
468     * @param string  $value
469     * @param boolean $useStorage
470     * @return string
471     */
472    private static function getUploadedFileFullPath(string $value, bool $useStorage): string
473    {
474        /** @var \Illuminate\Filesystem\FilesystemAdapter */
475        $disk = Storage::disk();
476        return !$useStorage ? (realpath($value) ?: $value) : $disk->path($value);
477    }
478
479    /**
480     * Get the file mimetype
481     *
482     * @param string  $value
483     * @param boolean $useStorage
484     * @return string|false
485     */
486    private static function getUploadedFileMimeType(string $value, bool $useStorage)
487    {
488        return !$useStorage ? File::mimeType($value) : Storage::mimeType($value);
489    }
490
491    /**
492     * Fetch class list from a specific namespace
493     *
494     * @param string $namespace
495     * @return array<string> An array of classe namespaces
496     */
497    public static function getClassesUsingNamespace(string $namespace): array
498    {
499        return collect(File::files(\app_path(Str::of($namespace)->replaceFirst('\App', ''))))
500            ->filter(fn (SplFileInfo $splFileInfo) => $splFileInfo->getExtension() === 'php')
501            ->map(fn (SplFileInfo $splFileInfo) => Str::of($splFileInfo->getBasename())
502                ->replace('.' . $splFileInfo->getExtension(), '')->prepend("{$namespace}\\"))->all();
503    }
504
505    /**
506     * Get all classes from a specific namespace that implement a specific interface
507     *
508     * @param string $namespace
509     * @param string $interface
510     * @return array<string> An array of classe namespaces
511     */
512    public static function getClassesUsingInterface(string $namespace, string $interface): array
513    {
514        return Arr::where(
515            static::getClassesUsingNamespace($namespace),
516            fn (string $class_namespace) => \collect(class_implements($class_namespace, true))->filter()
517                ->contains(fn (string $class_interface) => $class_interface === $interface)
518        );
519    }
520
521    /**
522     * Get validated pagination from request.
523     *
524     * @param integer $default
525     * @param string  $field
526     * @param string  $enumPath
527     * @return integer
528     */
529    public static function getValidatedEnum(int $default, string $field, string $enumPath): int
530    {
531        try {
532            return \intval(Validator::make(
533                [$field => \request()->get($field)],
534                [$field => new Enum($enumPath)]
535            )->validated()[$field]);
536        } catch (ValidationException $e) {
537            return $default;
538        }
539    }
540}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Lib/Helpers/dashboard.html b/tests/coverage/app/Lib/Helpers/dashboard.html deleted file mode 100644 index 2fba893..0000000 --- a/tests/coverage/app/Lib/Helpers/dashboard.html +++ /dev/null @@ -1,321 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Lib/Helpers - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Lib\Helpers\ToolboxHelper0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
ClassCRAP
App\Lib\Helpers\ToolboxHelper6642
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- - -
- - - - - - diff --git a/tests/coverage/app/Lib/Helpers/index.html b/tests/coverage/app/Lib/Helpers/index.html deleted file mode 100644 index 58b2694..0000000 --- a/tests/coverage/app/Lib/Helpers/index.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Lib/Helpers - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 209
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ExceptionsHelper.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ToolboxHelper.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 209
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Lib/MigrateOldData.php.html b/tests/coverage/app/Lib/MigrateOldData.php.html deleted file mode 100644 index 7ec9bad..0000000 --- a/tests/coverage/app/Lib/MigrateOldData.php.html +++ /dev/null @@ -1,401 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Lib/MigrateOldData.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
MigrateOldData
n/a
0 / 0
n/a
0 / 0
19
n/a
0 / 0
 runMigration
n/a
0 / 0
n/a
0 / 0
1
 instruct
n/a
0 / 0
n/a
0 / 0
15
 initFile
n/a
0 / 0
n/a
0 / 0
1
 write
n/a
0 / 0
n/a
0 / 0
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Lib;
4
5use App\Exceptions\AbortRowImportException;
6use App\Models\Brand;
7use App\Models\Customer;
8use App\Models\CustomerInfo;
9use App\Models\CustomerLogin;
10use App\Models\SingleOptin;
11use Carbon\Exceptions\InvalidFormatException;
12use Database\migrations\LeGaulois2016Migration;
13use Illuminate\Database\Eloquent\Builder;
14use Illuminate\Support\Carbon;
15use Illuminate\Support\Facades\File;
16use Illuminate\Support\Facades\Hash;
17use Illuminate\Support\Facades\Validator;
18use Illuminate\Support\Str;
19
20/**
21 * @codeCoverageIgnore
22 */
23class MigrateOldData extends LeGaulois2016Migration
24{
25    /** @var \App\Models\Brand */
26    private $brand;
27
28    /** @var string */
29    private $table;
30
31    /**
32     * RunMigration.
33     *
34     * @param \App\Models\Brand $brand
35     * @param string            $table
36     * @return void
37     */
38    public function runMigration(Brand $brand, string $table): void
39    {
40        $this->table = $table;
41        $this->brand = $brand;
42        $this->instruct();
43        $this->up();
44    }
45
46    /**
47     * Instruct.
48     *
49     * @return array
50     * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
51     */
52    public function instruct(): array
53    {
54        //phpcs:enable
55        $this->initFile();
56        $cleanDegeu = function (string $str) {
57            return html_entity_decode(
58                trim(str_replace('\\', '', ucwords(stripcslashes(strtolower($str))))),
59                ENT_QUOTES | ENT_HTML5,
60                'UTF-8'
61            );
62        };
63        return [
64            'Users' => [
65                'table' => $this->table,
66                'model' => Customer::class,
67                'comment' => sprintf('Migrating %s customers', $this->brand->name),
68                'bind' => [
69                    'email' => [
70                        'apply' => function ($v, $model) use ($cleanDegeu) {
71                            $v                      = \mb_convert_encoding($v, "UTF-8");
72                            $v                      = explode('#|#', $v);
73                            $oldId                  = $v[0];
74                            $first_name             = $cleanDegeu($v[1]);
75                            $last_name              = $cleanDegeu($v[2]);
76                            $birth_date             = $v[3];
77                            $address                = $cleanDegeu($v[4]);
78                            $address2               = $cleanDegeu($v[5]);
79                            $city                   = $cleanDegeu($v[6]);
80                            $postcode               = $v[7];
81                            $user_inscritNewsletter = $v[8];
82                            $email                  = strtolower($v[9]);
83                            $pwd                    = $v[10];
84                            $created_at             = $v[11];
85                            $updated_at             = $v[12];
86                            $last_cnx               = $v[13];
87
88                            // * Just save Single optin.
89                            if (empty($first_name) && empty($last_name)) {
90                                $sglOptin           = SingleOptin::query()->where('email', strtolower($email))
91                                    ->whereHas('brand', function (Builder $q) {
92                                        $q->where('id', $this->brand->id);
93                                    })->firstOrNew();
94                                $sglOptin->email    = strtolower($email);
95                                $sglOptin->brand_id = $this->brand->id;
96                                $sglOptin->save();
97                            } else {
98                                // * Validate Data.
99                                $d = [
100                                    'first_name' => $first_name,
101                                    'last_name' => $last_name,
102                                    'address' => $address,
103                                    'address2' => $address2,
104                                    'city' => $city,
105                                    'postcode' => $postcode,
106                                ];
107
108                                $validator = Validator::make($d, [
109                                    'first_name' => 'min:2',
110                                    'last_name' => 'min:2'
111                                ]);
112
113                                if ($validator->fails()) {
114                                    throw new AbortRowImportException();
115                                }
116
117                                $rules = [
118                                    'address' => 'string|min:2',
119                                    'address2' => 'string|min:2',
120                                    'city' => 'string|min:2',
121                                    'postcode' => 'digits_between:4,5'
122                                ];
123
124                                $validate = function (array $data, array $rule) {
125                                    return Validator::make($data, $rule)->fails();
126                                };
127
128                                foreach ($rules as $key => $rule) {
129                                    if ($validate([$key => $d[$key]], [$key => $rule])) {
130                                        ${$key} = null;
131                                    }
132                                }
133
134                                $model             = Customer::where('email', $email)->firstOrNew();
135                                $model->email      = $email;
136                                $model->created_at = $created_at;
137                                $model->updated_at = $updated_at;
138                                $model->save();
139
140                                // * Filtre birthdate puisque c'est du sale dans la vielle crm.
141                                try {
142                                    $expl = explode('-', $birth_date);
143                                    $d    = Carbon::parse($birth_date);
144                                    if (
145                                        $d->toDateString() === sprintf(
146                                            '%s-%s-%s',
147                                            $expl[2] ?? '',
148                                            $expl[1] ?? '',
149                                            $expl[0] ?? ''
150                                        )
151                                    ) {
152                                        $birth_date = $d->toDateString();
153                                    }
154                                } catch (InvalidFormatException $e) {
155                                    $birth_date = '';
156                                }
157
158
159                                if ($birth_date === '0000-00-00') {
160                                    $birth_date = '';
161                                }
162
163                                $city     = !empty($city) ? $city : null;
164                                $postcode = !empty($postcode) ? $postcode : null;
165                                $address  = !empty($address) ? $address : null;
166                                $address2 = !empty($address2) ? $address2 : null;
167
168                                $cInfo              = new CustomerInfo();
169                                $cInfo->hashcode    = Str::uuid();
170                                $cInfo->firstname   = ucfirst(strtolower($first_name));
171                                $cInfo->lastname    = ucfirst(strtolower($last_name));
172                                $cInfo->birth_date  = !strlen($birth_date) ? null : $birth_date;
173                                $cInfo->address     = $address;
174                                $cInfo->address2    = $address2;
175                                $cInfo->city        = $city;
176                                $cInfo->postcode    = $postcode;
177                                $cInfo->opt_in      = $user_inscritNewsletter ? true : false;
178                                $cInfo->brand_id    = $this->brand->id;
179                                $cInfo->customer_id = $model->id;
180                                $cInfo->created_at  = $created_at;
181                                $cInfo->updated_at  = $updated_at;
182                                $cInfo->save();
183
184                                $cLogin                  = new CustomerLogin();
185                                $cLogin->password        = Hash::make(trim($pwd));
186                                $cLogin->brand_id        = $this->brand->id;
187                                $cLogin->customer_id     = $model->id;
188                                $cLogin->status          = true;
189                                $cLogin->created_at      = $created_at;
190                                $cLogin->updated_at      = $updated_at;
191                                $cLogin->last_connection = $last_cnx;
192                                $cLogin->save();
193
194                                $this->write(
195                                    [
196                                        'new' => $model->id,
197                                        'old' => $oldId,
198                                        'hashcode' => $cInfo->hashcode,
199                                        'created_at' => $created_at,
200                                        'updated_at' => $updated_at
201                                    ]
202                                );
203                            } //end if
204                            throw new AbortRowImportException();
205                        },
206                        'name' => [
207                            'user_id',
208                            'firstname',
209                            'lastname',
210                            'birthdate',
211                            'address',
212                            'address2',
213                            'city',
214                            'postcode',
215                            'optin',
216                            'email',
217                            'pwd',
218                            'created_at',
219                            'updated_at',
220                            'last_cnx'
221                        ]
222                    ],
223                ]
224            ],
225        ];
226    }
227
228    /**
229     * Create the migration file.
230     *
231     * @return void
232     */
233    public function initFile(): void
234    {
235        File::put(storage_path('crm_migration.csv'), sprintf('new;old;hashcode;created_at;updated_at') . PHP_EOL);
236    }
237
238    /**
239     * Write date in the migration file.
240     *
241     * @param array $data
242     * @return void
243     */
244    public function write(array $data): void
245    {
246        foreach ($data as &$d) {
247            $d = sprintf('"%s"', $d);
248        }
249        File::append(storage_path('crm_migration.csv'), implode(';', $data) . PHP_EOL);
250    }
251}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Lib/dashboard.html b/tests/coverage/app/Lib/dashboard.html deleted file mode 100644 index 6cf5ac4..0000000 --- a/tests/coverage/app/Lib/dashboard.html +++ /dev/null @@ -1,322 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Lib - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Lib\Helpers\ToolboxHelper0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
ClassCRAP
App\Lib\Helpers\ToolboxHelper6642
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- - -
- - - - - - diff --git a/tests/coverage/app/Lib/index.html b/tests/coverage/app/Lib/index.html deleted file mode 100644 index e7a584c..0000000 --- a/tests/coverage/app/Lib/index.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Lib - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 19.25% covered (danger) -
-
-
19.25%
51 / 265
-
- 24.00% covered (danger) -
-
-
24.00%
6 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
Helpers
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 209
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Helper.php
-
- 91.07% covered (success) -
-
-
91.07%
51 / 56
-
- 85.71% covered (warning) -
-
-
85.71%
6 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
MigrateOldData.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Mail/CourrierArcadiaError.php.html b/tests/coverage/app/Mail/CourrierArcadiaError.php.html deleted file mode 100644 index 58d868b..0000000 --- a/tests/coverage/app/Mail/CourrierArcadiaError.php.html +++ /dev/null @@ -1,237 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Mail/CourrierArcadiaError.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CourrierArcadiaError
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 build
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Mail;
4
5use Illuminate\Bus\Queueable;
6use Illuminate\Contracts\Queue\ShouldQueue;
7use Illuminate\Mail\Mailable;
8use Illuminate\Queue\SerializesModels;
9
10class CourrierArcadiaError extends Mailable implements ShouldQueue
11{
12    use Queueable;
13    use SerializesModels;
14
15    /** @var string */
16    public $subject;
17
18    /** @var string */
19    public $msg;
20
21    /** @var string */
22    public $xml;
23
24    /**
25     * Create a new message instance.
26     *
27     * @param string $subject
28     * @param string $msg
29     * @param string $xml
30     * @return void
31     */
32    public function __construct(string $subject, string $msg, string $xml)
33    {
34        $this->subject = $subject;
35        $this->msg     = $msg;
36        $this->xml     = $xml;
37    }
38
39    /**
40     * Build the message.
41     *
42     * @return \Illuminate\Mail\Mailable
43     */
44    public function build(): \Illuminate\Mail\Mailable
45    {
46        $msg = $this->msg;
47        return $this->subject(
48            sprintf(
49                "[LDC CRM] %s",
50                $this->subject
51            )
52        )->view(
53            'mail.arcadia-error',
54            compact('msg')
55        )->attachData(
56            $this->xml,
57            date("Ymd_His") . '.xml',
58            ['mime' => 'application/xml']
59        );
60    }
61}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Mail/ServiceCredentialRenewed.php.html b/tests/coverage/app/Mail/ServiceCredentialRenewed.php.html deleted file mode 100644 index 3246861..0000000 --- a/tests/coverage/app/Mail/ServiceCredentialRenewed.php.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Mail/ServiceCredentialRenewed.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ServiceCredentialRenewed
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 build
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Mail;
4
5use App\Models\Service;
6use App\Models\User;
7use Illuminate\Mail\Mailable;
8
9class ServiceCredentialRenewed extends Mailable
10{
11    /**
12     * The concerned service.
13     *
14     * @var \App\Models\Service
15     */
16    public $service;
17
18    /**
19     * The user who did the action.
20     *
21     * @var \App\Models\User
22     */
23    public $user;
24
25    /**
26     * Create a new message instance.
27     *
28     * @param \App\Models\Service $service
29     * @param \App\Models\User    $user
30     */
31    public function __construct(Service $service, User $user)
32    {
33        $this->service = $service;
34        $this->user    = $user;
35    }
36
37    /**
38     * Build the message.
39     *
40     * @return \Illuminate\Mail\Mailable
41     */
42    public function build(): \Illuminate\Mail\Mailable
43    {
44        return $this->view('mail.service-renewed')
45            ->subject('!!! Warning !!!, New service credential have been generated !')
46            ->text('mail.service-renewed-plain')
47            ->with('appName', config('app.name'))
48            ->with('service', $this->service)
49            ->with('by', sprintf('%s %s (%s)', $this->user->first_name, $this->user->last_name, $this->user->email))
50            ->to(
51                config('mail.contactsList.serviceweb', 'equipe.web@ldc.fr'),
52                sprintf('%s service warning', config('app.name'))
53            );
54    }
55}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Mail/dashboard.html b/tests/coverage/app/Mail/dashboard.html deleted file mode 100644 index 49315d6..0000000 --- a/tests/coverage/app/Mail/dashboard.html +++ /dev/null @@ -1,291 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Mail - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
ClassCoverage
App\Mail\CourrierArcadiaError0%
App\Mail\ServiceCredentialRenewed0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - -
MethodCoverage
__construct0%
build0%
__construct0%
build0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Mail/index.html b/tests/coverage/app/Mail/index.html deleted file mode 100644 index b685a7e..0000000 --- a/tests/coverage/app/Mail/index.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Mail - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 29
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CourrierArcadiaError.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ServiceCredentialRenewed.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Models/ActivityLog.php.html b/tests/coverage/app/Models/ActivityLog.php.html deleted file mode 100644 index b5163a6..0000000 --- a/tests/coverage/app/Models/ActivityLog.php.html +++ /dev/null @@ -1,331 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/ActivityLog.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ActivityLog
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 addActivity
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 getChangedColumns
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 user
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use App\Enums\ActivityLogs\ActivityLogsEventEnum;
6use Carbon\Carbon;
7use Illuminate\Database\Eloquent\Factories\HasFactory;
8use Illuminate\Database\Eloquent\Model;
9use Illuminate\Notifications\Notifiable;
10use Illuminate\Support\Facades\Schema;
11
12/**
13 * @property string                          $model      Target model.
14 * @property string                          $model_id   Id of the target model.
15 * @property string                          $event      Event of this activity (ActivityLogsEventEnum).
16 * @property string                          $data       Changes.
17 * @property-read \Illuminate\Support\Carbon $created_at Created date.
18 *
19 * @method public static function addActivity($model, $eventEnum) Add new activity to the activity logs list.
20 * @method public static function getValuesChanged($activity, $model, $eventEnum)
21 * Get old, new and type of values changed.
22 *
23 * @property-read \App\Models\User $user User BelongsTo relation.
24 */
25class ActivityLog extends Model
26{
27    use HasFactory;
28    use Notifiable;
29
30    /**
31     * Indicates if the model should be timestamped.
32     *
33     * @var boolean
34     */
35    public $timestamps = false;
36
37    /**
38     * The attributes that are mass assignable.
39     *
40     * @var array<int, string>
41     */
42    protected $fillable = [
43        'is_anonymous',
44        'model_class',
45        'model_id',
46        'event',
47        'data',
48        'created_at',
49    ];
50
51    /**
52     * The attributes that should be cast.
53     *
54     * @var array<string, string>
55     */
56    protected $casts = [
57        'is_anonymous' => 'bool',
58        'event'        => ActivityLogsEventEnum::class,
59        'data'         => 'json',
60        'created_at'   => 'datetime',
61    ];
62
63    // * METHODS
64
65    /**
66     * Add new activity to the activity logs list.
67     *
68     * @param \Illuminate\Database\Eloquent\Model           $model
69     * @param \App\Enums\ActivityLogs\ActivityLogsEventEnum $eventEnum
70     * @return void
71     */
72    public static function addActivity(Model $model, ActivityLogsEventEnum $eventEnum): void
73    {
74        $isAnonymous = true;
75        /** @var \Illuminate\Database\Eloquent\Model|null */
76        $userModel = auth('backend')->user();
77        if (is_object($userModel)) {
78            $userModel   = $userModel->getKeyForSelectQuery();
79            $isAnonymous = false;
80        }
81        $activity               = new self();
82        $activity->user_id      = $userModel;
83        $activity->is_console   = app()->runningInConsole();
84        $activity->is_anonymous = $isAnonymous;
85        $activity->model_class  = \get_class($model);
86        $activity->model_id     = $model->getKey();
87        $activity->event        = $eventEnum;
88        $activity->data         = static::getChangedColumns($activity, $model, $eventEnum);
89        $activity->created_at   = Carbon::now();
90        $activity->saveOrFail();
91    }
92
93    /**
94     * Get old, new columns that has changed.
95     *
96     * @param \self                                         $activity
97     * @param \Illuminate\Database\Eloquent\Model           $model
98     * @param \App\Enums\ActivityLogs\ActivityLogsEventEnum $eventEnum
99     * @return array|null
100     */
101    public static function getChangedColumns(self $activity, Model $model, ActivityLogsEventEnum $eventEnum): array|null
102    {
103        $modelClassName = $activity->model_class;
104        /** Get type of each fields of the target model */
105        $targetModel = $activity->model_class::where(
106            (new $modelClassName())->getRouteKeyName(),
107            $activity->model_id
108        )->first();
109        if ($targetModel != null) {
110            // phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
111            $targetModelTypes = collect($targetModel->toArray())
112                ->map(function ($field, $fieldIndex) use ($targetModel) {
113                    return Schema::getColumnType($targetModel->getTable(), $fieldIndex);
114                })->toArray();
115            // phpcs:enable
116        }
117        /** Return old, new and type of values changed */
118        return ($eventEnum === ActivityLogsEventEnum::updated) ?
119            array_intersect_key($targetModelTypes, $model->getChanges()) : null;
120    }
121
122    // * RELATIONS
123
124    /**
125     * User BelongsTo relation.
126     *
127     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
128     */
129    public function user()
130    {
131        return $this->belongsTo(User::class);
132    }
133}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/Answer.php.html b/tests/coverage/app/Models/Answer.php.html deleted file mode 100644 index 35ad8f3..0000000 --- a/tests/coverage/app/Models/Answer.php.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/Answer.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
Answer
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 question
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 customers
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Factories\HasFactory;
6use Illuminate\Database\Eloquent\Model;
7
8/**
9 * @property integer $id                                   Id.
10 * @property string  $answer                               Answer.
11 * @property integer $question_id                          Foreign key Question.
12 * @property-read \Illuminate\Support\Carbon $created_at   Created date.
13 * @property-read \Illuminate\Support\Carbon $updated_at   Updated date.
14 *
15 * @property-read \App\Models\Question $question Question BelongsTo relation.
16 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\Customer>
17 * $customers Customer BelongsToMany relation.
18 */
19class Answer extends Model
20{
21    use HasFactory;
22
23    /**
24     * The attributes that are mass assignable.
25     *
26     * @var string[]
27     */
28    protected $fillable = [
29        'answer',
30    ];
31
32    // * RELATIONS
33
34    /**
35     * Question BelongsTo relation.
36     *
37     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
38     */
39    public function question(): \Illuminate\Database\Eloquent\Relations\BelongsTo
40    {
41        return $this->belongsTo(Question::class);
42    }
43
44    /**
45     * Customer belongsToMany relation.
46     *
47     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
48     */
49    public function customers(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
50    {
51        return $this->belongsToMany(Customer::class, 'customer_answer');
52    }
53}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/Brand.php.html b/tests/coverage/app/Models/Brand.php.html deleted file mode 100644 index 4c5646a..0000000 --- a/tests/coverage/app/Models/Brand.php.html +++ /dev/null @@ -1,522 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/Brand.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 61.90% covered (warning) -
-
-
61.90%
13 / 21
-
- 40.00% covered (danger) -
-
-
40.00%
4 / 10
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Brand
-
- 61.90% covered (warning) -
-
-
61.90%
13 / 21
-
- 40.00% covered (danger) -
-
-
40.00%
4 / 10
15.53
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getCacheBaseTags
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 booted
-
- 66.67% covered (warning) -
-
-
66.67%
6 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
1.04
 services
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 questions
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 customerInfos
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 servicesStats
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 singleOptins
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getAccountsAttribute
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getTotalOptinsAttribute
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use App\Traits\Models\ActivityLog;
6use Illuminate\Database\Eloquent\Factories\HasFactory;
7use Illuminate\Database\Eloquent\Model;
8use Rennokki\QueryCache\Traits\QueryCacheable;
9
10/**
11 * @property integer $id                                   Id.
12 * @property string  $name                                 Name.
13 * @property-read \Illuminate\Support\Carbon $created_at   Created date.
14 * @property-read \Illuminate\Support\Carbon $updated_at   Updated date.
15 *
16 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\Service>
17 * $services Service HasMany relation.
18 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\Question>
19 * $questions Question HasMany relation.
20 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\CustomerInfo>
21 * $customerInfos CustomerInfo HasMany relation.
22 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\ServicesStat>
23 * $servicesStats ServicesStat HasMany relation.
24 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\SingleOptin>
25 * $singleOptins SingleOptin HasMany relation.
26 */
27class Brand extends Model
28{
29    use ActivityLog;
30    use HasFactory;
31    use QueryCacheable;
32
33    /**
34     * The timeout cache for this model.
35     *
36     * @var integer
37     */
38    protected $cacheFor = 0;
39
40    /**
41     * The attributes that are mass assignable.
42     *
43     * @var string[]
44     */
45    protected $fillable = [
46        'name',
47    ];
48
49    /**
50     * Brand
51     *
52     * @param array $attributes
53     */
54    public function __construct(array $attributes = [])
55    {
56        $this->cacheFor = config('api.servicesDBCache') * 60;
57
58        parent::__construct($attributes);
59    }
60
61    /**
62     * Set the base cache tags that will be present
63     * on all queries.
64     *
65     * ! This is used to flush caching
66     *
67     * @return array
68     */
69    protected function getCacheBaseTags(): array
70    {
71        return [
72            'crm_brands',
73        ];
74    }
75
76    /**
77     * Perform any actions required after the model boots.
78     *
79     * @return void
80     */
81    protected static function booted(): void
82    {
83        static::created(function () {
84            // * Flush Eloquent cache.
85            self::flushQueryCache();
86        });
87        static::updated(function () {
88            // * Flush Eloquent cache.
89            self::flushQueryCache();
90        });
91        static::deleted(function () {
92            // * Flush Eloquent cache.
93            self::flushQueryCache();
94        });
95    }
96
97    // * RELATIONS
98
99    /**
100     * Service hasMany relation.
101     *
102     * @return \Illuminate\Database\Eloquent\Relations\HasMany
103     */
104    public function services(): \Illuminate\Database\Eloquent\Relations\HasMany
105    {
106        return $this->hasMany(Service::class);
107    }
108
109    /**
110     * Question hasMany relation.
111     *
112     * @return \Illuminate\Database\Eloquent\Relations\HasMany
113     */
114    public function questions(): \Illuminate\Database\Eloquent\Relations\HasMany
115    {
116        return $this->hasMany(Question::class);
117    }
118
119    /**
120     * CustomerInfo hasMany relation.
121     *
122     * @return \Illuminate\Database\Eloquent\Relations\HasMany
123     */
124    public function customerInfos(): \Illuminate\Database\Eloquent\Relations\HasMany
125    {
126        return $this->hasMany(CustomerInfo::class);
127    }
128
129    /**
130     * ServiceStat hasMany relation.
131     *
132     * @return \Illuminate\Database\Eloquent\Relations\HasMany
133     */
134    public function servicesStats(): \Illuminate\Database\Eloquent\Relations\HasMany
135    {
136        return $this->hasMany(ServiceStat::class);
137    }
138
139    /**
140     * SingleOptin hasMany relation.
141     *
142     * @return \Illuminate\Database\Eloquent\Relations\HasMany
143     */
144    public function singleOptins(): \Illuminate\Database\Eloquent\Relations\HasMany
145    {
146        return $this->hasMany(SingleOptin::class);
147    }
148
149    // * METHODS
150
151    /**
152     * Account attribute accessor.
153     *
154     * @return integer
155     */
156    public function getAccountsAttribute(): int
157    {
158        return $this->customerInfos()->count();
159    }
160
161    /**
162     * Total optins attribute accessor.
163     *
164     * @return integer
165     */
166    public function getTotalOptinsAttribute(): int
167    {
168        return $this->customerInfos()->where('opt_in', 1)->count() + $this->singleOptins()->count();
169    }
170}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/BrandStat.php.html b/tests/coverage/app/Models/BrandStat.php.html deleted file mode 100644 index 6b916f9..0000000 --- a/tests/coverage/app/Models/BrandStat.php.html +++ /dev/null @@ -1,252 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/BrandStat.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 40.00% covered (danger) -
-
-
40.00%
2 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BrandStat
-
- 40.00% covered (danger) -
-
-
40.00%
2 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
4.94
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 booted
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.50
 brand
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Model;
6
7/**
8 * @property integer $active
9 * @property integer $inactive
10 * @property integer $old_accounts
11 * @property integer $new_accounts
12 * @property integer $total_accounts
13 * @property integer $total_opt_in
14 * @property integer $brand_id                             Foreign key Brand.
15 * @property-read \Illuminate\Support\Carbon $created_at   Created date.
16 *
17 * @property-read \App\Models\Brand $brand Brand BelongsTo relation.
18 */
19class BrandStat extends Model
20{
21    /**
22     * Indicates if the model should be timestamped.
23     *
24     * @var boolean
25     */
26    public $timestamps = false;
27
28    /**
29     * The attributes that are mass assignable.
30     *
31     * @var string[]
32     */
33    protected $fillable = [
34        'active',
35        'inactive',
36        'old_accounts',
37        'new_accounts',
38        'total_accounts',
39        'total_opt_in',
40    ];
41
42    /**
43     * The attributes that should be cast to native types.
44     *
45     * @var array
46     */
47    public $casts = [
48        'created_at' => 'date',
49    ];
50
51    /**
52     * Perform any actions required after the model boots.
53     *
54     * @return void
55     */
56    protected static function booted(): void
57    {
58        static::creating(function (self $model) {
59            if (!$model->created_at) {
60                $model->created_at = now();
61            }
62        });
63    }
64
65    // * RELATIONS
66
67    /**
68     * Brand hasMany relation.
69     *
70     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
71     */
72    public function brand(): \Illuminate\Database\Eloquent\Relations\BelongsTo
73    {
74        return $this->belongsTo(Brand::class);
75    }
76}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/Customer.php.html b/tests/coverage/app/Models/Customer.php.html deleted file mode 100644 index 27cbcc2..0000000 --- a/tests/coverage/app/Models/Customer.php.html +++ /dev/null @@ -1,582 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/Customer.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 93.22% covered (success) -
-
-
93.22%
55 / 59
-
- 70.00% covered (warning) -
-
-
70.00%
7 / 10
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Customer
-
- 93.22% covered (success) -
-
-
93.22%
55 / 59
-
- 70.00% covered (warning) -
-
-
70.00%
7 / 10
24.18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 infos
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 logins
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 optInHistory
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 brands
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 answers
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 info
-
- 92.86% covered (success) -
-
-
92.86%
13 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6.01
 login
-
- 92.86% covered (success) -
-
-
92.86%
13 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6.01
 loadBrandData
-
- 84.62% covered (warning) -
-
-
84.62%
11 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5.09
 setOptIn
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getAnswers
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Builder;
6use Illuminate\Database\Eloquent\Collection;
7use Illuminate\Database\Eloquent\Factories\HasFactory;
8use Illuminate\Database\Eloquent\Model;
9use Illuminate\Database\Eloquent\ModelNotFoundException;
10use Illuminate\Database\Eloquent\Relations\HasMany;
11
12/**
13 * @property integer $id                                   Id.
14 * @property string  $email                                Email.
15 * @property-read \Illuminate\Support\Carbon $created_at   Created date.
16 * @property-read \Illuminate\Support\Carbon $updated_at   Updated date.
17 *
18 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\CustomerInfo>
19 * $infos CustomerInfo HasMany relation.
20 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\CustomerLogin>
21 * $logins CustomerLogin HasMany relation.
22 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\CustomerOptInHistory>
23 * $optInHistory CustomerOptInHistory HasMany relation.
24 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\Brand>
25 * $brands Brand BelongsToMany relation.
26 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\Answer>
27 * $answers Answer BelongsToMany relation.
28 */
29class Customer extends Model
30{
31    use HasFactory;
32
33    public const FIRST_OR_NULL = 0;
34    public const FIRST_OR_NEW  = 1;
35    public const FIRST_OR_FAIL = 2;
36
37    /**
38     * The attributes that are mass assignable.
39     *
40     * @var string[]
41     */
42    protected $fillable = [
43        'email',
44    ];
45
46    // * RELATIONS
47
48    /**
49     * CustomerInfo hasMany relation.
50     *
51     * @return \Illuminate\Database\Eloquent\Relations\HasMany
52     */
53    public function infos(): \Illuminate\Database\Eloquent\Relations\HasMany
54    {
55        return $this->hasMany(CustomerInfo::class);
56    }
57
58    /**
59     * CustomerLogin hasMany relation.
60     *
61     * @return \Illuminate\Database\Eloquent\Relations\HasMany
62     */
63    public function logins(): \Illuminate\Database\Eloquent\Relations\HasMany
64    {
65        return $this->hasMany(CustomerLogin::class);
66    }
67
68    /**
69     * CustomerOptInHistory hasMany relation.
70     *
71     * @return \Illuminate\Database\Eloquent\Relations\HasMany
72     */
73    public function optInHistory(): \Illuminate\Database\Eloquent\Relations\HasMany
74    {
75        return $this->hasMany(CustomerOptInHistory::class);
76    }
77
78    /**
79     * Customer Brand belongsToMany relation.
80     *
81     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
82     */
83    public function brands(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
84    {
85        return $this->belongsToMany(Brand::class, CustomerInfo::class);
86    }
87
88    /**
89     * Answers belongsToMany relation.
90     *
91     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
92     */
93    public function answers(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
94    {
95        return $this->belongsToMany(Answer::class, 'customer_answer');
96    }
97
98    // * METHODS
99
100    /**
101     * Get the CustomerInfo from a specific brand
102     * or create a New one if $firstOrNewOrFail is 1
103     * throw model not found exception if firstOrNewOrFail = 2.
104     *
105     * @param \App\Models\Brand $brand
106     * @param integer           $firstOrNewOrFail
107     * @return \App\Models\CustomerLogin|null
108     */
109    public function info(Brand $brand, int $firstOrNewOrFail = self::FIRST_OR_NULL): ?CustomerInfo
110    {
111        if (isset($this->relations['infos'])) {
112            /** @var \App\Models\CustomerInfo $info */
113            foreach ($this->relations['infos'] as $info) {
114                if ($info->brand_id === $brand->id) {
115                    return $info;
116                }
117            }
118        }
119        $query = CustomerInfo::query()->whereHas('brand', function (Builder $q) use ($brand) {
120            $q->where('id', $brand->id);
121        })->whereHas('customer', function (Builder $q) {
122            $q->where('id', $this->id);
123        });
124        if ($firstOrNewOrFail === self::FIRST_OR_NEW) {
125            return $query->firstOrNew();
126        }
127        if ($firstOrNewOrFail === self::FIRST_OR_FAIL) {
128            return $query->firstOrFail();
129        }
130        return $query->first();
131    }
132
133    /**
134     * Get the CustomerLogin from a specific brand
135     * or create a New one if $firstOrNewOrFail is 1
136     * throw model not found exception if firstOrNewOrFail = 2.
137     *
138     * @param \App\Models\Brand $brand
139     * @param integer           $firstOrNewOrFail
140     * @return \App\Models\CustomerLogin|null
141     */
142    public function login(Brand $brand, int $firstOrNewOrFail = self::FIRST_OR_NULL): ?CustomerLogin
143    {
144        if (isset($this->relations['logins'])) {
145            /** @var \App\Models\CustomerLogin $login */
146            foreach ($this->relations['logins'] as $login) {
147                if ($login->brand_id === $brand->id) {
148                    return $login;
149                }
150            }
151        }
152        $query = CustomerLogin::query()->whereHas('brand', function (Builder $q) use ($brand) {
153            $q->where('id', $brand->id);
154        })->whereHas('customer', function (Builder $q) {
155            $q->where('id', $this->id);
156        });
157        if ($firstOrNewOrFail === self::FIRST_OR_NEW) {
158            return $query->firstOrNew();
159        }
160        if ($firstOrNewOrFail === self::FIRST_OR_FAIL) {
161            return $query->firstOrFail();
162        }
163        return $query->first();
164    }
165
166    /**
167     * Load login and info for this customer and this specific brand.
168     *
169     * @param \App\Models\Brand $brand
170     * @param boolean           $orFail
171     * @return self
172     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException If no login or info was found for the brand.
173     */
174    public function loadBrandData(Brand $brand, bool $orFail = false): self
175    {
176        $this->load([
177            'logins' => function (HasMany $q) use ($brand) {
178                $q->where('brand_id', $brand->id);
179            },
180            'infos' => function (HasMany $q) use ($brand) {
181                $q->where('brand_id', $brand->id);
182            }
183        ]);
184        if ($orFail and !isset($this->relations['logins'][0])) {
185            throw (new ModelNotFoundException())->setModel(CustomerLogin::class);
186        }
187        if ($orFail and !isset($this->relations['infos'][0])) {
188            throw (new ModelNotFoundException())->setModel(CustomerInfo::class);
189        }
190        return $this;
191    }
192
193    /**
194     * Set this customer as optin.
195     *
196     * @param \App\Models\Brand $brand
197     * @param boolean           $optIn
198     * @return void
199     * @throws \Throwable If customer history update failed.
200     */
201    public function setOptIn(Brand $brand, bool $optIn): void
202    {
203        $this->opt_in = $optIn;
204
205        // * Ajout dans la table d'historique des opt-in de la nouvelle valeur.
206        $optInHistory            = new CustomerOptInHistory();
207        $optInHistory->new_value = $optIn;
208        $optInHistory->customer()->associate($this);
209        $optInHistory->brand()->associate($brand);
210        $optInHistory->saveOrFail();
211    }
212
213    /**
214     * Get All answers given by this customer
215     * for a specific service.
216     *
217     * @param \App\Models\Service $service
218     * @return \Illuminate\Database\Eloquent\Collection
219     */
220    public function getAnswers(Service $service): Collection
221    {
222        return Answer::query()->whereHas('customers', function (Builder $q) {
223            $q->where('id', $this->id);
224        })->whereHas('question', function (Builder $q) use ($service) {
225            $q->whereHas('brand', function (Builder $q) use ($service) {
226                $q->where('id', $service->brand->id);
227            });
228        })->get();
229    }
230}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/CustomerAnswer.php.html b/tests/coverage/app/Models/CustomerAnswer.php.html deleted file mode 100644 index 098fb87..0000000 --- a/tests/coverage/app/Models/CustomerAnswer.php.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/CustomerAnswer.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerAnswer
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 getUpdatedAtColumn
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 customer
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 answer
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Relations\Pivot;
6
7/**
8 * @property integer $answer_id                            Foreign key Answer.
9 * @property integer $customer_id                          Foreign key Customer.
10 * @property-read \Illuminate\Support\Carbon $created_at   Created date.
11 *
12 * @property-read \App\Models\Customer $customer Customer BelongsTo relation.
13 * @property-read \App\Models\Answer $answer Answer BelongsTo relation.
14 */
15class CustomerAnswer extends Pivot
16{
17    /**
18     * Inhibit update_at column as we only have
19     * created_at.
20     *
21     * @return null
22     */
23    public function getUpdatedAtColumn()
24    {
25        return null;
26    }
27
28    // * RELATIONS
29
30    /**
31     * Customer belongsTo relation.
32     *
33     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
34     */
35    public function customer(): \Illuminate\Database\Eloquent\Relations\BelongsTo
36    {
37        return $this->belongsTo(Customer::class);
38    }
39
40    /**
41     * Customer belongsTo relation.
42     *
43     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
44     */
45    public function answer(): \Illuminate\Database\Eloquent\Relations\BelongsTo
46    {
47        return $this->belongsTo(Answer::class);
48    }
49}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/CustomerInfo.php.html b/tests/coverage/app/Models/CustomerInfo.php.html deleted file mode 100644 index 1dc64f2..0000000 --- a/tests/coverage/app/Models/CustomerInfo.php.html +++ /dev/null @@ -1,410 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/CustomerInfo.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 80.95% covered (warning) -
-
-
80.95%
17 / 21
-
- 66.67% covered (warning) -
-
-
66.67%
4 / 6
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerInfo
-
- 80.95% covered (warning) -
-
-
80.95%
17 / 21
-
- 66.67% covered (warning) -
-
-
66.67%
4 / 6
6.25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 booted
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 customer
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 brand
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 login
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getFromEmail
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getFromHashcode
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use App\Enums\Country;
6use Illuminate\Database\Eloquent\Builder;
7use Illuminate\Support\Str;
8use Illuminate\Database\Eloquent\Factories\HasFactory;
9use Illuminate\Database\Eloquent\Model;
10
11/**
12 * @property integer             $id                     Id.
13 * @property integer             $customer_id            Foreign key Customer.
14 * @property integer             $brand_id               Foreign key Brand.
15 * @property string              $firstname              Firstname.
16 * @property string              $lastname               Lastname.
17 * @property \Carbon\Carbon|null $birth_date             Birth_date.
18 * @property string|null         $address                Address.
19 * @property string|null         $address2               Address2.
20 * @property string              $phone                  Phone.
21 * @property \App\Enums\Country  $country                Country.
22 * @property string|null         $city                   City.
23 * @property string|null         $postcode               Postcode.
24 * @property boolean             $opt_in                 Opt_in.
25 * @property string              $hashcode               Hashcode.
26 * @property \Illuminate\Support\Carbon $created_at Created date.
27 * @property \Illuminate\Support\Carbon $updated_at Updated date.
28 *
29 * @property-read \App\Models\Customer $customer Customer BelongsTo relation.
30 * @property-read \App\Models\Brand    $brand Brand BelongsTo relation.
31 */
32class CustomerInfo extends Model
33{
34    use HasFactory;
35
36    /**
37     * The attributes that are mass assignable.
38     *
39     * @var string[]
40     */
41    protected $fillable = [
42        'firstname',
43        'lastname',
44        'birth_date',
45        'address',
46        'address2',
47        'phone',
48        'country',
49        'city',
50        'postcode',
51        'opt_in'
52    ];
53
54    /**
55     * The attributes that should be cast to native types.
56     *
57     * @var array
58     */
59    protected $casts = [
60        'country' => Country::class,
61        'opt_in'  => 'bool',
62    ];
63
64    /**
65     * Perform any actions required after the model boots.
66     *
67     * @return void
68     */
69    protected static function booted(): void
70    {
71        static::creating(function (self $model) {
72            $model->hashcode = Str::uuid();
73        });
74        static::deleting(function (self $model) {
75            CustomerOptInHistory::query()->whereHas('customer', function (Builder $q) use ($model) {
76                $q->where('id', $model->customer->id);
77            })->whereHas('brand', function (Builder $q) use ($model) {
78                $q->where('id', $model->brand->id);
79            })->delete();
80        });
81    }
82
83    // * RELATIONS
84
85    /**
86     * Customer BelongsTo relation.
87     *
88     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
89     */
90    public function customer(): \Illuminate\Database\Eloquent\Relations\BelongsTo
91    {
92        return $this->belongsTo(Customer::class);
93    }
94
95    /**
96     * Brand BelongsTo relation.
97     *
98     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
99     */
100    public function brand(): \Illuminate\Database\Eloquent\Relations\BelongsTo
101    {
102        return $this->belongsTo(Brand::class);
103    }
104
105    // * METHODS
106
107    /**
108     * Get Login.
109     *
110     * @return \App\Models\CustomerLogin
111     */
112    public function login(): \App\Models\CustomerLogin
113    {
114        return $this->customer->login($this->brand);
115    }
116
117    /**
118     * Get customer info from email.
119     *
120     * @param \App\Models\Brand $brand
121     * @param string            $email
122     * @return \Illuminate\Database\Eloquent\Builder
123     */
124    public static function getFromEmail(Brand $brand, string $email): \Illuminate\Database\Eloquent\Builder
125    {
126        return CustomerInfo::query()->whereHas('brand', function (Builder $q) use ($brand) {
127            $q->where('id', $brand->id);
128        })->whereHas('customer', function (Builder $q) use ($email) {
129            $q->where('email', $email);
130        });
131    }
132
133    /**
134     * Get customer info from hashcode.
135     *
136     * @param \App\Models\Brand $brand
137     * @param string            $hashcode
138     * @return \Illuminate\Database\Eloquent\Builder
139     */
140    public static function getFromHashcode(Brand $brand, string $hashcode): \Illuminate\Database\Eloquent\Builder
141    {
142        return CustomerInfo::query()->whereHas('brand', function (Builder $q) use ($brand) {
143            $q->where('id', $brand->id);
144        })->where('hashcode', $hashcode);
145    }
146}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/CustomerLogin.php.html b/tests/coverage/app/Models/CustomerLogin.php.html deleted file mode 100644 index 742c6c7..0000000 --- a/tests/coverage/app/Models/CustomerLogin.php.html +++ /dev/null @@ -1,327 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/CustomerLogin.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerLogin
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 booted
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
 customer
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 brand
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 passwordMatch
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Factories\HasFactory;
6use Illuminate\Database\Eloquent\Model;
7use Illuminate\Support\Facades\Hash;
8
9/**
10 * @property integer        $id                          Id.
11 * @property integer        $customer_id                 Foreign key Customer.
12 * @property integer        $brand_id                    Foreign key Brand.
13 * @property string         $password                    Answer.
14 * @property \Carbon\Carbon $last_connection             Answer.
15 * @property boolean        $status                      Answer.
16 * @property \Illuminate\Support\Carbon $created_at Created date.
17 * @property \Illuminate\Support\Carbon $updated_at Updated date.
18 *
19 * @property-read \App\Models\Customer $customer Customer BelongsTo relation.
20 * @property-read \App\Models\Brand    $brand Brand BelongsTo relation.
21 */
22class CustomerLogin extends Model
23{
24    use HasFactory;
25
26    /**
27     * The model's attributes.
28     *
29     * @var array
30     */
31    protected $attributes = [
32        'status' => false,
33    ];
34
35    /**
36     * The attributes that are mass assignable.
37     *
38     * @var string[]
39     */
40    protected $fillable = [
41        'password',
42    ];
43
44    /**
45     * The attributes that should be cast to native types.
46     *
47     * @var array
48     */
49    protected $casts = [
50        'status'          => 'bool',
51        'last_connection' => 'datetime',
52    ];
53
54    /**
55     * Perform any actions required after the model boots.
56     *
57     * @return void
58     */
59    protected static function booted(): void
60    {
61        static::creating(function (self $model) {
62            if (Hash::needsRehash($model->password)) {
63                $model->password = Hash::make(trim($model->password));
64            }
65        });
66        static::updating(function (self $model) {
67            if (Hash::needsRehash($model->password)) {
68                $model->password = Hash::make(trim($model->password));
69            }
70        });
71    }
72
73    // * RELATIONS
74
75    /**
76     * Customer BelongsTo relation.
77     *
78     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
79     */
80    public function customer(): \Illuminate\Database\Eloquent\Relations\BelongsTo
81    {
82        return $this->belongsTo(Customer::class);
83    }
84
85    /**
86     * Brand BelongsTo relation.
87     *
88     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
89     */
90    public function brand(): \Illuminate\Database\Eloquent\Relations\BelongsTo
91    {
92        return $this->belongsTo(Brand::class);
93    }
94
95    // * METHODS
96
97    /**
98     * Check if the user password is correct.
99     *
100     * @param string $password
101     * @return boolean
102     */
103    public function passwordMatch(string $password): bool
104    {
105        return Hash::check($password, $this->password);
106    }
107}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/CustomerOptInHistory.php.html b/tests/coverage/app/Models/CustomerOptInHistory.php.html deleted file mode 100644 index f529475..0000000 --- a/tests/coverage/app/Models/CustomerOptInHistory.php.html +++ /dev/null @@ -1,236 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/CustomerOptInHistory.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerOptInHistory
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 customer
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 brand
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Factories\HasFactory;
6use Illuminate\Database\Eloquent\Model;
7
8/**
9 * @property integer $id                                 Id.
10 * @property integer $customer_id                        Foreign key Customer.
11 * @property integer $brand_id                           Foreign key Brand.
12 * @property boolean $new_value
13 * @property-read \Illuminate\Support\Carbon $created_at Created date.
14 * @property-read \Illuminate\Support\Carbon $updated_at Updated date.
15 *
16 * @property-read \App\Models\Customer $customer Customer BelongsTo relation.
17 * @property-read \App\Models\Brand    $brand Brand BelongsTo relation.
18 */
19class CustomerOptInHistory extends Model
20{
21    use HasFactory;
22
23    /**
24     * The table associated with the model.
25     *
26     * @var string
27     */
28    protected $table = "customer_opt_in_history";
29
30    /**
31     * The attributes that should be cast to native types.
32     *
33     * @var array
34     */
35    protected $casts = [
36        'new_value' => 'bool',
37    ];
38
39    // * RELATIONS
40
41    /**
42     * Customer BelongsTo relation.
43     *
44     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
45     */
46    public function customer(): \Illuminate\Database\Eloquent\Relations\BelongsTo
47    {
48        return $this->belongsTo(Customer::class);
49    }
50
51    /**
52     * Brand BelongsTo relation.
53     *
54     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
55     */
56    public function brand(): \Illuminate\Database\Eloquent\Relations\BelongsTo
57    {
58        return $this->belongsTo(Brand::class);
59    }
60}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/Question.php.html b/tests/coverage/app/Models/Question.php.html deleted file mode 100644 index b37df9d..0000000 --- a/tests/coverage/app/Models/Question.php.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/Question.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
Question
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 brand
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 answers
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use App\Enums\QuestionType;
6use App\Traits\Models\ActivityLog;
7use Illuminate\Database\Eloquent\Factories\HasFactory;
8use Illuminate\Database\Eloquent\Model;
9
10/**
11 * @property integer                 $id                 Id.
12 * @property integer                 $brand_id           Foreign key Brand.
13 * @property string                  $question           Question.
14 * @property \App\Enums\QuestionType $type               Type de question.
15 * @property-read \Illuminate\Support\Carbon $created_at Created date.
16 * @property-read \Illuminate\Support\Carbon $updated_at Updated date.
17 *
18 * @property-read \App\Models\Answer $answer Answer BelongsTo relation.
19 * @property-read \App\Models\Brand  $brand Brand BelongsTo relation.
20 */
21class Question extends Model
22{
23    use ActivityLog;
24    use HasFactory;
25
26    /**
27     * The attributes that are mass assignable.
28     *
29     * @var string[]
30     */
31    protected $fillable = [
32        'question',
33        'type',
34        'brand_id',
35    ];
36
37    /**
38     * Map attribute names to enum classes.
39     *
40     * @var array
41     */
42    protected $casts = [
43        'type' => QuestionType::class,
44    ];
45
46    // * RELATIONS
47
48    /**
49     * Brand BelongsTo relation.
50     *
51     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
52     */
53    public function brand(): \Illuminate\Database\Eloquent\Relations\BelongsTo
54    {
55        return $this->belongsTo(Brand::class);
56    }
57
58    /**
59     * Answer Has many relation.
60     *
61     * @return \Illuminate\Database\Eloquent\Relations\HasMany
62     */
63    public function answers(): \Illuminate\Database\Eloquent\Relations\HasMany
64    {
65        return $this->hasMany(Answer::class);
66    }
67}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/Service.php.html b/tests/coverage/app/Models/Service.php.html deleted file mode 100644 index f1a808e..0000000 --- a/tests/coverage/app/Models/Service.php.html +++ /dev/null @@ -1,609 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/Service.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 74.51% covered (warning) -
-
-
74.51%
38 / 51
-
- 50.00% covered (danger) -
-
-
50.00%
5 / 10
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Service
-
- 74.51% covered (warning) -
-
-
74.51%
38 / 51
-
- 50.00% covered (danger) -
-
-
50.00%
5 / 10
20.24
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 booted
-
- 61.54% covered (warning) -
-
-
61.54%
8 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
1.06
 brand
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 servicesStats
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getCacheBaseTags
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 generateBearerToken
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 generateBearerPassword
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 incrementStat
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getFromBearerToken
-
- 92.31% covered (success) -
-
-
92.31%
12 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5.01
 authenticateApi
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use App\Jobs\SetServiceStats;
6use App\Lib\Helper;
7use App\Traits\Models\ActivityLog;
8use Illuminate\Database\Eloquent\Factories\HasFactory;
9use Illuminate\Database\Eloquent\Model;
10use Illuminate\Database\Eloquent\ModelNotFoundException;
11use Illuminate\Http\Request;
12use Illuminate\Support\Facades\Crypt;
13use Illuminate\Support\Facades\Hash;
14use Illuminate\Support\Str;
15use Rennokki\QueryCache\Traits\QueryCacheable;
16
17/**
18 * @property integer                         $id                Id.
19 * @property integer                         $brand_id          Foreign key Brand.
20 * @property string                          $name              Nom.
21 * @property string                          $bearer_token
22 * @property string                          $bearer_pwd
23 * @property \Carbon\Carbon                  $bearer_token_date
24 * @property-read \Illuminate\Support\Carbon $created_at        Created date.
25 * @property-read \Illuminate\Support\Carbon $updated_at        Updated date.
26 *
27 * @property-read \App\Models\Brand    $brand Brand BelongsTo relation.
28 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\ServiceStat>
29 * $servicesStats ServiceStat HasMany relation.
30 */
31class Service extends Model
32{
33    use ActivityLog;
34    use HasFactory;
35    use QueryCacheable;
36
37    /**
38     * The timeout cache for this model
39     *
40     * @var integer
41     */
42    protected $cacheFor = 0;
43
44    /**
45     * The attributes that are mass assignable.
46     *
47     * @var string[]
48     */
49    protected $fillable = [
50        'name',
51        'brand_id',
52    ];
53
54    /**
55     * The attributes that should be cast to native types.
56     *
57     * @var array
58     */
59    protected $casts = [
60        'bearer_token_date' => 'datetime',
61    ];
62
63    /**
64     * Service.
65     *
66     * @param array $attributes
67     */
68    public function __construct(array $attributes = [])
69    {
70        parent::__construct($attributes);
71        $this->cacheFor = config('api.servicesDBCache') * 60;
72    }
73
74
75    /**
76     * Perform any actions required after the model boots.
77     *
78     * @return void
79     */
80    protected static function booted(): void
81    {
82        static::creating(function (self $model) {
83            $model->generateBearerToken();
84            $model->generateBearerPassword();
85        });
86        static::created(function () {
87            // * Flush Eloquent cache.
88            self::flushQueryCache();
89        });
90        static::updated(function () {
91            // * Flush Eloquent cache.
92            self::flushQueryCache();
93        });
94        static::deleted(function () {
95            // * Flush Eloquent cache.
96            self::flushQueryCache();
97        });
98    }
99
100    // * RELATIONS
101
102    /**
103     * Brand BelongsTo relation.
104     *
105     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
106     */
107    public function brand(): \Illuminate\Database\Eloquent\Relations\BelongsTo
108    {
109        return $this->belongsTo(Brand::class);
110    }
111
112    /**
113     * ServiceStat hasMany relation.
114     *
115     * @return \Illuminate\Database\Eloquent\Relations\HasMany
116     */
117    public function servicesStats(): \Illuminate\Database\Eloquent\Relations\HasMany
118    {
119        return $this->hasMany(ServiceStat::class);
120    }
121
122    // * METHODS
123
124    /**
125     * Set the base cache tags that will be present
126     * on all queries.
127     *
128     * ! This is used to flush caching
129     *
130     * @return array
131     */
132    protected function getCacheBaseTags(): array
133    {
134        return [
135            'crm_services',
136        ];
137    }
138
139    /**
140     * Generates new bearer token.
141     *
142     * @return string
143     */
144    public function generateBearerToken(): string
145    {
146        $this->bearer_token      = hash('ripemd160', Str::uuid());
147        $this->bearer_token_date = now();
148        return $this->bearer_token;
149    }
150
151    /**
152     * Generates new bearer password
153     * It store the crypted password in model
154     * and returns the plain password.
155     *
156     * @return string
157     */
158    public function generateBearerPassword(): string
159    {
160        $pwd              = hash('sha256', Str::uuid());
161        $this->bearer_pwd = Crypt::encryptString($pwd);
162        return $pwd;
163    }
164
165    /**
166     * Increment API CRM Stat.
167     *
168     * @return void
169     */
170    public function incrementStat(): void
171    {
172        SetServiceStats::dispatch($this)->afterResponse()
173            ->onConnection('database')->onQueue('stats');
174    }
175
176    /**
177     * Get Service from bearerToken with its brand.
178     *
179     * @param string $bearerToken
180     * @return \App\Models\Service
181     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException If the token matches no known service.
182     */
183    public static function getFromBearerToken(string $bearerToken): self
184    {
185        $services = static::all();
186        /** @var \App\Models\Service $service */
187        foreach ($services as $service) {
188            $tokenEquals = false;
189            // * Keep compatibility with V1.
190            if (!Hash::needsRehash($bearerToken)) {
191                // TODO: Remove this method when no more service will be in V1 (hashed instead of encrypted).
192                $tokenEquals = Hash::check($bearerToken, $service->bearer_token);
193            } else {
194                $tokenEquals = $bearerToken === $service->bearer_token;
195            }
196            if ($service->bearer_token and $tokenEquals) {
197                return $service->load([
198                    'brand' => function ($query) use ($service) {
199                        return $query->cacheTags(["service:{$service->id}:brand"]);
200                    },
201                ]);
202            }
203        }
204        throw new ModelNotFoundException('Could not find service from Service Token');
205    }
206
207    /**
208     * Authenticate the request for this service
209     *
210     * This will check hash-mac and that the request is wellformed
211     *
212     * The request should have the minimum following parameters
213     *  - timestamp using format Y-m-d H:i:s, and must be UTC (Greenwich Mean Time)
214     *  - bearerToken the public token generated by the crm
215     *  - signature the hashmac signature of the request
216     *
217     * ! Signature must be calculated with every parameter urlencode once only
218     * ! All parameters to calculate the signature must be sorted (natural sort asc)
219     *
220     * ! Signature should look like
221     * * httpVerb\n
222     * * uri\n
223     * * queryString
224     *
225     * ! httpVerb as well as uri must be lower case
226     * ! uri should include scheme, host and path and nothing else, if path is empty a trailing slash should be added
227     * ! eg: https://ldc-crm.fr/customer/1  or  https://ldc-crm.fr/
228     * ! The query string shall be separated with '&', eg param1=value1&param2=value2
229     * ! Key names and values of the query string must be url encoded using RFC 3986
230     * ! http://www.faqs.org/rfcs/rfc3986.html
231     * ! Signature must be hmac sha256 using the private key generatedby the crm
232     *
233     *     * ! They should then be concat in a string separated by \n
234     *
235     * @param \Illuminate\Http\Request $request
236     * @return boolean
237     * @throws \App\Exceptions\Api\V4\CrmException If an error occurs.
238     */
239    public function authenticateApi(Request $request): bool
240    {
241        // ! Hack to prevent Laravel to cast empty strings to null or the opposite.
242        // ! If cannot decode json user legacy all() method.
243        $data = \json_decode($request->getContent(), true);
244        $data = (\is_array($data) and \json_last_error() === \JSON_ERROR_NONE) ?
245            array_replace_recursive($request->all(), $data) : $request->all();
246
247        $calculatedHash = Helper::signRequest(
248            $this->bearer_pwd,
249            $request->getUri(),
250            $request->getMethod(),
251            $data
252        );
253
254        // ! Très important hash_equals https://fr.wikipedia.org/wiki/Attaque_temporelle
255        return \hash_equals($calculatedHash, $request->signature);
256    }
257}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/ServiceStat.php.html b/tests/coverage/app/Models/ServiceStat.php.html deleted file mode 100644 index e0e335c..0000000 --- a/tests/coverage/app/Models/ServiceStat.php.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/ServiceStat.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ServiceStat
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 brand
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 service
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Factories\HasFactory;
6use Illuminate\Database\Eloquent\Model;
7
8/**
9 * @property integer                         $id         Id.
10 * @property integer                         $brand_id   Foreign key Brand.
11 * @property integer                         $service_id Foreign key Service.
12 * @property \Illuminate\Support\Carbon      $date       Date.
13 * @property integer                         $nb_calls   Nombre d'appels.
14 * @property-read \Illuminate\Support\Carbon $created_at Created date.
15 * @property-read \Illuminate\Support\Carbon $updated_at Updated date.
16 *
17 * @property-read \App\Models\Brand   $brand Brand BelongsTo relation.
18 * @property-read \App\Models\Service $service Service BelongsTo relation.
19 */
20class ServiceStat extends Model
21{
22    use HasFactory;
23
24    /**
25     * The attributes that are mass assignable.
26     *
27     * @var string[]
28     */
29    protected $fillable = [
30        'date',
31    ];
32
33    /**
34     * The model's attributes.
35     *
36     * @var array
37     */
38    protected $attributes = [
39        'nb_calls' => 0,
40    ];
41
42    /**
43     * Map attribute names to enum classes.
44     *
45     * @var array
46     */
47    protected $casts = [
48        'date' => 'date',
49    ];
50
51    // * RELATIONS
52
53    /**
54     * Brand BelongsTo relation.
55     *
56     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
57     */
58    public function brand(): \Illuminate\Database\Eloquent\Relations\BelongsTo
59    {
60        return $this->belongsTo(Brand::class);
61    }
62
63    /**
64     * Service BelongsTo relation.
65     *
66     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
67     */
68    public function service(): \Illuminate\Database\Eloquent\Relations\BelongsTo
69    {
70        return $this->belongsTo(Service::class);
71    }
72}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/SingleOptin.php.html b/tests/coverage/app/Models/SingleOptin.php.html deleted file mode 100644 index ded41ac..0000000 --- a/tests/coverage/app/Models/SingleOptin.php.html +++ /dev/null @@ -1,251 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/SingleOptin.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SingleOptin
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 booted
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 brand
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Factories\HasFactory;
6use Illuminate\Database\Eloquent\Model;
7use Illuminate\Support\Str;
8
9/**
10 * @property integer $hashcode                           Hashcode.
11 * @property integer $brand_id                           Foreign key Brand.
12 * @property string  $email                              Email.
13 * @property-read \Illuminate\Support\Carbon $created_at Created date.
14 * @property-read \Illuminate\Support\Carbon $updated_at Updated date.
15
16 * @property-read \App\Models\Brand $brand Brand BelongsTo relation.
17 */
18class SingleOptin extends Model
19{
20    use HasFactory;
21
22    /**
23     * The primary key for the model.
24     *
25     * @var string
26     */
27    protected $primaryKey = 'hashcode';
28
29    /**
30     * The "type" of the primary key ID.
31     *
32     * @var string
33     */
34    protected $keyType = 'uuid';
35
36    /**
37     * Indicates if the IDs are auto-incrementing.
38     *
39     * @var boolean
40     */
41    public $incrementing = false;
42
43    /**
44     * The attributes that are mass assignable.
45     *
46     * @var string[]
47     */
48    protected $fillable = [
49        'email',
50    ];
51
52    /**
53     * Perform any actions required after the model boots.
54     *
55     * @return void
56     */
57    protected static function booted(): void
58    {
59        static::creating(function (self $model) {
60            $model->hashcode = Str::uuid();
61        });
62    }
63
64    // * RELATIONS
65
66    /**
67     * Brand BelongsTo relation.
68     *
69     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
70     */
71    public function brand(): \Illuminate\Database\Eloquent\Relations\BelongsTo
72    {
73        return $this->belongsTo(Brand::class);
74    }
75}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/User.php.html b/tests/coverage/app/Models/User.php.html deleted file mode 100644 index d412665..0000000 --- a/tests/coverage/app/Models/User.php.html +++ /dev/null @@ -1,327 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models/User.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 23
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
User
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 23
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
56
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 booted
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 20
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 updatePassword
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 activityLogs
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Models;
4
5use App\Enums\Users\RoleEnum;
6use App\Traits\Models\ActivityLog;
7use Illuminate\Database\Eloquent\Factories\HasFactory;
8use Illuminate\Foundation\Auth\User as Authenticatable;
9use Illuminate\Notifications\Notifiable;
10use Illuminate\Support\Facades\Hash;
11
12/**
13 * @property string                          $first_name   Prénom.
14 * @property string                          $last_name    Nom.
15 * @property string                          $email        Email.
16 * @property string                          $password     Mot de passe.
17 * @property \App\Enums\Users\RoleEnum       $role         Rôle.
18 * @property \Illuminate\Support\Carbon      $published    État de publication.
19 * @property \Illuminate\Support\Carbon      $published_at Date de mise à jour de l'état de publication.
20 * @property-read \Illuminate\Support\Carbon $created_at   Created date.
21 * @property-read \Illuminate\Support\Carbon $updated_at   Updated date.
22 *
23 * @method protected static function booted()             Perform any actions required after the model boots.
24 * @method private static function setOrder($model)       Set order after the last element of the list.
25 * @method private static function updatePassword($model) Update password.
26 *
27 * @property-read \App\Models\ActivityLog $activityLogs Activities logs One-to-many relationship.
28 */
29class User extends Authenticatable
30{
31    use ActivityLog;
32    use HasFactory;
33    use Notifiable;
34
35    /**
36     * The attributes that are mass assignable.
37     *
38     * @var array<int, string>
39     */
40    protected $fillable = [
41        'first_name',
42        'last_name',
43        'email',
44        'password',
45        'role',
46        'published',
47        'published_at',
48    ];
49
50    /**
51     * The attributes that should be hidden for serialization.
52     *
53     * @var array<int, string>
54     */
55    protected $hidden = [
56        'password',
57        'remember_token',
58    ];
59
60    /**
61     * The attributes that should be cast.
62     *
63     * @var array<string, string>
64     */
65    protected $casts = [
66        'role'              => RoleEnum::class,
67        'email_verified_at' => 'datetime',
68        'published'         => 'boolean',
69    ];
70
71    /**
72     * Perform any actions required after the model boots.
73     *
74     * @return void
75     */
76    protected static function booted(): void
77    {
78        static::creating(function (self $model) {
79            static::updatePassword($model);
80            // * Prevent user elevation privileges
81            throw_if(
82                auth('backend')->user() and auth('backend')->user()->role->value() > $model->role->value(),
83                AuthorizationException::class
84            );
85        });
86        static::updating(function (self $model) {
87            static::updatePassword($model);
88            if (optional(auth('backend')->user())->getKey() === $model->getKey()) {
89                \validator(
90                    ['published' => $model->published],
91                    ['published' => 'required|boolean|accepted'],
92                    ['published.accepted' => trans('Vous ne pouvez pas déactiver votre propre compte')],
93                )->validate();
94            }
95            // * Prevent user elevation privileges
96            throw_if(
97                auth('backend')->user() and auth('backend')->user()->role->value() > $model->role->value(),
98                AuthorizationException::class
99            );
100        });
101    }
102
103    // * METHODS
104
105    /**
106     * Update password.
107     *
108     * @param self $model
109     * @return void
110     */
111    private static function updatePassword(self $model): void
112    {
113        if (Hash::needsRehash($model->password)) {
114            $model->password = Hash::make($model->password);
115        }
116    }
117
118    // * RELATIONS
119
120    /**
121     * Activities logs One-to-many relationship.
122     *
123     * @return \Illuminate\Database\Eloquent\Relations\HasMany
124     */
125    public function activityLogs(): \Illuminate\Database\Eloquent\Relations\HasMany
126    {
127        return $this->hasMany(ActivityLog::class);
128    }
129}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Models/dashboard.html b/tests/coverage/app/Models/dashboard.html deleted file mode 100644 index 57c6369..0000000 --- a/tests/coverage/app/Models/dashboard.html +++ /dev/null @@ -1,322 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Models - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

- -
-
-

Project Risks

-
- - - - - - - - - - - - - - -
ClassCRAP
App\Models\User56
App\Models\ActivityLog42
App\Models\Service20
App\Models\BrandStat4
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
- -
-

Project Risks

-
- - - - - - - - - - - - - - - - -
MethodCRAP
booted20
getChangedColumns12
addActivity6
updatePassword6
loadBrandData5
booted2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Models/index.html b/tests/coverage/app/Models/index.html deleted file mode 100644 index f2c1c6f..0000000 --- a/tests/coverage/app/Models/index.html +++ /dev/null @@ -1,484 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Models - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 64.53% covered (warning) -
-
-
64.53%
151 / 234
-
- 60.66% covered (warning) -
-
-
60.66%
37 / 61
-
- 50.00% covered (danger) -
-
-
50.00%
7 / 14
ActivityLog.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Answer.php
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
Brand.php
-
- 61.90% covered (warning) -
-
-
61.90%
13 / 21
-
- 40.00% covered (danger) -
-
-
40.00%
4 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BrandStat.php
-
- 40.00% covered (danger) -
-
-
40.00%
2 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Customer.php
-
- 93.22% covered (success) -
-
-
93.22%
55 / 59
-
- 70.00% covered (warning) -
-
-
70.00%
7 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerAnswer.php
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerInfo.php
-
- 80.95% covered (warning) -
-
-
80.95%
17 / 21
-
- 66.67% covered (warning) -
-
-
66.67%
4 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerLogin.php
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CustomerOptInHistory.php
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
Question.php
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
Service.php
-
- 74.51% covered (warning) -
-
-
74.51%
38 / 51
-
- 50.00% covered (danger) -
-
-
50.00%
5 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ServiceStat.php
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SingleOptin.php
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
User.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 23
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Observers/ModelObserver.php.html b/tests/coverage/app/Observers/ModelObserver.php.html deleted file mode 100644 index ef5345e..0000000 --- a/tests/coverage/app/Observers/ModelObserver.php.html +++ /dev/null @@ -1,274 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Observers/ModelObserver.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ModelObserver
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
20
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 created
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 updated
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 duplicated
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 deleted
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Observers;
4
5use App\Enums\ActivityLogs\ActivityLogsEventEnum;
6use App\Models\ActivityLog;
7use Illuminate\Database\Eloquent\Model;
8
9class ModelObserver
10{
11    /**
12     * Handle the model "created" event.
13     *
14     * @param \Illuminate\Database\Eloquent\Model $model
15     * @return void
16     */
17    public static function created(Model $model): void
18    {
19        ActivityLog::addActivity($model, ActivityLogsEventEnum::created);
20    }
21
22    /**
23     * Handle the model "updated" event.
24     *
25     * @param \Illuminate\Database\Eloquent\Model $model
26     * @return void
27     */
28    public static function updated(Model $model): void
29    {
30        ActivityLog::addActivity($model, ActivityLogsEventEnum::updated);
31    }
32
33    /**
34     * Handle the model "duplicated" event.
35     *
36     * @param \Illuminate\Database\Eloquent\Model $model
37     * @return void
38     */
39    public static function duplicated(Model $model): void
40    {
41        ActivityLog::addActivity($model, ActivityLogsEventEnum::duplicated);
42    }
43
44    /**
45     * Handle the model "deleted" event.
46     *
47     * @param \Illuminate\Database\Eloquent\Model $model
48     * @return void
49     */
50    public static function deleted(Model $model): void
51    {
52        ActivityLog::addActivity($model, ActivityLogsEventEnum::deleted);
53    }
54}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Observers/dashboard.html b/tests/coverage/app/Observers/dashboard.html deleted file mode 100644 index af824ec..0000000 --- a/tests/coverage/app/Observers/dashboard.html +++ /dev/null @@ -1,290 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Observers - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Observers\ModelObserver0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - -
MethodCoverage
created0%
updated0%
duplicated0%
deleted0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Observers/index.html b/tests/coverage/app/Observers/index.html deleted file mode 100644 index 68fe5d0..0000000 --- a/tests/coverage/app/Observers/index.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Observers - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ModelObserver.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Policies/AnswerPolicy.php.html b/tests/coverage/app/Policies/AnswerPolicy.php.html deleted file mode 100644 index e99a004..0000000 --- a/tests/coverage/app/Policies/AnswerPolicy.php.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Policies/AnswerPolicy.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
AnswerPolicy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 view
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 viewAny
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 delete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Policies;
4
5use App\Policies\Rules\UserStaticRules as USR;
6
7class AnswerPolicy
8{
9    /**
10     * View an Answer.
11     *
12     * @return boolean
13     */
14    public function view(): bool
15    {
16        return USR::noOne();
17    }
18
19    /**
20     * ViewAny an Answer.
21     *
22     * @return boolean
23     */
24    public function viewAny(): bool
25    {
26        return USR::everyOne();
27    }
28
29    /**
30     * Create an Answer.
31     *
32     * @return boolean
33     */
34    public function create(): bool
35    {
36        return USR::everyOne();
37    }
38
39    /**
40     * Update an Answer.
41     *
42     * @return boolean
43     */
44    public function update(): bool
45    {
46        return USR::everyOne();
47    }
48
49    /**
50     * Delete an Answer.
51     *
52     * @return boolean
53     */
54    public function delete(): bool
55    {
56        return USR::everyOne();
57    }
58}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Policies/BrandPolicy.php.html b/tests/coverage/app/Policies/BrandPolicy.php.html deleted file mode 100644 index 1cb1b6d..0000000 --- a/tests/coverage/app/Policies/BrandPolicy.php.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Policies/BrandPolicy.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BrandPolicy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 view
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 viewAny
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 delete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Policies;
4
5use App\Policies\Rules\UserStaticRules as USR;
6
7class BrandPolicy
8{
9    /**
10     * View a Brand.
11     *
12     * @return boolean
13     */
14    public function view(): bool
15    {
16        return USR::noOne();
17    }
18
19    /**
20     * ViewAny a Brand.
21     *
22     * @return boolean
23     */
24    public function viewAny(): bool
25    {
26        return USR::everyOne();
27    }
28
29    /**
30     * Create a Brand.
31     *
32     * @return boolean
33     */
34    public function create(): bool
35    {
36        return USR::everyOne();
37    }
38
39    /**
40     * Update a Brand.
41     *
42     * @return boolean
43     */
44    public function update(): bool
45    {
46        return USR::everyOne();
47    }
48
49    /**
50     * Delete a Brand.
51     *
52     * @return boolean
53     */
54    public function delete(): bool
55    {
56        return USR::noOne();
57    }
58}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Policies/CustomerPolicy.php.html b/tests/coverage/app/Policies/CustomerPolicy.php.html deleted file mode 100644 index e481d08..0000000 --- a/tests/coverage/app/Policies/CustomerPolicy.php.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Policies/CustomerPolicy.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerPolicy
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
26.83
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 view
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 viewAny
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 delete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 customerBelongsToService
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Policies;
4
5use App\Models\Customer;
6use App\Models\Service;
7use Illuminate\Auth\Access\HandlesAuthorization;
8use App\Policies\Rules\UserStaticRules as USR;
9
10class CustomerPolicy
11{
12    use HandlesAuthorization;
13
14    /**
15     * View a Customer.
16     *
17     * @return boolean
18     */
19    public function view(): bool
20    {
21        return USR::everyOne();
22    }
23
24    /**
25     * View any a Customer.
26     *
27     * @return boolean
28     */
29    public function viewAny(): bool
30    {
31        return USR::everyOne();
32    }
33
34    /**
35     * Create a Customer.
36     *
37     * @return boolean
38     */
39    public function create(): bool
40    {
41        return USR::noOne();
42    }
43
44    /**
45     * Update a Customer.
46     *
47     * @return boolean
48     */
49    public function update(): bool
50    {
51        return USR::noOne();
52    }
53
54    /**
55     * Delete a Customer.
56     *
57     * @return boolean
58     */
59    public function delete(): bool
60    {
61        return USR::everyOne();
62    }
63
64    /**
65     * Check if the customer belongs to the service.
66     *
67     * @param \App\Models\Service  $service
68     * @param \App\Models\Customer $customer
69     * @return boolean
70     */
71    public function customerBelongsToService(Service $service, Customer $customer)
72    {
73        return !\is_null($customer->login($service->brand));
74    }
75}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Policies/QuestionPolicy.php.html b/tests/coverage/app/Policies/QuestionPolicy.php.html deleted file mode 100644 index b16f094..0000000 --- a/tests/coverage/app/Policies/QuestionPolicy.php.html +++ /dev/null @@ -1,336 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Policies/QuestionPolicy.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
QuestionPolicy
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
26.83
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 view
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 viewAny
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 delete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 questionBelongsToService
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Policies;
4
5use App\Models\Question;
6use App\Models\Service;
7use App\Policies\Rules\UserStaticRules as USR;
8
9class QuestionPolicy
10{
11    /**
12     * View a Question.
13     *
14     * @return boolean
15     */
16    public function view(): bool
17    {
18        return USR::everyOne();
19    }
20
21    /**
22     * ViewAny a Question.
23     *
24     * @return boolean
25     */
26    public function viewAny(): bool
27    {
28        return USR::everyOne();
29    }
30
31    /**
32     * Create a Question.
33     *
34     * @return boolean
35     */
36    public function create(): bool
37    {
38        return USR::everyOne();
39    }
40
41    /**
42     * Update a Question.
43     *
44     * @return boolean
45     */
46    public function update(): bool
47    {
48        return USR::everyOne();
49    }
50
51    /**
52     * Delete a Question.
53     *
54     * @return boolean
55     */
56    public function delete(): bool
57    {
58        return USR::everyOne();
59    }
60
61    /**
62     * Check if the question belongs to the service.
63     *
64     * @param \App\Models\Service  $service
65     * @param \App\Models\Question $question
66     * @return boolean
67     */
68    public function questionBelongsToService(Service $service, Question $question)
69    {
70        return $service->brand->id === $question->brand_id;
71    }
72}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Policies/Rules/UserStaticRules.php.html b/tests/coverage/app/Policies/Rules/UserStaticRules.php.html deleted file mode 100644 index 3540521..0000000 --- a/tests/coverage/app/Policies/Rules/UserStaticRules.php.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Policies/Rules/UserStaticRules.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
UserStaticRules
n/a
0 / 0
n/a
0 / 0
3
n/a
0 / 0
 everyOne
n/a
0 / 0
n/a
0 / 0
1
 noOne
n/a
0 / 0
n/a
0 / 0
1
 atLeastRole
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Policies\Rules;
4
5use App\Enums\Users\RoleEnum;
6use App\Models\User;
7
8/**
9 * Userlevel Policiy Static Rules
10 *
11 * @codeCoverageIgnore
12 */
13abstract class UserStaticRules
14{
15    /**
16     * Allow everyone.
17     *
18     * @return boolean
19     */
20    public static function everyOne(): bool
21    {
22        return true;
23    }
24
25    /**
26     * Allow no one.
27     *
28     * @return boolean
29     */
30    public static function noOne(): bool
31    {
32        return false;
33    }
34
35    /**
36     * At least a minimum role
37     *
38     * @param \App\Models\User          $user
39     * @param \App\Enums\Users\RoleEnum $minRole
40     * @return boolean
41     */
42    public static function atLeastRole(User $user, RoleEnum $minRole): bool
43    {
44        // phpcs:enable
45        return $user->role->value() <= $minRole->value();
46    }
47}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Policies/Rules/dashboard.html b/tests/coverage/app/Policies/Rules/dashboard.html deleted file mode 100644 index 173de1f..0000000 --- a/tests/coverage/app/Policies/Rules/dashboard.html +++ /dev/null @@ -1,286 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Policies/Rules - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Policies/Rules/index.html b/tests/coverage/app/Policies/Rules/index.html deleted file mode 100644 index a3394d8..0000000 --- a/tests/coverage/app/Policies/Rules/index.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Policies/Rules - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
UserStaticRules.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/app/Policies/ServicePolicy.php.html b/tests/coverage/app/Policies/ServicePolicy.php.html deleted file mode 100644 index ebb9f33..0000000 --- a/tests/coverage/app/Policies/ServicePolicy.php.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Policies/ServicePolicy.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ServicePolicy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 view
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 viewAny
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 delete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Policies;
4
5use App\Policies\Rules\UserStaticRules as USR;
6
7class ServicePolicy
8{
9    /**
10     * View an Answer.
11     *
12     * @return boolean
13     */
14    public function view(): bool
15    {
16        return USR::everyOne();
17    }
18
19    /**
20     * ViewAny an Service.
21     *
22     * @return boolean
23     */
24    public function viewAny(): bool
25    {
26        return USR::everyOne();
27    }
28
29    /**
30     * Create an Service.
31     *
32     * @return boolean
33     */
34    public function create(): bool
35    {
36        return USR::everyOne();
37    }
38
39    /**
40     * Update an Service.
41     *
42     * @return boolean
43     */
44    public function update(): bool
45    {
46        return USR::everyOne();
47    }
48
49    /**
50     * Delete an Service.
51     *
52     * @return boolean
53     */
54    public function delete(): bool
55    {
56        return USR::noOne();
57    }
58}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Policies/SingleOptinPolicy.php.html b/tests/coverage/app/Policies/SingleOptinPolicy.php.html deleted file mode 100644 index f075b92..0000000 --- a/tests/coverage/app/Policies/SingleOptinPolicy.php.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Policies/SingleOptinPolicy.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
SingleOptinPolicy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 view
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 viewAny
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 delete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Policies;
4
5use App\Policies\Rules\UserStaticRules as USR;
6
7class SingleOptinPolicy
8{
9    /**
10     * View an Answer.
11     *
12     * @return boolean
13     */
14    public function view(): bool
15    {
16        return USR::noOne();
17    }
18
19    /**
20     * ViewAny an Answer.
21     *
22     * @return boolean
23     */
24    public function viewAny(): bool
25    {
26        return USR::everyOne();
27    }
28
29    /**
30     * Create an Answer.
31     *
32     * @return boolean
33     */
34    public function create(): bool
35    {
36        return USR::noOne();
37    }
38
39    /**
40     * Update an Answer.
41     *
42     * @return boolean
43     */
44    public function update(): bool
45    {
46        return USR::noOne();
47    }
48
49    /**
50     * Delete an Answer.
51     *
52     * @return boolean
53     */
54    public function delete(): bool
55    {
56        return USR::everyOne();
57    }
58}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Policies/UserPolicy.php.html b/tests/coverage/app/Policies/UserPolicy.php.html deleted file mode 100644 index 5ec8d96..0000000 --- a/tests/coverage/app/Policies/UserPolicy.php.html +++ /dev/null @@ -1,459 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Policies/UserPolicy.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 22
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UserPolicy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 22
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
506
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 viewAny
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 view
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 create
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 update
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 delete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 restore
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 forceDelete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 duplicate
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 changePublished
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Policies;
4
5use App\Enums\Users\RoleEnum;
6use App\Models\User;
7use App\Policies\Rules\UserStaticRules;
8
9class UserPolicy
10{
11    /**
12     * Determine whether the user can view any models.
13     *
14     * @param \App\Models\User $authUser
15     * @return boolean
16     */
17    public function viewAny(User $authUser): bool
18    {
19        return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
20    }
21
22    /**
23     * Determine whether the user can view the model.
24     *
25     * @param \App\Models\User $authUser
26     * @param \App\Models\User $user
27     * @return boolean
28     */
29    public function view(User $authUser, User $user): bool
30    {
31        return UserStaticRules::atLeastRole($authUser, RoleEnum::admin) and
32            UserStaticRules::atLeastRole($authUser, $user->role);
33    }
34
35    /**
36     * Determine whether the user can create models.
37     *
38     * @param \App\Models\User $authUser
39     * @return boolean
40     */
41    public function create(User $authUser): bool
42    {
43        return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
44    }
45
46    /**
47     * Determine whether the user can update the model.
48     *
49     * @param \App\Models\User $authUser
50     * @param \App\Models\User $user
51     * @return boolean
52     */
53    public function update(User $authUser, User $user): bool
54    {
55        return $authUser->getRouteKey() === $user->getRouteKey() or
56            (UserStaticRules::atLeastRole($authUser, RoleEnum::admin) and
57                UserStaticRules::atLeastRole($authUser, $user->role));
58    }
59
60    /**
61     * Determine whether the user can delete the model.
62     *
63     * @param \App\Models\User $authUser
64     * @param \App\Models\User $user
65     * @return boolean
66     */
67    public function delete(User $authUser, User $user): bool
68    {
69        return $authUser->getRouteKey() !== $user->getRouteKey() and
70            UserStaticRules::atLeastRole($authUser, RoleEnum::admin) and
71            UserStaticRules::atLeastRole($authUser, $user->role);
72    }
73
74    /**
75     * Determine whether the user can restore the model.
76     *
77     * @param \App\Models\User $authUser
78     * @param \App\Models\User $user
79     * @return boolean
80     */
81    public function restore(User $authUser, User $user): bool
82    {
83        return $authUser->getRouteKey() !== $user->getRouteKey() and
84            UserStaticRules::atLeastRole($authUser, RoleEnum::admin) and
85            UserStaticRules::atLeastRole($authUser, $user->role);
86    }
87
88    /**
89     * Determine whether the user can permanently delete the model.
90     *
91     * @param \App\Models\User $authUser
92     * @param \App\Models\User $user
93     * @return booleanean
94     */
95    public function forceDelete(User $authUser, User $user): bool
96    {
97        return $authUser->getRouteKey() !== $user->getRouteKey() and
98            UserStaticRules::atLeastRole($authUser, RoleEnum::admin) and
99            UserStaticRules::atLeastRole($authUser, $user->role);
100    }
101
102    /**
103     * Determine whether the user can duplicate the model.
104     *
105     * @param \App\Models\User $authUser
106     * @param \App\Models\User $user
107     * @return booleanean
108     */
109    public function duplicate(User $authUser, User $user): bool
110    {
111        return $authUser->getRouteKey() !== $user->getRouteKey() and
112            UserStaticRules::atLeastRole($authUser, RoleEnum::admin) and
113            UserStaticRules::atLeastRole($authUser, $user->role);
114    }
115
116    /**
117     * Determine whether the user can publish/unpublish the model.
118     *
119     * @param \App\Models\User $authUser
120     * @param \App\Models\User $user
121     * @return booleanean
122     */
123    public function changePublished(User $authUser, User $user): bool
124    {
125        return $authUser->getRouteKey() !== $user->getRouteKey() and
126            UserStaticRules::atLeastRole($authUser, RoleEnum::admin) and
127            UserStaticRules::atLeastRole($authUser, $user->role);
128    }
129}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Policies/dashboard.html b/tests/coverage/app/Policies/dashboard.html deleted file mode 100644 index 48f62bc..0000000 --- a/tests/coverage/app/Policies/dashboard.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Policies - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
- -
-

Project Risks

-
- - - - - - - - - - - -
ClassCRAP
App\Policies\UserPolicy506
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodCoverage
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
viewAny0%
view0%
create0%
update0%
delete0%
restore0%
forceDelete0%
duplicate0%
changePublished0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - - - -
MethodCRAP
update12
delete12
restore12
forceDelete12
duplicate12
changePublished12
view6
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Policies/index.html b/tests/coverage/app/Policies/index.html deleted file mode 100644 index d4ca1a5..0000000 --- a/tests/coverage/app/Policies/index.html +++ /dev/null @@ -1,301 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Policies - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 3.70% covered (danger) -
-
-
3.70%
2 / 54
-
- 4.88% covered (danger) -
-
-
4.88%
2 / 41
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
Rules
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
AnswerPolicy.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BrandPolicy.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CustomerPolicy.php
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
QuestionPolicy.php
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ServicePolicy.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
SingleOptinPolicy.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UserPolicy.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 22
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Providers/AppServiceProvider.php.html b/tests/coverage/app/Providers/AppServiceProvider.php.html deleted file mode 100644 index 59c5e80..0000000 --- a/tests/coverage/app/Providers/AppServiceProvider.php.html +++ /dev/null @@ -1,204 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Providers/AppServiceProvider.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 88.24% covered (warning) -
-
-
88.24%
15 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
AppServiceProvider
-
- 88.24% covered (warning) -
-
-
88.24%
15 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.01
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 boot
-
- 88.24% covered (warning) -
-
-
88.24%
15 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.01
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Providers;
4
5use Illuminate\Cache\RateLimiting\Limit;
6use Illuminate\Http\Resources\Json\JsonResource;
7use Illuminate\Support\Carbon;
8use Illuminate\Support\Facades\App;
9use Illuminate\Support\Facades\RateLimiter;
10use Illuminate\Support\Facades\URL;
11use Illuminate\Support\ServiceProvider;
12
13class AppServiceProvider extends ServiceProvider
14{
15    /**
16     * Bootstrap any application services.
17     *
18     * @return void
19     */
20    public function boot(): void
21    {
22        // * STATS jobs Rate Limiting.
23        RateLimiter::for('stats', function () {
24            return Limit::perMinute(60)->by(2);
25        });
26
27        // * Empêche l'encapsulation dans data.
28        JsonResource::withoutWrapping();
29
30        // * LOCAL HTTPS FIX.
31        URL::forceScheme('https');
32
33        // * HA PROXY FIX.
34        App::singleton('clientIp', function () {
35            if (config('app.env') === 'local') {
36                return request()->getClientIp();
37            } else {
38                return request()->server('HTTP_X_FORWARDED_FOR') ??
39                    request()->getClientIp();
40            }
41        });
42        // * LOCAL FORCE eg: for Carbon.
43        setlocale(LC_ALL, \sprintf(
44            '%s_%s.UTF-8',
45            config('app.locale'),
46            \strtoupper(config('app.locale'))
47        ));
48        Carbon::setLocale(config('app.locale'));
49    }
50}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Providers/AuthServiceProvider.php.html b/tests/coverage/app/Providers/AuthServiceProvider.php.html deleted file mode 100644 index dcb7c61..0000000 --- a/tests/coverage/app/Providers/AuthServiceProvider.php.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Providers/AuthServiceProvider.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 95.00% covered (success) -
-
-
95.00%
19 / 20
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
AuthServiceProvider
-
- 95.00% covered (success) -
-
-
95.00%
19 / 20
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 boot
-
- 95.00% covered (success) -
-
-
95.00%
19 / 20
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Providers;
4
5use App\Enums\Users\RoleEnum;
6use App\Lib\Helper;
7use App\Models\Service;
8use App\Models\User;
9use Illuminate\Database\Eloquent\ModelNotFoundException;
10use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
11use Illuminate\Http\Request;
12use Illuminate\Support\Facades\Auth;
13use Illuminate\Support\Facades\Gate;
14
15class AuthServiceProvider extends ServiceProvider
16{
17    /**
18     * The model to policy mappings for the application.
19     *
20     * @var array<class-string, class-string>
21     */
22    protected $policies = [];
23
24    /**
25     * Register any authentication / authorization services.
26     *
27     * @return void
28     */
29    public function boot(): void
30    {
31        // Register policies.
32        $this->registerPolicies();
33
34        Gate::define('isConceptor', function (User $user) {
35            return $user->role === RoleEnum::conceptor;
36        });
37
38        Auth::viaRequest('api-hmac', function (Request $request) {
39
40            /**
41             * Un token devrais être fourni pour chaque requete
42             */
43            if (is_null($request->bearer_token)) {
44                return null;
45            }
46
47            // * Si la route actuelle n'as pas de nom alors on refuse de la traiter.
48            if (!(Helper::getRoute($request))) {
49                // @codeCoverageIgnoreStart
50                return null;
51                // @codeCoverageIgnoreEnd
52            }
53
54            $service = null;
55
56            try {
57                // * On récupère le service actuel correspondant au token fourni.
58                $service = Service::getFromBearerToken($request->bearer_token ?? '');
59            } catch (ModelNotFoundException $e) {
60                return null;
61            }
62
63            // * Preload the brand as we will access it often later.
64            $service = $service->load('brand');
65
66            /**
67             ** All ApiV4 routes must pass Brand model to controller action since a Brand owns
68             ** a service token, otherwise the api cannot be called.
69             ** This hack is a custom binder instead of passing
70             ** this to route as a parameter
71             */
72            app()->bind(Service::class, function () use ($service) {
73                return $service;
74            });
75
76            // * On authenticate la request en vérifiant sa signature.
77            if ($service->authenticateApi($request)) {
78                return $service;
79            }
80
81            return null;
82        });
83    }
84}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Providers/EventServiceProvider.php.html b/tests/coverage/app/Providers/EventServiceProvider.php.html deleted file mode 100644 index 27f3c86..0000000 --- a/tests/coverage/app/Providers/EventServiceProvider.php.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Providers/EventServiceProvider.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
EventServiceProvider
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 shouldDiscoverEvents
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Providers;
4
5use Illuminate\Auth\Events\Registered;
6use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
7use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
8
9class EventServiceProvider extends ServiceProvider
10{
11    /**
12     * The event to listener mappings for the application.
13     *
14     * @var array<class-string, array<int, class-string>>
15     */
16    protected $listen = [
17        Registered::class => [
18            SendEmailVerificationNotification::class,
19        ],
20    ];
21
22    /**
23     * Determine if events and listeners should be automatically discovered.
24     *
25     * @return boolean
26     */
27    public function shouldDiscoverEvents(): bool
28    {
29        return false;
30    }
31}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Providers/RouteServiceProvider.php.html b/tests/coverage/app/Providers/RouteServiceProvider.php.html deleted file mode 100644 index 8824dba..0000000 --- a/tests/coverage/app/Providers/RouteServiceProvider.php.html +++ /dev/null @@ -1,356 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Providers/RouteServiceProvider.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 69.09% covered (warning) -
-
-
69.09%
38 / 55
-
- 33.33% covered (danger) -
-
-
33.33%
1 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
RouteServiceProvider
-
- 69.09% covered (warning) -
-
-
69.09%
38 / 55
-
- 33.33% covered (danger) -
-
-
33.33%
1 / 3
17.99
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 boot
-
- 100.00% covered (success) -
-
-
100.00%
26 / 26
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
5
 configureRateLimiting
-
- 88.89% covered (warning) -
-
-
88.89%
8 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.01
 cspReportRoute
-
- 20.00% covered (danger) -
-
-
20.00%
4 / 20
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
17.80
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Providers;
4
5use App\Models\Answer;
6use App\Models\Brand;
7use App\Models\Customer;
8use App\Models\CustomerInfo;
9use App\Models\Question;
10use App\Models\Service;
11use App\Models\SingleOptin;
12use Illuminate\Cache\RateLimiting\Limit;
13use Illuminate\Contracts\Database\Eloquent\Builder;
14use Illuminate\Database\Eloquent\ModelNotFoundException;
15use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
16use Illuminate\Http\Request;
17use Illuminate\Support\Facades\RateLimiter;
18use Illuminate\Support\Facades\Route;
19
20class RouteServiceProvider extends ServiceProvider
21{
22    /**
23     * The path to the "home" route for your application.
24     *
25     * This is used by Laravel authentication to redirect users after login.
26     *
27     * @var string
28     */
29    public const HOME = '/';
30
31    /**
32     * Define your route model bindings, pattern filters, etc.
33     *
34     * @return void
35     */
36    public function boot(): void
37    {
38        $this->configureRateLimiting();
39
40        $this->cspReportRoute();
41
42        $this->routes(function () {
43            // @codeCoverageIgnoreStart
44            Route::prefix('api')->middleware('api')
45                ->namespace($this->namespace)
46                ->group(base_path('routes/api.php'));
47
48            Route::middleware('web')
49                ->namespace($this->namespace)
50                ->group(base_path('routes/web-bo.php'));
51
52            Route::middleware('web')
53                ->namespace($this->namespace)
54                ->group(base_path('routes/web-fo.php'));
55            // @codeCoverageIgnoreEnd
56        });
57
58        Route::model('brand', Brand::class);
59        Route::model('service', Service::class);
60        Route::model('single_optin', SingleOptin::class);
61        Route::model('question', Question::class);
62        Route::model('answer', Answer::class);
63        Route::model('customer', Customer::class);
64
65        // * Api parameters Bind.
66        Route::model('serviceQuestion', Question::class);
67        Route::bind('serviceCustomer', function ($value) {
68            // * Load brand
69            /** @var \App\Models\Brand $brand */
70            $brand = app(Service::class)->brand;
71
72            // ? Parameter is email
73            if (strpos($value, '@') !== false) {
74                $customer = Customer::query()->whereHas('brands', function (Builder $q) use ($brand) {
75                    $q->where('brands.id', '=', $brand->id);
76                })->where('email', '=', $value)->firstOrFail();
77            }
78
79            try {
80                // ? Have we found a customer yet
81                if (!isset($customer) or \get_class($customer) !== Customer::class) {
82                    // ? Parameter is hashcode
83                    $customer = CustomerInfo::query()->whereHas('brand', function (Builder $q) use ($brand) {
84                        $q->where('brands.id', '=', $brand->id);
85                    })->where('hashcode', $value)
86                        ->with('customer')->firstOrFail()->customer;
87                }
88
89                // * Load Customer Login and Info for this brand.
90                /** @var \App\Models\Customer $customer */
91
92                return $customer->loadBrandData($brand);
93            } catch (ModelNotFoundException $e) {
94                // * Uniform Not found exception using model Customer.
95                throw (new ModelNotFoundException())->setModel(Customer::class);
96            }
97        });
98    }
99
100    /**
101     * Configure the rate limiters for the application.
102     *
103     * @return void
104     */
105    protected function configureRateLimiting(): void
106    {
107        RateLimiter::for('web', function (Request $request) {
108            // @codeCoverageIgnoreStart
109            return Limit::perMinute(25)
110                ->by(optional($request->user())->id ?: app('clientIp'));
111            // @codeCoverageIgnoreEnd
112        });
113        // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
114        RateLimiter::for('api', function (Request $request) {
115            return Limit::perMinute(config('api.apiRequestRatePerMinute', 100))
116                ->by(app('clientIp'));
117        });
118        RateLimiter::for('credentials', function (Request $request) {
119            return Limit::perMinute(30)->by($request->user()?->id ?: app('clientIp'));
120        });
121    }
122
123    /**
124     * * Register CSP report URI
125     *
126     * Put this function inside RouteServiceProvider,
127     * and call it in RouteServiceProvider::boot
128     *
129     * @return void
130     */
131    private function cspReportRoute()
132    {
133        // * CSP REPORT URI, Please add /csp-report to VerifyCsrfToken $except middleware
134        \Illuminate\Support\Facades\Route::post('/csp-report', function () {
135            $isCspRequest = request()->header('Content-Type') === 'application/csp-report';
136            if (!$isCspRequest or !request()->json('csp-report') or !is_array(request()->json('csp-report'))) {
137                abort(401);
138            }
139            // * Flatten if needed
140            $cspReport = collect(request()->json('csp-report'))
141                ->flatMap(function ($v, $k) {
142                    return [$k => is_array($v) ? collect($v)->flatten()->implode(', ') : $v];
143                })->all();
144            // * Filter array keys
145            $cspReport = collect(array_intersect_key($cspReport, [
146                'blocked-uri' => '', 'document-uri' => '', 'original-policy' => '',
147                'referrer' => '', 'violated-directive' => ''
148            ]));
149            \Illuminate\Support\Facades\Log::warning(sprintf(
150                "CSP REPORT for %s : \n %s",
151                $cspReport->get('document-uri'),
152                $cspReport->implode("\n")
153            ));
154        })->middleware('throttle:5,2')
155            ->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class)
156            ->name('cspReportUri');
157    }
158}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Providers/TranslationServiceProvider.php.html b/tests/coverage/app/Providers/TranslationServiceProvider.php.html deleted file mode 100644 index 5194dec..0000000 --- a/tests/coverage/app/Providers/TranslationServiceProvider.php.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Providers/TranslationServiceProvider.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 95.24% covered (success) -
-
-
95.24%
20 / 21
-
- 75.00% covered (warning) -
-
-
75.00%
3 / 4
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
TranslationServiceProvider
-
- 95.24% covered (success) -
-
-
95.24%
20 / 21
-
- 75.00% covered (warning) -
-
-
75.00%
3 / 4
9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 boot
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 collectLocalesStrings
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
 phpTranslations
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 jsonTranslations
-
- 75.00% covered (warning) -
-
-
75.00%
3 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.14
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Providers;
4
5use Illuminate\Support\Collection;
6use Illuminate\Support\Facades\File;
7use Illuminate\Support\Facades\Cache;
8use Illuminate\Support\ServiceProvider;
9use Symfony\Component\Finder\SplFileInfo;
10
11class TranslationServiceProvider extends ServiceProvider
12{
13    /**
14     * Bootstrap the application services.
15     *
16     * @return void
17     */
18    public function boot(): void
19    {
20        foreach ($this->collectLocalesStrings() as $locale) {
21            // * Suported locales
22            Cache::rememberForever(sprintf('translations.%s', $locale), function () use ($locale) {
23                $translations = [
24                    'php' => $this->phpTranslations($locale),
25                    'json' => $this->jsonTranslations($locale),
26                ];
27                return $translations;
28            });
29        }
30    }
31
32    /**
33     * Gather provided langs checking from files
34     *
35     * @return \Illuminate\Support\Collection<string, string>
36     */
37    private function collectLocalesStrings(): Collection
38    {
39        return collect(File::allFiles(resource_path('lang/')))->flatMap(function (SplFileInfo $file) {
40            if ($file->getRelativePath() and \strpos($file->getRelativePath(), 'vendor') !== 0) {
41                return [$file->getRelativePath() => ''];
42            }
43        })->keys();
44    }
45
46    /**
47     * Gather all php translations
48     *
49     * @param string $locale
50     * @return array<string, string>
51     */
52    private function phpTranslations(string $locale): array
53    {
54        $path = resource_path("lang/$locale");
55
56        return collect(File::allFiles($path))->flatMap(function ($file) use ($locale) {
57            $translation = $file->getBasename('.php');
58            return [$translation => trans($translation, [], $locale)];
59        })->all();
60    }
61
62    /**
63     * Gather json translations
64     *
65     * @param string $locale
66     * @return array<string, string>
67     */
68    private function jsonTranslations(string $locale): array
69    {
70        $path = resource_path("lang/$locale.json");
71
72        if (is_string($path) && is_readable($path)) {
73            return json_decode(file_get_contents($path), true) ?? [];
74        }
75
76        return [];
77    }
78}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Providers/ViewServiceProvider.php.html b/tests/coverage/app/Providers/ViewServiceProvider.php.html deleted file mode 100644 index c153d23..0000000 --- a/tests/coverage/app/Providers/ViewServiceProvider.php.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Providers/ViewServiceProvider.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 75.00% covered (warning) -
-
-
75.00%
9 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ViewServiceProvider
-
- 75.00% covered (warning) -
-
-
75.00%
9 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6.56
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 boot
-
- 75.00% covered (warning) -
-
-
75.00%
9 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6.56
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Providers;
4
5use Illuminate\Pagination\Paginator;
6use Illuminate\Support\Facades\Cache;
7use Illuminate\Support\Facades\File;
8use Illuminate\Support\Facades\View;
9use Illuminate\Support\ServiceProvider;
10
11class ViewServiceProvider extends ServiceProvider
12{
13    /**
14     * Bootstrap any application services.
15     *
16     * @return void
17     */
18    public function boot(): void
19    {
20        $appInfos = Cache::remember('composer', 360, function () {
21            return json_decode(File::get(\app_path('../composer.json')));
22        });
23        // Share composer.json infos.
24        if (isset($appInfos->name) and isset($appInfos->version) and isset($appInfos->license)) {
25            View::share('cpsr_name', $appInfos->name);
26            View::share('cpsr_version', $appInfos->version);
27            View::share('cpsr_license', $appInfos->license);
28            View::share('cpsr_support', $appInfos->support->email);
29        }
30
31        if (!app()->runningInConsole()) {
32            // * FORCE BOOTSTRAP PAGINATOR (or custom if in front)
33            // Early boot, request wont be filled as expected.
34            if (collect(explode('/', \request()->getPathInfo()))->get(1) === 'bo') {
35                Paginator::defaultView('bo.modules.pagination');
36            } else {
37                Paginator::useBootstrapFive();
38            }
39        }
40    }
41}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Providers/dashboard.html b/tests/coverage/app/Providers/dashboard.html deleted file mode 100644 index 7df6979..0000000 --- a/tests/coverage/app/Providers/dashboard.html +++ /dev/null @@ -1,301 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Providers - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

- -
- -
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - -
MethodCoverage
cspReportRoute20%
jsonTranslations75%
boot75%
boot88%
configureRateLimiting88%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - -
MethodCRAP
cspReportRoute17
boot6
jsonTranslations3
configureRateLimiting3
boot2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Providers/index.html b/tests/coverage/app/Providers/index.html deleted file mode 100644 index 72d8e7d..0000000 --- a/tests/coverage/app/Providers/index.html +++ /dev/null @@ -1,260 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Providers - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 80.95% covered (warning) -
-
-
80.95%
102 / 126
-
- 45.45% covered (danger) -
-
-
45.45%
5 / 11
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
AppServiceProvider.php
-
- 88.24% covered (warning) -
-
-
88.24%
15 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
AuthServiceProvider.php
-
- 95.00% covered (success) -
-
-
95.00%
19 / 20
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
EventServiceProvider.php
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
RouteServiceProvider.php
-
- 69.09% covered (warning) -
-
-
69.09%
38 / 55
-
- 33.33% covered (danger) -
-
-
33.33%
1 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
TranslationServiceProvider.php
-
- 95.24% covered (success) -
-
-
95.24%
20 / 21
-
- 75.00% covered (warning) -
-
-
75.00%
3 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ViewServiceProvider.php
-
- 75.00% covered (warning) -
-
-
75.00%
9 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Traits/Controllers/ChangesModelOrder.php.html b/tests/coverage/app/Traits/Controllers/ChangesModelOrder.php.html deleted file mode 100644 index 282d989..0000000 --- a/tests/coverage/app/Traits/Controllers/ChangesModelOrder.php.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Traits/Controllers/ChangesModelOrder.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 21
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ChangesModelOrder
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 21
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 changeOrder
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 21
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
42
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Traits\Controllers;
4
5use App\Http\Requests\Bo\UpdateChangeOrderRequest;
6use Illuminate\Database\Eloquent\Model;
7use Illuminate\Support\Facades\DB;
8use Illuminate\Support\Facades\Session;
9use Illuminate\Support\Str;
10
11trait ChangesModelOrder
12{
13    /**
14     * Change order.
15     *
16     * @param \App\Http\Requests\Bo\UpdateChangeOrderRequest $request
17     * @param \Illuminate\Database\Eloquent\Model            $model
18     * @return \Illuminate\Http\RedirectResponse
19     * @throws \RuntimeException Si le nom du parametre de la route ne correspond pas au model utilisé.
20     */
21    public function changeOrder(UpdateChangeOrderRequest $request, Model $model): \Illuminate\Http\RedirectResponse
22    {
23        $params    = collect(request()->route()->parameterNames);
24        $className = Str::ucfirst(Str::lower($params->get($params->count() - 2)));
25        $className = "\\App\\Models\\$className";
26
27        if (!class_exists($className)) {
28            throw new \RuntimeException("The $className class doesn't exist.");
29        }
30
31        /** @var \Illuminate\Database\Eloquent\Model|null */
32        $model = $className::where($model->getRouteKeyName(), $model->getRouteKey())->first();
33
34        if (!$model) {
35            return back()->with('error', trans('crud.messages.order_not_changed'));
36        }
37
38        return DB::transaction(function () use ($request, $className, $model) {
39            /** @var \Illuminate\Database\Eloquent\Model|null */
40            $tmp = $className::where('order', $request->direction ? '<' : '>', $model->order)
41                ->orderBy('order', $request->direction ? 'DESC' : 'ASC')->first();
42
43            if (!$tmp) {
44                return back()->with('error', trans('crud.messages.order_not_changed'));
45            }
46
47            $newOrder     = $tmp->order;
48            $tmp->order   = $model->order;
49            $model->order = $newOrder;
50            $tmp->saveOrFail();
51            $model->saveOrFail();
52            Session::flash('success', trans('crud.messages.order_changed'));
53
54            return back();
55        });
56    }
57}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Traits/Controllers/UpdateModelPublished.php.html b/tests/coverage/app/Traits/Controllers/UpdateModelPublished.php.html deleted file mode 100644 index a3c6378..0000000 --- a/tests/coverage/app/Traits/Controllers/UpdateModelPublished.php.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Traits/Controllers/UpdateModelPublished.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateModelPublished
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 changePublished
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Traits\Controllers;
4
5use Illuminate\Database\Eloquent\Model;
6
7/**
8 * This trait works with Route::bind in App service provider
9 * to resolve the model and the DB row
10 * It does not work with binder Service
11 */
12trait UpdateModelPublished
13{
14    /**
15     * Change model published.
16     *
17     * @param \Illuminate\Database\Eloquent\Model $model
18     * @return \Illuminate\Http\RedirectResponse
19     */
20    public function changePublished(Model $model)
21    {
22        $model->published = !$model->published;
23        $model->saveOrFail();
24        return redirect()->back()->with('success', trans(__('crud.messages.publish_status_saved')));
25    }
26}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Traits/Controllers/dashboard.html b/tests/coverage/app/Traits/Controllers/dashboard.html deleted file mode 100644 index 4c10649..0000000 --- a/tests/coverage/app/Traits/Controllers/dashboard.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Traits/Controllers - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

- -
-
-

Project Risks

-
- - - - - - - - - - - -
ClassCRAP
App\Traits\Controllers\ChangesModelOrder42
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
MethodCoverage
changeOrder0%
changePublished0%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
MethodCRAP
changeOrder42
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Traits/Controllers/index.html b/tests/coverage/app/Traits/Controllers/index.html deleted file mode 100644 index e5e7958..0000000 --- a/tests/coverage/app/Traits/Controllers/index.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Traits/Controllers - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 24
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
ChangesModelOrder.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 21
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
UpdateModelPublished.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Traits/Enums/BaseEnum.php.html b/tests/coverage/app/Traits/Enums/BaseEnum.php.html deleted file mode 100644 index 338feb1..0000000 --- a/tests/coverage/app/Traits/Enums/BaseEnum.php.html +++ /dev/null @@ -1,720 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Traits/Enums/BaseEnum.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 55.70% covered (warning) -
-
-
55.70%
44 / 79
-
- 40.00% covered (danger) -
-
-
40.00%
6 / 15
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BaseEnum
-
- 55.70% covered (warning) -
-
-
55.70%
44 / 79
-
- 40.00% covered (danger) -
-
-
40.00%
6 / 15
148.70
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 value
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 label
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 name
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 toLabels
-
- 90.91% covered (success) -
-
-
90.91%
10 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5.02
 toValues
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 all
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 toArray
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 make
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 equals
-
- 75.00% covered (warning) -
-
-
75.00%
6 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5.39
 jsonSerialize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getCache
-
- 75.00% covered (warning) -
-
-
75.00%
3 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.06
 setCache
-
- 75.00% covered (warning) -
-
-
75.00%
3 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.06
 initCache
-
- 100.00% covered (success) -
-
-
100.00%
9 / 9
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 getLabelsConstant
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 getCustomDefinitions
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Traits\Enums;
4
5use Illuminate\Support\Str;
6
7trait BaseEnum
8{
9    // * GENERIC METHODS
10    /**
11     * Get enum value.
12     *
13     * @return string|integer
14     */
15    public function value(): string|int
16    {
17        return self::toValues()[$this->name];
18    }
19
20    /**
21     * Get enum label.
22     *
23     * @return string
24     */
25    public function label(): string
26    {
27        return self::toLabels()[$this->name];
28    }
29
30    /**
31     * Get enum name.
32     *
33     * @return string
34     */
35    public function name(): string
36    {
37        return $this->name;
38    }
39
40    // * STATIC FETCH METHODS
41
42    /**
43     * Get enum labels.
44     *
45     * @return array<string>
46     */
47    public static function toLabels(): array
48    {
49        if (empty(self::getCache('labels'))) {
50            $labels = self::getLabelsConstant();
51            self::setCache('labels', \collect(self::cases())
52                ->mapWithKeys(function ($enum) use ($labels) {
53                    if (!\is_null($labels) and !isset($labels[$enum->name])) {
54                        throw new \Error('Missing definition label ' . self::class . " for {$enum->name}");
55                    }
56                    return [$enum->name => \trans(
57                        !\is_null($labels) ? $labels[$enum->name] : Str::ucfirst($enum->name)
58                    )];
59                })->all());
60        }
61        return self::getCache('labels');
62    }
63
64    /**
65     * Get enum values.
66     *
67     * @return array<integer|string>
68     */
69    public static function toValues(): array
70    {
71        if (empty(self::getCache('values'))) {
72            self::setCache('values', \collect(self::cases())
73                ->mapWithKeys(fn ($enum) => [$enum->name => $enum->value])->all());
74        }
75        return self::getCache('values');
76    }
77
78    /**
79     * Get enums.
80     *
81     * @return array
82     */
83    public static function all(): array
84    {
85        return self::cases();
86    }
87
88    /**
89     * Get enums.
90     *
91     * @return array
92     */
93    public static function toArray(): array
94    {
95        if (empty(self::getCache('enums'))) {
96            $definitions = self::getCustomDefinitions();
97            self::setCache('enums', \collect(self::cases())
98                ->mapWithKeys(function ($enum) use ($definitions) {
99                    $baseArray = [
100                        'name' => $enum->name,
101                        'label' => $enum->label(),
102                        'value' => $enum->value,
103                    ];
104                    foreach ($definitions as $index => $elements) {
105                        $index = Str::lower(Str::singular($index));
106                        if (!isset($elements[$enum->name])) {
107                            throw new \Error("Missing definition {$index} " . self::class . " for {$enum->name}");
108                        }
109                        $baseArray[$index] = $elements[$enum->name];
110                    }
111                    return [$enum->name => (object)$baseArray];
112                })->all());
113        }
114        return self::getCache('enums');
115    }
116
117    /**
118     * Fetch enum using value.
119     *
120     * @param \App\Traits\Enums\BaseEnum|integer|string $value
121     * @param string                                    $field
122     * @return \App\Traits\Enums\BaseEnum|null
123     */
124    public static function make(self|int|string $value, string $field = 'value'): self|null
125    {
126        return !\is_object($value) ?
127            \collect(self::cases())->keyBy($field)->get($value) : $value;
128    }
129
130    /**
131     * Test if 2 enum are equals.
132     *
133     * @param object ...$others
134     * @return boolean
135     * @throws \Error If provided element are not enums taht extends BaseEnum.
136     */
137    public function equals(object ...$others): bool
138    {
139        foreach ($others as $other) {
140            if (!\in_array(BaseEnum::class, \class_uses_recursive($other))) {
141                throw new \Error(__METHOD__ .
142                    ' requires $enum to use ' . BaseEnum::class);
143            }
144            if (
145                get_class($this) === get_class($other)
146                && $this->value === $other->value
147            ) {
148                return true;
149            }
150        }
151        return false;
152    }
153
154    /**
155     * Serialize to json.
156     *
157     * @return mixed
158     */
159    public function jsonSerialize(): mixed
160    {
161        return $this->value;
162    }
163
164
165    // * CACHE
166
167    /**
168     * Get cache array.
169     *
170     * @param string $index
171     * @return array
172     */
173    private static function getCache(string $index): array
174    {
175        self::initCache();
176        if (!isset($GLOBALS[self::class]['props'][$index])) {
177            $GLOBALS[self::class]['props'][$index] = [];
178        }
179        return $GLOBALS[self::class]['props'][$index];
180    }
181
182    /**
183     * Set cache array.
184     *
185     * @param string $index
186     * @param array  $items
187     * @return void
188     */
189    private static function setCache(string $index, array $items): void
190    {
191        self::initCache();
192        if (!isset($GLOBALS[self::class]['props'][$index])) {
193            $GLOBALS[self::class]['props'][$index] = [];
194        }
195        $GLOBALS[self::class]['props'][$index] = $items;
196    }
197
198    /**
199     * Init cache if needed.
200     *
201     * @return void
202     */
203    private static function initCache(): void
204    {
205        if (!isset($GLOBALS[self::class])) {
206            $GLOBALS[self::class] = [
207                'props' => [
208                    'enums' => [],
209                    'values' => [],
210                    'labels' => []
211                ],
212                'customProps' => null
213            ];
214        }
215    }
216
217    // * PRIVATE
218
219    /**
220     * Fetch the LABELS constant if exists.
221     *
222     * @return array|null
223     */
224    private static function getLabelsConstant(): array|null
225    {
226        $class_name = self::class;
227        try {
228            $constant_reflex = new \ReflectionClassConstant($class_name, 'LABELS');
229            return $constant_reflex->getValue();
230        } catch (\ReflectionException $e) {
231            return null;
232        }
233    }
234
235    /**
236     * Get custom constants.
237     *
238     * @return array
239     */
240    private static function getCustomDefinitions(): array
241    {
242        // ? Has custom props in cache ?
243        if (!isset($GLOBALS[self::class]) or \is_null($GLOBALS[self::class]['customProps'])) {
244            $names = \collect(self::cases())->keyBy('name');
245
246            $GLOBALS[self::class]['customProps'] = \collect((new \ReflectionClass(self::class))->getConstants())
247                ->filter(function (mixed $constant, string $key) use ($names) {
248                    if ($key === 'LABELS' or !\is_array($constant)) {
249                        return false;
250                    }
251                    return \collect($constant)->keys()
252                        ->filter(fn (string $name) => $names->has($name))->count();
253                })->all();
254        }
255        return $GLOBALS[self::class]['customProps'];
256    }
257}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Traits/Enums/dashboard.html b/tests/coverage/app/Traits/Enums/dashboard.html deleted file mode 100644 index 93efc8c..0000000 --- a/tests/coverage/app/Traits/Enums/dashboard.html +++ /dev/null @@ -1,301 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Traits/Enums - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
App\Traits\Enums\BaseEnum55%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
ClassCRAP
App\Traits\Enums\BaseEnum148
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - - -
MethodCoverage
name0%
all0%
toArray0%
jsonSerialize0%
getCustomDefinitions0%
equals75%
getCache75%
setCache75%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - -
MethodCRAP
getCustomDefinitions30
toArray20
equals5
getCache2
setCache2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Traits/Enums/index.html b/tests/coverage/app/Traits/Enums/index.html deleted file mode 100644 index b3990b6..0000000 --- a/tests/coverage/app/Traits/Enums/index.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Traits/Enums - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 55.70% covered (warning) -
-
-
55.70%
44 / 79
-
- 40.00% covered (danger) -
-
-
40.00%
6 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BaseEnum.php
-
- 55.70% covered (warning) -
-
-
55.70%
44 / 79
-
- 40.00% covered (danger) -
-
-
40.00%
6 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Traits/Models/ActivityLog.php.html b/tests/coverage/app/Traits/Models/ActivityLog.php.html deleted file mode 100644 index d5fdc55..0000000 --- a/tests/coverage/app/Traits/Models/ActivityLog.php.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Traits/Models/ActivityLog.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ActivityLog
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 bootActivityLog
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Traits\Models;
4
5use App\Observers\ModelObserver;
6
7/**
8 * If there is a static function in a trait (named boot[TraitName]),
9 * it will be executed as the boot() function would on an Eloquent model.
10 * Futhermore, event in the Model observer doesn't erase actual events in the model,
11 * but adds them.
12 */
13trait ActivityLog
14{
15    /**
16     *
17     * @return void
18     */
19    public static function bootActivityLog(): void
20    {
21        static::observe(ModelObserver::class);
22    }
23}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Traits/Models/IsCachedAsCollection.php.html b/tests/coverage/app/Traits/Models/IsCachedAsCollection.php.html deleted file mode 100644 index 52754ab..0000000 --- a/tests/coverage/app/Traits/Models/IsCachedAsCollection.php.html +++ /dev/null @@ -1,390 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Traits/Models/IsCachedAsCollection.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
IsCachedAsCollection
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
110
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 getCached
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 removeCached
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 setCached
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 queryCached
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 filterQuery
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getCacheKeyName
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getCallClassBaseName
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Traits\Models;
4
5use Illuminate\Database\Eloquent\Builder;
6use Illuminate\Database\QueryException;
7use Illuminate\Support\Collection;
8use Illuminate\Support\Facades\Cache;
9
10/**
11 * ! Use this only on limited elements, (not on tags, or products, or posts for ex.)
12 *
13 * @property private static array $cacheConditions Eloquent condition to cache elements (to be used in where statement).
14 */
15trait IsCachedAsCollection
16{
17    /**
18     * Get all available instances from cache.
19     * If cache was reset, it will fetch them from DB.
20     *
21     * @return \Illuminate\Database\Eloquent\Collection
22     */
23    public static function getCached(): Collection
24    {
25        if (!Cache::has(static::getCacheKeyName())) {
26            try {
27                static::setCached();
28            } catch (QueryException $e) {
29                report($e);
30                return \collect();
31            }
32        }
33        return Cache::get(static::getCacheKeyName());
34    }
35
36    /**
37     * Remove cached elements
38     *
39     * @return void
40     */
41    public static function removeCached(): void
42    {
43        Cache::forget(static::getCacheKeyName());
44    }
45
46    /**
47     * Put all instances into cache.
48     *
49     * @return void
50     */
51    protected static function setCached(): void
52    {
53        $conditions = [];
54        if (property_exists(get_called_class(), 'cacheConditions')) {
55            $conditions = collect(static::${'cacheConditions'})->all();
56        }
57        Cache::put(static::getCacheKeyName(), static::queryCached(static::query())
58            ->where($conditions)->get()
59            ->pipe(fn (Collection $collection) => \call_user_func([self::class, 'filterQuery'], $collection)));
60    }
61
62    /**
63     * Change query for cached elements
64     *
65     * @param \Illuminate\Database\Eloquent\Builder $query
66     * @return \Illuminate\Database\Eloquent\Builder
67     */
68    protected static function queryCached(Builder $query): Builder
69    {
70        return $query;
71    }
72
73    /**
74     * Change query for cached elements
75     *
76     * @param \Illuminate\Support\Collection $results
77     * @return \Illuminate\Support\Collection
78     */
79    protected static function filterQuery(Collection $results): Collection
80    {
81        return $results;
82    }
83
84    /**
85     * Get the class basename
86     *
87     * @return string
88     */
89    protected static function getCacheKeyName(): string
90    {
91        return static::getCallClassBaseName();
92    }
93
94    /**
95     * Get the class basename
96     *
97     * @return string
98     */
99    protected static function getCallClassBaseName(): string
100    {
101        return str_replace(__NAMESPACE__ . '\\', '', get_called_class());
102    }
103}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Traits/Models/MiniCrudModel.php.html b/tests/coverage/app/Traits/Models/MiniCrudModel.php.html deleted file mode 100644 index 7f24c3a..0000000 --- a/tests/coverage/app/Traits/Models/MiniCrudModel.php.html +++ /dev/null @@ -1,511 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Traits/Models/MiniCrudModel.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 63
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
MiniCrudModel
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 63
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
992
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 fill
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 minicrudCreating
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 minicrudUpdating
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 minicrudUpdated
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 minicrudDeleted
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 setData
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 setDataAttribute
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getDataAttribute
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 serializeData
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 28
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
240
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace App\Traits\Models;
4
5use App\Enums\InputType;
6use App\Lib\Helpers\FileStorageHelper;
7use App\Lib\Helpers\ToolboxHelper;
8
9trait MiniCrudModel
10{
11    /**
12     * Fill the model with an array of attributes.
13     *
14     * @param  array $attributes
15     * @return void
16     * @throws \Illuminate\Database\Eloquent\MassAssignmentException If fill prop is not allowed.
17     * @phpcs:disable Squiz.Commenting.FunctionComment.EmptyThrows
18     */
19    public function fill(array $attributes)
20    {
21        // phpcs:enable
22        parent::fill($attributes);
23        if (isset($attributes['data'])) {
24            $this->setData($attributes['data']);
25        }
26    }
27
28    /**
29     * Apply function on data typed text while on save event
30     *
31     * @return void
32     */
33    public function minicrudCreating()
34    {
35        /** @var array<string,array> */
36        $data = $this->data;
37        foreach ($data as &$input) {
38            switch ($input['inputType']) {
39                case InputType::text->value:
40                    $input['text'] = clean($input['text']);
41                    $input['text'] = FileStorageHelper::storeModelFilesFromHtml($this, $input['text']);
42                    break;
43            } //end switch
44        } //end foreach
45        $this->data = $data;
46    }
47
48    /**
49     * Apply function on data typed text while on update event
50     *
51     * @return void
52     */
53    public function minicrudUpdating()
54    {
55        $this->minicrudCreating();
56    }
57
58    /**
59     * Apply function on data typed text while on updated event
60     *
61     * @return void
62     */
63    public function minicrudUpdated()
64    {
65        /** @var array */
66        foreach ($this->data as $index => $input) {
67            switch ($input['inputType']) {
68                case InputType::text->value:
69                    $original = ToolboxHelper::getOriginal($this, 'data');
70                    FileStorageHelper::removeOldModelFilesFromHtml(
71                        $input['text'],
72                        $original[$index]['text'] ?? ''
73                    );
74                    break;
75            } //end switch
76        } //end foreach
77    }
78
79    /**
80     * Apply function on data typed text while on deleted event
81     *
82     * @return void
83     */
84    public function minicrudDeleted()
85    {
86        /** @var array */
87        foreach ($this->data as $input) {
88            switch ($input['inputType']) {
89                case InputType::text->value:
90                    FileStorageHelper::removeModelFilesOfHtml($input['text']);
91                    break;
92            } //end switch
93        } //end foreach
94    }
95
96    /**
97     * Set a specific prop
98     *
99     * @param array $data
100     * @return void
101     */
102    private function setData(array $data): void
103    {
104        $attrs = $this->attributes;
105        if (isset($attrs['data'])) {
106            unset($attrs['data']);
107        }
108        $this->setAttribute('data', $data);
109    }
110
111    /**
112     * Set a specific prop
113     *
114     * @param array $value
115     * @return void
116     */
117    protected function setDataAttribute(array $value): void
118    {
119        $this->attributes['data'] = $this->castAttributeAsJson(
120            'data',
121            $this->serializeData($value)
122        );
123    }
124
125    /**
126     * Set a specific prop
127     *
128     * @param string|null $data
129     * @return array
130     */
131    protected function getDataAttribute(string|null $data): array
132    {
133        return $this->fromJson($data ?? $this->attributes['data'] ?? '[]');
134    }
135
136    /**
137     * Serialize properties
138     *
139     * @param array $data
140     * @return array
141     * @throws \ErrorException If input type is no handled.
142     * @throws \Illuminate\Validation\ValidationException If url is a bo url.
143     * @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
144     * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
145     */
146    private function serializeData(array $data): array
147    {
148        foreach ($data as $o => $input) {
149            switch ($input['inputType']) {
150                case InputType::image->value:
151                    $data[$o]['value'] = \preg_replace(
152                        '/^\/|^/',
153                        '',
154                        FileStorageHelper::storeFile($this, $input['value'], true)
155                    );
156                    break;
157                case InputType::selectEnum->value:
158                case InputType::boolean->value:
159                case InputType::password->value:
160                case InputType::email->value:
161                case InputType::number->value:
162                case InputType::videoVimeo->value:
163                case InputType::videoYoutube->value:
164                case InputType::video->value:
165                    break;
166                case InputType::string->value:
167                case InputType::text->value:
168                case InputType::url->value:
169                    ToolboxHelper::assertNoInternalBoUrls('content', $input['value']);
170                    break;
171                default:
172                    throw new \ErrorException(sprintf(
173                        'Unknown input Type %s',
174                        $input['inputType']
175                    ));
176            } //end switch
177        } //end foreach
178        return $data;
179    }
180}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/app/Traits/Models/dashboard.html b/tests/coverage/app/Traits/Models/dashboard.html deleted file mode 100644 index de718c1..0000000 --- a/tests/coverage/app/Traits/Models/dashboard.html +++ /dev/null @@ -1,314 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Traits/Models - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
ClassCoverage
App\Traits\Models\IsCachedAsCollection0%
App\Traits\Models\MiniCrudModel0%
-
-
-
-

Project Risks

- -
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
- -
-

Project Risks

-
- - - - - - - - - - - - - - - - - - -
MethodCRAP
serializeData240
getCached12
minicrudCreating12
minicrudUpdated12
minicrudDeleted12
setCached6
fill6
setData6
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/Traits/Models/index.html b/tests/coverage/app/Traits/Models/index.html deleted file mode 100644 index 54b502c..0000000 --- a/tests/coverage/app/Traits/Models/index.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Traits/Models - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 1.23% covered (danger) -
-
-
1.23%
1 / 81
-
- 5.88% covered (danger) -
-
-
5.88%
1 / 17
-
- 33.33% covered (danger) -
-
-
33.33%
1 / 3
ActivityLog.php
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
IsCachedAsCollection.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
MiniCrudModel.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 63
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/app/Traits/dashboard.html b/tests/coverage/app/Traits/dashboard.html deleted file mode 100644 index e5a6229..0000000 --- a/tests/coverage/app/Traits/dashboard.html +++ /dev/null @@ -1,334 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app/Traits - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- -
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- - -
- - - - - - diff --git a/tests/coverage/app/Traits/index.html b/tests/coverage/app/Traits/index.html deleted file mode 100644 index 23a56dc..0000000 --- a/tests/coverage/app/Traits/index.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app/Traits - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 24.46% covered (danger) -
-
-
24.46%
45 / 184
-
- 20.59% covered (danger) -
-
-
20.59%
7 / 34
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
Controllers
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 24
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
Enums
-
- 55.70% covered (warning) -
-
-
55.70%
44 / 79
-
- 40.00% covered (danger) -
-
-
40.00%
6 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Models
-
- 1.23% covered (danger) -
-
-
1.23%
1 / 81
-
- 5.88% covered (danger) -
-
-
5.88%
1 / 17
-
- 33.33% covered (danger) -
-
-
33.33%
1 / 3
-
- -
- - diff --git a/tests/coverage/app/dashboard.html b/tests/coverage/app/dashboard.html deleted file mode 100644 index b9c3a26..0000000 --- a/tests/coverage/app/dashboard.html +++ /dev/null @@ -1,755 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/app - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ClassCoverage
App\Console\Commands\TestMail0%
App\Console\Commands\UserCreate0%
App\Exceptions\Api\V2\CrmException0%
App\Exceptions\Api\V4\CrmException0%
App\Http\Controllers\Bo\ActivityLogsController0%
App\Http\Controllers\Bo\AnswerController0%
App\Http\Controllers\Bo\Auth\LoginController0%
App\Http\Controllers\Bo\Auth\ResetPasswordController0%
App\Http\Controllers\Bo\BrandController0%
App\Http\Controllers\Bo\CustomerController0%
App\Http\Controllers\Bo\DashboardController0%
App\Http\Controllers\Bo\QuestionController0%
App\Http\Controllers\Bo\ServiceController0%
App\Http\Controllers\Bo\SingleOptinController0%
App\Http\Controllers\Bo\StatsController0%
App\Http\Controllers\Bo\UsersController0%
App\Http\Controllers\Controller0%
App\Http\Middleware\RedirectIfAuthenticated0%
App\Http\Middleware\SecureHeaders0%
App\Http\Middleware\TrustHosts0%
App\Http\Requests\Bo\Answers\StoreAnswerRequest0%
App\Http\Requests\Bo\Brands\StoreBrandRequest0%
App\Http\Requests\Bo\CustomerExport0%
App\Http\Requests\Bo\GenerateServiceToken0%
App\Http\Requests\Bo\ManageBrandRequest0%
App\Http\Requests\Bo\ManageServiceRequest0%
App\Http\Requests\Bo\QuestionExport0%
App\Http\Requests\Bo\Questions\StoreQuestionRequest0%
App\Http\Requests\Bo\Services\StoreServiceRequest0%
App\Http\Requests\Bo\StatsByBrandRequest0%
App\Http\Requests\Bo\StatsByQuestionRequest0%
App\Http\Requests\Bo\UpdateChangeOrderRequest0%
App\Http\Requests\Bo\UpdateMiniCrudRequest0%
App\Http\Requests\Bo\Users\StoreUserRequest0%
App\Http\Requests\Bo\Users\UpdateUserRequest0%
App\Http\Resources\CustomerResource0%
App\Jobs\StartStatJobs0%
App\Jobs\StatJob0%
App\Lib\Helpers\ToolboxHelper0%
App\Mail\CourrierArcadiaError0%
App\Mail\ServiceCredentialRenewed0%
App\Models\ActivityLog0%
App\Models\User0%
App\Observers\ModelObserver0%
App\Policies\AnswerPolicy0%
App\Policies\BrandPolicy0%
App\Policies\ServicePolicy0%
App\Policies\SingleOptinPolicy0%
App\Policies\UserPolicy0%
App\Enums\ActivityLogs\ActivityLogsEventEnum0%
App\Traits\Controllers\ChangesModelOrder0%
App\Traits\Controllers\UpdateModelPublished0%
App\Traits\Models\IsCachedAsCollection0%
App\Traits\Models\MiniCrudModel0%
App\Policies\CustomerPolicy16%
App\Policies\QuestionPolicy16%
App\Models\BrandStat40%
App\Http\Middleware\Authenticate41%
App\Traits\Enums\BaseEnum55%
App\Models\Brand61%
App\Providers\RouteServiceProvider69%
App\Http\Middleware\HtmlSanitizer71%
App\Models\Service74%
App\Providers\ViewServiceProvider75%
App\Models\CustomerInfo80%
App\Exceptions\Handler88%
App\Providers\AppServiceProvider88%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ClassCRAP
App\Lib\Helpers\ToolboxHelper6642
App\Http\Controllers\Controller1332
App\Http\Requests\Bo\UpdateMiniCrudRequest1190
App\Http\Controllers\Bo\CustomerController992
App\Traits\Models\MiniCrudModel992
App\Policies\UserPolicy506
App\Http\Controllers\Bo\QuestionController462
App\Console\Commands\UserCreate380
App\Http\Controllers\Bo\ServiceController210
App\Http\Controllers\Bo\StatsController156
App\Http\Controllers\Bo\UsersController156
App\Traits\Enums\BaseEnum148
App\Http\Controllers\Bo\AnswerController110
App\Traits\Models\IsCachedAsCollection110
App\Http\Controllers\Bo\BrandController90
App\Http\Middleware\RedirectIfAuthenticated72
App\Models\User56
App\Http\Middleware\SecureHeaders42
App\Http\Requests\Bo\StatsByBrandRequest42
App\Http\Requests\Bo\StatsByQuestionRequest42
App\Models\ActivityLog42
App\Traits\Controllers\ChangesModelOrder42
App\Http\Controllers\Bo\SingleOptinController30
App\Http\Requests\Bo\Users\StoreUserRequest30
App\Http\Requests\Bo\Users\UpdateUserRequest30
App\Models\Service20
App\Http\Requests\Bo\UpdateChangeOrderRequest20
App\Exceptions\Handler18
App\Providers\RouteServiceProvider17
App\Http\Middleware\Authenticate13
App\Http\Controllers\Bo\ActivityLogsController12
App\Http\Requests\Bo\CustomerExport12
App\Http\Requests\Bo\ManageBrandRequest12
App\Http\Requests\Bo\ManageServiceRequest12
App\Http\Middleware\HtmlSanitizer9
App\Providers\ViewServiceProvider6
App\Jobs\StartStatJobs6
App\Models\BrandStat4
App\Providers\AppServiceProvider2
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodCoverage
handle0%
handle0%
addFirstName0%
addLastName0%
addEmail0%
addPassword0%
addRole0%
getApiError0%
report0%
getApiError0%
report0%
index0%
show0%
index0%
create0%
store0%
edit0%
update0%
destroy0%
__construct0%
guard0%
showLoginForm0%
redirectTo0%
attemptLogin0%
guard0%
redirectTo0%
index0%
create0%
store0%
edit0%
update0%
jsonPaginate0%
index0%
show0%
delete0%
export0%
exportSubmit0%
index0%
index0%
create0%
store0%
edit0%
update0%
show0%
destroy0%
export0%
exportSubmit0%
index0%
create0%
store0%
edit0%
update0%
show0%
destroy0%
generateServicePassword0%
index0%
destroy0%
viewStatsByBrand0%
exportByBrandCsv0%
viewByQuestion0%
exportByQuestionCsv0%
answersByDays0%
__construct0%
index0%
create0%
store0%
edit0%
update0%
destroy0%
duplicate0%
searchQuery0%
searchOnFields0%
getSearchValue0%
sortQuery0%
paginate0%
setTheme0%
handle0%
handle0%
removeUnwantedHeaders0%
hosts0%
authorize0%
rules0%
attributes0%
authorize0%
rules0%
attributes0%
authorize0%
rules0%
authorize0%
rules0%
authorize0%
rules0%
authorize0%
rules0%
authorize0%
rules0%
authorize0%
prepareForValidation0%
rules0%
attributes0%
authorize0%
prepareForValidation0%
rules0%
attributes0%
authorize0%
rules0%
authorize0%
rules0%
authorize0%
prepareForValidation0%
rules0%
authorize0%
rules0%
compileValidate0%
ruleHasToComeFirst0%
isUpdate0%
authorize0%
prepareForValidation0%
rules0%
attributes0%
prepareForValidation0%
rules0%
__construct0%
toArray0%
handle0%
__construct0%
handle0%
middleware0%
arrayMergeRecursiveDistinct0%
validateRecaptcha0%
stripCkEditorSchemesOnMediaInputs0%
assertNoInternalBoUrls0%
assertNoInternalUrls0%
mbReplace0%
assertFieldIsUnique0%
getOriginal0%
queryColumnWithLocales0%
dotStringToNestedArray0%
objectToArray0%
arrayToObject0%
validatePicture0%
getUploadedFileFullPath0%
getUploadedFileMimeType0%
getClassesUsingNamespace0%
getClassesUsingInterface0%
getValidatedEnum0%
__construct0%
build0%
__construct0%
build0%
addActivity0%
getChangedColumns0%
user0%
customerInfos0%
servicesStats0%
singleOptins0%
getAccountsAttribute0%
getTotalOptinsAttribute0%
brand0%
login0%
getFromHashcode0%
servicesStats0%
generateBearerToken0%
generateBearerPassword0%
booted0%
updatePassword0%
activityLogs0%
created0%
updated0%
duplicated0%
deleted0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
viewAny0%
view0%
create0%
update0%
delete0%
restore0%
forceDelete0%
duplicate0%
changePublished0%
bootstrapClass0%
changeOrder0%
changePublished0%
name0%
all0%
toArray0%
jsonSerialize0%
getCustomDefinitions0%
getCached0%
removeCached0%
setCached0%
queryCached0%
filterQuery0%
getCacheKeyName0%
getCallClassBaseName0%
fill0%
minicrudCreating0%
minicrudUpdating0%
minicrudUpdated0%
minicrudDeleted0%
setData0%
setDataAttribute0%
getDataAttribute0%
serializeData0%
cspReportRoute20%
redirectTo41%
register50%
prepareForValidation50%
booted50%
booted61%
booted66%
get66%
handle71%
jsonTranslations75%
boot75%
equals75%
getCache75%
setCache75%
loadBrandData84%
boot88%
signRequest88%
handleApiException88%
configureRateLimiting88%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodCRAP
rules462
serializeData240
validateRecaptcha210
index182
sortQuery182
validatePicture182
searchOnFields90
compileValidate90
mbReplace90
delete72
exportSubmit72
exportSubmit72
handle72
addRole42
objectToArray42
arrayToObject42
changeOrder42
searchQuery30
rules30
rules30
arrayMergeRecursiveDistinct30
getCustomDefinitions30
getSearchValue20
handle20
prepareForValidation20
assertNoInternalBoUrls20
assertNoInternalUrls20
queryColumnWithLocales20
booted20
toArray20
cspReportRoute17
redirectTo13
addFirstName12
addLastName12
addEmail12
addPassword12
index12
index12
index12
exportByBrandCsv12
answersByDays12
setTheme12
getUploadedFileFullPath12
getChangedColumns12
update12
delete12
restore12
forceDelete12
duplicate12
changePublished12
getCached12
minicrudCreating12
minicrudUpdated12
minicrudDeleted12
handleApiException10
handle9
signRequest7
boot6
index6
index6
store6
update6
destroy6
index6
store6
update6
store6
update6
destroy6
store6
update6
destroy6
generateServicePassword6
destroy6
viewStatsByBrand6
viewByQuestion6
exportByQuestionCsv6
index6
store6
update6
destroy6
paginate6
removeUnwantedHeaders6
rules6
rules6
rules6
prepareForValidation6
ruleHasToComeFirst6
prepareForValidation6
handle6
assertFieldIsUnique6
getOriginal6
dotStringToNestedArray6
getUploadedFileMimeType6
getValidatedEnum6
addActivity6
updatePassword6
view6
setCached6
fill6
setData6
equals5
loadBrandData5
jsonTranslations3
configureRateLimiting3
register2
prepareForValidation2
booted2
get2
getCache2
setCache2
boot2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/app/index.html b/tests/coverage/app/index.html deleted file mode 100644 index 3ea8c2d..0000000 --- a/tests/coverage/app/index.html +++ /dev/null @@ -1,427 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/app - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 41.04% covered (danger) -
-
-
41.04%
1328 / 3236
-
- 38.04% covered (danger) -
-
-
38.04%
159 / 418
-
- 40.16% covered (danger) -
-
-
40.16%
51 / 127
Console
-
- 2.11% covered (danger) -
-
-
2.11%
2 / 95
-
- 12.50% covered (danger) -
-
-
12.50%
1 / 8
-
- 33.33% covered (danger) -
-
-
33.33%
1 / 3
Enums
-
- 95.35% covered (success) -
-
-
95.35%
41 / 43
-
- 71.43% covered (warning) -
-
-
71.43%
5 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
Exceptions
-
- 86.67% covered (warning) -
-
-
86.67%
78 / 90
-
- 50.00% covered (danger) -
-
-
50.00%
6 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 5
Http
-
- 40.54% covered (danger) -
-
-
40.54%
834 / 2057
-
- 41.79% covered (danger) -
-
-
41.79%
84 / 201
-
- 52.00% covered (warning) -
-
-
52.00%
39 / 75
Jobs
-
- 40.00% covered (danger) -
-
-
40.00%
22 / 55
-
- 60.00% covered (warning) -
-
-
60.00%
6 / 10
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
Lib
-
- 19.25% covered (danger) -
-
-
19.25%
51 / 265
-
- 24.00% covered (danger) -
-
-
24.00%
6 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
Mail
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 29
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
Models
-
- 64.53% covered (warning) -
-
-
64.53%
151 / 234
-
- 60.66% covered (warning) -
-
-
60.66%
37 / 61
-
- 50.00% covered (danger) -
-
-
50.00%
7 / 14
Observers
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Policies
-
- 3.70% covered (danger) -
-
-
3.70%
2 / 54
-
- 4.88% covered (danger) -
-
-
4.88%
2 / 41
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
Providers
-
- 80.95% covered (warning) -
-
-
80.95%
102 / 126
-
- 45.45% covered (danger) -
-
-
45.45%
5 / 11
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
Traits
-
- 24.46% covered (danger) -
-
-
24.46%
45 / 184
-
- 20.59% covered (danger) -
-
-
20.59%
7 / 34
-
- 16.67% covered (danger) -
-
-
16.67%
1 / 6
-
- -
- - diff --git a/tests/coverage/client/dashboard.html b/tests/coverage/client/dashboard.html deleted file mode 100644 index 5f082db..0000000 --- a/tests/coverage/client/dashboard.html +++ /dev/null @@ -1,438 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/client - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- -
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
- - -
- -
- - - - - - diff --git a/tests/coverage/client/index.html b/tests/coverage/client/index.html deleted file mode 100644 index 75dac67..0000000 --- a/tests/coverage/client/index.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 69.13% covered (warning) -
-
-
69.13%
907 / 1312
-
- 45.56% covered (danger) -
-
-
45.56%
77 / 169
-
- 13.04% covered (danger) -
-
-
13.04%
3 / 23
src
-
- 69.13% covered (warning) -
-
-
69.13%
907 / 1312
-
- 45.56% covered (danger) -
-
-
45.56%
77 / 169
-
- 13.04% covered (danger) -
-
-
13.04%
3 / 23
-
- -
- - diff --git a/tests/coverage/client/src/CrmApiV4.php.html b/tests/coverage/client/src/CrmApiV4.php.html deleted file mode 100644 index b6b8da3..0000000 --- a/tests/coverage/client/src/CrmApiV4.php.html +++ /dev/null @@ -1,430 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/CrmApiV4.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 92.86% covered (success) -
-
-
92.86%
13 / 14
-
- 85.71% covered (warning) -
-
-
85.71%
6 / 7
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CrmApiV4
-
- 92.86% covered (success) -
-
-
92.86%
13 / 14
-
- 85.71% covered (warning) -
-
-
85.71%
6 / 7
8.02
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 ping
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getCustomerOrNew
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getCustomer
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 setStatus
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 unsetStatusWithHashcode
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 login
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM;
4
5use LDC\LDCCRM\Enums\ApiStatus;
6use LDC\LDCCRM\Models\Customer;
7use LDC\LDCCRM\Models\SingleOptin;
8use LDC\LDCCRM\Transport\ApiInterface;
9
10/**
11 * This is the main class to interact with the CRM
12 *
13 * @package LDCCrmClient
14 */
15class CrmApiV4
16{
17    /**
18     * The Api object that will handle requests and responses
19     *
20     * @var \LDC\LDCCRM\Transport\ApiInterface
21     */
22    private static $apiInterface;
23
24    /**
25     * CrmApiV4
26     *
27     * @param string|null $endpoint
28     * @param string|null $bearerToken
29     * @param string|null $bearerPwd
30     */
31    public function __construct(
32        #[\SensitiveParameter] string $endpoint = null,
33        #[\SensitiveParameter] string $bearerToken = null,
34        #[\SensitiveParameter] string $bearerPwd = null
35    ) {
36        self::$apiInterface = self::$apiInterface ?: new ApiInterface(
37            $endpoint,
38            $bearerToken,
39            $bearerPwd
40        );
41        return $this;
42    }
43
44    /**
45     * Use this the ping the crm and know its current status
46     *
47     * @return boolean
48     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs
49     * on server side or on getting response.
50     */
51    public function ping(): bool
52    {
53        $request  = Utils::getResquest('apiV4.ping');
54        $response = self::$apiInterface->call($request);
55        return $response->status->equals(ApiStatus::OK);
56    }
57
58    /**
59     *
60     * Get a customer from its hashcode or email
61     * If it does not exists a new instance
62     * will be returned. You would have
63     * to call its save method later on.
64     *
65     * @param string $identification The customer hashcode or email.
66     * @return \LDC\LDCCRM\Models\Customer A client Customer model.
67     *
68     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
69     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
70     * @phpcs:ignore Squiz.Commenting.FunctionComment.EmptyThrows
71     */
72    public function getCustomerOrNew(#[\SensitiveParameter] string $identification): Customer
73    {
74        return $this->getCustomer($identification) ?? new Customer();
75    }
76
77    /**
78     * Get a customer from its hashcode or email
79     * If it does not exists a new instance
80     * will be returned. You would have
81     * to call its save method later on.
82     *
83     * @param string $identification The customer hashcode or email.
84     * @return \LDC\LDCCRM\Models\Customer|null Return null if the customer was not found
85     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
86     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
87     * Possibles are : - modelNotFound, If this customer hashcode could not be found.
88     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
89     */
90    public function getCustomer(#[\SensitiveParameter] string $identification): ?Customer
91    {
92        return Customer::find($identification);
93    }
94
95    /**
96     * Set the single optin status for an email
97     *
98     * @param string  $email
99     * @param boolean $opt_in
100     * @return boolean true if succeeded
101     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field email could not be validated.
102     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
103     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
104     * Possibles are : - singleOptinCustomerExists, If a customer exists with this email.
105     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
106     */
107    public static function setStatus(#[\SensitiveParameter] string $email, bool $opt_in): bool
108    {
109        return SingleOptin::setStatus($email, $opt_in);
110    }
111
112    /**
113     * Set the single optin status for an email
114     *
115     * @param string $hashcode
116     * @return boolean true if succeeded
117     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field hashcode could not be validated.
118     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
119     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
120     * Possibles are : - modelNotFound, If a single optin does not exists.
121     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
122     */
123    public static function unsetStatusWithHashcode(string $hashcode): bool
124    {
125        return SingleOptin::unsetStatusWithHashcode($hashcode);
126    }
127
128    /**
129     * Test a customer credentials to see if it can login
130     *
131     * @param string $email
132     * @param string $password
133     * @return boolean
134     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
135     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
136     * Possibles are : - authFailed, If credentials are not valid.
137     *                 - customerNotActivated, If the account is not activated.
138     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
139     */
140    public static function login(#[\SensitiveParameter] string $email, #[\SensitiveParameter] string $password): bool
141    {
142        return Customer::login($email, $password);
143    }
144}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Enums/ApiError.php.html b/tests/coverage/client/src/Enums/ApiError.php.html deleted file mode 100644 index 35b49e6..0000000 --- a/tests/coverage/client/src/Enums/ApiError.php.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Enums/ApiError.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Enums;
4
5use LDC\LDCCRM\Traits\BaseEnum;
6
7enum ApiError: int
8{
9    use BaseEnum;
10
11    case modelNotFound             = 101;
12    case validationFailed          = 102;
13    case customerExists            = 103;
14    case customerAlreadyActive     = 110;
15    case customerNotActivated      = 116;
16    case authFailed                = 117;
17    case apiAuthFailed             = 119;
18    case singleOptinCustomerExists = 120;
19    case methodNotAllowed          = 150;
20    case wrongTimeStamp            = 151;
21    case missingParameter          = 400;
22    case authorizationException    = 403;
23    case throttleRequestsException = 429;
24
25    /**
26     * Optionnal labels definition
27     */
28    private const LABELS = [
29        self::modelNotFound->name             => '%s introuvable.',
30        self::validationFailed->name          => 'Impossible de valider les données',
31        self::customerExists->name            => 'L\'utilisateur est déjà enregistré sur ce site',
32        self::customerNotActivated->name      => 'Le compte n\'est pas activé',
33        self::customerAlreadyActive->name     => 'Le compte est déjà activé',
34        self::singleOptinCustomerExists->name => 'Le single optin ne peut être ajouté car un compte existe.',
35        self::authFailed->name                => 'Echec de l\'authentification du compte',
36        self::apiAuthFailed->name             => 'Echec de l\'authentification client à l\'Api LDC-CRM pour ce service',
37        self::methodNotAllowed->name          => 'This method is not allowed for this request',
38        self::wrongTimeStamp->name            => 'Your request is malformed, please check timestamp header and
39            parameter',
40        self::missingParameter->name          => 'The request is missing some parameters',
41        self::authorizationException->name    => 'You are not autorized to access this',
42        self::throttleRequestsException->name => 'Throttle: too many request have been attempted, please retry later'
43    ];
44}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Enums/ApiStatus.php.html b/tests/coverage/client/src/Enums/ApiStatus.php.html deleted file mode 100644 index 95b2b04..0000000 --- a/tests/coverage/client/src/Enums/ApiStatus.php.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Enums/ApiStatus.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Enums;
4
5use LDC\LDCCRM\Traits\BaseEnum;
6
7enum ApiStatus: int
8{
9    use BaseEnum;
10
11    case OK = 1;
12    case KO = 2;
13}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Enums/ArcadiaMailType.php.html b/tests/coverage/client/src/Enums/ArcadiaMailType.php.html deleted file mode 100644 index a504063..0000000 --- a/tests/coverage/client/src/Enums/ArcadiaMailType.php.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Enums/ArcadiaMailType.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Enums;
4
5use LDC\LDCCRM\Traits\BaseEnum;
6
7enum ArcadiaMailType: int
8{
9    use BaseEnum;
10
11    case default = 1;
12    case game    = 2;
13}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Enums/ArcadiaOrderType.php.html b/tests/coverage/client/src/Enums/ArcadiaOrderType.php.html deleted file mode 100644 index 242994d..0000000 --- a/tests/coverage/client/src/Enums/ArcadiaOrderType.php.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Enums/ArcadiaOrderType.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Enums;
4
5use LDC\LDCCRM\Traits\BaseEnum;
6
7enum ArcadiaOrderType: int
8{
9    use BaseEnum;
10
11    case cb    = 0;
12    case check = 1;
13}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Enums/Country.php.html b/tests/coverage/client/src/Enums/Country.php.html deleted file mode 100644 index 94b4e06..0000000 --- a/tests/coverage/client/src/Enums/Country.php.html +++ /dev/null @@ -1,792 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Enums/Country.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
Country
n/a
0 / 0
n/a
0 / 0
7
n/a
0 / 0
 getValidCountriesLabel
n/a
0 / 0
n/a
0 / 0
1
 getValidCountriesValues
n/a
0 / 0
n/a
0 / 0
1
 getValidIsoAplha2Codes
n/a
0 / 0
n/a
0 / 0
1
 getValidCountries
n/a
0 / 0
n/a
0 / 0
1
 isoCodes
n/a
0 / 0
n/a
0 / 0
1
 get
n/a
0 / 0
n/a
0 / 0
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Enums;
4
5use LDC\LDCCRM\Traits\BaseEnum;
6
7enum Country: int
8{
9    use BaseEnum;
10
11    case afghanistan                            = 1;
12    case alandIslands                           = 2;
13    case albania                                = 3;
14    case algeria                                = 4;
15    case americanSamoa                          = 5;
16    case andorra                                = 6;
17    case angola                                 = 7;
18    case anguilla                               = 8;
19    case antarctica                             = 9;
20    case antiguaAndBarbuda                      = 10;
21    case argentina                              = 11;
22    case armenia                                = 12;
23    case aruba                                  = 13;
24    case australia                              = 14;
25    case austria                                = 15;
26    case azerbaijan                             = 16;
27    case bahrain                                = 17;
28    case bahamas                                = 18;
29    case bangladesh                             = 19;
30    case barbados                               = 20;
31    case belarus                                = 21;
32    case belgium                                = 22;
33    case belize                                 = 23;
34    case benin                                  = 24;
35    case bermuda                                = 25;
36    case bhutan                                 = 26;
37    case boliviaPlurinationalStateOf            = 27;
38    case bonaireSintEustatiusAndSaba            = 28;
39    case bosniaAndHerzegovina                   = 29;
40    case botswana                               = 30;
41    case bouvetIsland                           = 31;
42    case brazil                                 = 32;
43    case britishIndianOceanTerritory            = 33;
44    case bruneiDarussalam                       = 34;
45    case bulgaria                               = 35;
46    case burkinaFaso                            = 36;
47    case burundi                                = 37;
48    case cambodia                               = 38;
49    case cameroon                               = 39;
50    case canada                                 = 40;
51    case capeVerde                              = 41;
52    case caymanIslands                          = 42;
53    case centralAfricanRepublic                 = 43;
54    case chad                                   = 44;
55    case chile                                  = 45;
56    case china                                  = 46;
57    case christmasIsland                        = 47;
58    case cocosKeelingIslands                    = 48;
59    case colombia                               = 49;
60    case comoros                                = 50;
61    case congo                                  = 51;
62    case congoTheDemocraticRepublicOfThe        = 52;
63    case cookIslands                            = 53;
64    case costaRica                              = 54;
65    case coteDivoire                            = 55;
66    case croatia                                = 56;
67    case cuba                                   = 57;
68    case curacao                                = 58;
69    case cyprus                                 = 59;
70    case czechRepublic                          = 60;
71    case denmark                                = 61;
72    case djibouti                               = 62;
73    case dominica                               = 63;
74    case dominicanRepublic                      = 64;
75    case ecuador                                = 65;
76    case egypt                                  = 66;
77    case elSalvador                             = 67;
78    case equatorialGuinea                       = 68;
79    case eritrea                                = 69;
80    case estonia                                = 70;
81    case ethiopia                               = 71;
82    case falklandIslandsMalvinas                = 72;
83    case faroeIslands                           = 73;
84    case fiji                                   = 74;
85    case finland                                = 75;
86    case france                                 = 76;
87    case frenchGuiana                           = 77;
88    case frenchPolynesia                        = 78;
89    case frenchSouthernTerritories              = 79;
90    case gabon                                  = 80;
91    case gambia                                 = 81;
92    case georgia                                = 82;
93    case germany                                = 83;
94    case ghana                                  = 84;
95    case gibraltar                              = 85;
96    case greece                                 = 86;
97    case greenland                              = 87;
98    case grenada                                = 88;
99    case guadeloupe                             = 89;
100    case guam                                   = 90;
101    case guatemala                              = 91;
102    case guernsey                               = 92;
103    case guinea                                 = 93;
104    case guineaBissau                           = 94;
105    case guyana                                 = 95;
106    case haiti                                  = 96;
107    case heardIslandAndMcdonaldIslands          = 97;
108    case holySeeVaticanCityState                = 98;
109    case honduras                               = 99;
110    case hongKong                               = 100;
111    case hungary                                = 101;
112    case iceland                                = 102;
113    case india                                  = 103;
114    case indonesia                              = 104;
115    case iranIslamicRepublicOf                  = 105;
116    case iraq                                   = 106;
117    case ireland                                = 107;
118    case isleOfMan                              = 108;
119    case israel                                 = 109;
120    case italy                                  = 110;
121    case jamaica                                = 111;
122    case japan                                  = 112;
123    case jersey                                 = 113;
124    case jordan                                 = 114;
125    case kazakhstan                             = 115;
126    case kenya                                  = 116;
127    case kiribati                               = 117;
128    case koreaDemocraticPeoplesRepublicOf       = 118;
129    case koreaRepublicOf                        = 119;
130    case kuwait                                 = 120;
131    case kyrgyzstan                             = 121;
132    case laoPeoplesDemocraticRepublic           = 122;
133    case latvia                                 = 123;
134    case lebanon                                = 124;
135    case lesotho                                = 125;
136    case liberia                                = 126;
137    case libya                                  = 127;
138    case liechtenstein                          = 128;
139    case lithuania                              = 129;
140    case luxembourg                             = 130;
141    case macao                                  = 131;
142    case macedoniaTheFormerYugoslavRepublicOf   = 132;
143    case madagascar                             = 133;
144    case malawi                                 = 134;
145    case malaysia                               = 135;
146    case maldives                               = 136;
147    case mali                                   = 137;
148    case malta                                  = 138;
149    case marshallIslands                        = 139;
150    case martinique                             = 140;
151    case mauritania                             = 141;
152    case mauritius                              = 142;
153    case mayotte                                = 143;
154    case mexico                                 = 144;
155    case micronesiaFederatedStatesOf            = 145;
156    case moldovaRepublicOf                      = 146;
157    case monaco                                 = 147;
158    case mongolia                               = 148;
159    case montenegro                             = 149;
160    case montserrat                             = 150;
161    case morocco                                = 151;
162    case mozambique                             = 152;
163    case myanmar                                = 153;
164    case namibia                                = 154;
165    case nauru                                  = 155;
166    case nepal                                  = 156;
167    case netherlands                            = 157;
168    case newCaledonia                           = 158;
169    case newZealand                             = 159;
170    case nicaragua                              = 160;
171    case niger                                  = 161;
172    case nigeria                                = 162;
173    case niue                                   = 163;
174    case norfolkIsland                          = 164;
175    case northernMarianaIslands                 = 165;
176    case norway                                 = 166;
177    case oman                                   = 167;
178    case pakistan                               = 168;
179    case palau                                  = 169;
180    case palestineStateOf                       = 170;
181    case panama                                 = 171;
182    case papuaNewGuinea                         = 172;
183    case paraguay                               = 173;
184    case peru                                   = 174;
185    case philippines                            = 175;
186    case pitcairn                               = 176;
187    case poland                                 = 177;
188    case portugal                               = 178;
189    case puertoRico                             = 179;
190    case qatar                                  = 180;
191    case reunion                                = 181;
192    case romania                                = 182;
193    case russianFederation                      = 183;
194    case rwanda                                 = 184;
195    case saintBarthelemy                        = 185;
196    case saintHelenaAscensionAndTristanDaCunha  = 186;
197    case saintKittsAndNevis                     = 187;
198    case saintLucia                             = 188;
199    case saintMartinFrenchPart                  = 189;
200    case saintPierreAndMiquelon                 = 190;
201    case saintVincentAndTheGrenadines           = 191;
202    case samoa                                  = 192;
203    case sanMarino                              = 193;
204    case saoTomeAndPrincipe                     = 194;
205    case saudiArabia                            = 195;
206    case senegal                                = 196;
207    case serbia                                 = 197;
208    case seychelles                             = 198;
209    case sierraLeone                            = 199;
210    case singapore                              = 200;
211    case sintMaartenDutchPart                   = 201;
212    case slovakia                               = 202;
213    case slovenia                               = 203;
214    case solomonIslands                         = 204;
215    case somalia                                = 205;
216    case southAfrica                            = 206;
217    case southGeorgiaAndTheSouthSandwichIslands = 207;
218    case southSudan                             = 208;
219    case spain                                  = 209;
220    case sriLanka                               = 210;
221    case sudan                                  = 211;
222    case suriname                               = 212;
223    case svalbardAndJanMayen                    = 213;
224    case swaziland                              = 214;
225    case sweden                                 = 215;
226    case switzerland                            = 216;
227    case syrianArabRepublic                     = 217;
228    case taiwanProvinceOfChina                  = 218;
229    case tajikistan                             = 219;
230    case tanzaniaUnitedRepublicOf               = 220;
231    case thailand                               = 221;
232    case timorLeste                             = 222;
233    case togo                                   = 223;
234    case tokelau                                = 224;
235    case tonga                                  = 225;
236    case trinidadAndTobago                      = 226;
237    case tunisia                                = 227;
238    case turkey                                 = 228;
239    case turkmenistan                           = 229;
240    case turksAndCaicosIslands                  = 230;
241    case tuvalu                                 = 231;
242    case uganda                                 = 232;
243    case ukraine                                = 233;
244    case unitedArabEmirates                     = 234;
245    case unitedKingdom                          = 235;
246    case unitedStates                           = 236;
247    case unitedStatesMinorOutlyingIslands       = 237;
248    case uruguay                                = 238;
249    case uzbekistan                             = 239;
250    case vanuatu                                = 240;
251    case venezuelaBolivarianRepublicOf          = 241;
252    case vietNam                                = 242;
253    case virginIslandsBritish                   = 243;
254    case virginIslandsUs                        = 244;
255    case wallisAndFutuna                        = 245;
256    case westernSahara                          = 246;
257    case yemen                                  = 247;
258    case zambia                                 = 248;
259    case zimbabwe                               = 249;
260
261    /**
262     * Optionnal labels definition
263     */
264    private const LABELS = [
265        self::afghanistan->name                            => 'Afghanistan',
266        self::alandIslands->name                           => 'Åland Islands',
267        self::albania->name                                => 'Albania',
268        self::algeria->name                                => 'Algeria',
269        self::americanSamoa->name                          => 'American Samoa',
270        self::andorra->name                                => 'Andorra',
271        self::angola->name                                 => 'Angola',
272        self::anguilla->name                               => 'Anguilla',
273        self::antarctica->name                             => 'Antarctica',
274        self::antiguaAndBarbuda->name                      => 'Antigua and Barbuda',
275        self::argentina->name                              => 'Argentina',
276        self::armenia->name                                => 'Armenia',
277        self::aruba->name                                  => 'Aruba',
278        self::australia->name                              => 'Australia',
279        self::austria->name                                => 'Austria',
280        self::azerbaijan->name                             => 'Azerbaijan',
281        self::bahrain->name                                => 'Bahrain',
282        self::bahamas->name                                => 'Bahamas',
283        self::bangladesh->name                             => 'Bangladesh',
284        self::barbados->name                               => 'Barbados',
285        self::belarus->name                                => 'Belarus',
286        self::belgium->name                                => 'Belgium',
287        self::belize->name                                 => 'Belize',
288        self::benin->name                                  => 'Benin',
289        self::bermuda->name                                => 'Bermuda',
290        self::bhutan->name                                 => 'Bhutan',
291        self::boliviaPlurinationalStateOf->name            => 'Bolivia, Plurinational State of',
292        self::bonaireSintEustatiusAndSaba->name            => 'Bonaire, Sint Eustatius and Saba',
293        self::bosniaAndHerzegovina->name                   => 'Bosnia and Herzegovina',
294        self::botswana->name                               => 'Botswana',
295        self::bouvetIsland->name                           => 'Bouvet Island',
296        self::brazil->name                                 => 'Brazil',
297        self::britishIndianOceanTerritory->name            => 'British Indian Ocean Territory',
298        self::bruneiDarussalam->name                       => 'Brunei Darussalam',
299        self::bulgaria->name                               => 'Bulgaria',
300        self::burkinaFaso->name                            => 'Burkina Faso',
301        self::burundi->name                                => 'Burundi',
302        self::cambodia->name                               => 'Cambodia',
303        self::cameroon->name                               => 'Cameroon',
304        self::canada->name                                 => 'Canada',
305        self::capeVerde->name                              => 'Cape Verde',
306        self::caymanIslands->name                          => 'Cayman Islands',
307        self::centralAfricanRepublic->name                 => 'Central African Republic',
308        self::chad->name                                   => 'Chad',
309        self::chile->name                                  => 'Chile',
310        self::china->name                                  => 'China',
311        self::christmasIsland->name                        => 'Christmas Island',
312        self::cocosKeelingIslands->name                    => 'Cocos (Keeling) Islands',
313        self::colombia->name                               => 'Colombia',
314        self::comoros->name                                => 'Comoros',
315        self::congo->name                                  => 'Congo',
316        self::congoTheDemocraticRepublicOfThe->name        => 'Congo, the Democratic Republic of the',
317        self::cookIslands->name                            => 'Cook Islands',
318        self::costaRica->name                              => 'Costa Rica',
319        self::coteDivoire->name                            => 'Côte d\'Ivoire',
320        self::croatia->name                                => 'Croatia',
321        self::cuba->name                                   => 'Cuba',
322        self::curacao->name                                => 'Curaçao',
323        self::cyprus->name                                 => 'Cyprus',
324        self::czechRepublic->name                          => 'Czech Republic',
325        self::denmark->name                                => 'Denmark',
326        self::djibouti->name                               => 'Djibouti',
327        self::dominica->name                               => 'Dominica',
328        self::dominicanRepublic->name                      => 'Dominican Republic',
329        self::ecuador->name                                => 'Ecuador',
330        self::egypt->name                                  => 'Egypt',
331        self::elSalvador->name                             => 'El Salvador',
332        self::equatorialGuinea->name                       => 'Equatorial Guinea',
333        self::eritrea->name                                => 'Eritrea',
334        self::estonia->name                                => 'Estonia',
335        self::ethiopia->name                               => 'Ethiopia',
336        self::falklandIslandsMalvinas->name                => 'Falkland Islands (Malvinas)',
337        self::faroeIslands->name                           => 'Faroe Islands',
338        self::fiji->name                                   => 'Fiji',
339        self::finland->name                                => 'Finland',
340        self::france->name                                 => 'France',
341        self::frenchGuiana->name                           => 'French Guiana',
342        self::frenchPolynesia->name                        => 'French Polynesia',
343        self::frenchSouthernTerritories->name              => 'French Southern Territories',
344        self::gabon->name                                  => 'Gabon',
345        self::gambia->name                                 => 'Gambia',
346        self::georgia->name                                => 'Georgia',
347        self::germany->name                                => 'Germany',
348        self::ghana->name                                  => 'Ghana',
349        self::gibraltar->name                              => 'Gibraltar',
350        self::greece->name                                 => 'Greece',
351        self::greenland->name                              => 'Greenland',
352        self::grenada->name                                => 'Grenada',
353        self::guadeloupe->name                             => 'Guadeloupe',
354        self::guam->name                                   => 'Guam',
355        self::guatemala->name                              => 'Guatemala',
356        self::guernsey->name                               => 'Guernsey',
357        self::guinea->name                                 => 'Guinea',
358        self::guineaBissau->name                           => 'GuineaBissau',
359        self::guyana->name                                 => 'Guyana',
360        self::haiti->name                                  => 'Haiti',
361        self::heardIslandAndMcdonaldIslands->name          => 'Heard Island and McDonald Islands',
362        self::holySeeVaticanCityState->name                => 'Holy See (Vatican City State)',
363        self::honduras->name                               => 'Honduras',
364        self::hongKong->name                               => 'Hong Kong',
365        self::hungary->name                                => 'Hungary',
366        self::iceland->name                                => 'Iceland',
367        self::india->name                                  => 'India',
368        self::indonesia->name                              => 'Indonesia',
369        self::iranIslamicRepublicOf->name                  => 'Iran, Islamic Republic of',
370        self::iraq->name                                   => 'Iraq',
371        self::ireland->name                                => 'Ireland',
372        self::isleOfMan->name                              => 'Isle of Man',
373        self::israel->name                                 => 'Israel',
374        self::italy->name                                  => 'Italy',
375        self::jamaica->name                                => 'Jamaica',
376        self::japan->name                                  => 'Japan',
377        self::jersey->name                                 => 'Jersey',
378        self::jordan->name                                 => 'Jordan',
379        self::kazakhstan->name                             => 'Kazakhstan',
380        self::kenya->name                                  => 'Kenya',
381        self::kiribati->name                               => 'Kiribati',
382        self::koreaDemocraticPeoplesRepublicOf->name       => 'Korea, Democratic People\'s Republic of',
383        self::koreaRepublicOf->name                        => 'Korea, Republic of',
384        self::kuwait->name                                 => 'Kuwait',
385        self::kyrgyzstan->name                             => 'Kyrgyzstan',
386        self::laoPeoplesDemocraticRepublic->name           => 'Lao People\'s Democratic Republic',
387        self::latvia->name                                 => 'Latvia',
388        self::lebanon->name                                => 'Lebanon',
389        self::lesotho->name                                => 'Lesotho',
390        self::liberia->name                                => 'Liberia',
391        self::libya->name                                  => 'Libya',
392        self::liechtenstein->name                          => 'Liechtenstein',
393        self::lithuania->name                              => 'Lithuania',
394        self::luxembourg->name                             => 'Luxembourg',
395        self::macao->name                                  => 'Macao',
396        self::macedoniaTheFormerYugoslavRepublicOf->name   => 'Macedonia, the Former Yugoslav Republic of',
397        self::madagascar->name                             => 'Madagascar',
398        self::malawi->name                                 => 'Malawi',
399        self::malaysia->name                               => 'Malaysia',
400        self::maldives->name                               => 'Maldives',
401        self::mali->name                                   => 'Mali',
402        self::malta->name                                  => 'Malta',
403        self::marshallIslands->name                        => 'Marshall Islands',
404        self::martinique->name                             => 'Martinique',
405        self::mauritania->name                             => 'Mauritania',
406        self::mauritius->name                              => 'Mauritius',
407        self::mayotte->name                                => 'Mayotte',
408        self::mexico->name                                 => 'Mexico',
409        self::micronesiaFederatedStatesOf->name            => 'Micronesia, Federated States of',
410        self::moldovaRepublicOf->name                      => 'Moldova, Republic of',
411        self::monaco->name                                 => 'Monaco',
412        self::mongolia->name                               => 'Mongolia',
413        self::montenegro->name                             => 'Montenegro',
414        self::montserrat->name                             => 'Montserrat',
415        self::morocco->name                                => 'Morocco',
416        self::mozambique->name                             => 'Mozambique',
417        self::myanmar->name                                => 'Myanmar',
418        self::namibia->name                                => 'Namibia',
419        self::nauru->name                                  => 'Nauru',
420        self::nepal->name                                  => 'Nepal',
421        self::netherlands->name                            => 'Netherlands',
422        self::newCaledonia->name                           => 'New Caledonia',
423        self::newZealand->name                             => 'New Zealand',
424        self::nicaragua->name                              => 'Nicaragua',
425        self::niger->name                                  => 'Niger',
426        self::nigeria->name                                => 'Nigeria',
427        self::niue->name                                   => 'Niue',
428        self::norfolkIsland->name                          => 'Norfolk Island',
429        self::northernMarianaIslands->name                 => 'Northern Mariana Islands',
430        self::norway->name                                 => 'Norway',
431        self::oman->name                                   => 'Oman',
432        self::pakistan->name                               => 'Pakistan',
433        self::palau->name                                  => 'Palau',
434        self::palestineStateOf->name                       => 'Palestine, State of',
435        self::panama->name                                 => 'Panama',
436        self::papuaNewGuinea->name                         => 'Papua New Guinea',
437        self::paraguay->name                               => 'Paraguay',
438        self::peru->name                                   => 'Peru',
439        self::philippines->name                            => 'Philippines',
440        self::pitcairn->name                               => 'Pitcairn',
441        self::poland->name                                 => 'Poland',
442        self::portugal->name                               => 'Portugal',
443        self::puertoRico->name                             => 'Puerto Rico',
444        self::qatar->name                                  => 'Qatar',
445        self::reunion->name                                => 'Réunion',
446        self::romania->name                                => 'Romania',
447        self::russianFederation->name                      => 'Russian Federation',
448        self::rwanda->name                                 => 'Rwanda',
449        self::saintBarthelemy->name                        => 'Saint Barthélemy',
450        self::saintHelenaAscensionAndTristanDaCunha->name  => 'Saint Helena, Ascension and Tristan da Cunha',
451        self::saintKittsAndNevis->name                     => 'Saint Kitts and Nevis',
452        self::saintLucia->name                             => 'Saint Lucia',
453        self::saintMartinFrenchPart->name                  => 'Saint Martin (French part)',
454        self::saintPierreAndMiquelon->name                 => 'Saint Pierre and Miquelon',
455        self::saintVincentAndTheGrenadines->name           => 'Saint Vincent and the Grenadines',
456        self::samoa->name                                  => 'Samoa',
457        self::sanMarino->name                              => 'San Marino',
458        self::saoTomeAndPrincipe->name                     => 'Sao Tome and Principe',
459        self::saudiArabia->name                            => 'Saudi Arabia',
460        self::senegal->name                                => 'Senegal',
461        self::serbia->name                                 => 'Serbia',
462        self::seychelles->name                             => 'Seychelles',
463        self::sierraLeone->name                            => 'Sierra Leone',
464        self::singapore->name                              => 'Singapore',
465        self::sintMaartenDutchPart->name                   => 'Sint Maarten (Dutch part)',
466        self::slovakia->name                               => 'Slovakia',
467        self::slovenia->name                               => 'Slovenia',
468        self::solomonIslands->name                         => 'Solomon Islands',
469        self::somalia->name                                => 'Somalia',
470        self::southAfrica->name                            => 'South Africa',
471        self::southGeorgiaAndTheSouthSandwichIslands->name => 'South Georgia and the South Sandwich Islands',
472        self::southSudan->name                             => 'South Sudan',
473        self::spain->name                                  => 'Spain',
474        self::sriLanka->name                               => 'Sri Lanka',
475        self::sudan->name                                  => 'Sudan',
476        self::suriname->name                               => 'Suriname',
477        self::svalbardAndJanMayen->name                    => 'Svalbard and Jan Mayen',
478        self::swaziland->name                              => 'Swaziland',
479        self::sweden->name                                 => 'Sweden',
480        self::switzerland->name                            => 'Switzerland',
481        self::syrianArabRepublic->name                     => 'Syrian Arab Republic',
482        self::taiwanProvinceOfChina->name                  => 'Taiwan, Province of China',
483        self::tajikistan->name                             => 'Tajikistan',
484        self::tanzaniaUnitedRepublicOf->name               => 'Tanzania, United Republic of',
485        self::thailand->name                               => 'Thailand',
486        self::timorLeste->name                             => 'TimorLeste',
487        self::togo->name                                   => 'Togo',
488        self::tokelau->name                                => 'Tokelau',
489        self::tonga->name                                  => 'Tonga',
490        self::trinidadAndTobago->name                      => 'Trinidad and Tobago',
491        self::tunisia->name                                => 'Tunisia',
492        self::turkey->name                                 => 'Turkey',
493        self::turkmenistan->name                           => 'Turkmenistan',
494        self::turksAndCaicosIslands->name                  => 'Turks and Caicos Islands',
495        self::tuvalu->name                                 => 'Tuvalu',
496        self::uganda->name                                 => 'Uganda',
497        self::ukraine->name                                => 'Ukraine',
498        self::unitedArabEmirates->name                     => 'United Arab Emirates',
499        self::unitedKingdom->name                          => 'United Kingdom',
500        self::unitedStates->name                           => 'United States',
501        self::unitedStatesMinorOutlyingIslands->name       => 'United States Minor Outlying Islands',
502        self::uruguay->name                                => 'Uruguay',
503        self::uzbekistan->name                             => 'Uzbekistan',
504        self::vanuatu->name                                => 'Vanuatu',
505        self::venezuelaBolivarianRepublicOf->name          => 'Venezuela, Bolivarian Republic of',
506        self::vietNam->name                                => 'Viet Nam',
507        self::virginIslandsBritish->name                   => 'Virgin Islands, British',
508        self::virginIslandsUs->name                        => 'Virgin Islands, U.S.',
509        self::wallisAndFutuna->name                        => 'Wallis and Futuna',
510        self::westernSahara->name                          => 'Western Sahara',
511        self::yemen->name                                  => 'Yemen',
512        self::zambia->name                                 => 'Zambia',
513        self::zimbabwe->name                               => 'Zimbabwe'
514    ];
515
516    /**
517     * Get valid countries label.
518     *
519     * @return array<string>
520     * @codeCoverageIgnore
521     */
522    public static function getValidCountriesLabel(): array
523    {
524        return collect(self::getValidCountries())->map(function (self $country) {
525            return $country->label();
526        })->all();
527    }
528
529    /**
530     * Get valid countries value.
531     *
532     * @return array<string|integer>
533     * @codeCoverageIgnore
534     */
535    public static function getValidCountriesValues(): array
536    {
537        return collect(self::getValidCountries())->map(function (self $country) {
538            return $country->value();
539        })->all();
540    }
541
542    /**
543     * Get Alpha 2 ISO code of valid countries
544     *
545     * @return array
546     * @codeCoverageIgnore
547     */
548    public static function getValidIsoAplha2Codes(): array
549    {
550        return \array_values(self::isoCodes());
551    }
552
553    /**
554     * Get valid countries
555     *
556     * @return array
557     * @codeCoverageIgnore
558     */
559    public static function getValidCountries(): array
560    {
561        return [
562            Country::belgium,
563            Country::luxembourg,
564            Country::france,
565            Country::guadeloupe,
566            Country::martinique,
567            Country::frenchGuiana,
568            Country::reunion,
569            Country::saintPierreAndMiquelon,
570            Country::mayotte,
571            Country::saintBarthelemy,
572            Country::saintMartinFrenchPart,
573            Country::wallisAndFutuna,
574            Country::frenchPolynesia,
575            Country::newCaledonia
576        ];
577    }
578
579    /**
580     * Enum classes
581     *
582     * @return array
583     * @codeCoverageIgnore
584     */
585    protected static function isoCodes(): array
586    {
587        return [
588            'france' => 'FR',
589            'belgium' => 'BE',
590            'luxembourg' => 'LU',
591            'guadeloupe' => 'GP',
592            'martinique' => 'MQ',
593            'frenchGuiana' => 'GF',
594            'reunion' => 'RE',
595            'saintPierreAndMiquelon' => 'PM',
596            'mayotte' => 'YT',
597            'saintBarthelemy' => 'BL',
598            'saintMartinFrenchPart' => 'MF',
599            'wallisAndFutuna' => 'WF',
600            'frenchPolynesia' => 'PF',
601            'newCaledonia' => 'NC',
602        ];
603    }
604
605    /**
606     * @param string $attribute
607     * @return integer|string|null
608     * @codeCoverageIgnore
609     */
610    public function get(string $attribute): int|string|null
611    {
612        if ($attribute === 'iso') {
613            return $this->isoCodes()[$this->name] ?? null;
614        }
615        return $this->{$attribute};
616    }
617}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Enums/HttpMethods.php.html b/tests/coverage/client/src/Enums/HttpMethods.php.html deleted file mode 100644 index 4c5afca..0000000 --- a/tests/coverage/client/src/Enums/HttpMethods.php.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Enums/HttpMethods.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Enums;
4
5use LDC\LDCCRM\Traits\BaseEnum;
6
7enum HttpMethods: int
8{
9    use BaseEnum;
10
11    case get    = 1;
12    case post   = 2;
13    case put    = 3;
14    case delete = 4;
15}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Enums/LogLevel.php.html b/tests/coverage/client/src/Enums/LogLevel.php.html deleted file mode 100644 index f0260cd..0000000 --- a/tests/coverage/client/src/Enums/LogLevel.php.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Enums/LogLevel.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Enums;
4
5use LDC\LDCCRM\Traits\BaseEnum;
6
7enum LogLevel: int
8{
9    use BaseEnum;
10
11    case EMERG   = 'LOG_EMERG';
12    case ALERT   = 'LOG_ALERT';
13    case CRIT    = 'LOG_CRIT';
14    case ERR     = 'LOG_ERR';
15    case WARNING = 'LOG_WARNING';
16    case NOTICE  = 'LOG_NOTICE';
17    case INFO    = 'LOG_INFO';
18    case DEBUG   = 'LOG_DEBUG';
19}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Enums/QuestionType.php.html b/tests/coverage/client/src/Enums/QuestionType.php.html deleted file mode 100644 index 68f4fdc..0000000 --- a/tests/coverage/client/src/Enums/QuestionType.php.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Enums/QuestionType.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Enums;
4
5use LDC\LDCCRM\Traits\BaseEnum;
6
7enum QuestionType: int
8{
9    use BaseEnum;
10
11    case select   = 1;
12    case radio    = 2;
13    case checkbox = 3;
14}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Enums/dashboard.html b/tests/coverage/client/src/Enums/dashboard.html deleted file mode 100644 index c354f68..0000000 --- a/tests/coverage/client/src/Enums/dashboard.html +++ /dev/null @@ -1,286 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/client/src/Enums - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
ClassCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - -
MethodCoverage
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/client/src/Enums/index.html b/tests/coverage/client/src/Enums/index.html deleted file mode 100644 index cb3cba0..0000000 --- a/tests/coverage/client/src/Enums/index.html +++ /dev/null @@ -1,182 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Enums - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ApiError.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ApiStatus.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ArcadiaMailType.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ArcadiaOrderType.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
Country.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
HttpMethods.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
LogLevel.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
QuestionType.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
-
- -
- - diff --git a/tests/coverage/client/src/Exceptions/AccessError.php.html b/tests/coverage/client/src/Exceptions/AccessError.php.html deleted file mode 100644 index f625471..0000000 --- a/tests/coverage/client/src/Exceptions/AccessError.php.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Exceptions/AccessError.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
AccessError
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Exceptions;
4
5/**
6 * This is thrown when trying to set a value on an object property that does not exist.
7 *
8 * @package LDCCrmClient
9 * @subpackage exceptions
10 */
11class AccessError extends \Error
12{
13    /**
14     * AccessError
15     *
16     * @param string $objectName   The object name where the property does not exist.
17     * @param string $propertyName The property name that does not exist.
18     */
19    public function __construct(string $objectName, string $propertyName)
20    {
21        parent::__construct("Tried to set value in $objectName->$propertyName, it does not exists.");
22    }
23}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Exceptions/ApiErrorException.php.html b/tests/coverage/client/src/Exceptions/ApiErrorException.php.html deleted file mode 100644 index a190447..0000000 --- a/tests/coverage/client/src/Exceptions/ApiErrorException.php.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Exceptions/ApiErrorException.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 90.00% covered (success) -
-
-
90.00%
9 / 10
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ApiErrorException
-
- 90.00% covered (success) -
-
-
90.00%
9 / 10
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
5.03
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 getApiError
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getStatusCode
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 report
n/a
0 / 0
n/a
0 / 0
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Exceptions;
4
5use LDC\LDCCRM\Enums\ApiError;
6use Illuminate\Support\Facades\Log;
7
8/**
9 * This would be thrown if any of the case
10 * referenced in \LDC\LDCCRM\Enums\ApiError would
11 * occur within the crm.
12 *
13 * On the client an ApiErrorException would
14 * also be throw with the ApiError corresponding to
15 * the situation.
16 *
17 * @package LDCCrmClient
18 * @subpackage exceptions
19 */
20class ApiErrorException extends \RuntimeException
21{
22    /**
23     * Api Error
24     * This value makes the error more explicit.
25     * Handling these errors are normal as inputs or
26     * request may be undesired or refused by the crm.
27     *
28     * @var \LDC\LDCCRM\Enums\ApiError
29     */
30    protected $error;
31
32    /**
33     * This is an explicit error message,
34     * ou may print this to the front or not depending
35     * on $error value.
36     *
37     * @var string
38     */
39    protected $message;
40
41    /**
42     * This is the http code returned by the crm.
43     * This value could be used to handle errors.
44     * But please take in consideration $error first.
45     *
46     * @var integer
47     */
48    protected $httpCode;
49
50    /**
51     * Create a new exception base on ApiError enum.
52     *
53     * @param \LDC\LDCCRM\Enums\ApiError $error
54     * @param integer                    $httpCode
55     * @param string                     $message
56     * @param \Throwable|null            $previous
57     */
58    public function __construct(ApiError $error, int $httpCode = 400, string $message = '', \Throwable $previous = null)
59    {
60        $this->error    = $error;
61        $this->message  = $message;
62        $this->httpCode = $httpCode;
63        parent::__construct(
64            strlen($this->message) ? $this->message : $error->label(),
65            $error->value(),
66            $previous
67        );
68    }
69
70    /**
71     * Get the Api Error.
72     *
73     * @return \LDC\LDCCRM\Enums\ApiError
74     */
75    public function getApiError(): ApiError
76    {
77        return $this->error;
78    }
79
80    /**
81     * Get the http code.
82     *
83     * @return integer
84     */
85    public function getStatusCode(): int
86    {
87        return $this->httpCode;
88    }
89
90    /**
91     * This is used by laravel only.
92     * It uses Log class to print the error.
93     *
94     * @return void
95     */
96    public function report(): void
97    {
98        // @codeCoverageIgnoreStart
99        Log::debug(sprintf('CRM API: %s', $this->getMessage()));
100        // @codeCoverageIgnoreEnd
101    }
102}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Exceptions/CrmException.php.html b/tests/coverage/client/src/Exceptions/CrmException.php.html deleted file mode 100644 index 5b2be5e..0000000 --- a/tests/coverage/client/src/Exceptions/CrmException.php.html +++ /dev/null @@ -1,182 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Exceptions/CrmException.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CrmException
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 report
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Exceptions;
4
5use Illuminate\Support\Facades\Log;
6
7/**
8 * This is a critical error.
9 * The request could not be handled. You may dump any value you can
10 * get before submitting a ticker to https://support.uwil.fr/
11 *
12 * @package LDCCrmClient
13 * @subpackage exceptions
14 */
15class CrmException extends \RuntimeException
16{
17    /**
18     * This is used by laravel only.
19     * It uses Log class to print the error.
20     *
21     * @return void
22     */
23    public function report(): void
24    {
25        Log::critical(sprintf('CRM API: %s', $this->getMessage()));
26    }
27}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Exceptions/SkipValidationException.php.html b/tests/coverage/client/src/Exceptions/SkipValidationException.php.html deleted file mode 100644 index 6e0e8ea..0000000 --- a/tests/coverage/client/src/Exceptions/SkipValidationException.php.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Exceptions/SkipValidationException.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
SkipValidationException
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
-
- - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Exceptions;
4
5/**
6 * Used only for internal validator
7 *
8 * @package LDCCrmClient
9 * @subpackage exceptions
10 */
11class SkipValidationException extends \RuntimeException
12{
13}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Exceptions/ValidationException.php.html b/tests/coverage/client/src/Exceptions/ValidationException.php.html deleted file mode 100644 index 029c4ce..0000000 --- a/tests/coverage/client/src/Exceptions/ValidationException.php.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Exceptions/ValidationException.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ValidationException
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 report
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Exceptions;
4
5use Illuminate\Support\Facades\Log;
6
7/**
8 * This would be thrown if a data could not be validated
9 * on any models
10 *
11 * @package LDCCrmClient
12 * @subpackage exceptions
13 */
14class ValidationException extends \RuntimeException
15{
16    /**
17     * This is used by laravel only.
18     * It uses Log class to print the error.
19     *
20     * @return void
21     */
22    public function report()
23    {
24        Log::error(sprintf('CRM Client: %s', $this->getMessage()));
25    }
26}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Exceptions/WpCrmInvalidJsonUserInfo.php.html b/tests/coverage/client/src/Exceptions/WpCrmInvalidJsonUserInfo.php.html deleted file mode 100644 index 55b548c..0000000 --- a/tests/coverage/client/src/Exceptions/WpCrmInvalidJsonUserInfo.php.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Exceptions/WpCrmInvalidJsonUserInfo.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
WpCrmInvalidJsonUserInfo
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Exceptions;
4
5use LDC\LDCCRM\Enums\LogLevel;
6use LDC\LDCCRM\Utils;
7
8/**
9 * This is thrown when trying to read WP customer from DB json data.
10 *
11 * @package LDCCrmClient
12 * @subpackage exceptions
13 */
14class WpCrmInvalidJsonUserInfo extends \Error
15{
16    /**
17     * WpCrmInvalidJsonUserInfo
18     *
19     * @param string $message The error message.
20     */
21    public function __construct(string $message)
22    {
23        Utils::log($message, LogLevel::CRIT);
24        parent::__construct($message);
25    }
26}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Exceptions/dashboard.html b/tests/coverage/client/src/Exceptions/dashboard.html deleted file mode 100644 index df64ef5..0000000 --- a/tests/coverage/client/src/Exceptions/dashboard.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/client/src/Exceptions - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
- -
-

Project Risks

-
- - - - - - - - - - -
ClassCRAP
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - -
MethodCoverage
getStatusCode0%
report0%
report0%
__construct0%
-
-
-
-

Project Risks

-
- - - - - - - - - - -
MethodCRAP
-
-
-
- -
- - - - - - diff --git a/tests/coverage/client/src/Exceptions/index.html b/tests/coverage/client/src/Exceptions/index.html deleted file mode 100644 index a308954..0000000 --- a/tests/coverage/client/src/Exceptions/index.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Exceptions - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 66.67% covered (warning) -
-
-
66.67%
10 / 15
-
- 42.86% covered (danger) -
-
-
42.86%
3 / 7
-
- 20.00% covered (danger) -
-
-
20.00%
1 / 5
AccessError.php
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
ApiErrorException.php
-
- 90.00% covered (success) -
-
-
90.00%
9 / 10
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CrmException.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
SkipValidationException.php
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
ValidationException.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
WpCrmInvalidJsonUserInfo.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/client/src/Models/Answer.php.html b/tests/coverage/client/src/Models/Answer.php.html deleted file mode 100644 index 0ae75ce..0000000 --- a/tests/coverage/client/src/Models/Answer.php.html +++ /dev/null @@ -1,334 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Models/Answer.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 96.15% covered (success) -
-
-
96.15%
25 / 26
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Answer
-
- 96.15% covered (success) -
-
-
96.15%
25 / 26
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 setQuestionAnswers
-
- 94.74% covered (success) -
-
-
94.74%
18 / 19
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.00
 jsonSerialize
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Models;
4
5use LDC\LDCCRM\Enums\ApiStatus;
6use LDC\LDCCRM\Utils;
7
8/**
9 * This class represents an answer
10 * It has a method to submit answers
11 *
12 * @property integer $id The answer id
13 * @property string $question The actual question as a string
14 * @property \LDC\LDCCRM\Enums\QuestionType $type
15 * The question type to display,
16 * it also hints wether it can accept one or multiple responses,
17 * so only checkbox allows multiple responses
18 * @property \LDC\LDCCRM\Models\Answer[] $answers An array with answers
19 *
20 * @category Api Models
21 * @package LDCCrmClient
22 * @subpackage models
23 * @author Jérémy Munsch <jeremy.munsch@ldc.fr>
24 */
25class Answer extends ClientModel
26{
27    /**
28     * The question id
29     *
30     * Required
31     * Field Type bigInt
32     *
33     * @var integer
34     */
35    private int $id;
36
37    /**
38     * The actual answer as a string
39     *
40     * Required
41     * Max length 255
42     * Field Type varchar
43     *
44     * @var string
45     */
46    private ?string $answer = null;
47
48    /**
49     * The crm customer fields
50     *
51     * @var array
52     */
53    protected array $modelFields = [
54        'id',
55        'answer',
56    ];
57
58    /**
59     * Validation rules
60     *
61     * @var array
62     */
63    protected static array $validation = [
64        'id'     => 'required|int',
65        'answer' => 'required|string|max:255',
66    ];
67
68    /**
69     * Answer
70     *
71     * @param array $properties
72     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
73     */
74    public function __construct(array $properties = [])
75    {
76        parent::__construct();
77        $this->fill($properties);
78        return $this;
79    }
80
81    // * PUBLIC METHODS
82
83    /**
84     * Set unanswered question for a specific customer
85     *
86     * @param string  $hashcode   The customer hashcode.
87     * @param integer $questionId The question id.
88     * @param array   $answersId  An array with answers id.
89     * @return boolean true if succeeded
90     *
91     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a hashcode is not a valid UUID.
92     * @throws \LDC\LDCCRM\Exceptions\ValidationException If any of the provided ids are invalid.
93     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error \LDC\LDCCRM\Enums\ApiError occurs.
94     * Possibles are : - validationFailed, If given ids are wrong(CRM side).
95     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
96     */
97    public static function setQuestionAnswers(string $hashcode, int $questionId, array $answersId): bool
98    {
99        self::assertValidHascode($hashcode);
100        self::assertValidPrimaryKey($questionId);
101        if (!count($answersId)) {
102            return true;
103        }
104        foreach ($answersId as $answerId) {
105            self::assertValidPrimaryKey($answerId);
106        }
107        static::setUpApiInterface();
108        $request = Utils::getResquest(
109            'apiV4.customers.answers.store',
110            [
111                'serviceCustomer' => $hashcode
112            ],
113            [
114                'question' => $questionId,
115                'answers' => $answersId
116            ]
117        );
118
119        $response = static::$apiInterface->call($request);
120        return $response->status->equals(ApiStatus::OK);
121    }
122
123    /**
124     * Serialize this object to an array
125     *
126     * @return array
127     */
128    public function jsonSerialize()
129    {
130        return [
131            'id'     => $this->id,
132            'answer' => $this->answer
133        ];
134    }
135}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Models/ArcadiaMailDefault.php.html b/tests/coverage/client/src/Models/ArcadiaMailDefault.php.html deleted file mode 100644 index f0b292b..0000000 --- a/tests/coverage/client/src/Models/ArcadiaMailDefault.php.html +++ /dev/null @@ -1,703 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Models/ArcadiaMailDefault.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 93.33% covered (success) -
-
-
93.33%
56 / 60
-
- 71.43% covered (warning) -
-
-
71.43%
5 / 7
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ArcadiaMailDefault
-
- 93.33% covered (success) -
-
-
93.33%
56 / 60
-
- 71.43% covered (warning) -
-
-
71.43%
5 / 7
21.13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 __get
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 __set
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 fill
-
- 75.00% covered (warning) -
-
-
75.00%
6 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6.56
 validateAllValues
-
- 80.00% covered (warning) -
-
-
80.00%
8 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.07
 send
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 jsonSerialize
-
- 100.00% covered (success) -
-
-
100.00%
19 / 19
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Models;
4
5use LDC\LDCCRM\Enums\ApiStatus;
6use LDC\LDCCRM\Enums\ArcadiaOrderType;
7use LDC\LDCCRM\Utils;
8
9/**
10 * This class represents the customer info with
11 * the account validation status
12 *
13 * @property string|null $email Must be a rfc valid email on a valid domain name
14 * @property string|null $firstname The account first name
15 * @property string|null $lastname The account last name
16 * @property string|null $phone The account phone
17 * @property string|null $address The account address (street number, name, build, flat number)
18 * @property string|null $address2 The account phone (address complement)
19 * @property string|null $city The account city name
20 * @property string|null $postcode The account city postcode
21 *
22 * @property integer|null $operation The arcadia operation code
23 * @property integer|null $support_code The arcadia support code
24 * @property string|null  $label_type_support The arcadia type support label
25 * @property string|null  $order_date The arcadia order date  'yyyy-mm-dd HH:ii:ss'
26 * @property integer|null $order_num The arcadia order number
27 * @property \LDC\LDCCRM\Enums\ArcadiaOrderType|null $state_order The arcadia order date
28 * @property integer|null $package_unit_weight The arcadia package unit weight
29 *
30 * @category Api Models
31 * @package LDCCrmClient
32 * @subpackage models
33 * @author Jérémy Munsch <jeremy.munsch@ldc.fr>
34 */
35class ArcadiaMailDefault extends ClientModel
36{
37    /**
38     * An RFC Valid Email
39     *
40     * Validate: rfc,dns,spoof,filter
41     *
42     * Required
43     * Min length N/A
44     * Max length 255
45     * Field Type varchar
46     *
47     * @var string|null
48     */
49    private ?string $email = null;
50
51    /**
52     * First name
53     *
54     * Required
55     * Min length 2
56     * Max length 255
57     * Field Type varchar
58     *
59     * @var string|null
60     */
61    private ?string $firstname = null;
62
63    /**
64     * Last name
65     *
66     * Required
67     * Min length 2
68     * Max length 255
69     * Field Type varchar
70     *
71     * @var string|null
72     */
73    private ?string $lastname = null;
74
75    /**
76     * The user phone
77     *
78     * Validate: sometimes,string
79     *
80     * Required
81     * Min length NA
82     * Max length 255
83     * Field Type varchar
84     *
85     * @var string|null
86     */
87    private ?string $phone = null;
88
89    /**
90     * The user address (street number, name, etc)
91     *
92     * Validate: sometimes,string
93     *
94     * Min length NA
95     * Max length 255
96     * Field Type varchar
97     *
98     * @var string|null
99     */
100    private ?string $address = null;
101
102    /**
103     * The user address 2nd part (street number, name, more, etc)
104     *
105     * Validate: sometimes,string
106     *
107     * Min length NA
108     * Max length 255
109     * Field Type varchar
110     *
111     * @var string|null
112     */
113    private ?string $address2 = null;
114
115    /**
116     * The user address city
117     *
118     * Validate: sometimes,string
119     *
120     * Min length NA
121     * Max length 255
122     * Field Type varchar
123     *
124     * @var string|null
125     */
126    private ?string $city = null;
127
128    /**
129     * The user address postcode
130     *
131     * Validate: string
132     *
133     * Required
134     * Min length NA
135     * Max length 255
136     * Field Type varchar
137     *
138     * @var string|null
139     */
140    private ?string $postcode = null;
141
142    /**
143     * The arcadia operation code
144     *
145     * Validate: int
146     *
147     * Required
148     *
149     * @var integer|null
150     */
151    private ?int $operation = null;
152
153    /**
154     * The arcadia support code
155     *
156     * Validate: int
157     *
158     * Required
159     *
160     * @var integer|null
161     */
162    private ?int $support_code = null;
163
164    /**
165     * The arcadia type support label
166     *
167     * Validate: string
168     *
169     * Required
170     *
171     * @var string|null
172     */
173    private ?string $label_type_support = null;
174
175    /**
176     * The arcadia order date
177     *
178     * Validate: date
179     *
180     * Required
181     *
182     * @var string|null
183     */
184    private ?string $order_date = null;
185
186    /**
187     * The arcadia order number
188     *
189     * Validate: numeric,digits:9
190     *
191     * Required
192     *
193     * @var integer|null
194     */
195    private ?int $order_num = null;
196
197    /**
198     * The arcadia state order
199     *
200     * Validate: in ArcadiaOrderType::toValues()
201     *
202     * Required
203     *
204     * @var \LDC\LDCCRM\Enums\ArcadiaOrderType|null
205     */
206    private ?int $state_order = null;
207
208    /**
209     * The arcadia package unit weight
210     *
211     * Validate: integer
212     *
213     * Required
214     *
215     * @var integer|null
216     */
217    private ?int $package_unit_weight = null;
218
219    /**
220     * The crm customer fields
221     *
222     * @var array
223     */
224    protected array $modelFields = [
225        'email',
226        'firstname',
227        'lastname',
228        'phone',
229        'address',
230        'address2',
231        'city',
232        'postcode',
233        'operation',
234        'support_code',
235        'label_type_support',
236        'order_date',
237        'order_num',
238        'state_order',
239        'package_unit_weight',
240    ];
241
242    /**
243     * Validation rules
244     *
245     * @var array
246     */
247    protected static array $validation = [
248        'email'               => 'required|email',
249        'firstname'           => 'required|string|min:2|max:255',
250        'lastname'            => 'required|string|min:2|max:255',
251        'phone'               => 'sometimes|string|min:10|max:255',
252        'address'             => 'sometimes|string|max:255',
253        'address2'            => 'sometimes|string|max:255',
254        'city'                => 'sometimes|string|max:255',
255        'postcode'            => 'sometimes|string|max:255',
256        'operation'           => 'required|int',
257        'support_code'        => 'required|int',
258        'label_type_support'  => 'required|string|min:2|max:255',
259        'order_date'          => 'required|date_format:Y/m/d H:i:s',
260        'order_num'           => 'required|int',
261        'state_order'         => ['required'],
262        'package_unit_weight' => 'required|int'
263    ];
264
265    /**
266     * ArcadiaMailDefault
267     *
268     * @param array $properties
269     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
270     */
271    public function __construct(array $properties = [])
272    {
273        parent::__construct();
274        $this->fill($properties);
275        return $this;
276    }
277
278    /**
279     * Generic accessor
280     *
281     * @param string $field
282     * @return mixed
283     */
284    public function __get(string $field)
285    {
286        $props = \array_diff(
287            $this->modelFields,
288            $this->invisibleFields
289        );
290        if (in_array($field, $props)) {
291            if ($field === 'state_order' and !\is_object($this->{$field})) {
292                return ArcadiaOrderType::make($this->{$field});
293            }
294        }
295        return parent::__get($field);
296    }
297
298    /**
299     * Set prop
300     *
301     * @param string $field
302     * @param mixed  $value
303     * @return void
304     * @throws \TypeError If the field has an incorrect value.
305     * @throws \LDC\LDCCRM\Exceptions\AccessError If trying to set a value on a unknown property.
306     */
307    public function __set(string $field, mixed $value): void
308    {
309        if ($field === 'state_order') {
310            $value = (\is_object($value) and
311                get_class($value) === ArcadiaOrderType::class) ? $value->value() : $value;
312        }
313        parent::__set($field, $value);
314    }
315
316    /**
317     * Fill data into this model
318     * using validation rules
319     *
320     * @param array $properties
321     * @return void
322     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
323     */
324    public function fill(array $properties)
325    {
326        if (isset($properties['state_order'])) {
327            try {
328                $properties['state_order'] = (\is_object($properties['state_order']) and
329                    get_class($properties['state_order']) === ArcadiaOrderType::class) ?
330                    $properties['state_order']->value() : (ctype_digit($properties['state_order']) ?
331                        (int)$properties['state_order'] : $properties['state_order']);
332            } catch (\TypeError | \BadMethodCallException) {
333                // * Cast anyway
334                $properties['state_order'] = (int)$properties['state_order'];
335            }
336        }
337        parent::fill($properties);
338    }
339
340    /**
341     * Validate all model properties
342     *
343     * @param array $ignore
344     * @return array the validated values
345     * @throws ValidationException If a field could not be validated.
346     */
347    protected function validateAllValues(array $ignore = []): array
348    {
349        $out = [];
350        if (!\in_array('state_order', $ignore)) {
351            try {
352                $this->validateValue(
353                    'state_order',
354                    ArcadiaOrderType::make(Utils::getRawProperty($this, 'state_order'))
355                );
356            } catch (\TypeError | \BadMethodCallException) {
357                // Use this to throw validation error.
358                $this->validateValue('state_order', Utils::getRawProperty($this, 'state_order'));
359            }
360            $out['state_order'] = Utils::getRawProperty($this, 'state_order');
361        }
362        return array_merge($out, parent::validateAllValues(array_merge(['state_order'], $ignore)));
363    }
364
365    // * PUBLIC METHODS
366
367    /**
368     * Send The actual mail
369     *
370     * @return boolean true if succeeded
371     * @throws ValidationException If a field could not be validated.
372     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
373     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
374     * Possibles are : - validationFailed, If provided data is wrong(CRM side).
375     */
376    public function send(): bool
377    {
378        $this->validateAllValues();
379        static::setUpApiInterface();
380        $request  = Utils::getResquest('apiV4.arcadia.outgoingMailDefault', [], $this->jsonSerialize());
381        $response = static::$apiInterface->call($request);
382        if ($status = $response->status->equals(ApiStatus::OK)) {
383            $this->updatedValues = [];
384        }
385        $this->isNew = !$status;
386        return $status;
387    }
388
389    /**
390     * Serialize this object to an array
391     *
392     * @return array
393     */
394    public function jsonSerialize()
395    {
396        return [
397            'deliver'             => [
398                'email'     => $this->email,
399                'firstname' => $this->firstname,
400                'lastname'  => $this->lastname,
401                'phone'     => $this->phone,
402                'address'   => $this->address,
403                'address2'  => $this->address2,
404                'city'      => $this->city,
405                'postcode'  => $this->postcode,
406            ],
407            'operation'           => $this->operation,
408            'support_code'        => $this->support_code,
409            'label_type_support'  => $this->label_type_support,
410            'order_date'          => $this->order_date,
411            'order_num'           => $this->order_num,
412            'state_order'         => $this->state_order,
413            'package_unit_weight' => $this->package_unit_weight
414        ];
415    }
416}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Models/ArcadiaMailGame.php.html b/tests/coverage/client/src/Models/ArcadiaMailGame.php.html deleted file mode 100644 index a651278..0000000 --- a/tests/coverage/client/src/Models/ArcadiaMailGame.php.html +++ /dev/null @@ -1,601 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Models/ArcadiaMailGame.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 80.49% covered (warning) -
-
-
80.49%
33 / 41
-
- 60.00% covered (warning) -
-
-
60.00%
3 / 5
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ArcadiaMailGame
-
- 80.49% covered (warning) -
-
-
80.49%
33 / 41
-
- 60.00% covered (warning) -
-
-
60.00%
3 / 5
15.46
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 __set
-
- 50.00% covered (danger) -
-
-
50.00%
2 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6.00
 fill
-
- 25.00% covered (danger) -
-
-
25.00%
2 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
21.19
 send
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 jsonSerialize
-
- 100.00% covered (success) -
-
-
100.00%
18 / 18
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Models;
4
5use LDC\LDCCRM\Enums\ApiStatus;
6use LDC\LDCCRM\Enums\ArcadiaOrderType;
7use LDC\LDCCRM\Utils;
8
9/**
10 * This class represents the customer info with
11 * the account validation status
12 *
13 * @property integer $operation The arcadia operation code
14 *                          Validate: int
15 *                          Required
16 *
17 * @property string|null $email Must be a rfc valid email on a valid domain name
18 * @property string|null $firstname The account first name
19 * @property string|null $lastname The account last name
20 * @property string|null $phone The account phone
21 * @property string|null $address The account address (street number, name, build, flat number)
22 * @property string|null $address2 The account phone (address complement)
23 * @property string|null $city The account city name
24 * @property string|null $postcode The account city postcode
25 *
26 * @property integer|null $support_code The arcadia support code
27 * @property string|null  $label_type_support The arcadia type support label
28 * @property string|null  $order_date The arcadia order date  'yyyy-mm-dd HH:ii:ss'
29 * @property string|null  $code_unique The arcadia code unique
30 * @property string|null  $code_on_pack The arcadia code on pack
31 *
32 * @category Api Models
33 * @package LDCCrmClient
34 * @subpackage models
35 * @author Jérémy Munsch <jeremy.munsch@ldc.fr>
36 */
37class ArcadiaMailGame extends ClientModel
38{
39    /**
40     * An RFC Valid Email
41     *
42     * Validate: rfc,dns,spoof,filter
43     *
44     * Required
45     * Min length N/A
46     * Max length 255
47     * Field Type varchar
48     *
49     * @var string|null
50     */
51    private ?string $email = null;
52
53    /**
54     * First name
55     *
56     * Required
57     * Min length 2
58     * Max length 255
59     * Field Type varchar
60     *
61     * @var string|null
62     */
63    private ?string $firstname = null;
64
65    /**
66     * Last name
67     *
68     * Required
69     * Min length 2
70     * Max length 255
71     * Field Type varchar
72     *
73     * @var string|null
74     */
75    private ?string $lastname = null;
76
77    /**
78     * The user phone
79     *
80     * Validate: sometimes,string
81     *
82     * Required
83     * Min length NA
84     * Max length 255
85     * Field Type varchar
86     *
87     * @var string|null
88     */
89    private ?string $phone = null;
90
91    /**
92     * The user address (street number, name, etc)
93     *
94     * Validate: sometimes,string
95     *
96     * Min length NA
97     * Max length 255
98     * Field Type varchar
99     *
100     * @var string|null
101     */
102    private ?string $address = null;
103
104    /**
105     * The user address 2nd part (street number, name, more, etc)
106     *
107     * Validate: sometimes,string
108     *
109     * Min length NA
110     * Max length 255
111     * Field Type varchar
112     *
113     * @var string|null
114     */
115    private ?string $address2 = null;
116
117    /**
118     * The user address city
119     *
120     * Validate: sometimes,string
121     *
122     * Min length NA
123     * Max length 255
124     * Field Type varchar
125     *
126     * @var string|null
127     */
128    private ?string $city = null;
129
130    /**
131     * The user address postcode
132     *
133     * Validate: string
134     *
135     * Required
136     * Min length NA
137     * Max length 255
138     * Field Type varchar
139     *
140     * @var string|null
141     */
142    private ?string $postcode = null;
143
144    /**
145     * The arcadia operation code
146     *
147     * Validate: int
148     *
149     * Required
150     *
151     * @var integer|null
152     */
153    private ?int $operation = null;
154
155    /**
156     * The arcadia support code
157     *
158     * Validate: int
159     *
160     * Required
161     *
162     * @var integer|null
163     */
164    private ?int $support_code = null;
165
166    /**
167     * The arcadia type support label
168     *
169     * Validate: string
170     *
171     * Required
172     *
173     * @var string|null
174     */
175    private ?string $label_type_support = null;
176
177    /**
178     * The arcadia order date
179     *
180     * Validate: date
181     *
182     * Required
183     *
184     * @var string|null
185     */
186    private ?string $order_date = null;
187
188    /**
189     * The arcadia code unique
190     *
191     * Validate: string
192     *
193     * Required
194     *
195     * @var string|null
196     */
197    private ?string $code_unique = null;
198
199    /**
200     * The arcadia code on pack
201     *
202     * Validate: sometimes
203     *
204     * Required
205     *
206     * @var string|null
207     */
208    private ?string $code_on_pack = null;
209
210    /**
211     * The crm customer fields
212     *
213     * @var array
214     */
215    protected array $modelFields = [
216        'email',
217        'firstname',
218        'lastname',
219        'phone',
220        'address',
221        'address2',
222        'city',
223        'postcode',
224        'operation',
225        'support_code',
226        'label_type_support',
227        'order_date',
228        'code_unique',
229        'code_on_pack',
230    ];
231
232    /**
233     * Validation rules
234     *
235     * @var array
236     */
237    protected static array $validation = [
238        'email'              => 'required|email',
239        'firstname'          => 'required|string|min:2|max:255',
240        'lastname'           => 'required|string|min:2|max:255',
241        'phone'              => 'sometimes|string|min:10|max:255',
242        'address'            => 'sometimes|string|max:255',
243        'address2'           => 'sometimes|string|max:255',
244        'city'               => 'sometimes|string|max:255',
245        'postcode'           => 'sometimes|string|max:255',
246        'operation'          => 'required|int',
247        'support_code'       => 'required|int',
248        'label_type_support' => 'required|string|min:2|max:255',
249        'order_date'         => 'required|date_format:Y/m/d H:i:s',
250        'code_unique'        => 'required|string',
251        'code_on_pack'       => 'sometimes|string'
252    ];
253
254    /**
255     * ArcadiaMailGame
256     *
257     * @param array $properties
258     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
259     */
260    public function __construct(array $properties = [])
261    {
262        parent::__construct();
263        $this->fill($properties);
264        return $this;
265    }
266
267    /**
268     * Set prop
269     *
270     * @param string $field
271     * @param mixed  $value
272     * @return void
273     * @throws \TypeError If the field has an incorrect value.
274     * @throws \LDC\LDCCRM\Exceptions\AccessError If trying to set a value on a unknown property.
275     */
276    public function __set(string $field, mixed $value): void
277    {
278        if ($field === 'state_order') {
279            $value = (\is_object($value) and
280                get_class($value) === ArcadiaOrderType::class) ? $value->value() : $value;
281        }
282        parent::__set($field, $value);
283    }
284
285    /**
286     * Fill data into this model
287     * using validation rules
288     *
289     * @param array $properties
290     * @return void
291     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
292     */
293    public function fill(array $properties)
294    {
295        if (isset($properties['state_order'])) {
296            try {
297                $properties['state_order'] = (\is_object($properties['state_order']) and
298                    get_class($properties['state_order']) === ArcadiaOrderType::class) ?
299                    $properties['state_order']->value : (ctype_digit($properties['state_order']) ?
300                        (int)$properties['state_order'] : $properties['state_order']);
301            } catch (\TypeError | \BadMethodCallException) {
302                // * Cast anyway
303                $properties['state_order'] = (int)$properties['state_order'];
304            }
305        }
306        parent::fill($properties);
307    }
308
309    // * PUBLIC METHODS
310
311    /**
312     * Send The actual mail
313     *
314     * @return boolean true if succeeded
315     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
316     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
317     * Possibles are : - validationFailed, If provided data is wrong(CRM side).
318     */
319    public function send(): bool
320    {
321        $this->validateAllValues();
322        static::setUpApiInterface();
323        $request  = Utils::getResquest('apiV4.arcadia.outgoingMailGame', [], $this->jsonSerialize());
324        $response = static::$apiInterface->call($request);
325        if ($status = $response->status->equals(ApiStatus::OK)) {
326            $this->updatedValues = [];
327        }
328        $this->isNew = !$status;
329        return $status;
330    }
331
332    /**
333     * Serialize this object to an array
334     *
335     * @return array
336     */
337    public function jsonSerialize()
338    {
339        return [
340            'deliver'            => [
341                'email'     => $this->email,
342                'firstname' => $this->firstname,
343                'lastname'  => $this->lastname,
344                'phone'     => $this->phone,
345                'address'   => $this->address,
346                'address2'  => $this->address2,
347                'city'      => $this->city,
348                'postcode'  => $this->postcode,
349            ],
350            'operation'          => $this->operation,
351            'support_code'       => $this->support_code,
352            'label_type_support' => $this->label_type_support,
353            'order_date'         => $this->order_date,
354            'code_unique'        => $this->code_unique,
355            'code_on_pack'       => $this->code_on_pack
356        ];
357    }
358}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Models/ClientModel.php.html b/tests/coverage/client/src/Models/ClientModel.php.html deleted file mode 100644 index f79167a..0000000 --- a/tests/coverage/client/src/Models/ClientModel.php.html +++ /dev/null @@ -1,747 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Models/ClientModel.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 78.22% covered (warning) -
-
-
78.22%
79 / 101
-
- 41.67% covered (danger) -
-
-
41.67%
5 / 12
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ClientModel
-
- 78.22% covered (warning) -
-
-
78.22%
79 / 101
-
- 41.67% covered (danger) -
-
-
41.67%
5 / 12
73.81
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 __get
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 __set
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
5
 setUpApiInterface
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 fill
-
- 47.06% covered (danger) -
-
-
47.06%
8 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
24.84
 fillRaw
-
- 30.00% covered (danger) -
-
-
30.00%
3 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
9.49
 validateAllValues
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 validateValue
-
- 87.50% covered (warning) -
-
-
87.50%
7 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.01
 checkFieldType
-
- 93.33% covered (success) -
-
-
93.33%
14 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12.04
 getPropType
-
- 83.33% covered (warning) -
-
-
83.33%
10 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
4.07
 assertValidPrimaryKey
-
- 83.33% covered (warning) -
-
-
83.33%
5 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.02
 assertValidHascode
-
- 83.33% covered (warning) -
-
-
83.33%
5 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.02
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Models;
4
5use LDC\LDCCRM\Enums\ArcadiaOrderType;
6use LDC\LDCCRM\Enums\Country;
7use LDC\LDCCRM\Enums\LogLevel;
8use LDC\LDCCRM\Enums\QuestionType;
9use LDC\LDCCRM\Exceptions\AccessError;
10use LDC\LDCCRM\Exceptions\ValidationException;
11use LDC\LDCCRM\Transport\ApiInterface;
12use LDC\LDCCRM\Utils;
13
14/**
15 * @ignore
16 * Base Class for crm client models
17 *
18 * @category Api Models
19 * @package LDCCrmClient
20 * @subpackage models
21 * @author Jérémy Munsch <jeremy.munsch@ldc.fr>
22 */
23abstract class ClientModel implements \JsonSerializable
24{
25    /**
26     * Is true if this model was not filled from crm
27     *
28     * @var boolean
29     */
30    protected bool $isNew = true;
31
32    /**
33     * The Api object that will handle requests and responses
34     *
35     * @var \LDC\LDCCRM\Transport\ApiInterface
36     */
37    protected static ApiInterface $apiInterface;
38
39    /**
40     * Validation rules
41     *
42     * @var array
43     */
44    protected static array $validation = [];
45
46    /**
47     * Model fields
48     *
49     * @var array
50     */
51    protected array $modelFields = [];
52
53    /**
54     * The crm fields
55     * that should not be visible
56     *
57     * @var array
58     */
59    protected array $invisibleFields = [];
60
61    /**
62     * Model updated values
63     *
64     * @var array
65     */
66    protected array $updatedValues = [];
67
68    /**
69     * CrmClientModel
70     */
71    public function __construct()
72    {
73        self::setUpApiInterface();
74        return $this;
75    }
76
77    /**
78     * Generic accessor
79     *
80     * @param string $field
81     * @return mixed|null Returns null if the property was not found any way.
82     */
83    public function __get(string $field)
84    {
85        $props = \array_diff(
86            $this->modelFields,
87            $this->invisibleFields
88        );
89        if (in_array($field, $props)) {
90            return Utils::getRawProperty($this, $field);
91        }
92        return null;
93    }
94
95    /**
96     * Set prop on the model.
97     *
98     * @param string $field
99     * @param mixed  $value
100     * @return void
101     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
102     * @throws \LDC\LDCCRM\Exceptions\AccessError If trying to set a value on a unknown property.
103     */
104    public function __set(string $field, #[\SensitiveParameter] mixed $value): void
105    {
106        try {
107            if (in_array($field, $this->modelFields)) {
108                $type = $this->getPropType($field);
109                if (!is_null($value) and !$this->checkFieldType($type, $value)) {
110                    throw new ValidationException("Wrong type for $field");
111                }
112                $this->validateValue($field, $value);
113                $this->updatedValues[$field] = $value;
114                Utils::setRawProperty($this, $field, $value);
115                return;
116            }
117            // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
118        } catch (\ReflectionException $e) {
119            // Do nothing.
120        }
121        throw new AccessError(\get_class($this), $field);
122    }
123
124    /**
125     * Create the Api interface
126     *
127     * @return void
128     */
129    protected static function setUpApiInterface()
130    {
131        self::$apiInterface = self::$apiInterface ?? new ApiInterface();
132    }
133
134    /**
135     * Fill values into model using validation rules.
136     *
137     * @param array $properties
138     * @return void
139     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
140     */
141    public function fill(#[\SensitiveParameter] array $properties)
142    {
143        if (count($properties)) {
144            foreach ($properties as $field => $value) {
145                try {
146                    $type = $this->getPropType($field);
147                    // * Force boolean
148                    if ($type === 'bool') {
149                        $value = (\is_int($value) and ($value === 1 or $value === 0)) ? (bool)$value : $value;
150                    }
151                    if (!is_null($value) and !$this->checkFieldType($type, $value)) {
152                        throw new ValidationException("Wrong type for $field");
153                    }
154                    $this->validateValue($field, $value);
155                    $this->updatedValues[$field] = $value;
156                    Utils::setRawProperty($this, $field, $value);
157                } catch (AccessError | \ReflectionException) {
158                    Utils::log(\sprintf(
159                        '%s::fill : unknown property access for %s, it does not exist on object.',
160                        \get_class($this),
161                        $field
162                    ), LogLevel::DEBUG);
163                    continue;
164                }
165            } //end foreach
166        } //end if
167    }
168
169    /**
170     * Set all properties to without any validation
171     *
172     * @param array $properties
173     * @return void
174     */
175    protected function fillRaw(#[\SensitiveParameter] array $properties)
176    {
177        if (count($properties)) {
178            foreach ($properties as $field => $value) {
179                try {
180                    Utils::setRawProperty($this, $field, $value);
181                } catch (AccessError $e) {
182                    Utils::log(\sprintf(
183                        '%s::fillRaw : unknown property access for %s, it does not exist on object.',
184                        \get_class($this),
185                        $field
186                    ), LogLevel::DEBUG);
187                    continue;
188                }
189            }
190        }
191    }
192
193    /**
194     * Validate all model properties
195     *
196     * * All properties are nullable
197     *
198     * @param array $ignore
199     * @return array the validated values
200     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
201     */
202    protected function validateAllValues(array $ignore = []): array
203    {
204        $out = [];
205        foreach (static::$validation as $field => $validationRules) {
206            if (\in_array($field, $ignore) or \is_null(Utils::getRawProperty($this, $field))) {
207                continue;
208            }
209            $this->validateValue($field, Utils::getRawProperty($this, $field));
210            $out[$field] = Utils::getRawProperty($this, $field);
211        }
212        return $out;
213    }
214
215    /**
216     * Validate a value against its rules
217     *
218     * @param string $field
219     * @param mixed  $value
220     * @return boolean
221     * @throws \ErrorException If a field has no validation rule.
222     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
223     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
224     */
225    protected static function validateValue(string $field, #[\SensitiveParameter] mixed $value): bool
226    {
227        if (!isset(static::$validation[$field])) {
228            throw new \ErrorException("$field has no validation rule");
229        }
230        $validator = Utils::makeValidator(
231            [$field => $value],
232            [$field => static::$validation[$field]]
233        );
234        /** @throws \LDC\LDCCRM\Exceptions\ValidationException */
235        $validator();
236        return true;
237    }
238
239    /**
240     * Check a value against its field type
241     *
242     * @param string $type
243     * @param mixed  $value
244     * @return boolean Return true if $type matches $value type.
245     * @throws \ErrorException If type is not handled,
246     * handled types are boolean, string, integer, \LDC\LDCCRM\Enums\Country,  \LDC\LDCCRM\Enums\ArcadiaOrderType .
247     * @phpcs:ignore Generic.Files.LineLength.TooLong
248     */
249    protected function checkFieldType(string $type, #[\SensitiveParameter] mixed $value): bool
250    {
251        /**
252         * Checks if the value is valid for a specific enum class
253         *
254         * @param string $className
255         * @param mixed  $value
256         * @return boolean
257         */
258        $checkValueIsEnum = function (string $className, $value) {
259            try {
260                $value = \is_int($value) ? $className::make($value) : $value;
261            } finally {
262                return \is_object($value) and (get_class($value) === $className or
263                    \in_array($className, \class_parents($value)));
264            }
265        };
266
267        switch ($type) {
268            case '\\' . Country::class:
269            case '\\' . QuestionType::class:
270            case '\\' . ArcadiaOrderType::class:
271                return $checkValueIsEnum(\ltrim($type, '\\'), $value);
272            case 'boolean':
273                return \is_bool(\is_int($value) ? (bool)$value : $value);
274            case 'array':
275                return \is_array($value);
276            case 'string':
277                return \is_string($value);
278            case 'integer':
279                return \is_int($value);
280        }
281        throw new \ErrorException(\sprintf("Unhandled $type for %s", \json_encode($value)));
282    }
283
284    /**
285     * Get the type of any of this class property
286     * from doc comment
287     *
288     * @param string $property
289     * @return string|null the type or null if not defined
290     * @throws \ErrorException If the property has no comment to read.
291     * @throws \ErrorException If a type for a property could ne be recognized.
292     * @throws \ReflectionException If the class or property does not exist.
293     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
294     */
295    protected function getPropType(string $property)
296    {
297        $matches        = [];
298        $propReflection = new \ReflectionProperty(static::class, $property);
299        $docComment     = $propReflection->getDocComment();
300        if (!$docComment) {
301            throw new \ErrorException(\sprintf("%s $property has not comment to parse.", \get_class($this)));
302        }
303        preg_match_all('/@var ([\w_\x5c]+)/', $docComment, $matches);
304        if (
305            isset($matches[1][0]) and \in_array($matches[1][0], [
306                'string', 'integer', 'boolean', 'array', '\\' . Country::class, '\\' . ArcadiaOrderType::class,
307                '\\' . QuestionType::class
308            ], true)
309        ) {
310            return $matches[1][0];
311        }
312        throw new \ErrorException("Unknown type for property $property");
313    }
314
315    /**
316     * Assert primaryKey is valid.
317     *
318     * @param mixed $primaryKey
319     * @return void
320     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a primary key is not a valid integer.
321     */
322    protected static function assertValidPrimaryKey(mixed $primaryKey): void
323    {
324        $validator = Utils::makeValidator(
325            ['id' => $primaryKey],
326            ['id' => 'required|int']
327        );
328        if ($validator()) {
329            throw new ValidationException(implode(' ', $validator->errors()->get('id')));
330        }
331    }
332
333    /**
334     * Assert hashcode is valid.
335     *
336     * @param mixed $hashcode
337     * @return void
338     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a hashcode is not a valid UUID.
339     */
340    protected static function assertValidHascode(mixed $hashcode): void
341    {
342        $validator = Utils::makeValidator(
343            ['hashcode' => $hashcode],
344            ['hashcode' => 'required|uuid']
345        );
346        if ($validator()) {
347            throw new ValidationException(implode(' ', $validator->errors()->get('hashcode')));
348        }
349    }
350}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Models/Customer.php.html b/tests/coverage/client/src/Models/Customer.php.html deleted file mode 100644 index cf848c6..0000000 --- a/tests/coverage/client/src/Models/Customer.php.html +++ /dev/null @@ -1,1099 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Models/Customer.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 94.07% covered (success) -
-
-
94.07%
111 / 118
-
- 66.67% covered (warning) -
-
-
66.67%
10 / 15
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Customer
-
- 94.07% covered (success) -
-
-
94.07%
111 / 118
-
- 66.67% covered (warning) -
-
-
66.67%
10 / 15
36.27
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 __get
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 __set
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 fill
-
- 75.00% covered (warning) -
-
-
75.00%
6 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6.56
 validateAllValues
-
- 71.43% covered (warning) -
-
-
71.43%
5 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.21
 find
-
- 92.31% covered (success) -
-
-
92.31%
12 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.00
 findWithEmail
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 save
-
- 92.86% covered (success) -
-
-
92.86%
13 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5.01
 store
-
- 100.00% covered (success) -
-
-
100.00%
9 / 9
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 update
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 delete
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 activate
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 toggleOptin
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 login
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 jsonSerialize
-
- 100.00% covered (success) -
-
-
100.00%
16 / 16
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Models;
4
5use LDC\LDCCRM\Enums\ApiError;
6use LDC\LDCCRM\Enums\ApiStatus;
7use LDC\LDCCRM\Enums\Country;
8use LDC\LDCCRM\Exceptions\ApiErrorException;
9use LDC\LDCCRM\Utils;
10use TypeError;
11
12/**
13 * This class represents the customer info with
14 * the account validation status. You can use it as
15 * a standalone class but beware of catching exceptions
16 *
17 * Be warned that on server side data is normalized
18 * - firstname and lastname are 'capitalized'
19 * - fields are trimmed
20 * - non numeric chars are removed from postcode
21 *
22 * @property string|null $hashcode The crm hashcode this is a readonly field
23 * @property string|null $email Must be a rfc valid email on a valid domain name
24 * @property string|null $password Required only on create, must have upper and lowers chars,
25 * at least 1 number, at leat 1 upper char, at least 1 lower char and
26 * at leat 1 special char
27 * @property string|null $firstname The account first name
28 * @property string|null $lastname The account last name
29 * @property string|null $birth_date The account birth date 'yyyy-mm-dd'
30 * @property string|null $phone The account phone
31 * @property string|null $address The account address (street number, name, build, flat number)
32 * @property string|null $address2 The account phone (address complement)
33 * @property string|null $city The account city name
34 * @property string|null $postcode The account city postcode
35 * @property \LDC\LDCCRM\Enums\Country $country The account country residence
36 * @property boolean $opt_in true if the account is opt in
37 * @property boolean $status true if the account is activated
38 * @property string|null $last_connection the last time user was connected 'yyyy-mm-dd HH:ii:ss'
39 *
40 * @example examples/CustomerExample.php
41 *
42 * @category Api Models
43 * @package LDCCrmClient
44 * @subpackage models
45 * @author Jérémy Munsch <jeremy.munsch@ldc.fr>
46 */
47class Customer extends ClientModel
48{
49    /**
50     * The user hashcode, this is link with the customer and the brand it is related to
51     * It is used to identify the customer itself.
52     *
53     * Validate: UUID, in customer_infos
54     *
55     * Required
56     * Min length 36
57     * Max length 36
58     * Field Type varchar
59     *
60     * @var string|null
61     */
62    private ?string $hashcode = null;
63
64    /**
65     * An RFC Valid Email
66     *
67     * Validate: rfc,dns,spoof,filter
68     *
69     * Required
70     * Min length N/A
71     * Max length 255
72     * Field Type varchar
73     *
74     * @var string|null
75     */
76    private ?string $email = null;
77
78    /**
79     * The user password
80     * This is set only when creating a user
81     * Otherwise it has to be set to null
82     *
83     * Validate: case_diff,numbers,letters,symbols,min:8
84     *
85     * Min length 8
86     * Max length 255
87     * Field Type varchar
88     *
89     * @var string|null
90     */
91    private ?string $password = null;
92
93    /**
94     * First name
95     *
96     * Required
97     * Min length 2
98     * Max length 255
99     * Field Type varchar
100     *
101     * @var string|null
102     */
103    private ?string $firstname = null;
104
105    /**
106     * Last name
107     *
108     * Required
109     * Min length 2
110     * Max length 255
111     * Field Type varchar
112     *
113     * @var string|null
114     */
115    private ?string $lastname = null;
116
117    /**
118     * Birth date
119     *
120     * Validate: date_format:Y-m-d
121     *
122     * Required
123     * Field Type Date
124     *
125     * @var string|null
126     */
127    private ?string $birth_date = null;
128
129    /**
130     * The user phone
131     *
132     * Validate: sometimes,string
133     *
134     * Required
135     * Min length NA
136     * Max length 255
137     * Field Type varchar
138     *
139     * @var string|null
140     */
141    private ?string $phone = null;
142
143    /**
144     * The user address (street number, name, etc)
145     *
146     * Validate: sometimes,string
147     *
148     * Min length NA
149     * Max length 255
150     * Field Type varchar
151     *
152     * @var string|null
153     */
154    private ?string $address = null;
155
156    /**
157     * The user address 2nd part (street number, name, more, etc)
158     *
159     * Validate: sometimes,string
160     *
161     * Min length NA
162     * Max length 255
163     * Field Type varchar
164     *
165     * @var string|null
166     */
167    private ?string $address2 = null;
168
169    /**
170     * The user address city
171     *
172     * Validate: sometimes,string
173     *
174     * Min length NA
175     * Max length 255
176     * Field Type varchar
177     *
178     * @var string|null
179     */
180    private ?string $city = null;
181
182    /**
183     * The user address postcode
184     *
185     * Validate: string
186     *
187     * Required
188     * Min length NA
189     * Max length 255
190     * Field Type varchar
191     *
192     * @var string|null
193     */
194    private ?string $postcode = null;
195
196    /**
197     * The user address postcode
198     *
199     * Validate: sometimes, in Country::toValues()
200     *
201     * Required
202     * Field Type tinyInt
203     *
204     * @var \LDC\LDCCRM\Enums\Country
205     */
206    private ?int $country = null;
207
208    /**
209     * The user optin choice
210     *
211     * Validate: boolean
212     *
213     * Required
214     * Field Type TinyInt
215     *
216     * @var boolean
217     */
218    private bool $opt_in = false;
219
220    /**
221     * Is the account activated ?
222     *
223     * This field is read only
224     *
225     * @var boolean
226     */
227    private bool $status = false;
228
229    /**
230     * The last time the account was connected
231     *
232     * This field is read only
233     *
234     * @var string|null
235     */
236    private ?string $last_connection = null;
237
238    /**
239     * The crm customer fields
240     *
241     * @var array
242     */
243    protected array $modelFields = [
244        'hashcode',
245        'email',
246        'firstname',
247        'password',
248        'lastname',
249        'birth_date',
250        'phone',
251        'address',
252        'address2',
253        'city',
254        'postcode',
255        'country',
256        'opt_in',
257        'status',
258        'last_connection',
259    ];
260
261    /**
262     * The crm customer fields
263     * the should not be visible
264     *
265     * @var array
266     */
267    protected array $invisibleFields = [
268        'password',
269    ];
270
271    /**
272     * Validation rules
273     *
274     * @var array
275     */
276    protected static array $validation = [
277        'hashcode'        => 'required|uuid',
278        'email'           => 'required|email',
279        'firstname'       => 'required|string|min:1|max:255',
280        'lastname'        => 'required|string|min:1|max:255',
281        'password'        => 'required|min:8|max:255|mixedCase|containDigit|containSymbol',
282        'birth_date'      => 'required|date_format:Y-m-d',
283        'phone'           => 'sometimes|nullable|string|max:255',
284        'address'         => 'sometimes|string|max:255',
285        'address2'        => 'sometimes|string|max:255',
286        'city'            => 'sometimes|string|min:2|max:255',
287        'postcode'        => 'sometimes|string|max:255',
288        'country'         => ['sometimes'],
289        'opt_in'          => 'required|bool',
290        'status'          => 'required|bool',
291        'last_connection' => 'sometimes|date',
292    ];
293
294    /**
295     * Customer
296     *
297     * @param array $properties
298     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
299     */
300    public function __construct(#[\SensitiveParameter] array $properties = [])
301    {
302        parent::__construct();
303        $this->fill($properties);
304        return $this;
305    }
306
307    /**
308     * Generic accessor
309     *
310     * @param string $field
311     * @return mixed|null Returns null if the property was not found any way.
312     */
313    public function __get(string $field)
314    {
315        $props = \array_diff(
316            $this->modelFields,
317            $this->invisibleFields
318        );
319        if (in_array($field, $props)) {
320            if ($field === 'country' and !\is_object($this->{$field})) {
321                return Country::make($this->{$field});
322            }
323        }
324        return parent::__get($field);
325    }
326
327    /**
328     * Set prop on the model.
329     *
330     * @param string $field
331     * @param mixed  $value
332     * @return void
333     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
334     * @throws \LDC\LDCCRM\Exceptions\AccessError If trying to set a value on a unknown property.
335     */
336    public function __set(string $field, #[\SensitiveParameter] mixed $value): void
337    {
338        if ($field === 'country') {
339            $value = (\is_object($value) and
340                get_class($value) === Country::class) ? $value->value() : $value;
341        }
342        parent::__set($field, $value);
343    }
344
345    /**
346     * Fill values into model using validation rules.
347     *
348     * @param array $properties
349     * @return void
350     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
351     */
352    public function fill(#[\SensitiveParameter] array $properties)
353    {
354        if (isset($properties['country'])) {
355            try {
356                $properties['country'] = (\is_object($properties['country']) and
357                    get_class($properties['country']) === Country::class) ?
358                    $properties['country']->value : (ctype_digit($properties['country']) ?
359                        (int)$properties['country'] : $properties['country']);
360            } catch (TypeError | \BadMethodCallException $e) {
361                // * Cast anyway
362                $properties['country'] = (int)$properties['country'];
363            }
364        }
365        parent::fill($properties);
366    }
367
368    /**
369     * Validate all model properties
370     *
371     * @param array $ignore
372     * @return array the validated values
373     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
374     */
375    protected function validateAllValues(array $ignore = []): array
376    {
377        $out = [];
378        if (!\in_array('country', $ignore)) {
379            try {
380                $this->validateValue('country', Country::make(Utils::getRawProperty($this, 'country')));
381            } catch (\TypeError | \BadMethodCallException $e) {
382                // Use this to throw validation error.
383                $this->validateValue('country', Utils::getRawProperty($this, 'country'));
384            }
385            $out['country'] = Utils::getRawProperty($this, 'country');
386        }
387        return array_merge($out, parent::validateAllValues(array_merge(['country'], $ignore)));
388    }
389
390    // * PUBLIC METHODS
391
392    /**
393     * Find a customer using its hashcode in the crm
394     *
395     * @param string $hashcode
396     * @return self|null Return null if the customer was not found
397     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
398     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
399     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
400     */
401    public static function find(#[\SensitiveParameter] string $hashcode): ?self
402    {
403        static::setUpApiInterface();
404        $request  = Utils::getResquest('apiV4.customers.show', [
405            'serviceCustomer' => $hashcode
406        ]);
407        $customer = null;
408        try {
409            $response = static::$apiInterface->call($request);
410            $customer = new self();
411            // ! Use fillRaw here because we cant validate comming
412            // ! from CRM since it has crappy data comming from the old crm (jellix).
413            $customer->fillRaw($response->data);
414            Utils::setRawProperty($customer, 'isNew', false);
415        } catch (ApiErrorException $e) {
416            if (!$e->getApiError()->equals(ApiError::modelNotFound)) {
417                throw $e;
418            }
419        }
420        return $customer;
421    }
422
423    /**
424     * Find a customer using its email in the crm
425     * This is an alias of Customer::find()
426     *
427     * @param string $email
428     * @return self|null
429     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
430     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
431     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
432     */
433    public static function findWithEmail(#[\SensitiveParameter] string $email): ?self
434    {
435        return static::find($email);
436    }
437
438    /**
439     * Save the customer on CRM.
440     *
441     * @return boolean True if save was successfull.
442     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
443     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
444     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
445     * Possibles are : - validationFailed, If provided data is wrong(CRM side).
446     *                 - modelNotFound, If this customer hashcode could not be found (new customers only).
447     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
448     */
449    public function save(): bool
450    {
451        $saved = false;
452        if ($this->isNew) {
453            $saved               = $this->store();
454            $this->isNew         = !$saved;
455            $this->updatedValues = [];
456            if ($saved) {
457                Utils::setRawProperty($this, 'password', null);
458            }
459            return $saved;
460        } else {
461            if (empty($this->updatedValues)) {
462                return true;
463            }
464            if ($saved = $this->update()) {
465                $this->updatedValues = [];
466                Utils::setRawProperty($this, 'password', null);
467            }
468        }
469        return $saved;
470    }
471
472    /**
473     * Calls api store customer method
474     *
475     * @return boolean True if save was successfull.
476     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
477     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
478     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
479     * Possibles are : - validationFailed, If provided data is wrong(CRM side).
480     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
481     */
482    private function store(): bool
483    {
484        $data             = $this->validateAllValues(['hashcode', 'last_connection', 'status']);
485        $data['password'] = $this->password;
486
487        static::setUpApiInterface();
488        $request = Utils::getResquest('apiV4.customers.store', [], $data);
489
490        $response = static::$apiInterface->call($request);
491        if ($status = $response->status->equals(ApiStatus::OK)) {
492            $this->updatedValues = [];
493            $this->fill($response->data);
494        }
495        return $status;
496    }
497
498    /**
499     * Calls api update customer method
500     *
501     * @return boolean True if save was successfull.
502     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
503     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
504     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
505     * Possibles are : - validationFailed, If provided data is wrong(CRM side).
506     *                 - modelNotFound, If this customer hashcode could not be found.
507     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
508     */
509    private function update(): bool
510    {
511        $this->validateValue('hashcode', $this->hashcode);
512        static::setUpApiInterface();
513        $request = Utils::getResquest('apiV4.customers.update', [
514            'serviceCustomer' => $this->hashcode
515        ], $this->updatedValues);
516
517        $response = static::$apiInterface->call($request);
518        if ($status = $response->status->equals(ApiStatus::OK)) {
519            $this->updatedValues = [];
520            $this->fill($response->data);
521        }
522        return $status;
523    }
524
525    /**
526     * Removes the customer from CRM.
527     *
528     * @return boolean true if succeeded
529     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
530     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
531     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
532     * Possibles are : - modelNotFound, If this customer hashcode could not be found.
533     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
534     */
535    public function delete(): bool
536    {
537        $this->validateValue('hashcode', $this->hashcode);
538        static::setUpApiInterface();
539        $request = Utils::getResquest('apiV4.customers.destroy', [
540            'serviceCustomer' => $this->hashcode
541        ]);
542
543        $response = static::$apiInterface->call($request);
544        return $response->status->equals(ApiStatus::OK);
545    }
546
547    /**
548     * Active the customer on CRM.
549     *
550     * @return boolean true if succeeded
551     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a customer's hashcode could not be validated.
552     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
553     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
554     * Possibles are : - modelNotFound, If this customer hashcode could not be found.
555     *                 - customerAlreadyActive, It the customer is already activated.
556     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
557     */
558    public function activate(): bool
559    {
560        $this->validateValue('hashcode', $this->hashcode);
561        static::setUpApiInterface();
562        $request = Utils::getResquest('apiV4.customers.activate', [
563            'serviceCustomer' => $this->hashcode
564        ]);
565
566        $response = static::$apiInterface->call($request);
567        $this->__set('status', true);
568        return $response->status->equals(ApiStatus::OK);
569    }
570
571    /**
572     * Toggle the account optin value in the crm
573     *
574     * @return boolean true if succeeded
575     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
576     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
577     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
578     * Possibles are : - modelNotFound, If this customer hashcode could not be found.
579     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
580     */
581    public function toggleOptin(): bool
582    {
583        $this->__set('opt_in', !$this->opt_in);
584        return $this->update();
585    }
586
587    /**
588     * Test customer credentials
589     *
590     * @param string $email
591     * @param string $password
592     * @return boolean
593     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a customer's email could not be validated.
594     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
595     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
596     * Possibles are : - authFailed, If credentials are not valid.
597     *                 - customerNotActivated, If the account is not activated.
598     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
599     */
600    public static function login(#[\SensitiveParameter] string $email, #[\SensitiveParameter] string $password): bool
601    {
602        self::validateValue('email', $email);
603        static::setUpApiInterface();
604        $request  = Utils::getResquest('apiV4.customers.authenticate', [], [
605            'email' => $email,
606            'password' => $password
607        ]);
608        $response = static::$apiInterface->call($request);
609        return $response->status->equals(ApiStatus::OK);
610    }
611
612    /**
613     * Serialize this object to an array
614     *
615     * @return array
616     */
617    public function jsonSerialize()
618    {
619        return [
620            'hashcode'        => $this->hashcode,
621            'email'           => $this->email,
622            'firstname'       => $this->firstname,
623            'lastname'        => $this->lastname,
624            'birth_date'      => $this->birth_date,
625            'phone'           => $this->phone,
626            'address'         => $this->address,
627            'address2'        => $this->address2,
628            'city'            => $this->city,
629            'postcode'        => $this->postcode,
630            'country'         => $this->country,
631            'opt_in'          => $this->opt_in,
632            'status'          => $this->status,
633            'last_connection' => $this->last_connection
634        ];
635    }
636}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Models/Question.php.html b/tests/coverage/client/src/Models/Question.php.html deleted file mode 100644 index 3beb7ee..0000000 --- a/tests/coverage/client/src/Models/Question.php.html +++ /dev/null @@ -1,641 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Models/Question.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 84.34% covered (warning) -
-
-
84.34%
70 / 83
-
- 66.67% covered (warning) -
-
-
66.67%
6 / 9
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Question
-
- 84.34% covered (warning) -
-
-
84.34%
70 / 83
-
- 66.67% covered (warning) -
-
-
66.67%
6 / 9
27.40
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 __get
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
4
 __set
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 fill
-
- 75.00% covered (warning) -
-
-
75.00%
6 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6.56
 validateAllValues
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 all
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 allWithCustomerAnswers
-
- 100.00% covered (success) -
-
-
100.00%
21 / 21
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 unansweredBy
-
- 100.00% covered (success) -
-
-
100.00%
15 / 15
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 jsonSerialize
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Models;
4
5use LDC\LDCCRM\Enums\QuestionType;
6use LDC\LDCCRM\Utils;
7
8/**
9 * This class represents a question
10 * It has some static methods to retrieve questions and answers
11 *
12 * @property string $id The question id
13 * @property string|null $question The actual question as a string
14 * @property \LDC\LDCCRM\Enums\QuestionType|null $type
15 * The question type to display,
16 * it also hints wether it can accept one or multiple responses,
17 * so only checkbox allows multiple responses
18 * @property \LDC\LDCCRM\Models\Answer[] $answers An array with answers
19 *
20 * @category Api Models
21 * @package LDCCrmClient
22 * @subpackage models
23 * @author Jérémy Munsch <jeremy.munsch@ldc.fr>
24 */
25class Question extends ClientModel
26{
27    /**
28     * The question id
29     *
30     * Required
31     * Field Type bigInt
32     *
33     * @var integer
34     */
35    private int $id;
36
37    /**
38     * The actual question as a string
39     *
40     * Required
41     * Max length 255
42     * Field Type varchar
43     *
44     * @var string|null
45     */
46    private ?string $question = null;
47
48    /**
49     * The question type
50     *
51     * Validate: in QuestionType::toValues()
52     *
53     * Required
54     * Field Type tinyInteger
55     *
56     * @var \LDC\LDCCRM\Enums\QuestionType|null
57     */
58    private ?int $type = null;
59
60    /**
61     * The question answers
62     *
63     * \LDC\LDCCRM\Models\Answer
64     *
65     * @var array
66     */
67    private array $answers = [];
68
69    /**
70     * The crm customer fields
71     *
72     * @var array
73     */
74    protected array $modelFields = [
75        'id',
76        'question',
77        'type',
78        'answers',
79    ];
80
81    /**
82     * Validation rules
83     *
84     * @var array
85     */
86    protected static array $validation = [
87        'id'       => 'required|int',
88        'question' => 'required|string|max:255',
89        'type'     => ['required'],
90        'answers'  => 'required|array'
91    ];
92
93    /**
94     * Question
95     *
96     * @param array $properties
97     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
98     */
99    public function __construct(array $properties = [])
100    {
101        parent::__construct();
102        $this->fill($properties);
103        return $this;
104    }
105
106    /**
107     * General accessor
108     *
109     * @param string $field
110     * @return mixed
111     */
112    public function __get(string $field)
113    {
114        $props = \array_diff(
115            $this->modelFields,
116            $this->invisibleFields
117        );
118        if (in_array($field, $props)) {
119            if ($field === 'type' and !\is_object($this->{$field})) {
120                return QuestionType::make($this->{$field});
121            }
122        }
123        return parent::__get($field);
124    }
125
126    /**
127     * Set prop on the model.
128     *
129     * @param string $field
130     * @param mixed  $value
131     * @return void
132     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
133     * @throws \LDC\LDCCRM\Exceptions\AccessError If trying to set a value on a unknown property.
134     */
135    public function __set(string $field, mixed $value): void
136    {
137        if ($field === 'type') {
138            $value = (\is_object($value) and
139                get_class($value) === QuestionType::class) ? $value->value() : $value;
140        }
141        parent::__set($field, $value);
142    }
143
144    /**
145     * Fill values into model using validation rules.
146     *
147     * @param array $properties
148     * @return void
149     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
150     */
151    public function fill(array $properties)
152    {
153        if (isset($properties['type'])) {
154            try {
155                $properties['type'] = (\is_object($properties['type']) and
156                    get_class($properties['type']) === QuestionType::class) ?
157                    $properties['type']->value : (ctype_digit($properties['type']) ?
158                        (int)$properties['type'] : $properties['type']);
159            } catch (\TypeError | \BadMethodCallException) {
160                // * Cast anyway
161                $properties['type'] = (int)$properties['type'];
162            }
163        }
164        parent::fill($properties);
165    }
166
167    /**
168     * Validate all model properties
169     *
170     * @param array $ignore
171     * @return array the validated values
172     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
173     */
174    protected function validateAllValues(array $ignore = []): array
175    {
176        $out = [];
177        if (!\in_array('type', $ignore)) {
178            try {
179                $this->validateValue('type', QuestionType::make(Utils::getRawProperty($this, 'type')));
180            } catch (\TypeError | \BadMethodCallException) {
181                // Use this to throw validation error.
182                $this->validateValue('type', Utils::getRawProperty($this, 'type'));
183            }
184            $out['type'] = Utils::getRawProperty($this, 'type');
185        }
186        return array_merge($out, parent::validateAllValues(array_merge(['type'], $ignore)));
187    }
188
189    // * PUBLIC METHODS
190
191    /**
192     * Get all questions only
193     *
194     * @return array of \LDC\LDCCRM\Models\Question
195     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
196     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
197     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
198     */
199    public static function all(): array
200    {
201        static::setUpApiInterface();
202        $request = Utils::getResquest('apiV4.questions.index');
203
204        $response = static::$apiInterface->call($request);
205        $out      = [];
206        foreach ($response->data as $question) {
207            $answers             = \array_map(function ($answer) {
208                return new Answer($answer);
209            }, $question['answers']);
210            $question['answers'] = $answers;
211            $out[]               = new self($question);
212        }
213        return $out;
214    }
215
216    /**
217     * Get all the questions with customer answers
218     *
219     * @param \LDC\LDCCRM\Models\Customer $customer
220     * @return array
221     *
222     *   [
223     *        0 => [
224     *             'question' => \LDC\LDCCRM\Models\Question,
225     *             'customerAnswers' => \LDC\LDCCRM\Models\Answer[]
226     *        ]
227     *   ]
228     *
229     * with \LDC\LDCCRM\Models\Question[]
230     * and the customer \LDC\LDCCRM\Models\Answer[]
231     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a customer's hashcode could not be validated.
232     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
233     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
234     * Possibles are : - modelNotFound, If the customer could not be found(CRM side).
235     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
236     */
237    public static function allWithCustomerAnswers(Customer $customer): array
238    {
239        self::assertValidHascode($customer->hashcode);
240        static::setUpApiInterface();
241        $request = Utils::getResquest('apiV4.questions.indexWithResponse', [
242            'serviceCustomer' => $customer->hashcode
243        ]);
244
245        $response = static::$apiInterface->call($request);
246        $out      = [];
247        foreach ($response->data as $question) {
248            $answers         = \array_map(function ($answer) {
249                return new Answer($answer);
250            }, $question['answers']);
251            $customerAnswers = \array_map(function ($answer) {
252                return new Answer($answer);
253            }, $question['customerAnswers']);
254            unset($question['customerAnswers']);
255            $question['answers'] = $answers;
256            $out[]               = [
257                'question' => new self($question),
258                'customerAnswers' => $customerAnswers,
259            ];
260        }
261        return $out;
262    }
263
264    /**
265     * Get unanswered question for a specific customer
266     *
267     * @param \LDC\LDCCRM\Models\Customer $customer
268     * @return array of \LDC\LDCCRM\Models\Question
269     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a customer's hashcode could not be validated.
270     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
271     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
272     * Possibles are : - modelNotFound, If the customer could not be found(CRM side).
273     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
274     */
275    public static function unansweredBy(Customer $customer): array
276    {
277        self::assertValidHascode($customer->hashcode);
278        static::setUpApiInterface();
279        $request = Utils::getResquest(
280            'apiV4.questions.unAnsweredBy',
281            ['serviceCustomer' => $customer->hashcode]
282        );
283
284        $response = static::$apiInterface->call($request);
285        $out      = [];
286        foreach ($response->data as $question) {
287            $answers             = \array_map(function ($answer) {
288                return new Answer($answer);
289            }, $question['answers']);
290            $question['answers'] = $answers;
291            $out[]               = new self($question);
292        }
293        return $out;
294    }
295
296    /**
297     * Serialize this object to an array
298     *
299     * @return array
300     */
301    public function jsonSerialize()
302    {
303        return [
304            'id'       => $this->id,
305            'question' => $this->question,
306            'type'     => $this->type,
307            'answers'  => $this->answers
308        ];
309    }
310}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Models/SingleOptin.php.html b/tests/coverage/client/src/Models/SingleOptin.php.html deleted file mode 100644 index fd3ade9..0000000 --- a/tests/coverage/client/src/Models/SingleOptin.php.html +++ /dev/null @@ -1,251 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Models/SingleOptin.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
15 / 15
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
SingleOptin
-
- 100.00% covered (success) -
-
-
100.00%
15 / 15
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 setStatus
-
- 100.00% covered (success) -
-
-
100.00%
8 / 8
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 unsetStatusWithHashcode
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Models;
4
5use LDC\LDCCRM\Enums\ApiStatus;
6use LDC\LDCCRM\Utils;
7
8/**
9 * This class allows to handle single opt in
10 *
11 * @category Api Models
12 * @package LDCCrmClient
13 * @subpackage models
14 * @author Jérémy Munsch <jeremy.munsch@ldc.fr>
15 */
16abstract class SingleOptin extends ClientModel
17{
18    /**
19     * Validation rules
20     *
21     * @var array
22     */
23    protected static array $validation = [
24        'email'    => 'required|email',
25        'hashcode' => 'required|string|size:36',
26        'opt_in'   => 'required|bool',
27    ];
28
29    /**
30     * Set the single opt in status for an email
31     *
32     * @param string  $email
33     * @param boolean $opt_in
34     * @return boolean true if succeeded
35     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field email could not be validated.
36     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
37     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
38     * Possibles are : - singleOptinCustomerExists, If a customer exists with this email.
39     */
40    public static function setStatus(#[\SensitiveParameter] string $email, bool $opt_in): bool
41    {
42        self::validateValue('email', $email);
43        static::setUpApiInterface();
44        $request = Utils::getResquest('apiV4.optin', [], [
45            'email' => $email,
46            'opt_in' => $opt_in
47        ]);
48
49        $response = static::$apiInterface->call($request);
50        return $response->status->equals(ApiStatus::OK);
51    }
52
53    /**
54     * Unset the single opt in for a hashcode (unsubscribe)
55     *
56     * @param string $hashcode
57     * @return boolean true if succeeded
58     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field hashcode could not be validated.
59     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
60     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
61     * Possibles are : - singleOptinCustomerExists, If a customer exists with this email.
62     */
63    public static function unsetStatusWithHashcode(string $hashcode): bool
64    {
65        self::validateValue('hashcode', $hashcode);
66        static::setUpApiInterface();
67        $request = Utils::getResquest('apiV4.optout-hashcode', [], [
68            'hashcode' => $hashcode
69        ]);
70
71        $response = static::$apiInterface->call($request);
72        return $response->status->equals(ApiStatus::OK);
73    }
74}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Models/Stats.php.html b/tests/coverage/client/src/Models/Stats.php.html deleted file mode 100644 index 0c428aa..0000000 --- a/tests/coverage/client/src/Models/Stats.php.html +++ /dev/null @@ -1,264 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Models/Stats.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 100.00% covered (success) -
-
-
100.00%
21 / 21
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
CRAP
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
Stats
-
- 100.00% covered (success) -
-
-
100.00%
21 / 21
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
 getBrandStats
-
- 100.00% covered (success) -
-
-
100.00%
9 / 9
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 getQuestionStats
-
- 100.00% covered (success) -
-
-
100.00%
12 / 12
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Models;
4
5use LDC\LDCCRM\Utils;
6
7/**
8 * This class is used to get stats from CRM
9 *
10 * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If an error occurs
11 * @throws \LDC\LDCCRM\Exceptions\CrmException If the CRM encounters an error
12 *
13 * @category Api Models
14 * @package LDCCrmClient
15 * @subpackage models
16 * @author Jérémy Munsch <jeremy.munsch@ldc.fr>
17 */
18abstract class Stats extends ClientModel
19{
20    /**
21     * Validation rules
22     *
23     * @var array
24     */
25    protected static array $validation = [
26        'question.id' => 'required|int|min:1',
27        'start'       => 'required|date_format:Y-m-d',
28        'end'         => 'required|date_format:Y-m-d'
29    ];
30
31    /**
32     * Get brand stats ordered by ascendent days
33     *
34     * @param string $start Une date valide au format Y-m-d .
35     * @param string $end   Une date valide au format Y-m-d .
36     * @return array The stats array by day
37     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field start could not be validated.
38     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field end could not be validated.
39     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
40     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
41     * Possibles are : - validationFailed, If provided data is wrong(CRM side).
42     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
43     */
44    public static function getBrandStats(string $start, string $end): array
45    {
46        self::validateValue('start', $start);
47        self::validateValue('end', $end);
48        static::setUpApiInterface();
49        $request  = Utils::getResquest('apiV4.stats.brandStats', [], [
50            'start' => $start,
51            'end' => $end
52        ]);
53        $response = static::$apiInterface->call($request);
54        return $response->data['stats'];
55    }
56
57    /**
58     * Get brand stats ordered by ascendent days
59     *
60     * @param \LDC\LDCCRM\Models\Question $question Une question CRM possèdant un id réel.
61     * @param string                      $start    Une date valide au format Y-m-d .
62     * @param string                      $end      Une date valide au format Y-m-d .
63     * @return array The stats array by day
64     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a question's id could not be validated.
65     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field start could not be validated.
66     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field end could not be validated.
67     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
68     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
69     * Possibles are : - validationFailed, If provided data is wrong(CRM side).
70     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
71     */
72    public static function getQuestionStats(Question $question, string $start, string $end): array
73    {
74        self::validateValue('question.id', $question->id);
75        self::validateValue('start', $start);
76        self::validateValue('end', $end);
77        static::setUpApiInterface();
78        $request  = Utils::getResquest('apiV4.stats.questionStats', [
79            'serviceQuestion' => $question->id,
80        ], [
81            'start' => $start,
82            'end' => $end
83        ]);
84        $response = static::$apiInterface->call($request);
85        return $response->data;
86    }
87}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Models/dashboard.html b/tests/coverage/client/src/Models/dashboard.html deleted file mode 100644 index 63ec5a4..0000000 --- a/tests/coverage/client/src/Models/dashboard.html +++ /dev/null @@ -1,323 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/client/src/Models - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

- -
-
-

Project Risks

- -
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodCoverage
findWithEmail0%
__set0%
validateAllValues0%
fill25%
fillRaw30%
fill47%
__set50%
validateAllValues71%
fill75%
fill75%
fill75%
validateAllValues80%
getPropType83%
assertValidPrimaryKey83%
assertValidHascode83%
validateValue87%
-
-
-
-

Project Risks

- -
-
- -
- - - - - - diff --git a/tests/coverage/client/src/Models/index.html b/tests/coverage/client/src/Models/index.html deleted file mode 100644 index 16e381e..0000000 --- a/tests/coverage/client/src/Models/index.html +++ /dev/null @@ -1,317 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Models - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 88.17% covered (warning) -
-
-
88.17%
410 / 465
-
- 63.64% covered (warning) -
-
-
63.64%
35 / 55
-
- 25.00% covered (danger) -
-
-
25.00%
2 / 8
Answer.php
-
- 96.15% covered (success) -
-
-
96.15%
25 / 26
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ArcadiaMailDefault.php
-
- 93.33% covered (success) -
-
-
93.33%
56 / 60
-
- 71.43% covered (warning) -
-
-
71.43%
5 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ArcadiaMailGame.php
-
- 80.49% covered (warning) -
-
-
80.49%
33 / 41
-
- 60.00% covered (warning) -
-
-
60.00%
3 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ClientModel.php
-
- 78.22% covered (warning) -
-
-
78.22%
79 / 101
-
- 41.67% covered (danger) -
-
-
41.67%
5 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Customer.php
-
- 94.07% covered (success) -
-
-
94.07%
111 / 118
-
- 66.67% covered (warning) -
-
-
66.67%
10 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Question.php
-
- 84.34% covered (warning) -
-
-
84.34%
70 / 83
-
- 66.67% covered (warning) -
-
-
66.67%
6 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
SingleOptin.php
-
- 100.00% covered (success) -
-
-
100.00%
15 / 15
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
Stats.php
-
- 100.00% covered (success) -
-
-
100.00%
21 / 21
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- -
- - diff --git a/tests/coverage/client/src/Traits/BaseEnum.php.html b/tests/coverage/client/src/Traits/BaseEnum.php.html deleted file mode 100644 index 8ba2943..0000000 --- a/tests/coverage/client/src/Traits/BaseEnum.php.html +++ /dev/null @@ -1,720 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Traits/BaseEnum.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 54.43% covered (warning) -
-
-
54.43%
43 / 79
-
- 40.00% covered (danger) -
-
-
40.00%
6 / 15
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BaseEnum
-
- 54.43% covered (warning) -
-
-
54.43%
43 / 79
-
- 40.00% covered (danger) -
-
-
40.00%
6 / 15
158.64
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 value
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 label
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 name
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 toLabels
-
- 90.91% covered (success) -
-
-
90.91%
10 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5.02
 toValues
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 all
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 toArray
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 make
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 equals
-
- 75.00% covered (warning) -
-
-
75.00%
6 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5.39
 jsonSerialize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getCache
-
- 75.00% covered (warning) -
-
-
75.00%
3 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.06
 setCache
-
- 75.00% covered (warning) -
-
-
75.00%
3 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.06
 initCache
-
- 100.00% covered (success) -
-
-
100.00%
9 / 9
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 getLabelsConstant
-
- 60.00% covered (warning) -
-
-
60.00%
3 / 5
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.26
 getCustomDefinitions
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Traits;
4
5use Illuminate\Support\Str;
6
7trait BaseEnum
8{
9    // * GENERIC METHODS
10    /**
11     * Get enum value.
12     *
13     * @return string|integer
14     */
15    public function value(): string|int
16    {
17        return self::toValues()[$this->name];
18    }
19
20    /**
21     * Get enum label.
22     *
23     * @return string
24     */
25    public function label(): string
26    {
27        return self::toLabels()[$this->name];
28    }
29
30    /**
31     * Get enum name.
32     *
33     * @return string
34     */
35    public function name(): string
36    {
37        return $this->name;
38    }
39
40    // * STATIC FETCH METHODS
41
42    /**
43     * Get enum labels.
44     *
45     * @return array<string>
46     */
47    public static function toLabels(): array
48    {
49        if (empty(self::getCache('labels'))) {
50            $labels = self::getLabelsConstant();
51            self::setCache('labels', \collect(self::cases())
52                ->mapWithKeys(function ($enum) use ($labels) {
53                    if (!\is_null($labels) and !isset($labels[$enum->name])) {
54                        throw new \Error('Missing definition label ' . self::class . " for {$enum->name}");
55                    }
56                    return [$enum->name => \trans(
57                        !\is_null($labels) ? $labels[$enum->name] : Str::ucfirst($enum->name)
58                    )];
59                })->all());
60        }
61        return self::getCache('labels');
62    }
63
64    /**
65     * Get enum values.
66     *
67     * @return array<integer|string>
68     */
69    public static function toValues(): array
70    {
71        if (empty(self::getCache('values'))) {
72            self::setCache('values', \collect(self::cases())
73                ->mapWithKeys(fn ($enum) => [$enum->name => $enum->value])->all());
74        }
75        return self::getCache('values');
76    }
77
78    /**
79     * Get enums.
80     *
81     * @return array
82     */
83    public static function all(): array
84    {
85        return self::cases();
86    }
87
88    /**
89     * Get enums.
90     *
91     * @return array
92     */
93    public static function toArray(): array
94    {
95        if (empty(self::getCache('enums'))) {
96            $definitions = self::getCustomDefinitions();
97            self::setCache('enums', \collect(self::cases())
98                ->mapWithKeys(function ($enum) use ($definitions) {
99                    $baseArray = [
100                        'name' => $enum->name,
101                        'label' => $enum->label(),
102                        'value' => $enum->value,
103                    ];
104                    foreach ($definitions as $index => $elements) {
105                        $index = Str::lower(Str::singular($index));
106                        if (!isset($elements[$enum->name])) {
107                            throw new \Error("Missing definition {$index} " . self::class . " for {$enum->name}");
108                        }
109                        $baseArray[$index] = $elements[$enum->name];
110                    }
111                    return [$enum->name => (object)$baseArray];
112                })->all());
113        }
114        return self::getCache('enums');
115    }
116
117    /**
118     * Fetch enum using value.
119     *
120     * @param \LDC\LDCCRM\Traits\BaseEnum|integer|string $value
121     * @param string                                     $field
122     * @return \LDC\LDCCRM\Traits\BaseEnum|null
123     */
124    public static function make(self|int|string $value, string $field = 'value'): self|null
125    {
126        return !\is_object($value) ?
127            \collect(self::cases())->keyBy($field)->get($value) : $value;
128    }
129
130    /**
131     * Test if 2 enum are equals.
132     *
133     * @param object ...$others
134     * @return boolean
135     * @throws \Error If provided element are not enums taht extends BaseEnum.
136     */
137    public function equals(object ...$others): bool
138    {
139        foreach ($others as $other) {
140            if (!\in_array(BaseEnum::class, \class_uses_recursive($other))) {
141                throw new \Error(__METHOD__ .
142                    ' requires $enum to use ' . BaseEnum::class);
143            }
144            if (
145                get_class($this) === get_class($other)
146                && $this->value === $other->value
147            ) {
148                return true;
149            }
150        }
151        return false;
152    }
153
154    /**
155     * Serialize to json.
156     *
157     * @return mixed
158     */
159    public function jsonSerialize(): mixed
160    {
161        return $this->value;
162    }
163
164
165    // * CACHE
166
167    /**
168     * Get cache array.
169     *
170     * @param string $index
171     * @return array
172     */
173    private static function getCache(string $index): array
174    {
175        self::initCache();
176        if (!isset($GLOBALS[self::class]['props'][$index])) {
177            $GLOBALS[self::class]['props'][$index] = [];
178        }
179        return $GLOBALS[self::class]['props'][$index];
180    }
181
182    /**
183     * Set cache array.
184     *
185     * @param string $index
186     * @param array  $items
187     * @return void
188     */
189    private static function setCache(string $index, array $items): void
190    {
191        self::initCache();
192        if (!isset($GLOBALS[self::class]['props'][$index])) {
193            $GLOBALS[self::class]['props'][$index] = [];
194        }
195        $GLOBALS[self::class]['props'][$index] = $items;
196    }
197
198    /**
199     * Init cache if needed.
200     *
201     * @return void
202     */
203    private static function initCache(): void
204    {
205        if (!isset($GLOBALS[self::class])) {
206            $GLOBALS[self::class] = [
207                'props' => [
208                    'enums' => [],
209                    'values' => [],
210                    'labels' => []
211                ],
212                'customProps' => null
213            ];
214        }
215    }
216
217    // * PRIVATE
218
219    /**
220     * Fetch the LABELS constant if exists.
221     *
222     * @return array|null
223     */
224    private static function getLabelsConstant(): array|null
225    {
226        $class_name = self::class;
227        try {
228            $constant_reflex = new \ReflectionClassConstant($class_name, 'LABELS');
229            return $constant_reflex->getValue();
230        } catch (\ReflectionException $e) {
231            return null;
232        }
233    }
234
235    /**
236     * Get custom constants.
237     *
238     * @return array
239     */
240    private static function getCustomDefinitions(): array
241    {
242        // ? Has custom props in cache ?
243        if (!isset($GLOBALS[self::class]) or \is_null($GLOBALS[self::class]['customProps'])) {
244            $names = \collect(self::cases())->keyBy('name');
245
246            $GLOBALS[self::class]['customProps'] = \collect((new \ReflectionClass(self::class))->getConstants())
247                ->filter(function (mixed $constant, string $key) use ($names) {
248                    if ($key === 'LABELS' or !\is_array($constant)) {
249                        return false;
250                    }
251                    return \collect($constant)->keys()
252                        ->filter(fn (string $name) => $names->has($name))->count();
253                })->all();
254        }
255        return $GLOBALS[self::class]['customProps'];
256    }
257}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Traits/dashboard.html b/tests/coverage/client/src/Traits/dashboard.html deleted file mode 100644 index 1de11d3..0000000 --- a/tests/coverage/client/src/Traits/dashboard.html +++ /dev/null @@ -1,302 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/client/src/Traits - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - -
ClassCoverage
LDC\LDCCRM\Traits\BaseEnum54%
-
-
-
-

Project Risks

-
- - - - - - - - - - - -
ClassCRAP
LDC\LDCCRM\Traits\BaseEnum158
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - - -
MethodCoverage
all0%
toArray0%
jsonSerialize0%
getCustomDefinitions0%
getLabelsConstant60%
equals75%
getCache75%
setCache75%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - - -
MethodCRAP
getCustomDefinitions30
toArray20
equals5
getLabelsConstant2
getCache2
setCache2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/client/src/Traits/index.html b/tests/coverage/client/src/Traits/index.html deleted file mode 100644 index 70b4cbc..0000000 --- a/tests/coverage/client/src/Traits/index.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Traits - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 54.43% covered (warning) -
-
-
54.43%
43 / 79
-
- 40.00% covered (danger) -
-
-
40.00%
6 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
BaseEnum.php
-
- 54.43% covered (warning) -
-
-
54.43%
43 / 79
-
- 40.00% covered (danger) -
-
-
40.00%
6 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/client/src/Transport/ApiInterface.php.html b/tests/coverage/client/src/Transport/ApiInterface.php.html deleted file mode 100644 index 029a19a..0000000 --- a/tests/coverage/client/src/Transport/ApiInterface.php.html +++ /dev/null @@ -1,540 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Transport/ApiInterface.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 84.27% covered (warning) -
-
-
84.27%
75 / 89
-
- 42.86% covered (danger) -
-
-
42.86%
3 / 7
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
ApiInterface
-
- 84.27% covered (warning) -
-
-
84.27%
75 / 89
-
- 42.86% covered (danger) -
-
-
42.86%
3 / 7
21.56
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 61.54% covered (warning) -
-
-
61.54%
8 / 13
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6.42
 call
-
- 83.33% covered (warning) -
-
-
83.33%
5 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.04
 processRequest
-
- 100.00% covered (success) -
-
-
100.00%
11 / 11
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 setHeaders
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 setCredentials
-
- 28.57% covered (danger) -
-
-
28.57%
2 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.46
 setTimestamp
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 calulateSignature
-
- 93.02% covered (success) -
-
-
93.02%
40 / 43
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6.01
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Transport;
4
5use LDC\LDCCRM\Enums\ApiStatus;
6use LDC\LDCCRM\Exceptions\ApiErrorException;
7use LDC\LDCCRM\Exceptions\CrmException;
8use LDC\LDCCRM\Utils;
9
10/**
11 * @ignore
12 *
13 * This class contains static api credentials
14 * It handles a request to get a response
15 *
16 * @package LDCCrmClient
17 * @subpackage transport
18 */
19class ApiInterface
20{
21    /**
22     * The api endpoint url
23     * This is the CRM FQDN
24     *
25     * @var string
26     */
27    protected static string $endpoint;
28
29    /**
30     * The bearer token
31     * This is related to a specific brand which allows
32     * the crm to identify the concerned brand
33     *
34     * @var string
35     */
36    protected static string $bearerToken;
37
38    /**
39     * The bearer token password
40     *
41     * @var string
42     */
43    protected static string $bearerPwd;
44
45    /**
46     * HTTP AUTH string
47     *
48     * @var string|null
49     */
50    protected static ?string $authentification = null;
51
52    /**
53     * ApiInterface
54     *
55     * @param string|null $endpoint    The crm endpoint.
56     * @param string|null $bearerToken The crm service token.
57     * @param string|null $bearerPwd   The crm service password.
58     *
59     * @throws \LDC\LDCCRM\Exceptions\CrmException If crm.token, crm.password or
60     * crm.endpoint is missing on .env file or in laravel config.
61     */
62    public function __construct(
63        #[\SensitiveParameter] string $endpoint = null,
64        #[\SensitiveParameter] string $bearerToken = null,
65        #[\SensitiveParameter] string $bearerPwd = null
66    ) {
67        $endpoint    = self::$endpoint ?? $endpoint ?? Utils::getConfig('crm.endpoint');
68        $bearerToken = self::$bearerToken ?? $bearerToken ?? Utils::getConfig('crm.token');
69        $bearerPwd   = self::$bearerPwd ?? $bearerPwd ?? Utils::getConfig('crm.password');
70
71        if (!$bearerToken or !$bearerPwd or !$endpoint) {
72            throw new CrmException(
73                'Config need to have the token var set (crm.token, crm.password, crm.endpoint)'
74            );
75        }
76
77        self::$endpoint    = $endpoint;
78        self::$bearerToken = $bearerToken;
79        self::$bearerPwd   = $bearerPwd;
80
81        // Handle HTTP Auth .
82        if (\strpos(self::$endpoint, '@')) {
83            $vars                   = \parse_url(self::$endpoint);
84            self::$authentification = \base64_encode($vars['user'] . ':' . $vars['pass']);
85        }
86    }
87
88    /**
89     * Make a Flucollector http call to get a reponse
90     *
91     * @param \LDC\LDCCRM\Transport\Request $request
92     * @return \LDC\LDCCRM\Transport\Response
93     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side
94     *                                                              or on getting response.
95     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
96     */
97    public function call(Request $request): Response
98    {
99        $response = $this->processRequest($request);
100
101        // * Handle response Status.
102        if ($response->status->equals(ApiStatus::KO)) {
103            if (\is_int($response->apiError)) {
104                throw new CrmException($response->message, $response->apiError);
105            } else {
106                throw new ApiErrorException($response->apiError, $response->httpCode, $response->message);
107            }
108        }
109        return $response;
110    }
111
112    /**
113     * Process request
114     *
115     * @param Request $request
116     * @return \LDC\LDCCRM\Transport\Response
117     */
118    private function processRequest(Request $request): Response
119    {
120        $this->setCredentials($request);
121        $this->setHeaders($request);
122        $this->setTimestamp($request);
123        $request->setEndpoint(self::$endpoint);
124        $request->addData([
125            'signature' => $this->calulateSignature($request)
126        ]);
127
128        /** @var \Psr\Http\Message\ResponseInterface $response */
129        $response = $request->call();
130        $status   = in_array($response->getStatusCode(), [200, 201]) ?
131            ApiStatus::OK : ApiStatus::KO;
132
133        return new Response($status, $response);
134    }
135
136    /**
137     * Add spécific headers to he request
138     *
139     * @param \LDC\LDCCRM\Transport\Request $request
140     * @return void
141     */
142    private function setHeaders(Request &$request): void
143    {
144        $headers = [
145            'User-Agent'   => sprintf('LDC CRM client version %s', Utils::getPackageInfo()['version']),
146            'Accept'       => 'application/json',
147            'Content-Type' => 'application/json'
148        ];
149        $request->addHeaders($headers);
150    }
151
152    /**
153     * Inject bearer credentials into the request
154     *
155     * @param \LDC\LDCCRM\Transport\Request $request
156     * @return void
157     */
158    protected function setCredentials(Request $request)
159    {
160        if (self::$authentification) {
161            $request->addHeaders([
162                'Authorization' => implode(',', [
163                    sprintf('Basic %s', self::$authentification)
164                ])
165            ]);
166        }
167        $request->addData(['bearer_token' => self::$bearerToken]);
168    }
169
170    /**
171     * Add a timestamp (UTC) to the request
172     *
173     * @param Request $request
174     * @return void
175     */
176    protected function setTimestamp(Request $request): void
177    {
178        $request->addData([
179            // ! UTC date time.
180            'timestamp' => \gmdate('Y-m-d H:i:s')
181        ]);
182    }
183
184    /**
185     * Calculates request signature
186     *
187     * @param Request $request
188     * @return string
189     * @throws \LDC\LDCCRM\Exceptions\CrmException In case of failure.
190     */
191    protected function calulateSignature(Request $request): string
192    {
193        $uri        = \parse_url(sprintf('%s/%s', self::$endpoint, $request->uri));
194        $method     = \strtolower($request->method->name);
195        $parameters = $request->data;
196
197        // * Merge query in url with Data
198        $q     = $uri['query'] ?? '';
199        $q     = array_filter(explode('&', $q), fn ($el) => !empty($el));
200        $query = [];
201        foreach ($q as $qParam) {
202            $qParam            = explode('=', $qParam, 2);
203            $query[$qParam[0]] = $qParam[1];
204        }
205        $parameters = array_merge($query, $parameters);
206
207        $signature = [
208            'uri' => sprintf(
209                '%s://%s%s',
210                // Assume https if non provided, security first.
211                $uri['scheme'] ?? 'https',
212                $uri['host'],
213                $uri['path'] ?? '',
214            ),
215            'method' => $method
216        ];
217
218        $flattenRequestArray = function (array $array) use (&$flattenRequestArray) {
219            $out = [];
220            foreach ($array as $key => $value) {
221                if (is_array($value)) {
222                    $subArray = $flattenRequestArray($value);
223                    foreach ($subArray as $subKey => $subValue) {
224                        $out["$key.$subKey"] = $subValue;
225                    }
226                    continue;
227                }
228                $out[$key] = $value;
229            }
230            return $out;
231        };
232
233        $parameters = $flattenRequestArray($parameters);
234
235        // ! Natural sort by keys.
236        if (!uksort($parameters, "strnatcmp")) {
237            throw new CrmException('Natural sorting the request parameters failed.');
238        }
239
240        $parameters = \array_map(function ($key, $value) {
241            return sprintf('%s=%s', \rawurlencode($key), \rawurlencode($value));
242        }, \array_keys($parameters), $parameters);
243
244        $signature[] = \implode('&', $parameters);
245
246        return base64_encode(hash_hmac(
247            'sha256',
248            \implode('\n', $signature),
249            self::$bearerPwd,
250            true
251        ));
252    }
253}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Transport/Request.php.html b/tests/coverage/client/src/Transport/Request.php.html deleted file mode 100644 index 5e009f9..0000000 --- a/tests/coverage/client/src/Transport/Request.php.html +++ /dev/null @@ -1,494 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Transport/Request.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 93.48% covered (success) -
-
-
93.48%
43 / 46
-
- 71.43% covered (warning) -
-
-
71.43%
5 / 7
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Request
-
- 93.48% covered (success) -
-
-
93.48%
43 / 46
-
- 71.43% covered (warning) -
-
-
71.43%
5 / 7
12.04
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 100.00% covered (success) -
-
-
100.00%
12 / 12
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 __get
-
- 66.67% covered (warning) -
-
-
66.67%
2 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.15
 makeRequest
-
- 90.91% covered (success) -
-
-
90.91%
20 / 22
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5.02
 setEndpoint
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 call
-
- 100.00% covered (success) -
-
-
100.00%
6 / 6
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 addHeaders
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 addData
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Transport;
4
5use GuzzleHttp\Client;
6use GuzzleHttp\Psr7\Request as Psr7Request;
7use GuzzleHttp\Psr7\Utils as Psr7Utils;
8use GuzzleHttp\RequestOptions;
9use GuzzleHttp\Utils as GuzzleHttpUtils;
10use LDC\LDCCRM\Enums\HttpMethods;
11use LDC\LDCCRM\Utils;
12use Psr\Http\Message\ResponseInterface;
13
14/**
15 * The UWIL Flucollector request
16 * Contains the http method, the requested url and data to pass
17 *
18 * @property \LDC\LDCCRM\Enums\HttpMethods $method readonly method
19 * @property string $uri readonly uri
20 * @property array $headers headers
21 * @property array $data readonly data
22 *
23 * @package LDCCrmClient
24 * @subpackage transport
25 */
26class Request
27{
28    /**
29     * GuzzleHttp client
30     *
31     * @var \GuzzleHttp\Client
32     */
33    private Client $client;
34
35    /**
36     * The http method
37     *
38     * @var \LDC\LDCCRM\Enums\HttpMethods
39     */
40    protected HttpMethods $method;
41
42    /**
43     * The http url
44     *
45     * @var string
46     */
47    protected string $uri;
48
49    /**
50     * Data to pass to the http headers
51     *
52     * @var array
53     */
54    protected array $headers = [];
55
56    /**
57     * Data to pass to the http body
58     *
59     * @var array
60     */
61    protected array $data = [];
62
63    /**
64     * Guzzle request
65     *
66     * @var callable the returns \GuzzleHttp\Psr7\Request
67     */
68    private \Closure $request;
69
70    /**
71     * The Api endpoint
72     *
73     * @var string
74     */
75    private string $endpoint;
76
77    /**
78     * Request
79     *
80     * @param \LDC\LDCCRM\Enums\HttpMethods $method
81     * @param string                        $uri
82     * @param array                         $headers
83     * @param array                         $data
84     */
85    public function __construct(
86        HttpMethods $method,
87        string $uri,
88        array $headers = [],
89        #[\SensitiveParameter] array $data = []
90    ) {
91        $this->method  = $method;
92        $this->uri     = $uri;
93        $this->data    = $data;
94        $this->headers = $headers;
95        $this->client  = new Client([
96            RequestOptions::HEADERS => [
97                'User-Agent' => sprintf(
98                    'LDC CRM Client v%s',
99                    Utils::getPackageInfo()['version']
100                )
101            ]
102        ]);
103    }
104
105    /**
106     * Generic accessor
107     *
108     * @param string $field
109     * @return mixed|null
110     */
111    public function __get(string $field)
112    {
113        if (\in_array($field, ['method', 'uri', 'data'])) {
114            return $this->{$field};
115        }
116        return null;
117    }
118
119    /**
120     * make the guzzle request
121     *
122     * @return void
123     */
124    private function makeRequest(): void
125    {
126        $this->request = function () {
127            $uri = $this->uri;
128            // * If query merge query and data, set data to empty.
129            if ($this->method->equals(HttpMethods::get)) {
130                // * Merge query in url with Data
131                $q     = \parse_url($uri, \PHP_URL_QUERY) ?? '';
132                $q     = \strpos($q, '&') !== false ? explode('&', $q) : ($q ? [$q] : []);
133                $query = [];
134                foreach ($q as $qParam) {
135                    $qParam = explode('=', $qParam, 2);
136
137                    $query[$qParam[0]] = $qParam[1];
138                }
139                // * Remove query part.
140                $uri = strtok($uri, '?');
141                // * Append build query
142                $uri = sprintf("%s?%s", $uri, http_build_query(array_merge($query, $this->data)));
143
144                $this->data = [];
145            }
146            $request = new Psr7Request(
147                \strtoupper($this->method->name()),
148                sprintf('%s/%s', $this->endpoint, $uri),
149                $this->headers
150            );
151            $request = Psr7Utils::modifyRequest($request, [
152                'body' => GuzzleHttpUtils::jsonEncode($this->data)
153            ]);
154            return $request;
155        };
156    }
157
158    /**
159     * Set the api endpoint to the request
160     *
161     * @param string $endpoint
162     * @return void
163     */
164    public function setEndpoint(string $endpoint): void
165    {
166        $this->endpoint = $endpoint;
167    }
168
169    /**
170     * Make the Http request
171     *
172     * @return ResponseInterface
173     */
174    public function call(): ResponseInterface
175    {
176        $this->makeRequest();
177        /** @var \GuzzleHttp\Psr7\Request */
178        $request = ($this->request)();
179        return $this->client->send($request, [
180            // ! Do not throw HTTP Exceptions.
181            'http_errors' => false,
182            'allow_redirects' => false
183        ]);
184    }
185
186    /**
187     * Add headers to the request
188     *
189     * @param array $headers
190     * @return void
191     */
192    public function addHeaders(#[\SensitiveParameter] array $headers)
193    {
194        $this->headers = \array_merge($this->headers, $headers);
195    }
196
197    /**
198     * Add data to the request
199     *
200     * @param array $data
201     * @return void
202     */
203    public function addData(#[\SensitiveParameter] array $data)
204    {
205        $this->data = \array_merge($this->data, $data);
206    }
207}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Transport/Response.php.html b/tests/coverage/client/src/Transport/Response.php.html deleted file mode 100644 index 3d0a82d..0000000 --- a/tests/coverage/client/src/Transport/Response.php.html +++ /dev/null @@ -1,430 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Transport/Response.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 68.63% covered (warning) -
-
-
68.63%
35 / 51
-
- 25.00% covered (danger) -
-
-
25.00%
1 / 4
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Response
-
- 68.63% covered (warning) -
-
-
68.63%
35 / 51
-
- 25.00% covered (danger) -
-
-
25.00%
1 / 4
25.92
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 84.00% covered (warning) -
-
-
84.00%
21 / 25
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
8.26
 __get
-
- 87.50% covered (warning) -
-
-
87.50%
7 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
4.03
 tryDecodeJson
-
- 100.00% covered (success) -
-
-
100.00%
2 / 2
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 checkVersion
-
- 31.25% covered (danger) -
-
-
31.25%
5 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
5.92
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM\Transport;
4
5use LDC\LDCCRM\Enums\ApiError;
6use LDC\LDCCRM\Enums\ApiStatus;
7use LDC\LDCCRM\Enums\LogLevel;
8use LDC\LDCCRM\Exceptions\CrmException;
9use LDC\LDCCRM\Utils;
10use Psr\Http\Message\ResponseInterface;
11use Psr\Http\Message\StreamInterface;
12use RecursiveArrayIterator;
13use RecursiveIteratorIterator;
14
15/**
16 * @property \LDC\LDCCRM\Enums\ApiStatus $status The response api status
17 * @property \LDC\LDCCRM\Enums\ApiError $apiError The api error status it there is any
18 * @property int $httpCode The http response code
19 * @property string $message The api message
20 * @property array $headers The http reponse headers
21 * @property array $content The http response content, this is parsed json
22 * @property ?array $data The reponse data
23 *
24 * @package LDCCrmClient
25 * @subpackage transport
26 */
27class Response
28{
29    /**
30     * The response status
31     *
32     * @var \LDC\LDCCRM\Enums\ApiStatus
33     */
34    private ApiStatus $status;
35
36    /**
37     * The api error
38     *
39     * @var \LDC\LDCCRM\Enums\ApiError
40     */
41    private ApiError $apiError;
42
43    /**
44     * The response http code
45     *
46     * @var integer
47     */
48    private int $httpCode = 0;
49
50    /**
51     * The response headers
52     *
53     * @var array<string,string[]>
54     */
55    private array $headers;
56
57    /**
58     * The response body
59     *
60     * @var \Psr\Http\Message\StreamInterface
61     */
62    private StreamInterface $body;
63
64    /**
65     * The response decoded content
66     *
67     * @var array
68     */
69    private array $content;
70
71    /**
72     * The interface message
73     *
74     * @var string
75     */
76    private string $message;
77
78    /**
79     * PSR response
80     *
81     * @var \Psr\Http\Message\ResponseInterface
82     */
83    private ResponseInterface $response;
84
85    /**
86     * Response
87     *
88     * @param \LDC\LDCCRM\Enums\ApiStatus         $status
89     * @param \Psr\Http\Message\ResponseInterface $response
90     * @throws \LDC\LDCCRM\Exceptions\CrmException If HTTP response body in not JSON.
91     */
92    public function __construct(ApiStatus $status, ResponseInterface $response)
93    {
94        $this->response = $response;
95        $this->status   = $status;
96        $this->httpCode = $response->getStatusCode();
97        $this->headers  = $response->getHeaders();
98        $this->body     = $response->getBody();
99
100        if (!in_array($response->getStatusCode(), [200, 201])) {
101            $this->message = $response->getReasonPhrase();
102        }
103
104
105        // * Body should be json data.
106        if (($decodedJson = $this->tryDecodeJson($this->body->getContents())) === false) {
107            if (Utils::getConfig('app.env') === 'testing') {
108                dump((string)$this->body);
109            }
110            throw new CrmException('The Api should have returned JSON data');
111        }
112        $this->content = $decodedJson;
113
114        // * If Api Error.
115        if ($this->status->equals(ApiStatus::KO)) {
116            // * If CRM Exception or Any Exception.
117            if ($this->httpCode === 500) {
118                $this->apiError = $this->content['data']['code'];
119            } else {
120                // * From here it should be an ApiErrorException.
121                $this->apiError = ApiError::make($this->content['data']['code']);
122                $this->message  = $this->content['data']['message'];
123                if ($this->apiError->equals(ApiError::validationFailed)) {
124                    $errors = new RecursiveIteratorIterator(
125                        new RecursiveArrayIterator($this->content['data']['errors'])
126                    );
127                    foreach ($errors as $error) {
128                        $this->message = "$this->message $error";
129                    }
130                }
131            }
132        }
133
134        $this->checkVersion($this->content['version']);
135
136        return $this;
137    }
138
139    /**
140     * Generic accessor
141     *
142     * @param string $field
143     * @return mixed|null
144     */
145    public function __get(string $field)
146    {
147        if (
148            \in_array($field, [
149                'status', 'httpCode', 'headers',
150                'content', 'message', 'response', 'apiError'
151            ])
152        ) {
153            return $this->{$field};
154        }
155        if ($field === 'data' and isset($this->content[$field])) {
156            return $this->content[$field];
157        }
158        return null;
159    }
160
161    /**
162     * Try to decode json and return false if it is
163     * not a valid json
164     *
165     * @param string $string
166     * @return array|false Returns an associative data array or false if failed to parse.
167     */
168    private function tryDecodeJson(string $string)
169    {
170        /** @var array|null */
171        $data = json_decode($string, true);
172        return (json_last_error() == JSON_ERROR_NONE) ? $data : false;
173    }
174
175    /**
176     * This checks if the Flucollector version is way far beyond the client version.
177     * If a minor version mismatch is detected we will log this as a warning.
178     * If a major version mismatch is detected we will throw a AppilcationException as
179     * there shall be an incompatibility with the response.
180     *
181     * The goal here is to force clients to be up to date.
182     * A major version change means breaking change.
183     *
184     * @param string $version
185     * @return void
186     * @throws \LDC\LDCCRM\Exceptions\CrmException If a major version mismatch is detected.
187     */
188    private function checkVersion(string $version)
189    {
190        $packageInfo  = Utils::getPackageInfo();
191        $ApackageInfo = explode('.', $packageInfo['version']);
192        $Aversion     = \explode('.', $version);
193        if ($ApackageInfo[0] != $Aversion[0]) {
194            throw new CrmException(sprintf(
195                'Incompatible major versions between CRM server %s and client %s',
196                $version,
197                $packageInfo['version']
198            ));
199        }
200        if ($ApackageInfo[1] != $Aversion[1]) {
201            $message = sprintf(
202                'Minor version mismatch between CRM server %s and client %s, this could lead to errors',
203                $version,
204                $packageInfo['version']
205            );
206            Utils::log($message, LogLevel::WARNING);
207        }
208    }
209}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/Transport/dashboard.html b/tests/coverage/client/src/Transport/dashboard.html deleted file mode 100644 index fcb48f2..0000000 --- a/tests/coverage/client/src/Transport/dashboard.html +++ /dev/null @@ -1,304 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/client/src/Transport - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - -
ClassCoverage
LDC\LDCCRM\Transport\Response68%
LDC\LDCCRM\Transport\ApiInterface84%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - -
ClassCRAP
LDC\LDCCRM\Transport\Response25
LDC\LDCCRM\Transport\ApiInterface21
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - -
MethodCoverage
setCredentials28%
checkVersion31%
__construct61%
__get66%
call83%
__construct84%
__get87%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - - - -
MethodCRAP
__construct8
__construct6
checkVersion5
__get4
setCredentials3
call3
__get2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/client/src/Transport/index.html b/tests/coverage/client/src/Transport/index.html deleted file mode 100644 index a34758a..0000000 --- a/tests/coverage/client/src/Transport/index.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Transport - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 82.26% covered (warning) -
-
-
82.26%
153 / 186
-
- 50.00% covered (danger) -
-
-
50.00%
9 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
ApiInterface.php
-
- 84.27% covered (warning) -
-
-
84.27%
75 / 89
-
- 42.86% covered (danger) -
-
-
42.86%
3 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Request.php
-
- 93.48% covered (success) -
-
-
93.48%
43 / 46
-
- 71.43% covered (warning) -
-
-
71.43%
5 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Response.php
-
- 68.63% covered (warning) -
-
-
68.63%
35 / 51
-
- 25.00% covered (danger) -
-
-
25.00%
1 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/client/src/Utils.php.html b/tests/coverage/client/src/Utils.php.html deleted file mode 100644 index f9ddc35..0000000 --- a/tests/coverage/client/src/Utils.php.html +++ /dev/null @@ -1,1462 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/Utils.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 86.88% covered (warning) -
-
-
86.88%
278 / 320
-
- 66.67% covered (warning) -
-
-
66.67%
18 / 27
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Utils
-
- 86.88% covered (warning) -
-
-
86.88%
278 / 320
-
- 66.67% covered (warning) -
-
-
66.67%
18 / 27
90.41
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 makeValidator
-
- 100.00% covered (success) -
-
-
100.00%
13 / 13
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
7
 makeValidatorFromRule
-
- 97.06% covered (success) -
-
-
97.06%
33 / 34
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
10
 validationRequired
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 validationNullable
-
- 100.00% covered (success) -
-
-
100.00%
12 / 12
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 validationSometimes
-
- 100.00% covered (success) -
-
-
100.00%
12 / 12
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 validationInt
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 validationString
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 validationBool
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
 validationSize
-
- 92.86% covered (success) -
-
-
92.86%
13 / 14
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.00
 validationMin
-
- 93.75% covered (success) -
-
-
93.75%
15 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.00
 validationMax
-
- 93.75% covered (success) -
-
-
93.75%
15 / 16
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
3.00
 validationUuid
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 validationMixedCase
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 validationContainDigit
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 validationContainSymbol
-
- 100.00% covered (success) -
-
-
100.00%
10 / 10
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 validationDate
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 validationDateFormat
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 validationEmail
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 validationArray
-
- 100.00% covered (success) -
-
-
100.00%
7 / 7
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
1
 validationClosure
-
- 90.00% covered (success) -
-
-
90.00%
9 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
1.00
 getConfig
-
- 100.00% covered (success) -
-
-
100.00%
4 / 4
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 getResquest
-
- 89.66% covered (warning) -
-
-
89.66%
26 / 29
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
9.09
 getPackageInfo
-
- 100.00% covered (success) -
-
-
100.00%
3 / 3
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
2
 translate
-
- 100.00% covered (success) -
-
-
100.00%
5 / 5
-
- 100.00% covered (success) -
-
-
100.00%
1 / 1
3
 log
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 29
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
110
 setRawProperty
-
- 66.67% covered (warning) -
-
-
66.67%
6 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
4.59
 getRawProperty
-
- 66.67% covered (warning) -
-
-
66.67%
4 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2.15
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3namespace LDC\LDCCRM;
4
5use LDC\LDCCRM\Enums\HttpMethods;
6use LDC\LDCCRM\Enums\LogLevel;
7use LDC\LDCCRM\Exceptions\AccessError;
8use LDC\LDCCRM\Exceptions\SkipValidationException;
9use LDC\LDCCRM\Exceptions\ValidationException;
10use LDC\LDCCRM\Transport\Request;
11use Respect\Validation\Validator;
12use Illuminate\Support\Str;
13
14/**
15 * This is the LDCCRM utility class
16 *
17 * @category Utility
18 * @uses \LDC\LDCCRM\Enums\HttpMethods
19 * @uses \LDC\LDCCRM\Transport\Request
20 *
21 * @package LDCCrmClient
22 * @subpackage utilities
23 */
24class Utils
25{
26    /**
27     * Package infos
28     *
29     * @var array
30     */
31    private static array $packageInfos;
32
33    /**
34     * Loaded translations
35     *
36     * @var array
37     */
38    private static array $translations = [];
39
40    /**
41     * Create a new Validator instance.
42     *
43     * @param array $data
44     * @param array $rules
45     * @return closure
46     * @throws \ErrorException If an unknown validation rule is used.
47     */
48    public static function makeValidator(
49        #[\SensitiveParameter] array $data,
50        array $rules
51    ): object {
52        foreach ($rules as $attribute => $attrRules) {
53            $validators = [];
54            if (\is_string($attrRules)) {
55                $attrRules = \explode('|', $attrRules);
56            }
57            foreach ($attrRules as $rule) {
58                $validators[] = self::makeValidatorFromRule($rule, $data, $attribute);
59            } //end foreach
60        } //end foreach
61        return function () use ($validators) {
62            foreach ($validators as $validator) {
63                try {
64                    if (!$validator['validate']()) {
65                        throw new ValidationException($validator['error']);
66                    }
67                } catch (SkipValidationException $e) {
68                    break;
69                }
70            }
71        };
72    }
73
74    /**
75     * Generate a validator
76     *
77     * @param mixed  $rule
78     * @param array  $data
79     * @param string $attribute
80     * @return array
81     * @throws \ErrorException If a rule is unknown.
82     */
83    private static function makeValidatorFromRule(
84        mixed $rule,
85        #[\SensitiveParameter] array $data,
86        string $attribute
87    ): array {
88        $rParams = [];
89        $closure = null;
90        if (\is_callable($rule) and !is_string($rule)) {
91            /** @var \Closure $closure */
92            $closure = $rule;
93            $rule    = '#closure#';
94        } elseif (\strpos($rule, ':') !== false) {
95            $rParams = \explode(':', $rule, 2);
96            $rule    = \array_shift($rParams);
97        }
98        switch (true) {
99            case in_array($rule, [
100                'nullable', 'sometimes',
101                'int', 'bool', 'uuid', 'string',
102                'date', 'email', 'array',
103                'mixedCase', 'containDigit', 'containSymbol',
104            ]):
105                return self::{sprintf('validation%s', \ucfirst($rule))}(
106                    $attribute,
107                    $data[$attribute] ?? null
108                );
109            case in_array($rule, ['size', 'min', 'max']):
110                return self::{sprintf('validation%s', \ucfirst($rule))}(
111                    $attribute,
112                    $data[$attribute],
113                    $rParams
114                );
115            case in_array($rule, ['required', 'sometimes']):
116                return self::{sprintf('validation%s', \ucfirst($rule))}(
117                    $attribute,
118                    $data,
119                );
120            case $rule === 'date_format':
121                return self::validationDateFormat($attribute, $data[$attribute], $rParams);
122            case $rule === '#closure#':
123                /** @var \Closure $rule */
124                return self::validationClosure($attribute, $data[$attribute], $closure);
125            default:
126                throw new \ErrorException("Unknown validation rule $rule " . implode(': ', $rParams));
127        } //end switch
128    }
129
130    // * VALIDATION RULES
131
132    /**
133     * Make Required validator
134     *
135     * @param string $attribute
136     * @param array  $data
137     * @return array
138     */
139    private static function validationRequired(string $attribute, #[\SensitiveParameter] array $data): array
140    {
141        return [
142            'type' => 'required',
143            'error' => sprintf(
144                '%s est obligatoire',
145                self::translate($attribute)
146            ),
147            'validate' => function () use ($attribute, $data) {
148                return isset($data[$attribute]);
149            }
150        ];
151    }
152
153    /**
154     * Make Nullable validator
155     *
156     * @param string $attribute
157     * @param mixed  $value
158     * @return array
159     */
160    private static function validationNullable(string $attribute, #[\SensitiveParameter] mixed $value): array
161    {
162        return [
163            'type' => 'nullable',
164            'error' => sprintf(
165                '%s peut être égale à nul',
166                self::translate($attribute)
167            ),
168            'validate' => function () use ($value) {
169                if (is_null($value)) {
170                    throw new SkipValidationException();
171                }
172                return true;
173            }
174        ];
175    }
176
177    /**
178     * Make Sometimes validator
179     *
180     * @param string $attribute
181     * @param mixed  $data
182     * @return array
183     */
184    private static function validationSometimes(string $attribute, #[\SensitiveParameter] mixed $data): array
185    {
186        return [
187            'type' => 'sometimes',
188            'error' => sprintf(
189                '%s est falcutatif',
190                self::translate($attribute)
191            ),
192            'validate' => function () use ($data) {
193                if (empty($data)) {
194                    throw new SkipValidationException();
195                }
196                return true;
197            }
198        ];
199    }
200
201    /**
202     * Make Int validator
203     *
204     * @param string $attribute
205     * @param mixed  $value
206     * @return array
207     */
208    private static function validationInt(string $attribute, #[\SensitiveParameter] mixed $value): array
209    {
210        return [
211            'type' => 'int',
212            'error' => sprintf(
213                '%s doit être un entier',
214                self::translate($attribute)
215            ),
216            'validate' => function () use ($value) {
217                return \is_int($value);
218            }
219        ];
220    }
221
222    /**
223     * Make String validator
224     *
225     * @param string $attribute
226     * @param mixed  $value
227     * @return array
228     */
229    private static function validationString(string $attribute, #[\SensitiveParameter] mixed $value): array
230    {
231        return [
232            'type' => 'string',
233            'error' => sprintf(
234                '%s doit être une chaine de charactères',
235                self::translate($attribute)
236            ),
237            'validate' => function () use ($value) {
238                return \is_string($value);
239            }
240        ];
241    }
242
243    /**
244     * Make Bool validator
245     *
246     * @param string $attribute
247     * @param mixed  $value
248     * @return array
249     */
250    private static function validationBool(string $attribute, #[\SensitiveParameter] mixed $value): array
251    {
252        return [
253            'type' => 'bool',
254            'error' => sprintf(
255                '%s doit être un booléen',
256                self::translate($attribute)
257            ),
258            'validate' => function () use ($value) {
259                return \is_bool($value) or $value === 1 or $value === 0;
260            }
261        ];
262    }
263
264    /**
265     * Make Size validator
266     *
267     * @param string $attribute
268     * @param mixed  $value
269     * @param array  $params
270     * @return array
271     */
272    private static function validationSize(string $attribute, #[\SensitiveParameter] mixed $value, array $params): array
273    {
274        return [
275            'type' => 'min',
276            'error' => sprintf(
277                '%s doit avoir %s caratères',
278                self::translate($attribute),
279                $params[0],
280                $params[0]
281            ),
282            'validate' => function () use ($value, $params) {
283                if (\is_string($value)) {
284                    return \strlen($value) === (int)$params[0];
285                }
286                return false;
287            }
288        ];
289    }
290
291    /**
292     * Make Min validator
293     *
294     * @param string $attribute
295     * @param mixed  $value
296     * @param array  $params
297     * @return array
298     */
299    private static function validationMin(string $attribute, #[\SensitiveParameter] mixed $value, array $params): array
300    {
301        return [
302            'type' => 'min',
303            'error' => sprintf(
304                '%s doit avoir au moins %s caratères, ou être plus grand que %s si c\'est un nombre',
305                self::translate($attribute),
306                $params[0],
307                $params[0]
308            ),
309            'validate' => function () use ($value, $params) {
310                if (\is_string($value)) {
311                    return \strlen($value) >= (int)$params[0];
312                }
313                if (\is_int($value)) {
314                    return $value >= (int)$params[0];
315                }
316                return false;
317            }
318        ];
319    }
320
321    /**
322     * Make Max validator
323     *
324     * @param string $attribute
325     * @param mixed  $value
326     * @param array  $params
327     * @return array
328     */
329    private static function validationMax(string $attribute, #[\SensitiveParameter] mixed $value, array $params): array
330    {
331        return [
332            'type' => 'max',
333            'error' => sprintf(
334                '%s doit avoir au moins %s caratères, ou être plus grand que %s si c\'est un nombre',
335                self::translate($attribute),
336                $params[0],
337                $params[0]
338            ),
339            'validate' => function () use ($value, $params) {
340                if (\is_string($value)) {
341                    return \strlen($value) <= (int)$params[0];
342                }
343                if (\is_int($value)) {
344                    return $value <= (int)$params[0];
345                }
346                return false;
347            }
348        ];
349    }
350
351    /**
352     * Make Uuid validator
353     *
354     * @param string $attribute
355     * @param mixed  $value
356     * @return array
357     */
358    private static function validationUuid(string $attribute, #[\SensitiveParameter] mixed $value): array
359    {
360        return [
361            'type' => 'uuid',
362            'error' => sprintf(
363                '%s doit être un uuid valide',
364                self::translate($attribute)
365            ),
366            'validate' => function () use ($value) {
367                return Validator::uuid()->validate($value);
368            }
369        ];
370    }
371
372    /**
373     * Make MixedCase validator
374     *
375     * @param string $attribute
376     * @param mixed  $value
377     * @return array
378     */
379    private static function validationMixedCase(string $attribute, #[\SensitiveParameter] mixed $value): array
380    {
381        return [
382            'type' => 'mixedCase',
383            'error' => sprintf(
384                '%s doit contenir des lettre minuscules et majuscules',
385                self::translate($attribute)
386            ),
387            'validate' => function () use ($value) {
388                return \preg_match('/[a-z]/', $value) and \preg_match('/[A-Z]/', $value);
389            }
390        ];
391    }
392
393    /**
394     * Make ContainDigit validator
395     *
396     * @param string $attribute
397     * @param mixed  $value
398     * @return array
399     */
400    private static function validationContainDigit(string $attribute, #[\SensitiveParameter] mixed $value): array
401    {
402        return [
403            'type' => 'containDigit',
404            'error' => sprintf(
405                '%s doit contenir au moins un chiffre',
406                self::translate($attribute)
407            ),
408            'validate' => function () use ($value) {
409                return \preg_match('/[0-9]/', $value);
410            }
411        ];
412    }
413
414    /**
415     * Make ContainSymbol validator
416     *
417     * @param string $attribute
418     * @param mixed  $value
419     * @return array
420     */
421    private static function validationContainSymbol(string $attribute, #[\SensitiveParameter] mixed $value): array
422    {
423        return [
424            'type' => 'containSymbol',
425            'error' => sprintf(
426                '%s doit contenir au moins un caractère spécial comme une virgule par exemple',
427                self::translate($attribute)
428            ),
429            'validate' => function () use ($value) {
430                return \preg_match('/[^a-zA-Z0-9]/', $value);
431            }
432        ];
433    }
434
435    /**
436     * Make Date validator
437     *
438     * @param string $attribute
439     * @param mixed  $value
440     * @return array
441     */
442    private static function validationDate(string $attribute, #[\SensitiveParameter] mixed $value): array
443    {
444        return [
445            'type' => 'date',
446            'error' => sprintf('%s doit être une date valide', self::translate($attribute)),
447            'validate' => function () use ($value) {
448                return Validator::dateTime()->validate($value);
449            }
450        ];
451    }
452
453    /**
454     * Make DateFormat validator
455     *
456     * @param string $attribute
457     * @param mixed  $value
458     * @param array  $params
459     * @return array
460     */
461    private static function validationDateFormat(
462        string $attribute,
463        #[\SensitiveParameter] mixed $value,
464        array $params
465    ): array {
466        return [
467            'type' => 'date_format',
468            'error' => sprintf('%s doit être une date au format %s', self::translate($attribute), $params[0]),
469            'validate' => function () use ($value, $params) {
470                return Validator::dateTime($params[0])->validate($value);
471            }
472        ];
473    }
474
475    /**
476     * Make Email validator
477     *
478     * @param string $attribute
479     * @param mixed  $value
480     * @return array
481     */
482    private static function validationEmail(string $attribute, #[\SensitiveParameter] mixed $value): array
483    {
484        return [
485            'type' => 'email',
486            'error' => sprintf('%s doit être un email valide', self::translate($attribute)),
487            'validate' => function () use ($value) {
488                return Validator::email()->validate($value);
489            }
490        ];
491    }
492
493    /**
494     * Make Array validator
495     *
496     * @param string $attribute
497     * @param mixed  $value
498     * @return array
499     */
500    private static function validationArray(string $attribute, #[\SensitiveParameter] mixed $value): array
501    {
502        return [
503            'type' => 'array',
504            'error' => sprintf('%s doit être un tableau valide', self::translate($attribute)),
505            'validate' => function () use ($value) {
506                return Validator::arrayType()->validate($value);
507            }
508        ];
509    }
510
511    /**
512     * Make Closure validator
513     *
514     * @param string   $attribute
515     * @param mixed    $value
516     * @param \Closure $closure
517     * @return array
518     */
519    private static function validationClosure(
520        string $attribute,
521        #[\SensitiveParameter] mixed $value,
522        \Closure $closure
523    ): array {
524        return [
525            'type' => 'closure',
526            'error' => sprintf('%s doit être validé', self::translate($attribute)),
527            'validate' => function () use ($attribute, $value, $closure) {
528                $closure($attribute, $value, function ($message) {
529                    throw new ValidationException($message);
530                });
531                return true;
532            }
533        ];
534    }
535
536    // * END VALIDATION RULES
537
538    /**
539     * This is only used for unit tests.
540     * Get config
541     *
542     * @param string $key
543     * @param string $default
544     * @return string|null
545     */
546    public static function getConfig(string $key, string $default = null): ?string
547    {
548        $value = null;
549        if (function_exists('config')) {
550            $value = \config($key, $default);
551        }
552
553        return $value;
554    }
555
556    /**
557     * Generate a Request from the route name
558     *
559     * @param string $routeName
560     * @param array  $query     Params to pass on to the route.
561     * @param array  $data      Http body params.
562     * @return \LDC\LDCCRM\Transport\Request
563     * @throws \ErrorException If the requested route is unknown.
564     * @throws \ErrorException If a required parameter is missing.
565     */
566    public static function getResquest(
567        string $routeName,
568        array $query = [],
569        #[\SensitiveParameter] array $data = []
570    ): Request {
571        // Convert bool to integer.
572        $query = \array_map(function ($v) {
573            return is_bool($v) ? (int)$v : $v;
574        }, $query);
575        $data  = \array_map(function ($v) {
576            return is_bool($v) ? (int)$v : $v;
577        }, $data);
578
579        $routes = \json_decode(\file_get_contents(__DIR__ . '/routes.json'), true);
580        if (!isset($routes[$routeName])) {
581            throw new \ErrorException("Unknown route $routeName from the crm");
582        }
583        $route        = $routes[$routeName];
584        $matches      = [];
585        $matchedIndex = [];
586        \preg_match_all('/{([\w-]*)}/', $route['uri'], $matches);
587        if (\count($matches[0])) {
588            foreach ($matches[0] as $k => $match) {
589                if (!isset($query[$matches[1][$k]])) {
590                    throw new \ErrorException(sprintf('Missing required parameter %s', $matches[1][$k]));
591                }
592                $route['uri']                  = str_replace($match, $query[$matches[1][$k]], $route['uri']);
593                $matchedIndex[$matches[1][$k]] = $query[$matches[1][$k]];
594            }
595        }
596        foreach ($matchedIndex as $key => $value) {
597            unset($query[$key]);
598        }
599        if (count($query)) {
600            $route['uri'] = sprintf('%s?%s', $route['uri'], \http_build_query($query));
601        }
602        return new Request(
603            HttpMethods::make(Str::lower($route['methods'][0]), 'name'),
604            $route['uri'],
605            [],
606            $data
607        );
608    }
609
610    /**
611     * Get composer.json infos
612     *
613     * @return array
614     */
615    public static function getPackageInfo(): array
616    {
617        if (empty(static::$packageInfos)) {
618            static::$packageInfos = \json_decode(\file_get_contents(__DIR__ . '/../composer.json'), true);
619        }
620        return static::$packageInfos;
621    }
622
623    /**
624     * Translation a string using php file lang
625     *
626     * @param string $key
627     * @param string $lang
628     * @return string
629     */
630    public static function translate(string $key, string $lang = 'fr'): string
631    {
632        try {
633            if (!array_key_exists($lang, self::$translations)) {
634                self::$translations = require __DIR__ . "/../resources/lang/$lang.php";
635            }
636        } finally {
637            if (!isset(self::$translations['validation'][$key])) {
638                return $key;
639            } else {
640                return self::$translations['validation'][$key];
641            }
642        }
643    }
644
645    /**
646     * Write log using syslog
647     * It also write log using \Illuminate\Support\Facades\Log
648     * if it is present
649     *
650     * @param string                     $message The message is prefixed with "LDC CRM:" .
651     * @param \LDC\LDCCRM\Enums\LogLevel $level   The log level to apply.
652     * @return void
653     */
654    public static function log(string $message, LogLevel $level)
655    {
656        $message = "LDC CRM: $message";
657        if (\class_exists('\Illuminate\Support\Facades\Log')) {
658            switch ($level->value) {
659                case LogLevel::EMERG->value():
660                    \Illuminate\Support\Facades\Log::emergency($message);
661                    break;
662                case LogLevel::ALERT->value():
663                    \Illuminate\Support\Facades\Log::alert($message);
664                    break;
665                case LogLevel::CRIT->value():
666                    \Illuminate\Support\Facades\Log::critical($message);
667                    break;
668                case LogLevel::ERR->value():
669                    \Illuminate\Support\Facades\Log::error($message);
670                    break;
671                case LogLevel::WARNING->value():
672                    \Illuminate\Support\Facades\Log::warning($message);
673                    break;
674                case LogLevel::NOTICE->value():
675                    \Illuminate\Support\Facades\Log::notice($message);
676                    break;
677                case LogLevel::INFO->value():
678                    \Illuminate\Support\Facades\Log::info($message);
679                    break;
680                case LogLevel::DEBUG->value():
681                    \Illuminate\Support\Facades\Log::debug($message);
682                    break;
683            } //end switch
684            \Illuminate\Support\Facades\Log::warning($message);
685        } //end if
686        \syslog(\constant($level->value), $message);
687    }
688
689    /**
690     * Set a property without any validation.
691     *
692     * ! Warning : this can change any property of the object, use with caution.
693     *
694     * @param object $object   The object to inspect.
695     * @param string $property The object property to assign to.
696     * @param mixed  $value    The value to insert.
697     * @return void
698     * @throws \LDC\LDCCRM\Exceptions\AccessError If trying to set a value on a unknown property.
699     */
700    public static function setRawProperty(object $object, string $property, #[\SensitiveParameter] mixed $value): void
701    {
702        if (is_object($value) and in_array(BaseEnum::class, class_parents($value))) {
703            $value = $value->value;
704        }
705        $objectName = \get_class($object);
706        $refClass   = new \ReflectionClass($objectName);
707        try {
708            $refProp = $refClass->getProperty($property);
709        } catch (\ReflectionException $e) {
710            throw new AccessError($objectName, $property);
711        }
712        $refProp->setAccessible(true);
713        $refProp->setValue($object, $value);
714    }
715
716    /**
717     * Get a property of an object.
718     *
719     * ! Warning : this will return any property of the object, use with caution.
720     *
721     * @param object $object   The object to inspect.
722     * @param string $property The object property to inspect.
723     * @return mixed|null Returns null if the property was not found any way.
724     */
725    public static function getRawProperty(object $object, string $property)
726    {
727        $refClass = new \ReflectionClass(\get_class($object));
728        try {
729            $refProp = $refClass->getProperty($property);
730        } catch (\ReflectionException $e) {
731            return null;
732        }
733        $refProp->setAccessible(true);
734        return $refProp->getValue($object);
735    }
736}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/WordPress/WPCrm.php.html b/tests/coverage/client/src/WordPress/WPCrm.php.html deleted file mode 100644 index 59abb71..0000000 --- a/tests/coverage/client/src/WordPress/WPCrm.php.html +++ /dev/null @@ -1,1330 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/WordPress/WPCrm.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 181
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 26
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
WPCrm
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 181
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 26
6320
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 getUser
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 forceLogin
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 getUserFromApi
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
 login
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 logout
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 check
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 saveUser
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
56
 deleteUser
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
72
 toggleUserOptin
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
72
 setSingleOptin
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 activateUser
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 8
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
 getNewUser
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 unsetActiveUser
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 loginUserWithApi
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getCustomer
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 setUser
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 initLdcApi
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 makeApiV4Call
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 11
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
 bootSessionIfNeeded
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
156
 getUserFromTable
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getUserFromTableByEmail
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getUserFromTableByUuid
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 saveOrUpdateUserToTable
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 17
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 deleteUserFromTable
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 6
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 query
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 getWpDb
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3/**
4 * LDCCRM For Wordpress usage
5 *
6 * @category API
7 * @package  None
8 * @author   Jérémy Munsch <jeremy.munsch@ldc.fr>
9 * @license  MIT https://opensource.org/licenses/MIT
10 * @link     /
11 */
12
13namespace LDC\LDCCRM\WordPress;
14
15use LDC\LDCCRM\CrmApiV4;
16use LDC\LDCCRM\Enums\ApiError;
17use LDC\LDCCRM\Enums\LogLevel;
18use LDC\LDCCRM\Exceptions\ApiErrorException;
19use LDC\LDCCRM\Exceptions\CrmException;
20use LDC\LDCCRM\Models\Customer;
21use LDC\LDCCRM\Models\SingleOptin;
22use LDC\LDCCRM\Utils;
23
24/* phpcs:ignore Squiz.PHP.CommentedOutCode.Found
25    TABLE LDC CUSTOMERS
26    CREATE TABLE `ldc_wp_customers` (
27    `hashcode` VARCHAR(36) NOT NULL DEFAULT '' COMMENT 'Le hashcode (UUID)',
28    `email` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Le customer email',
29    `uuid` VARCHAR(50) NOT NULL DEFAULT '' COMMENT 'Code unique (inscripton, validation, etc)',
30    PRIMARY KEY (`hashcode`)
31    )
32    COMMENT='Les customers sur un WP liées à la CRM'
33    COLLATE='utf8mb4_unicode_ci';
34*/
35
36/**
37 * Class de gestion des users en session avec Wordpress
38 *
39 * @category API
40 * @package LDCCrmClient
41 * @subpackage Wordpress
42 * @author   Jérémy Munsch <jeremy.munsch@ldc.fr>
43 * @license  MIT https://opensource.org/licenses/MIT
44 * @link     /
45 */
46class WPCrm
47{
48    /**
49     * The session key name
50     *
51     * @var string|null
52     */
53    private static ?string $sessionKey = null;
54
55    /**
56     * The session live status
57     *
58     * @var boolean
59     */
60    private static bool $sessionDestroyed = false;
61
62    /**
63     * The user object
64     *
65     * @var \LDC\LDCCRM\CrmApiV4|null
66     */
67    protected static ?CrmApiV4 $api = null;
68
69    /**
70     * The user object
71     *
72     * @var \LDC\LDCCRM\WordPress\WPCrmUser|null
73     */
74    protected static ?WPCrmUser $user = null;
75
76    /**
77     * Get the current user
78     * return null if the user is not logged in
79     *
80     * @return \LDC\LDCCRM\WordPress\WPCrmUser|null
81     */
82    public static function getUser()
83    {
84        self::bootSessionIfNeeded();
85        return self::$user;
86    }
87
88    /**
89     * Manually login a user
90     * If self::$user is already set.
91     *
92     * @return \LDCCRM\WPCrmUser|null
93     */
94    public static function forceLogin()
95    {
96        self::bootSessionIfNeeded();
97        if ($user = self::getUser()) {
98            $_SESSION['wpcrm'][self::$sessionKey] = json_encode($user);
99        }
100        return $user;
101    }
102
103    /**
104     * Get the current user
105     * return api response code if an error occurs
106     *
107     * @param string $identification The customer hashcode or email.
108     *
109     * @return \LDC\LDCCRM\Wordpress\WPCrmUser|false
110     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
111     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
112     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
113     */
114    public static function getUserFromApi(string $identification)
115    {
116        self::initLdcApi();
117        try {
118            if (!($response = self::makeApiV4Call(self::$api, 'getCustomer', [$identification]))) {
119                return false;
120            }
121        } catch (ApiErrorException $e) {
122            switch ($e->getApiError()) {
123                case ApiError::modelNotFound->value():
124                    return false;
125                default:
126                    throw $e;
127            }
128        }
129        /** @var \LDC\LDCCRM\Models\Customer */
130        $customer = $response;
131        self::setUser($customer);
132        return self::$user;
133    }
134
135    /**
136     * Try to login with CRM API
137     * A session will be started if credentials are valid.
138     *
139     * @param string $email    The customer email.
140     * @param string $password The customer password.
141     *
142     * @return boolean
143     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
144     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
145     * Possibles are : - authFailed, If credentials are not valid.
146     *                 - customerNotActivated, If the account is not activated.
147     */
148    public static function login(string $email, string $password)
149    {
150        self::bootSessionIfNeeded();
151        $validCredentials = self::loginUserWithApi($email, $password);
152
153        if ($validCredentials and ($user = self::getUserFromApi($email))) {
154            self::saveOrUpdateUserToTable();
155            $_SESSION['wpcrm'][self::$sessionKey] = json_encode($user);
156        }
157
158        return $validCredentials;
159    }
160
161    /**
162     * Destroy the customer from session
163     * and therefore logout
164     *
165     * @return void
166     */
167    public static function logout()
168    {
169        self::bootSessionIfNeeded();
170        $_SESSION['wpcrm'] = [];
171        session_destroy();
172        self::$sessionDestroyed = true;
173    }
174
175    /**
176     * Check if the user is logged in.
177     * This means he has an active valid session.
178     *
179     * @return boolean
180     */
181    public static function check()
182    {
183        self::bootSessionIfNeeded();
184        return (bool)self::getUser();
185    }
186
187    /**
188     * Save current customer to
189     * the local database and on crm
190     *
191     * @return boolean true if the operation succeeded false otherwise
192     * @throws \LDC\LDCCRM\Exceptions\CrmException If a critical error occured.
193     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
194     * Possibles are : - validationFailed, If provided data is wrong(CRM side).
195     *                 - modelNotFound, If this customer hashcode could not be found.
196     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
197     */
198    public static function saveUser(): bool
199    {
200        if (!self::getUser() or !($customer = self::getCustomer())) {
201            return false;
202        }
203        try {
204            if (!self::makeApiV4Call($customer, 'save')) {
205                return false;
206            }
207        } catch (ApiErrorException $e) {
208            switch ($e->getApiError()) {
209                case ApiError::modelNotFound->value():
210                    return false;
211                default:
212                    throw $e;
213            }
214        }
215        self::saveOrUpdateUserToTable();
216        return true;
217    }
218
219    /**
220     * Delete current customer from
221     * the local database and the crm
222     *
223     * @return boolean true if the operation succeeded
224     * @throws \LDC\LDCCRM\Exceptions\CrmException If a critical error occured.
225     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
226     * Possibles are : - modelNotFound, If this customer hashcode could not be found.
227     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
228     */
229    public static function deleteUser(): bool
230    {
231        if (!self::getUser() or !($customer = self::getCustomer())) {
232            return false;
233        }
234        try {
235            if (!self::makeApiV4Call($customer, 'delete')) {
236                return false;
237            }
238        } catch (ApiErrorException $e) {
239            switch ($e->getApiError()) {
240                case ApiError::authorizationException->value():
241                case ApiError::modelNotFound->value():
242                    return false;
243                default:
244                    throw $e;
245            }
246        }
247        self::deleteUserFromTable();
248        return true;
249    }
250
251    /**
252     * Toggle the current user optin value
253     * on the current user and the crm
254     *
255     * @return boolean true if the operation succeeded
256     * @throws \LDC\LDCCRM\Exceptions\CrmException If a critical error occured.
257     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
258     * Possibles are : - modelNotFound, If this customer hashcode could not be found.
259     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
260     */
261    public static function toggleUserOptin(): bool
262    {
263        if (!self::getUser() or !($customer = self::getCustomer())) {
264            return false;
265        }
266        try {
267            if (!self::makeApiV4Call($customer, 'save')) {
268                return false;
269            }
270        } catch (ApiErrorException $e) {
271            switch ($e->getApiError()) {
272                case ApiError::authorizationException->value():
273                case ApiError::modelNotFound->value():
274                    return false;
275                default:
276                    throw $e;
277            }
278        }
279        $customer->opt_in = !$customer->opt_in;
280        return true;
281    }
282
283    /**
284     * Set the single optin status for an email
285     * on the crm
286     *
287     * @param string  $email
288     * @param boolean $opt_in
289     *
290     * @return boolean true if the operation succeeded false otherwise
291     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a field email could not be validated.
292     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
293     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
294     * Possibles are : - singleOptinCustomerExists, If a customer exists with this email.
295     */
296    public static function setSingleOptin(string $email, bool $opt_in): bool
297    {
298        return self::makeApiV4Call(SingleOptin::class, 'setStatus', [
299            $email, $opt_in
300        ]);
301    }
302
303    /**
304     * Toggle the current user optin value
305     * on the current user and the crm
306     *
307     * @return boolean True if the operation succeeded.
308     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a customer's hashcode could not be validated.
309     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
310     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
311     * Possibles are : - modelNotFound, If this customer hashcode could not be found.
312     *                 - customerAlreadyActive, It the customer is already activated.
313     */
314    public static function activateUser(): bool
315    {
316        if (!self::getUser() or !($customer = self::getCustomer())) {
317            return false;
318        }
319        if ($customer->status) {
320            return true;
321        }
322        if (!self::makeApiV4Call($customer, 'activate')) {
323            return false;
324        }
325        $customer->opt_in = !$customer->opt_in;
326        return true;
327    }
328
329    /**
330     * Generate a new user
331     *
332     * @return WPCrmUser
333     */
334    public static function getNewUser(): WPCrmUser
335    {
336        self::$user = new WPCrmUser();
337        return self::$user;
338    }
339
340    /**
341     * Remove active user
342     * to prevent WPCrm::check to return true
343     *
344     * @return void
345     */
346    public static function unsetActiveUser(): void
347    {
348        self::$user = null;
349    }
350
351    // * --- PRIVATE --- METHODS
352
353    /**
354     * Check customer credentials using the CRM.
355     *
356     * @param string $email    The customer email.
357     * @param string $password The customer password.
358     *
359     * @return boolean
360     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
361     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
362     * Possibles are : - authFailed, If credentials are not valid.
363     *                 - customerNotActivated, If the account is not activated.
364     */
365    private static function loginUserWithApi(string $email, string $password): bool
366    {
367        self::initLdcApi();
368
369        /** @var boolean $response */
370        $response = self::makeApiV4Call(self::$api, 'login', [$email, $password]);
371        return $response;
372    }
373
374    /**
375     * Get all customer infos
376     *
377     * @return \LDC\LDCCRM\Models\Customer|null
378     */
379    private static function getCustomer(): ?Customer
380    {
381        if (!self::getUser()) {
382            return null;
383        }
384        if (!Utils::getRawProperty(self::$user, 'info')) {
385            self::getUserFromApi(self::$user->hashcode);
386        }
387        /** @var \LDC\LDCCRM\Models\Customer */
388        $customer = Utils::getRawProperty(self::$user, 'info');
389        return $customer;
390    }
391
392    /**
393     * Create a user
394     * stores it to the session
395     * and finally saves it to the database if it does not exists
396     *
397     * @param \LDC\LDCCRM\Models\Customer $customer
398     *
399     * @return void
400     */
401    private static function setUser(Customer $customer): void
402    {
403        self::bootSessionIfNeeded();
404        if (!self::$user) {
405            self::$user = new WPCrmUser($customer->hashcode, $customer->email);
406        }
407        self::$user->setInfo($customer);
408    }
409
410    /**
411     * Get the initialized API object
412     *
413     * @return \LDC\LDCCRM\CrmApiV4
414     * @throws \ErrorException If php does not have extension curl.
415     */
416    private static function initLdcApi(): CrmApiV4
417    {
418        if (!self::$api) {
419            if (!extension_loaded('curl')) {
420                throw new \ErrorException(
421                    'WPCrm requires php extension curl'
422                );
423            }
424            self::$api = new CrmApiV4();
425        }
426        return self::$api;
427    }
428
429    /**
430     * Make a call using apiV4
431     *
432     * @param object|string $obj       An object or a class name.
433     * @param string        $method    The method to call.
434     * @param array         $arguments Arguments to pass.
435     * @return mixed|false
436     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any of this exception is thrown.
437     * @throws \LDC\LDCCRM\Exceptions\CrmException If a critical error occured.
438     */
439    private static function makeApiV4Call($obj, string $method, array $arguments = [])
440    {
441        try {
442            return \forward_static_call_array([$obj, $method], $arguments);
443        } catch (ApiErrorException $e) {
444            switch ($e->getApiError()) {
445                case ApiError::apiAuthFailed->value():
446                    Utils::log($e->getMessage(), LogLevel::CRIT);
447                    throw $e;
448                default:
449                    Utils::log($e->getMessage(), LogLevel::DEBUG);
450                    throw $e;
451            }
452        } catch (CrmException $e) {
453            Utils::log($e->getMessage(), LogLevel::CRIT);
454            throw $e;
455        }
456    }
457
458    /**
459     * Boot the php session if needed
460     *
461     * @return void
462     */
463    private static function bootSessionIfNeeded(): void
464    {
465        self::$sessionKey = ($_SERVER['HTTP_USER_AGENT'] ?? '') . ($_SERVER['REMOTE_ADDR'] ?? '');
466        /** @var string self::$sessionKey */
467        self::$sessionKey = \strlen(self::$sessionKey) ? self::$sessionKey : (date('d') ? date('d') : '');
468        if (!session_id() && !self::$sessionDestroyed) {
469            session_start();
470        }
471        if (!isset($_SESSION['wpcrm'])) {
472            $_SESSION['wpcrm'] = [];
473        }
474        if (
475            // If session identity is violated.
476            count($_SESSION['wpcrm']) > 1 or
477            // If session timed out.
478            (isset($_SESSION['wpcrm'][self::$sessionKey]) and
479                isset($_SESSION['lastActivity']) and
480                // * 15 minutes session.
481                ($_SESSION['lastActivity'] + (15 * 60)) < time())
482        ) {
483            // Destroy session.
484            self::$sessionDestroyed = true;
485            $_SESSION['wpcrm']      = [];
486        } else {
487            $_SESSION['lastActivity'] = time();
488        }
489        if (!self::$user and isset($_SESSION['wpcrm'][self::$sessionKey])) {
490            self::$user = WPCrmUser::parseFromJson(
491                $_SESSION['wpcrm'][self::$sessionKey]
492            );
493        }
494    }
495
496    /**
497     * Get a customer from table
498     *
499     * @param string $hashcode The customer hashcode.
500     *
501     * @return array|null Database query result in format specified by $output or null on failure.
502     */
503    public static function getUserFromTable(string $hashcode): ?array
504    {
505        return self::getWpDb()->get_row(
506            self::getWpDb()->prepare(
507                'SELECT * FROM `ldc_wp_customers` WHERE `hashcode` = %s',
508                [
509                    'hashcode' => $hashcode
510                ]
511            ),
512            'ARRAY_A'
513        );
514    }
515
516    /**
517     * Get a customer from table by an email
518     *
519     * @param string $email The customer email.
520     *
521     * @return array|null Database query result in format specified by $output or null on failure.
522     */
523    public static function getUserFromTableByEmail(string $email): ?array
524    {
525        return self::getWpDb()->get_row(
526            self::getWpDb()->prepare(
527                'SELECT * FROM `ldc_wp_customers` WHERE `email` = %s',
528                [
529                    'email' => $email
530                ]
531            ),
532            'ARRAY_A'
533        );
534    }
535
536    /**
537     * Get a customer from table by an email
538     *
539     * @param string $uuid The customer transaction uuid.
540     *
541     * @return array|null Database query result in format specified by $output or null on failure.
542     */
543    public static function getUserFromTableByUuid(string $uuid): ?array
544    {
545        return self::getWpDb()->get_row(
546            self::getWpDb()->prepare(
547                'SELECT * FROM `ldc_wp_customers` WHERE `uuid` = %s',
548                [
549                    'uuid' => $uuid
550                ]
551            ),
552            'ARRAY_A'
553        );
554    }
555
556    /**
557     * Save or update the user to the table
558     *
559     * @return integer The number of row affected on the table.
560     */
561    private static function saveOrUpdateUserToTable(): int
562    {
563        if (is_string(self::$user->hashcode) and self::getUserFromTable(self::$user->hashcode)) {
564            return self::query(
565                'UPDATE `ldc_wp_customers` SET `email` = %s, `uuid` = %s WHERE `hashcode` = %s',
566                [
567                    'email' => self::$user->email,
568                    'uuid' => self::$user->uuidToken,
569                    'hashcode' => self::$user->hashcode
570                ]
571            );
572        }
573        return self::query(
574            'INSERT INTO `ldc_wp_customers`(hashcode, email, uuid) VALUES (%s, %s, %s)',
575            [
576                'hashcode' => self::$user->hashcode,
577                'email' => self::$user->email,
578                'uuid' => self::$user->uuidToken
579            ]
580        );
581    }
582
583    /**
584     * Save or update the user to the table
585     *
586     * @return integer The number of row removed from the table.
587     */
588    private static function deleteUserFromTable(): int
589    {
590        return self::query(
591            'DELETE FROM `ldc_wp_customers` WHERE `hashcode` = %s;',
592            [
593                'hashcode' => self::$user->hashcode
594            ]
595        );
596    }
597
598    /**
599     * Query in DB
600     *
601     * @param string $query  La request avec les variables en points d'interrogation.
602     * @param array  $params Les paramètres des la requète.
603     *
604     * @return integer|boolean Boolean true for CREATE, ALTER, TRUNCATE and DROP queries.
605     * Number of rows affected/selected for all other queries. Boolean false on error.
606     */
607    private static function query(string $query, array $params = [])
608    {
609        return self::getWpDb()->query(
610            self::getWpDb()->prepare($query, $params)
611        );
612    }
613
614    /**
615     * Get WP 'pdo instance'
616     *
617     * @return object The $wpdb variable
618     */
619    private static function getWpDb(): object
620    {
621        // phpcs:ignore Squiz.PHP.GlobalKeyword.NotAllowed
622        global $wpdb;
623        return $wpdb;
624    }
625}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/WordPress/WPCrmAnswer.php.html b/tests/coverage/client/src/WordPress/WPCrmAnswer.php.html deleted file mode 100644 index 003c576..0000000 --- a/tests/coverage/client/src/WordPress/WPCrmAnswer.php.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/WordPress/WPCrmAnswer.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
WPCrmAnswer
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 setQuestionAnswers
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3/**
4 * LDCCRM For Wordpress usage
5 *
6 * @category API
7 * @package  None
8 * @author   Jérémy Munsch <jeremy.munsch@ldc.fr>
9 * @license  MIT https://opensource.org/licenses/MIT
10 * @link     /
11 */
12
13namespace LDC\LDCCRM\WordPress;
14
15use LDC\LDCCRM\Models\Answer;
16
17/**
18 * Class de gestion de la segmentation question avec Wordpress
19 *
20 * @category API
21 * @package LDCCrmClient
22 * @subpackage Wordpress
23 * @author   Jérémy Munsch <jeremy.munsch@ldc.fr>
24 * @license  MIT https://opensource.org/licenses/MIT
25 * @link     /
26 */
27abstract class WPCrmAnswer
28{
29    /**
30     * Set answers to a question for a specific user
31     *
32     * @param \LDC\LDCCRM\WordPress\WPCrmUser $user
33     * @param integer                         $questionId The question id .
34     * @param array                           $answersId  An array with answers id .
35     * @return boolean true if succeeded
36     *
37     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
38     * @throws \LDC\LDCCRM\Exceptions\ValidationException If $user hashcode is not a valid UUID.
39     * @throws \LDC\LDCCRM\Exceptions\ValidationException If any of the provided ids are invalid.
40     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error \LDC\LDCCRM\Enums\ApiError occurs.
41     * Possibles are : - validationFailed, If given ids are wrong(CRM side).
42     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
43     */
44    public function setQuestionAnswers(WPCrmUser $user, int $questionId, array $answersId): bool
45    {
46        return Answer::setQuestionAnswers($user->hashcode, $questionId, $answersId);
47    }
48}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/WordPress/WPCrmQuestion.php.html b/tests/coverage/client/src/WordPress/WPCrmQuestion.php.html deleted file mode 100644 index fe0b8dd..0000000 --- a/tests/coverage/client/src/WordPress/WPCrmQuestion.php.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/WordPress/WPCrmQuestion.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
WPCrmQuestion
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
30
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 getAll
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 allWithCustomerAnswers
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
 unansweredBy
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
6
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3/**
4 * LDCCRM For Wordpress usage
5 *
6 * @category API
7 * @package  None
8 * @author   Jérémy Munsch <jeremy.munsch@ldc.fr>
9 * @license  MIT https://opensource.org/licenses/MIT
10 * @link     /
11 */
12
13namespace LDC\LDCCRM\WordPress;
14
15use LDC\LDCCRM\Models\Question;
16use LDC\LDCCRM\Utils;
17
18/**
19 * Class de gestion de la segmentation question avec Wordpress
20 *
21 * @category API
22 * @package LDCCrmClient
23 * @subpackage Wordpress
24 * @author   Jérémy Munsch <jeremy.munsch@ldc.fr>
25 * @license  MIT https://opensource.org/licenses/MIT
26 * @link     /
27 */
28abstract class WPCrmQuestion
29{
30    /**
31     * Get all questions only
32     *
33     * @return array Of \LDC\LDCCRM\Models\Question
34     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
35     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
36     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
37     */
38    public static function getAll(): array
39    {
40        return Question::all();
41    }
42
43    /**
44     * Get all the questions with user answers
45     *
46     * @param \LDC\LDCCRM\WordPress\WPCrmUser $user
47     * @return array Of \LDC\LDCCRM\Models\Question and their \LDC\LDCCRM\Models\Answer.
48     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
49     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a hashcode is not a valid UUID.
50     * @throws \LDC\LDCCRM\Exceptions\ValidationException If any of the provided ids are invalid.
51     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
52     * Possibles are : - modelNotFound, If the customer could not be found(CRM side).
53     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
54     */
55    public static function allWithCustomerAnswers(WPCrmUser $user): array
56    {
57        // * Force loading of user info from crm
58        if (!Utils::getRawProperty($user, 'info')) {
59            WPCrm::getUserFromApi($user->hashcode);
60        }
61        // * Get the raw customer
62        /** @var \LDC\LDCCRM\Models\Customer */
63        $customer = Utils::getRawProperty($user, 'info');
64        return Question::allWithCustomerAnswers($customer);
65    }
66
67    /**
68     * Get unanswered question for a specific customer
69     *
70     * @param \LDC\LDCCRM\WordPress\WPCrmUser $user
71     * @return \LDC\LDCCRM\Models\Question[]
72     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
73     * @throws \LDC\LDCCRM\Exceptions\ValidationException If $user hashcode is not a valid UUID.
74     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
75     * Possibles are : - modelNotFound, If the customer could not be found(CRM side).
76     * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
77     */
78    public static function unansweredBy(WPCrmUser $user): array
79    {
80        // * Force loading of user info from crm
81        if (!Utils::getRawProperty($user, 'info')) {
82            WPCrm::getUserFromApi($user->hashcode);
83        }
84        // * Get the raw customer
85        /** @var \LDC\LDCCRM\Models\Customer */
86        $customer = Utils::getRawProperty($user, 'info');
87        return Question::unansweredBy($customer);
88    }
89}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/WordPress/WPCrmUser.php.html b/tests/coverage/client/src/WordPress/WPCrmUser.php.html deleted file mode 100644 index 7afb057..0000000 --- a/tests/coverage/client/src/WordPress/WPCrmUser.php.html +++ /dev/null @@ -1,608 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/WordPress/WPCrmUser.php - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
CRAP
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
WPCrmUser
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
380
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
 __construct
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 2
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 __get
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
20
 __set
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
30
 setInfo
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 parseFromJson
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 12
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
12
 jsonSerialize
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 save
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 delete
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 toggleOptin
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
 activate
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
2
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1<?php
2
3/**
4 * LDCCRM For Wordpress usage
5 *
6 * @category API
7 * @package  None
8 * @author   Jérémy Munsch <jeremy.munsch@ldc.fr>
9 * @license  MIT https://opensource.org/licenses/MIT
10 * @link     /
11 */
12
13namespace LDC\LDCCRM\WordPress;
14
15use JsonSerializable;
16use LDC\LDCCRM\Exceptions\WpCrmInvalidJsonUserInfo;
17use LDC\LDCCRM\Models\Customer;
18
19/**
20 * Class de gestion des users en session avec Wordpress
21 *
22 * @property string|null $uuidToken — A local transaction token for this user
23 * @property string|null $hashcode — The crm hashcode this is a readonly field
24 * @property string|null $pemail — Must be a rfc valid email on a valid domain name
25 * @property string $password
26 * Required only on create,
27 * must have upper and lowers chars,
28 * at least 1 number,
29 * at leat 1 upper char,
30 * at least 1 lower char and
31 * at leat 1 special char
32 * @property string $firstname — The account first name
33 * @property string $lastname — The account last name
34 * @property string $birth_date — The account birth date 'yyyy-mm-dd'
35 * @property string $phone — The account phone
36 * @property string $address
37 * The account address (street number, name, build, flat number)
38 * @property string $address2 — The account phone (address complement)
39 * @property string $city — The account city name
40 * @property string $postcode — The account city postcode
41 * @property \LDC\LDCCRM\Enums\Country $country — The account country residence
42 * @property bool $opt_in — true if the account is opt in
43 * @property bool $status — true if the account is activated
44 * @property string $last_connection the last time user was connected 'yyyy-mm-dd HH:ii:ss'
45 *
46 * @category API
47 * @package LDCCrmClient
48 * @subpackage Wordpress
49 * @author   Jérémy Munsch <jeremy.munsch@ldc.fr>
50 * @license  MIT https://opensource.org/licenses/MIT
51 * @link     /
52 */
53class WPCrmUser implements JsonSerializable
54{
55    /**
56     * The CRM hashcode (UUID)
57     *
58     * @var string|null
59     */
60    protected ?string $phashcode = null;
61
62    /**
63     * The CRM customer email
64     *
65     * @var string|null
66     */
67    protected ?string $pemail = null;
68
69    /**
70     * The CRM customer info (the api response)
71     *
72     * @var \LDC\LDCCRM\Models\Customer|null
73     */
74    protected ?Customer $info = null;
75
76    /**
77     * The CRM customer temp uuidToken to validate transactions
78     *
79     * @var string|null UUID
80     */
81    protected ?string $uuidToken = null;
82
83    /**
84     * WPCrmUser construct
85     *
86     * @param string $hashcode The customer hashcode (UUID).
87     * @param string $email    The customer email.
88     */
89    public function __construct(string $hashcode = null, string $email = null)
90    {
91        $this->phashcode = $hashcode;
92        $this->pemail    = $email;
93    }
94
95    /**
96     * Generic accessor
97     *
98     * @param string $prop The prop to get.
99     *
100     * @return boolean|string|\LDC\LDCCRM\Enums\Country|null
101     */
102    public function __get(string $prop)
103    {
104        if ($prop === 'uuidToken') {
105            return $this->uuidToken;
106        }
107        if (is_null($this->info)) {
108            if (!is_null($this->pemail)) {
109                WPCrm::getUserFromApi($this->pemail);
110            } else {
111                $this->info = new Customer();
112            }
113        }
114        return $this->info->{$prop};
115    }
116
117    /**
118     * Generic mutator
119     *
120     * @param string $prop  The property to assign.
121     * @param mixed  $value The value to set.
122     *
123     * @return void
124     */
125    public function __set(string $prop, mixed $value): void
126    {
127        if ($prop === 'uuidToken') {
128            $this->uuidToken = $value;
129            return;
130        }
131        if (is_null($this->info)) {
132            if (!is_null($this->pemail)) {
133                WPCrm::getUserFromApi($this->pemail);
134            } else {
135                $this->info = new Customer();
136            }
137        }
138        $this->info->{$prop} = $value;
139        if ($prop === 'email') {
140            $this->pemail = $value;
141        }
142    }
143
144    /**
145     * Set the customer info
146     * with api response
147     *
148     * @param \LDC\LDCCRM\Models\Customer $customer The Api object reponse (user).
149     *
150     * @return void
151     */
152    public function setInfo(Customer $customer)
153    {
154        $this->info      = $customer;
155        $this->pemail    = $customer->email;
156        $this->phashcode = $customer->hashcode;
157    }
158
159    /**
160     * Generate a user from session data
161     *
162     * @param string $string The json data stored in session.
163     *
164     * @return \LDC\LDCCRM\WordPress\WPCrmUser
165     * @throws \LDC\LDCCRM\Exceptions\WpCrmInvalidJsonUserInfo If the json string does no
166     *  contain the needed information.
167     */
168    public static function parseFromJson(string $string): WPCrmUser
169    {
170        $a = json_decode($string, true);
171        if (!isset($a['hashcode']) or !isset($a['email'])) {
172            throw new WpCrmInvalidJsonUserInfo(\sprintf(
173                '%s::%s is missing some information to parse from, uuid was %s',
174                __CLASS__,
175                __METHOD__,
176                $a['hashcode']
177            ));
178        }
179        return new self(
180            $a['hashcode'],
181            $a['email']
182        );
183    }
184
185    /**
186     * Serialize this object to an array
187     *
188     * @return array
189     */
190    public function jsonSerialize()
191    {
192        return [
193            'hashcode' => $this->phashcode,
194            'email'    => $this->pemail
195        ];
196    }
197
198    /**
199     * Save current customer to
200     * the local database and on crm
201     *
202     * @return boolean true if the operation succeeded false otherwise
203     * @throws \LDC\LDCCRM\Exceptions\CrmException If a critical error occured.
204     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
205     * Possibles are : - validationFailed, If provided data is wrong(CRM side).
206     *                 - modelNotFound, If this customer hashcode could not be found.
207     */
208    public function save(): bool
209    {
210        return WPCrm::saveUser();
211    }
212
213    /**
214     * Delete current customer to
215     * the local database and on crm
216     *
217     * @return boolean true if the operation succeeded false otherwise
218     * @throws \LDC\LDCCRM\Exceptions\CrmException If a critical error occured.
219     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
220     * Possibles are : - modelNotFound, If this customer hashcode could not be found.
221     */
222    public function delete(): bool
223    {
224        return WPCrm::deleteUser();
225    }
226
227    /**
228     * Toggle the current user optin value
229     * on the current user and the crm
230     *
231     * @return boolean true if the operation succeeded
232     * @throws \LDC\LDCCRM\Exceptions\CrmException If a critical error occured.
233     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
234     * Possibles are : - modelNotFound, If this customer hashcode could not be found.
235     */
236    public function toggleOptin(): bool
237    {
238        return WPCrm::toggleUserOptin();
239    }
240
241    /**
242     * Activate the account in the crm
243     *
244     * @return boolean true if succeeded
245     * @throws \LDC\LDCCRM\Exceptions\ValidationException If a customer's hashcode could not be validated.
246     * @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
247     * @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
248     * Possibles are : - modelNotFound, If this customer hashcode could not be found.
249     *                 - customerAlreadyActive, It the customer is already activated.
250     */
251    public function activate(): bool
252    {
253        return WPCrm::activateUser();
254    }
255}
- - -
-
-

Legend

-

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

-

- Generated by php-code-coverage 10.1.7 using PHP 8.2.10 and PHPUnit 10.4.0 at Fri Oct 6 15:56:10 CEST 2023. -

- - - -
-
- - - - - - diff --git a/tests/coverage/client/src/WordPress/dashboard.html b/tests/coverage/client/src/WordPress/dashboard.html deleted file mode 100644 index 338caef..0000000 --- a/tests/coverage/client/src/WordPress/dashboard.html +++ /dev/null @@ -1,351 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/client/src/WordPress - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

- -
-
-

Project Risks

- -
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- - -
- - - - - - diff --git a/tests/coverage/client/src/WordPress/index.html b/tests/coverage/client/src/WordPress/index.html deleted file mode 100644 index 532f820..0000000 --- a/tests/coverage/client/src/WordPress/index.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src/WordPress - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 233
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 40
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
WPCrm.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 181
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 26
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
WPCrmAnswer.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
WPCrmQuestion.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 9
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
WPCrmUser.php
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 42
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 10
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/client/src/dashboard.html b/tests/coverage/client/src/dashboard.html deleted file mode 100644 index dca2c67..0000000 --- a/tests/coverage/client/src/dashboard.html +++ /dev/null @@ -1,439 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm/client/src - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
- -
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
- - -
- -
- - - - - - diff --git a/tests/coverage/client/src/index.html b/tests/coverage/client/src/index.html deleted file mode 100644 index fc361cf..0000000 --- a/tests/coverage/client/src/index.html +++ /dev/null @@ -1,301 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm/client/src - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 69.13% covered (warning) -
-
-
69.13%
907 / 1312
-
- 45.56% covered (danger) -
-
-
45.56%
77 / 169
-
- 13.04% covered (danger) -
-
-
13.04%
3 / 23
Enums
n/a
0 / 0
n/a
0 / 0
n/a
0 / 0
Exceptions
-
- 66.67% covered (warning) -
-
-
66.67%
10 / 15
-
- 42.86% covered (danger) -
-
-
42.86%
3 / 7
-
- 20.00% covered (danger) -
-
-
20.00%
1 / 5
Models
-
- 88.17% covered (warning) -
-
-
88.17%
410 / 465
-
- 63.64% covered (warning) -
-
-
63.64%
35 / 55
-
- 25.00% covered (danger) -
-
-
25.00%
2 / 8
Traits
-
- 54.43% covered (warning) -
-
-
54.43%
43 / 79
-
- 40.00% covered (danger) -
-
-
40.00%
6 / 15
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Transport
-
- 82.26% covered (warning) -
-
-
82.26%
153 / 186
-
- 50.00% covered (danger) -
-
-
50.00%
9 / 18
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 3
WordPress
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 233
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 40
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 4
CrmApiV4.php
-
- 92.86% covered (success) -
-
-
92.86%
13 / 14
-
- 85.71% covered (warning) -
-
-
85.71%
6 / 7
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
Utils.php
-
- 86.88% covered (warning) -
-
-
86.88%
278 / 320
-
- 66.67% covered (warning) -
-
-
66.67%
18 / 27
-
- 0.00% covered (danger) -
-
-
0.00%
0 / 1
-
- -
- - diff --git a/tests/coverage/dashboard.html b/tests/coverage/dashboard.html deleted file mode 100644 index a9f54df..0000000 --- a/tests/coverage/dashboard.html +++ /dev/null @@ -1,908 +0,0 @@ - - - - - Dashboard for /home/jeremy/projets/crm - - - - - - - -
-
-
-
- -
-
-
-
-
-
-
-

Classes

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ClassCoverage
App\Console\Commands\TestMail0%
App\Console\Commands\UserCreate0%
App\Exceptions\Api\V2\CrmException0%
App\Exceptions\Api\V4\CrmException0%
App\Http\Controllers\Bo\ActivityLogsController0%
App\Http\Controllers\Bo\AnswerController0%
App\Http\Controllers\Bo\Auth\LoginController0%
App\Http\Controllers\Bo\Auth\ResetPasswordController0%
App\Http\Controllers\Bo\BrandController0%
App\Http\Controllers\Bo\CustomerController0%
App\Http\Controllers\Bo\DashboardController0%
App\Http\Controllers\Bo\QuestionController0%
App\Http\Controllers\Bo\ServiceController0%
App\Http\Controllers\Bo\SingleOptinController0%
App\Http\Controllers\Bo\StatsController0%
App\Http\Controllers\Bo\UsersController0%
App\Http\Controllers\Controller0%
App\Http\Middleware\RedirectIfAuthenticated0%
App\Http\Middleware\SecureHeaders0%
App\Http\Middleware\TrustHosts0%
App\Http\Requests\Bo\Answers\StoreAnswerRequest0%
App\Http\Requests\Bo\Brands\StoreBrandRequest0%
App\Http\Requests\Bo\CustomerExport0%
App\Http\Requests\Bo\GenerateServiceToken0%
App\Http\Requests\Bo\ManageBrandRequest0%
App\Http\Requests\Bo\ManageServiceRequest0%
App\Http\Requests\Bo\QuestionExport0%
App\Http\Requests\Bo\Questions\StoreQuestionRequest0%
App\Http\Requests\Bo\Services\StoreServiceRequest0%
App\Http\Requests\Bo\StatsByBrandRequest0%
App\Http\Requests\Bo\StatsByQuestionRequest0%
App\Http\Requests\Bo\UpdateChangeOrderRequest0%
App\Http\Requests\Bo\UpdateMiniCrudRequest0%
App\Http\Requests\Bo\Users\StoreUserRequest0%
App\Http\Requests\Bo\Users\UpdateUserRequest0%
App\Http\Resources\CustomerResource0%
App\Jobs\StartStatJobs0%
App\Jobs\StatJob0%
App\Lib\Helpers\ToolboxHelper0%
App\Mail\CourrierArcadiaError0%
App\Mail\ServiceCredentialRenewed0%
App\Models\ActivityLog0%
App\Models\User0%
App\Observers\ModelObserver0%
App\Policies\AnswerPolicy0%
App\Policies\BrandPolicy0%
App\Policies\ServicePolicy0%
App\Policies\SingleOptinPolicy0%
App\Policies\UserPolicy0%
LDC\LDCCRM\Exceptions\CrmException0%
LDC\LDCCRM\Exceptions\ValidationException0%
LDC\LDCCRM\Exceptions\WpCrmInvalidJsonUserInfo0%
LDC\LDCCRM\WordPress\WPCrm0%
LDC\LDCCRM\WordPress\WPCrmAnswer0%
LDC\LDCCRM\WordPress\WPCrmQuestion0%
LDC\LDCCRM\WordPress\WPCrmUser0%
App\Enums\ActivityLogs\ActivityLogsEventEnum0%
App\Traits\Controllers\ChangesModelOrder0%
App\Traits\Controllers\UpdateModelPublished0%
App\Traits\Models\IsCachedAsCollection0%
App\Traits\Models\MiniCrudModel0%
App\Policies\CustomerPolicy16%
App\Policies\QuestionPolicy16%
App\Models\BrandStat40%
App\Http\Middleware\Authenticate41%
LDC\LDCCRM\Traits\BaseEnum54%
App\Traits\Enums\BaseEnum55%
App\Models\Brand61%
LDC\LDCCRM\Transport\Response68%
App\Providers\RouteServiceProvider69%
App\Http\Middleware\HtmlSanitizer71%
App\Models\Service74%
App\Providers\ViewServiceProvider75%
LDC\LDCCRM\Models\ClientModel78%
LDC\LDCCRM\Models\ArcadiaMailGame80%
App\Models\CustomerInfo80%
LDC\LDCCRM\Transport\ApiInterface84%
LDC\LDCCRM\Models\Question84%
LDC\LDCCRM\Utils86%
App\Exceptions\Handler88%
App\Providers\AppServiceProvider88%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ClassCRAP
App\Lib\Helpers\ToolboxHelper6642
LDC\LDCCRM\WordPress\WPCrm6320
App\Http\Controllers\Controller1332
App\Http\Requests\Bo\UpdateMiniCrudRequest1190
App\Http\Controllers\Bo\CustomerController992
App\Traits\Models\MiniCrudModel992
App\Policies\UserPolicy506
App\Http\Controllers\Bo\QuestionController462
App\Console\Commands\UserCreate380
LDC\LDCCRM\WordPress\WPCrmUser380
App\Http\Controllers\Bo\ServiceController210
LDC\LDCCRM\Traits\BaseEnum158
App\Http\Controllers\Bo\StatsController156
App\Http\Controllers\Bo\UsersController156
App\Traits\Enums\BaseEnum148
App\Http\Controllers\Bo\AnswerController110
App\Traits\Models\IsCachedAsCollection110
LDC\LDCCRM\Utils90
App\Http\Controllers\Bo\BrandController90
LDC\LDCCRM\Models\ClientModel73
App\Http\Middleware\RedirectIfAuthenticated72
App\Models\User56
App\Http\Middleware\SecureHeaders42
App\Http\Requests\Bo\StatsByBrandRequest42
App\Http\Requests\Bo\StatsByQuestionRequest42
App\Models\ActivityLog42
App\Traits\Controllers\ChangesModelOrder42
App\Http\Controllers\Bo\SingleOptinController30
App\Http\Requests\Bo\Users\StoreUserRequest30
App\Http\Requests\Bo\Users\UpdateUserRequest30
LDC\LDCCRM\WordPress\WPCrmQuestion30
LDC\LDCCRM\Models\Question27
LDC\LDCCRM\Transport\Response25
LDC\LDCCRM\Transport\ApiInterface21
App\Models\Service20
App\Http\Requests\Bo\UpdateChangeOrderRequest20
App\Exceptions\Handler18
App\Providers\RouteServiceProvider17
LDC\LDCCRM\Models\ArcadiaMailGame15
App\Http\Middleware\Authenticate13
App\Http\Controllers\Bo\ActivityLogsController12
App\Http\Requests\Bo\CustomerExport12
App\Http\Requests\Bo\ManageBrandRequest12
App\Http\Requests\Bo\ManageServiceRequest12
App\Http\Middleware\HtmlSanitizer9
App\Providers\ViewServiceProvider6
App\Jobs\StartStatJobs6
App\Models\BrandStat4
App\Providers\AppServiceProvider2
-
-
-
-
-
-

Methods

-
-
-
-
-

Coverage Distribution

-
- -
-
-
-

Complexity

-
- -
-
-
-
-
-

Insufficient Coverage

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodCoverage
handle0%
handle0%
addFirstName0%
addLastName0%
addEmail0%
addPassword0%
addRole0%
getApiError0%
report0%
getApiError0%
report0%
index0%
show0%
index0%
create0%
store0%
edit0%
update0%
destroy0%
__construct0%
guard0%
showLoginForm0%
redirectTo0%
attemptLogin0%
guard0%
redirectTo0%
index0%
create0%
store0%
edit0%
update0%
jsonPaginate0%
index0%
show0%
delete0%
export0%
exportSubmit0%
index0%
index0%
create0%
store0%
edit0%
update0%
show0%
destroy0%
export0%
exportSubmit0%
index0%
create0%
store0%
edit0%
update0%
show0%
destroy0%
generateServicePassword0%
index0%
destroy0%
viewStatsByBrand0%
exportByBrandCsv0%
viewByQuestion0%
exportByQuestionCsv0%
answersByDays0%
__construct0%
index0%
create0%
store0%
edit0%
update0%
destroy0%
duplicate0%
searchQuery0%
searchOnFields0%
getSearchValue0%
sortQuery0%
paginate0%
setTheme0%
handle0%
handle0%
removeUnwantedHeaders0%
hosts0%
authorize0%
rules0%
attributes0%
authorize0%
rules0%
attributes0%
authorize0%
rules0%
authorize0%
rules0%
authorize0%
rules0%
authorize0%
rules0%
authorize0%
rules0%
authorize0%
prepareForValidation0%
rules0%
attributes0%
authorize0%
prepareForValidation0%
rules0%
attributes0%
authorize0%
rules0%
authorize0%
rules0%
authorize0%
prepareForValidation0%
rules0%
authorize0%
rules0%
compileValidate0%
ruleHasToComeFirst0%
isUpdate0%
authorize0%
prepareForValidation0%
rules0%
attributes0%
prepareForValidation0%
rules0%
__construct0%
toArray0%
handle0%
__construct0%
handle0%
middleware0%
arrayMergeRecursiveDistinct0%
validateRecaptcha0%
stripCkEditorSchemesOnMediaInputs0%
assertNoInternalBoUrls0%
assertNoInternalUrls0%
mbReplace0%
assertFieldIsUnique0%
getOriginal0%
queryColumnWithLocales0%
dotStringToNestedArray0%
objectToArray0%
arrayToObject0%
validatePicture0%
getUploadedFileFullPath0%
getUploadedFileMimeType0%
getClassesUsingNamespace0%
getClassesUsingInterface0%
getValidatedEnum0%
__construct0%
build0%
__construct0%
build0%
addActivity0%
getChangedColumns0%
user0%
customerInfos0%
servicesStats0%
singleOptins0%
getAccountsAttribute0%
getTotalOptinsAttribute0%
brand0%
login0%
getFromHashcode0%
servicesStats0%
generateBearerToken0%
generateBearerPassword0%
booted0%
updatePassword0%
activityLogs0%
created0%
updated0%
duplicated0%
deleted0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
view0%
viewAny0%
create0%
update0%
delete0%
viewAny0%
view0%
create0%
update0%
delete0%
restore0%
forceDelete0%
duplicate0%
changePublished0%
unsetStatusWithHashcode0%
getStatusCode0%
report0%
report0%
__construct0%
findWithEmail0%
__set0%
validateAllValues0%
log0%
getUser0%
forceLogin0%
getUserFromApi0%
login0%
logout0%
check0%
saveUser0%
deleteUser0%
toggleUserOptin0%
setSingleOptin0%
activateUser0%
getNewUser0%
unsetActiveUser0%
loginUserWithApi0%
getCustomer0%
setUser0%
initLdcApi0%
makeApiV4Call0%
bootSessionIfNeeded0%
getUserFromTable0%
getUserFromTableByEmail0%
getUserFromTableByUuid0%
saveOrUpdateUserToTable0%
deleteUserFromTable0%
query0%
getWpDb0%
setQuestionAnswers0%
getAll0%
allWithCustomerAnswers0%
unansweredBy0%
__construct0%
__get0%
__set0%
setInfo0%
parseFromJson0%
jsonSerialize0%
save0%
delete0%
toggleOptin0%
activate0%
bootstrapClass0%
changeOrder0%
changePublished0%
name0%
all0%
toArray0%
jsonSerialize0%
getCustomDefinitions0%
getCached0%
removeCached0%
setCached0%
queryCached0%
filterQuery0%
getCacheKeyName0%
getCallClassBaseName0%
fill0%
minicrudCreating0%
minicrudUpdating0%
minicrudUpdated0%
minicrudDeleted0%
setData0%
setDataAttribute0%
getDataAttribute0%
serializeData0%
all0%
toArray0%
jsonSerialize0%
getCustomDefinitions0%
cspReportRoute20%
fill25%
setCredentials28%
fillRaw30%
checkVersion31%
redirectTo41%
fill47%
register50%
prepareForValidation50%
booted50%
__set50%
getLabelsConstant60%
booted61%
__construct61%
booted66%
__get66%
setRawProperty66%
getRawProperty66%
get66%
handle71%
validateAllValues71%
jsonTranslations75%
boot75%
fill75%
fill75%
fill75%
equals75%
getCache75%
setCache75%
equals75%
getCache75%
setCache75%
validateAllValues80%
getPropType83%
assertValidPrimaryKey83%
assertValidHascode83%
call83%
__construct84%
loadBrandData84%
validateValue87%
__get87%
boot88%
signRequest88%
handleApiException88%
configureRateLimiting88%
getResquest89%
-
-
-
-

Project Risks

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodCRAP
rules462
serializeData240
validateRecaptcha210
index182
sortQuery182
validatePicture182
bootSessionIfNeeded156
log110
searchOnFields90
compileValidate90
mbReplace90
delete72
exportSubmit72
exportSubmit72
handle72
deleteUser72
toggleUserOptin72
saveUser56
addRole42
objectToArray42
arrayToObject42
changeOrder42
searchQuery30
rules30
rules30
arrayMergeRecursiveDistinct30
getUserFromApi30
activateUser30
makeApiV4Call30
__set30
getCustomDefinitions30
getCustomDefinitions30
fill24
fill21
getSearchValue20
handle20
prepareForValidation20
assertNoInternalBoUrls20
assertNoInternalUrls20
queryColumnWithLocales20
booted20
__set20
__get20
toArray20
toArray20
cspReportRoute17
redirectTo13
addFirstName12
addLastName12
addEmail12
addPassword12
index12
index12
index12
exportByBrandCsv12
answersByDays12
setTheme12
getUploadedFileFullPath12
getChangedColumns12
update12
delete12
restore12
forceDelete12
duplicate12
changePublished12
validateAllValues12
login12
getCustomer12
initLdcApi12
saveOrUpdateUserToTable12
parseFromJson12
getCached12
minicrudCreating12
minicrudUpdated12
minicrudDeleted12
handleApiException10
handle9
fillRaw9
getResquest9
__construct8
signRequest7
boot6
fill6
fill6
fill6
__construct6
index6
index6
store6
update6
destroy6
index6
store6
update6
store6
update6
destroy6
store6
update6
destroy6
generateServicePassword6
destroy6
viewStatsByBrand6
viewByQuestion6
exportByQuestionCsv6
index6
store6
update6
destroy6
paginate6
removeUnwantedHeaders6
rules6
rules6
rules6
prepareForValidation6
ruleHasToComeFirst6
prepareForValidation6
handle6
assertFieldIsUnique6
getOriginal6
dotStringToNestedArray6
getUploadedFileMimeType6
getValidatedEnum6
addActivity6
updatePassword6
view6
__set6
forceLogin6
setUser6
allWithCustomerAnswers6
unansweredBy6
setCached6
fill6
setData6
checkVersion5
equals5
equals5
loadBrandData5
setRawProperty4
getPropType4
__get4
setCredentials3
validateAllValues3
jsonTranslations3
validateAllValues3
call3
configureRateLimiting3
register2
prepareForValidation2
booted2
getLabelsConstant2
__get2
getRawProperty2
get2
getCache2
setCache2
getCache2
setCache2
assertValidPrimaryKey2
assertValidHascode2
boot2
validateValue2
-
-
-
- -
- - - - - - diff --git a/tests/coverage/index.html b/tests/coverage/index.html deleted file mode 100644 index 15c742e..0000000 --- a/tests/coverage/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - Code Coverage for /home/jeremy/projets/crm - - - - - - - -
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
-
- 49.14% covered (danger) -
-
-
49.14%
2235 / 4548
-
- 40.20% covered (danger) -
-
-
40.20%
236 / 587
-
- 36.00% covered (danger) -
-
-
36.00%
54 / 150
app
-
- 41.04% covered (danger) -
-
-
41.04%
1328 / 3236
-
- 38.04% covered (danger) -
-
-
38.04%
159 / 418
-
- 40.16% covered (danger) -
-
-
40.16%
51 / 127
client
-
- 69.13% covered (warning) -
-
-
69.13%
907 / 1312
-
- 45.56% covered (danger) -
-
-
45.56%
77 / 169
-
- 13.04% covered (danger) -
-
-
13.04%
3 / 23
-
- -
- - From 61641660e62ef45421bb6b09d0f29762c9262c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 22 Oct 2026 15:57:51 +0200 Subject: [PATCH 2/8] chore: bump composer (php8.5 with advisories) --- composer.json | 10 +- composer.lock | 3899 ++++++++++++++++++++++++++----------------------- 2 files changed, 2064 insertions(+), 1845 deletions(-) diff --git a/composer.json b/composer.json index 4344564..49c6598 100644 --- a/composer.json +++ b/composer.json @@ -12,16 +12,17 @@ "laravel" ], "platform": { - "php": "^8.3" + "php": "^8.5" }, "repositories": [ { + "name": "lab.s-web.fr", "type": "composer", "url": "https://lab.s-web.fr/api/v4/group/23/-/packages/composer/packages.json" } ], "require": { - "php": "^8.3", + "php": "^8.5", "ext-curl": "*", "ext-dom": "*", "ext-json": "*", @@ -50,7 +51,7 @@ "laravel-lang/common": "^4.0", "mockery/mockery": "^1.4.4", "nunomaduro/collision": "^8.1", - "phpunit/phpunit": "^10.0", + "phpunit/phpunit": "^12.5", "respect/validation": "^2.2", "slevomat/coding-standard": "^8.10", "spatie/laravel-ignition": "^2.3", @@ -65,6 +66,9 @@ "composer/package-versions-deprecated": true, "php-http/discovery": true, "pestphp/pest-plugin": true + }, + "audit": { + "block-insecure": false } }, "extra": { diff --git a/composer.lock b/composer.lock index 16c22e5..6d0b4c5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,34 +4,33 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1417f675b37867e72bdd34d5b0fcf629", + "content-hash": "5c57f125ee6389ff10d80f29bd887be6", "packages": [ { "name": "24slides/laravel-saml2", - "version": "2.4.2", + "version": "2.5.2", "source": { "type": "git", - "url": "https://github.com/24Slides/laravel-saml2.git", - "reference": "e7f4938586c65fbe1fdd91552c582cac745223b9" + "url": "https://github.com/scaler-tech/laravel-saml2.git", + "reference": "d105b12995008ad6d1b40fe239f881ae47dbb553" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/24Slides/laravel-saml2/zipball/e7f4938586c65fbe1fdd91552c582cac745223b9", - "reference": "e7f4938586c65fbe1fdd91552c582cac745223b9", + "url": "https://api.github.com/repos/scaler-tech/laravel-saml2/zipball/d105b12995008ad6d1b40fe239f881ae47dbb553", + "reference": "d105b12995008ad6d1b40fe239f881ae47dbb553", "shasum": "" }, "require": { "ext-openssl": "*", - "illuminate/console": "~5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/database": "~5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/support": "~5.4|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", - "onelogin/php-saml": "^3.0|^4.0", - "php": ">=7.1", - "ramsey/uuid": "^3.8|^4.0" + "illuminate/console": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "illuminate/database": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "onelogin/php-saml": "^3.0 || ^4.0", + "php": ">=7.1" }, "require-dev": { "mockery/mockery": "^0.9.9", - "phpunit/phpunit": "^7.5|^9.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.0", "squizlabs/php_codesniffer": "^2.3" }, "type": "library", @@ -45,7 +44,7 @@ ] }, "branch-aliases": { - "dev-master": "2.0.8-dev" + "dev-master": "2.4.x-dev" } }, "autoload": { @@ -61,13 +60,17 @@ "MIT" ], "authors": [ + { + "name": "Scaler Tech", + "role": "Maintainer" + }, { "name": "Artem Brezhnev", "email": "brezzhnev@gmail.com" } ], - "description": "SAML2 Service Provider integration to your Laravel 5.4+ application, based on OneLogin toolkit", - "homepage": "https://github.com/24slides/laravel-saml2", + "description": "SAML2 Service Provider integration for Laravel applications, based on OneLogin toolkit", + "homepage": "https://github.com/scaler-tech/laravel-saml2", "keywords": [ "SAML2", "SSO", @@ -76,10 +79,11 @@ "saml" ], "support": { - "issues": "https://github.com/24Slides/laravel-saml2/issues", - "source": "https://github.com/24Slides/laravel-saml2/tree/2.4.2" + "issues": "https://github.com/scaler-tech/laravel-saml2/issues", + "source": "https://github.com/scaler-tech/laravel-saml2" }, - "time": "2025-03-12T12:39:37+00:00" + "abandoned": "scaler-tech/laravel-saml2", + "time": "2026-02-15T17:02:55+00:00" }, { "name": "arondeparon/laravel-request-sanitizer", @@ -146,22 +150,22 @@ }, { "name": "axlon/laravel-postal-code-validation", - "version": "v3.7.0", + "version": "v3.10.0", "source": { "type": "git", "url": "https://github.com/axlon/laravel-postal-code-validation.git", - "reference": "20b5483b75556dacb6a2795e70865cc80fa7d492" + "reference": "ad5b9f08acd7c3a07aaebfa29e98e9c04c2ba110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/axlon/laravel-postal-code-validation/zipball/20b5483b75556dacb6a2795e70865cc80fa7d492", - "reference": "20b5483b75556dacb6a2795e70865cc80fa7d492", + "url": "https://api.github.com/repos/axlon/laravel-postal-code-validation/zipball/ad5b9f08acd7c3a07aaebfa29e98e9c04c2ba110", + "reference": "ad5b9f08acd7c3a07aaebfa29e98e9c04c2ba110", "shasum": "" }, "require": { - "illuminate/contracts": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0", - "illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0", - "illuminate/validation": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0", + "illuminate/contracts": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0", + "illuminate/validation": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0", "php": "^7.2 || ^8.0" }, "require-dev": { @@ -206,32 +210,32 @@ ], "support": { "issues": "https://github.com/axlon/laravel-postal-code-validation/issues", - "source": "https://github.com/axlon/laravel-postal-code-validation/tree/v3.7.0" + "source": "https://github.com/axlon/laravel-postal-code-validation/tree/v3.10.0" }, - "time": "2024-09-10T15:23:59+00:00" + "time": "2026-08-09T20:25:46+00:00" }, { "name": "barryvdh/laravel-dompdf", - "version": "v3.1.1", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-dompdf.git", - "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d" + "reference": "ee3b72b19ccdf57d0243116ecb2b90261344dedc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", - "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/ee3b72b19ccdf57d0243116ecb2b90261344dedc", + "reference": "ee3b72b19ccdf57d0243116ecb2b90261344dedc", "shasum": "" }, "require": { "dompdf/dompdf": "^3.0", - "illuminate/support": "^9|^10|^11|^12", + "illuminate/support": "^9|^10|^11|^12|^13.0", "php": "^8.1" }, "require-dev": { "larastan/larastan": "^2.7|^3.0", - "orchestra/testbench": "^7|^8|^9|^10", + "orchestra/testbench": "^7|^8|^9.16|^10|^11.0", "phpro/grumphp": "^2.5", "squizlabs/php_codesniffer": "^3.5" }, @@ -273,7 +277,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-dompdf/issues", - "source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.1" + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.2" }, "funding": [ { @@ -285,29 +289,29 @@ "type": "github" } ], - "time": "2025-02-13T15:07:54+00:00" + "time": "2026-02-21T08:51:10+00:00" }, { "name": "brick/math", - "version": "0.12.1", + "version": "0.14.8", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "f510c0a40911935b77b86859eb5223d58d660df1" + "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", - "reference": "f510c0a40911935b77b86859eb5223d58d660df1", + "url": "https://api.github.com/repos/brick/math/zipball/63422359a44b7f06cae63c3b429b59e8efcc0629", + "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.2" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^10.1", - "vimeo/psalm": "5.16.0" + "phpstan/phpstan": "2.1.22", + "phpunit/phpunit": "^11.5" }, "type": "library", "autoload": { @@ -337,7 +341,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.1" + "source": "https://github.com/brick/math/tree/0.14.8" }, "funding": [ { @@ -345,20 +349,20 @@ "type": "github" } ], - "time": "2023-11-29T23:19:16+00:00" + "time": "2026-02-10T14:33:43+00:00" }, { "name": "carbonphp/carbon-doctrine-types", - "version": "2.1.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", - "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb" + "reference": "bf72f821b9952722ea9f9c3912f85946e1af9e3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", - "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/bf72f821b9952722ea9f9c3912f85946e1af9e3d", + "reference": "bf72f821b9952722ea9f9c3912f85946e1af9e3d", "shasum": "" }, "require": { @@ -398,7 +402,7 @@ ], "support": { "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", - "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0" + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.1" }, "funding": [ { @@ -414,7 +418,7 @@ "type": "tidelift" } ], - "time": "2023-12-11T17:09:12+00:00" + "time": "2026-09-06T14:11:23+00:00" }, { "name": "dflydev/dot-access-data", @@ -562,135 +566,43 @@ }, "time": "2024-03-12T00:42:39+00:00" }, - { - "name": "doctrine/cache", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", - "shasum": "" - }, - "require": { - "php": "~7.1 || ^8.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "keywords": [ - "abstraction", - "apcu", - "cache", - "caching", - "couchdb", - "memcached", - "php", - "redis", - "xcache" - ], - "support": { - "issues": "https://github.com/doctrine/cache/issues", - "source": "https://github.com/doctrine/cache/tree/2.2.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", - "type": "tidelift" - } - ], - "time": "2022-05-20T20:07:39+00:00" - }, { "name": "doctrine/dbal", - "version": "3.9.3", + "version": "3.10.6", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "61446f07fcb522414d6cfd8b1c3e5f9e18c579ba" + "reference": "c95589d775a0b2e543467d40f8c3ecccf586f2b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/61446f07fcb522414d6cfd8b1c3e5f9e18c579ba", - "reference": "61446f07fcb522414d6cfd8b1c3e5f9e18c579ba", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/c95589d775a0b2e543467d40f8c3ecccf586f2b4", + "reference": "c95589d775a0b2e543467d40f8c3ecccf586f2b4", "shasum": "" }, "require": { "composer-runtime-api": "^2", - "doctrine/cache": "^1.11|^2.0", "doctrine/deprecations": "^0.5.3|^1", "doctrine/event-manager": "^1|^2", "php": "^7.4 || ^8.0", "psr/cache": "^1|^2|^3", "psr/log": "^1|^2|^3" }, + "conflict": { + "doctrine/cache": "< 1.11" + }, "require-dev": { - "doctrine/coding-standard": "12.0.0", + "doctrine/cache": "^1.11|^2.0", + "doctrine/coding-standard": "14.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.12.6", - "phpstan/phpstan-strict-rules": "^1.6", - "phpunit/phpunit": "9.6.20", - "psalm/plugin-phpunit": "0.18.4", - "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.10.2", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/console": "^4.4|^5.4|^6.0|^7.0", - "vimeo/psalm": "4.30.0" + "phpstan/phpstan": "2.1.30", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "9.6.34", + "slevomat/coding-standard": "8.27.1", + "squizlabs/php_codesniffer": "4.0.1", + "symfony/cache": "^5.4|^6.0|^7.0|^8.0", + "symfony/console": "^4.4|^5.4|^6.0|^7.0|^8.0" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -750,7 +662,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.9.3" + "source": "https://github.com/doctrine/dbal/tree/3.10.6" }, "funding": [ { @@ -766,30 +678,33 @@ "type": "tidelift" } ], - "time": "2024-10-10T17:56:43+00:00" + "time": "2026-07-21T12:57:49+00:00" }, { "name": "doctrine/deprecations", - "version": "1.1.4", + "version": "1.1.6", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9" + "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/31610dbb31faa98e6b5447b62340826f54fbc4e9", - "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca", + "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=14" + }, "require-dev": { - "doctrine/coding-standard": "^9 || ^12", - "phpstan/phpstan": "1.4.10 || 2.0.3", + "doctrine/coding-standard": "^9 || ^12 || ^14", + "phpstan/phpstan": "1.4.10 || 2.1.30", "phpstan/phpstan-phpunit": "^1.0 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12.4 || ^13.0", "psr/log": "^1 || ^2 || ^3" }, "suggest": { @@ -809,22 +724,22 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.4" + "source": "https://github.com/doctrine/deprecations/tree/1.1.6" }, - "time": "2024-12-07T21:18:45+00:00" + "time": "2026-02-07T07:09:04+00:00" }, { "name": "doctrine/event-manager", - "version": "2.0.1", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e" + "reference": "dda33921b198841ca8dbad2eaa5d4d34769d18cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e", - "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/dda33921b198841ca8dbad2eaa5d4d34769d18cf", + "reference": "dda33921b198841ca8dbad2eaa5d4d34769d18cf", "shasum": "" }, "require": { @@ -834,10 +749,10 @@ "doctrine/common": "<2.9" }, "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.8.8", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.24" + "doctrine/coding-standard": "^14", + "phpdocumentor/guides-cli": "^1.4", + "phpstan/phpstan": "^2.1.32", + "phpunit/phpunit": "^10.5.58" }, "type": "library", "autoload": { @@ -886,7 +801,7 @@ ], "support": { "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.0.1" + "source": "https://github.com/doctrine/event-manager/tree/2.1.1" }, "funding": [ { @@ -902,37 +817,36 @@ "type": "tidelift" } ], - "time": "2024-05-22T20:47:39+00:00" + "time": "2026-01-29T07:11:08+00:00" }, { "name": "doctrine/inflector", - "version": "2.0.10", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^11.0", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.3", - "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25 || ^5.4" + "doctrine/coding-standard": "^12.0 || ^13.0", + "phpstan/phpstan": "^1.12 || ^2.0", + "phpstan/phpstan-phpunit": "^1.4 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", + "phpunit/phpunit": "^8.5 || ^12.2" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + "Doctrine\\Inflector\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -977,7 +891,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.10" + "source": "https://github.com/doctrine/inflector/tree/2.1.0" }, "funding": [ { @@ -993,31 +907,29 @@ "type": "tidelift" } ], - "time": "2024-02-18T20:23:39+00:00" + "time": "2025-08-10T19:31:58+00:00" }, { "name": "doctrine/lexer", - "version": "3.0.1", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + "reference": "71d305eaa6480d3d3460c7d053d1da7749fa9cca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/71d305eaa6480d3d3460c7d053d1da7749fa9cca", + "reference": "71d305eaa6480d3d3460c7d053d1da7749fa9cca", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.21" + "doctrine/coding-standard": "^14", + "phpstan/phpstan": "^2", + "phpunit/phpunit": "^10.5.58 || ^12.5.4" }, "type": "library", "autoload": { @@ -1054,7 +966,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.1" + "source": "https://github.com/doctrine/lexer/tree/3.0.3" }, "funding": [ { @@ -1070,20 +982,20 @@ "type": "tidelift" } ], - "time": "2024-02-05T11:56:58+00:00" + "time": "2026-10-01T06:59:29+00:00" }, { "name": "dompdf/dompdf", - "version": "v3.1.4", + "version": "v3.1.6", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "db712c90c5b9868df3600e64e68da62e78a34623" + "reference": "6d4b4eb8500f7a786da8868ba463a71b725a4005" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/db712c90c5b9868df3600e64e68da62e78a34623", - "reference": "db712c90c5b9868df3600e64e68da62e78a34623", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/6d4b4eb8500f7a786da8868ba463a71b725a4005", + "reference": "6d4b4eb8500f7a786da8868ba463a71b725a4005", "shasum": "" }, "require": { @@ -1132,22 +1044,22 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v3.1.4" + "source": "https://github.com/dompdf/dompdf/tree/v3.1.6" }, - "time": "2025-10-29T12:43:30+00:00" + "time": "2026-07-20T12:29:38+00:00" }, { "name": "dompdf/php-font-lib", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/dompdf/php-font-lib.git", - "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d" + "reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", - "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a6e9a688a2a80016ac080b97be73d3e10c444c9a", + "reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a", "shasum": "" }, "require": { @@ -1155,7 +1067,7 @@ "php": "^7.1 || ^8.0" }, "require-dev": { - "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11 || ^12" }, "type": "library", "autoload": { @@ -1177,31 +1089,31 @@ "homepage": "https://github.com/dompdf/php-font-lib", "support": { "issues": "https://github.com/dompdf/php-font-lib/issues", - "source": "https://github.com/dompdf/php-font-lib/tree/1.0.1" + "source": "https://github.com/dompdf/php-font-lib/tree/1.0.2" }, - "time": "2024-12-02T14:37:59+00:00" + "time": "2026-01-20T14:10:26+00:00" }, { "name": "dompdf/php-svg-lib", - "version": "1.0.0", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af" + "reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af", - "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/8259ffb930817e72b1ff1caef5d226501f3dfeb1", + "reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^7.1 || ^8.0", - "sabberworm/php-css-parser": "^8.4" + "sabberworm/php-css-parser": "^8.4 || ^9.0" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11" }, "type": "library", "autoload": { @@ -1223,35 +1135,34 @@ "homepage": "https://github.com/dompdf/php-svg-lib", "support": { "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0" + "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.2" }, - "time": "2024-04-29T13:26:35+00:00" + "time": "2026-01-02T16:01:13+00:00" }, { "name": "dragonmantank/cron-expression", - "version": "v3.4.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "8c784d071debd117328803d86b2097615b457500" + "reference": "4189372ffeff09bf14f731f67a9de90c7b413ebe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", - "reference": "8c784d071debd117328803d86b2097615b457500", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/4189372ffeff09bf14f731f67a9de90c7b413ebe", + "reference": "4189372ffeff09bf14f731f67a9de90c7b413ebe", "shasum": "" }, "require": { - "php": "^7.2|^8.0", - "webmozart/assert": "^1.0" + "php": "^8.2|^8.3|^8.4|^8.5" }, "replace": { "mtdowling/cron-expression": "^1.0" }, "require-dev": { - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.0", - "phpunit/phpunit": "^7.0|^8.0|^9.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.31", + "phpunit/phpunit": "^11.5.43 || ^12.4" }, "type": "library", "extra": { @@ -1282,7 +1193,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.1" }, "funding": [ { @@ -1290,7 +1201,7 @@ "type": "github" } ], - "time": "2024-10-09T13:47:03+00:00" + "time": "2026-10-19T17:53:57+00:00" }, { "name": "dxw/cidr", @@ -1390,16 +1301,16 @@ }, { "name": "egulias/email-validator", - "version": "4.0.3", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "b115554301161fa21467629f1e1391c1936de517" + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/b115554301161fa21467629f1e1391c1936de517", - "reference": "b115554301161fa21467629f1e1391c1936de517", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", "shasum": "" }, "require": { @@ -1445,7 +1356,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.3" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" }, "funding": [ { @@ -1453,24 +1364,24 @@ "type": "github" } ], - "time": "2024-12-27T00:36:43+00:00" + "time": "2025-03-06T22:45:56+00:00" }, { "name": "ezyang/htmlpurifier", - "version": "v4.18.0", + "version": "v4.19.1", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "cb56001e54359df7ae76dc522d08845dc741621b" + "reference": "5e0539132d934f936fbae2c88b55d58f9438623f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b", - "reference": "cb56001e54359df7ae76dc522d08845dc741621b", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/5e0539132d934f936fbae2c88b55d58f9438623f", + "reference": "5e0539132d934f936fbae2c88b55d58f9438623f", "shasum": "" }, "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { "cerdic/css-tidy": "^1.7 || ^2.0", @@ -1512,9 +1423,9 @@ ], "support": { "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0" + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.19.1" }, - "time": "2024-11-01T03:51:45+00:00" + "time": "2026-09-15T15:42:51+00:00" }, { "name": "facade/ignition-contracts", @@ -1571,31 +1482,31 @@ }, { "name": "fruitcake/php-cors", - "version": "v1.3.0", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/fruitcake/php-cors.git", - "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", - "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", + "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", "shasum": "" }, "require": { - "php": "^7.4|^8.0", - "symfony/http-foundation": "^4.4|^5.4|^6|^7" + "php": "^8.1", + "symfony/http-foundation": "^5.4|^6.4|^7.3|^8" }, "require-dev": { - "phpstan/phpstan": "^1.4", + "phpstan/phpstan": "^2", "phpunit/phpunit": "^9", - "squizlabs/php_codesniffer": "^3.5" + "squizlabs/php_codesniffer": "^4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -1626,7 +1537,7 @@ ], "support": { "issues": "https://github.com/fruitcake/php-cors/issues", - "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + "source": "https://github.com/fruitcake/php-cors/tree/v1.4.0" }, "funding": [ { @@ -1638,20 +1549,20 @@ "type": "github" } ], - "time": "2023-10-12T05:21:21+00:00" + "time": "2025-12-03T09:33:47+00:00" }, { "name": "giggsey/libphonenumber-for-php-lite", - "version": "8.13.52", + "version": "9.0.41", "source": { "type": "git", "url": "https://github.com/giggsey/libphonenumber-for-php-lite.git", - "reference": "9d48e4e112d4a24d46a5fb7c65d000ca3d3faac1" + "reference": "6ffb41a259c950d6f4df5596e32917f631052910" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php-lite/zipball/9d48e4e112d4a24d46a5fb7c65d000ca3d3faac1", - "reference": "9d48e4e112d4a24d46a5fb7c65d000ca3d3faac1", + "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php-lite/zipball/6ffb41a259c950d6f4df5596e32917f631052910", + "reference": "6ffb41a259c950d6f4df5596e32917f631052910", "shasum": "" }, "require": { @@ -1663,18 +1574,19 @@ }, "require-dev": { "ext-dom": "*", - "friendsofphp/php-cs-fixer": "^3.12", - "infection/infection": "^0.28", - "pear/pear-core-minimal": "^1.10.11", - "pear/pear_exception": "^1.0.2", - "pear/versioncontrol_git": "^0.7", - "phing/phing": "^2.17.4", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.2", - "phpunit/phpunit": "^10.5", - "symfony/console": "^6.0", - "symfony/var-exporter": "^6.0" + "friendsofphp/php-cs-fixer": "^3.71", + "infection/infection": "^0.29|^0.31.0", + "nette/php-generator": "^4.1", + "php-coveralls/php-coveralls": "^2.7", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.7", + "phpstan/phpstan-deprecation-rules": "^2.0.1", + "phpstan/phpstan-phpunit": "^2.0.4", + "phpstan/phpstan-strict-rules": "^2.0.3", + "phpunit/phpunit": "^10.5.45", + "symfony/console": "^6.4", + "symfony/filesystem": "^6.4", + "symfony/process": "^6.4" }, "suggest": { "giggsey/libphonenumber-for-php": "Use libphonenumber-for-php for geocoding, carriers, timezones and matching" @@ -1682,19 +1594,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "9.x-dev" } }, "autoload": { "psr-4": { "libphonenumber\\": "src/" - }, - "exclude-from-classmap": [ - "/src/data/", - "/src/carrier/data/", - "/src/geocoding/data/", - "/src/timezone/data/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1721,28 +1627,28 @@ "issues": "https://github.com/giggsey/libphonenumber-for-php-lite/issues", "source": "https://github.com/giggsey/libphonenumber-for-php-lite" }, - "time": "2024-12-13T09:11:09+00:00" + "time": "2026-10-08T08:51:54+00:00" }, { "name": "graham-campbell/result-type", - "version": "v1.1.3", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + "reference": "adccca3324eece92ca35463648c12b9e6293c05b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", - "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/adccca3324eece92ca35463648c12b9e6293c05b", + "reference": "adccca3324eece92ca35463648c12b9e6293c05b", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.3" + "phpoption/phpoption": "^1.10" }, "require-dev": { - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "phpunit/phpunit": "^8.5.52 || ^9.6.34 || ^10.5.63 || ^11.5.55 || ^12.5.14" }, "type": "library", "autoload": { @@ -1771,7 +1677,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.2.0" }, "funding": [ { @@ -1783,29 +1689,30 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:45:45+00:00" + "time": "2026-08-24T09:06:52+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.9.2", + "version": "7.16.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "d281ed313b989f213357e3be1a179f02196ac99b" + "reference": "ffb62ec787050ae4fa9449cdd6b80335db69bda2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", - "reference": "d281ed313b989f213357e3be1a179f02196ac99b", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ffb62ec787050ae4fa9449cdd6b80335db69bda2", + "reference": "ffb62ec787050ae4fa9449cdd6b80335db69bda2", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.3", - "guzzlehttp/psr7": "^2.7.0", + "guzzlehttp/promises": "^2.6", + "guzzlehttp/psr7": "^2.13.2", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", - "symfony/deprecation-contracts": "^2.2 || ^3.0" + "symfony/deprecation-contracts": "^2.5 || ^3.0", + "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-client-implementation": "1.0" @@ -1813,9 +1720,10 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "guzzle/client-integration-tests": "3.0.2", + "guzzle/client-integration-tests": "3.0.3", + "guzzlehttp/test-server": "^0.7", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "phpunit/phpunit": "^8.5.52 || ^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -1893,7 +1801,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.9.2" + "source": "https://github.com/guzzle/guzzle/tree/7.16.0" }, "funding": [ { @@ -1909,28 +1817,29 @@ "type": "tidelift" } ], - "time": "2024-07-24T11:22:20+00:00" + "time": "2026-10-18T13:38:36+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.4", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" + "reference": "3d88c829bd5f13d13847b39067dbf09a60af2154" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", - "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "url": "https://api.github.com/repos/guzzle/promises/zipball/3d88c829bd5f13d13847b39067dbf09a60af2154", + "reference": "3d88c829bd5f13d13847b39067dbf09a60af2154", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0" + "php": "^7.2.5 || ^8.0", + "symfony/deprecation-contracts": "^2.5 || ^3.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "type": "library", "extra": { @@ -1976,7 +1885,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.4" + "source": "https://github.com/guzzle/promises/tree/2.6.0" }, "funding": [ { @@ -1992,27 +1901,29 @@ "type": "tidelift" } ], - "time": "2024-10-17T10:06:22+00:00" + "time": "2026-10-18T12:46:59+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.7.0", + "version": "2.13.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" + "reference": "adee536f95101929f262b8c59e8a61472f347d58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", - "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/adee536f95101929f262b8c59e8a61472f347d58", + "reference": "adee536f95101929f262b8c59e8a61472f347d58", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.1 || ^2.0", - "ralouphie/getallheaders": "^3.0" + "ralouphie/getallheaders": "^3.0", + "symfony/deprecation-contracts": "^2.5 || ^3.0", + "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-factory-implementation": "1.0", @@ -2020,8 +1931,9 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "http-interop/http-factory-tests": "1.1.0", + "jshttp/mime-db": "1.54.0.1", + "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -2092,7 +2004,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.0" + "source": "https://github.com/guzzle/psr7/tree/2.13.2" }, "funding": [ { @@ -2108,29 +2020,29 @@ "type": "tidelift" } ], - "time": "2024-07-18T11:15:46+00:00" + "time": "2026-10-17T23:49:46+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.3", + "version": "v1.0.11", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c" + "reference": "d0058dccf4299d70c3d9da3378b8908b32780368" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/ecea8feef63bd4fef1f037ecb288386999ecc11c", - "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/d0058dccf4299d70c3d9da3378b8908b32780368", + "reference": "d0058dccf4299d70c3d9da3378b8908b32780368", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "symfony/polyfill-php80": "^1.24" + "symfony/polyfill-php80": "^1.25" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.52 || ^9.6.34", "uri-template/tests": "1.0.0" }, "type": "library", @@ -2178,7 +2090,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.3" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.11" }, "funding": [ { @@ -2194,30 +2106,30 @@ "type": "tidelift" } ], - "time": "2023-12-03T19:50:20+00:00" + "time": "2026-08-24T09:15:32+00:00" }, { "name": "intervention/gif", - "version": "4.2.2", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/Intervention/gif.git", - "reference": "5999eac6a39aa760fb803bc809e8909ee67b451a" + "reference": "bb395af960deffe64d70c976b4df9283f68e762d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/gif/zipball/5999eac6a39aa760fb803bc809e8909ee67b451a", - "reference": "5999eac6a39aa760fb803bc809e8909ee67b451a", + "url": "https://api.github.com/repos/Intervention/gif/zipball/bb395af960deffe64d70c976b4df9283f68e762d", + "reference": "bb395af960deffe64d70c976b4df9283f68e762d", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.3" }, "require-dev": { "phpstan/phpstan": "^2.1", - "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "phpunit/phpunit": "^12.0", "slevomat/coding-standard": "~8.0", - "squizlabs/php_codesniffer": "^3.8" + "squizlabs/php_codesniffer": "^4" }, "type": "library", "autoload": { @@ -2236,7 +2148,7 @@ "homepage": "https://intervention.io/" } ], - "description": "Native PHP GIF Encoder/Decoder", + "description": "PHP GIF Encoder/Decoder", "homepage": "https://github.com/intervention/gif", "keywords": [ "animation", @@ -2246,7 +2158,7 @@ ], "support": { "issues": "https://github.com/Intervention/gif/issues", - "source": "https://github.com/Intervention/gif/tree/4.2.2" + "source": "https://github.com/Intervention/gif/tree/5.0.1" }, "funding": [ { @@ -2262,33 +2174,33 @@ "type": "ko_fi" } ], - "time": "2025-03-29T07:46:21+00:00" + "time": "2026-05-03T06:04:47+00:00" }, { "name": "intervention/image", - "version": "3.11.3", + "version": "4.4.0", "source": { "type": "git", "url": "https://github.com/Intervention/image.git", - "reference": "d0f097b8a3fa8fb758efc9440b513aa3833cda17" + "reference": "ddf4d8438493b1e5b98c8f95986cdc127c2b752b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/image/zipball/d0f097b8a3fa8fb758efc9440b513aa3833cda17", - "reference": "d0f097b8a3fa8fb758efc9440b513aa3833cda17", + "url": "https://api.github.com/repos/Intervention/image/zipball/ddf4d8438493b1e5b98c8f95986cdc127c2b752b", + "reference": "ddf4d8438493b1e5b98c8f95986cdc127c2b752b", "shasum": "" }, "require": { "ext-mbstring": "*", - "intervention/gif": "^4.2", - "php": "^8.1" + "intervention/gif": "^5", + "php": "^8.3" }, "require-dev": { + "intervention/coding-standard": "^1", "mockery/mockery": "^1.6", "phpstan/phpstan": "^2.1", - "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", - "slevomat/coding-standard": "~8.0", - "squizlabs/php_codesniffer": "^3.8" + "phpunit/phpunit": "^12.0", + "psr/http-message": "^2" }, "suggest": { "ext-exif": "Recommended to be able to read EXIF data properly." @@ -2307,11 +2219,11 @@ { "name": "Oliver Vogel", "email": "oliver@intervention.io", - "homepage": "https://intervention.io/" + "homepage": "https://intervention.io" } ], - "description": "PHP image manipulation", - "homepage": "https://image.intervention.io/", + "description": "PHP Image Processing", + "homepage": "https://image.intervention.io", "keywords": [ "gd", "image", @@ -2322,7 +2234,7 @@ ], "support": { "issues": "https://github.com/Intervention/image/issues", - "source": "https://github.com/Intervention/image/tree/3.11.3" + "source": "https://github.com/Intervention/image/tree/4.4.0" }, "funding": [ { @@ -2338,20 +2250,20 @@ "type": "ko_fi" } ], - "time": "2025-05-22T17:26:23+00:00" + "time": "2026-10-17T07:53:40+00:00" }, { "name": "jean85/pretty-package-versions", - "version": "2.1.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10" + "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/3c4e5f62ba8d7de1734312e4fff32f67a8daaf10", - "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a", + "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a", "shasum": "" }, "require": { @@ -2361,8 +2273,9 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "jean85/composer-provided-replaced-stub-package": "^1.0", - "phpstan/phpstan": "^1.4", + "phpstan/phpstan": "^2.0", "phpunit/phpunit": "^7.5|^8.5|^9.6", + "rector/rector": "^2.0", "vimeo/psalm": "^4.3 || ^5.0" }, "type": "library", @@ -2395,33 +2308,33 @@ ], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.0" + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1" }, - "time": "2024-11-18T16:19:46+00:00" + "time": "2025-03-19T14:43:43+00:00" }, { "name": "kwaadpepper/image-resizer", - "version": "3.1.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/Kwaadpepper/image-resizer.git", - "reference": "e0747fddc4e31ce57bda9db735060e279ae01780" + "reference": "938b5fe1df035af8441ce38f3e69b937a8c3e49c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Kwaadpepper/image-resizer/zipball/e0747fddc4e31ce57bda9db735060e279ae01780", - "reference": "e0747fddc4e31ce57bda9db735060e279ae01780", + "url": "https://api.github.com/repos/Kwaadpepper/image-resizer/zipball/938b5fe1df035af8441ce38f3e69b937a8c3e49c", + "reference": "938b5fe1df035af8441ce38f3e69b937a8c3e49c", "shasum": "" }, "require": { - "illuminate/support": "~11|~12", - "intervention/image": "^3.6", - "laravel/framework": "~11|~12", - "php": "^8.2" + "illuminate/support": "~11|~12|~13", + "intervention/image": "^4.0", + "laravel/framework": "~11|~12|~13", + "php": "^8.3" }, "require-dev": { - "larastan/larastan": "^2.0", - "orchestra/testbench": "^9.0", + "larastan/larastan": "^3.9", + "orchestra/testbench": "^9.0|^10.0", "slevomat/coding-standard": "^8.11" }, "type": "library", @@ -2457,26 +2370,26 @@ ], "support": { "issues": "https://github.com/Kwaadpepper/image-resizer/issues", - "source": "https://github.com/Kwaadpepper/image-resizer/tree/3.1.0" + "source": "https://github.com/Kwaadpepper/image-resizer/tree/4.0.1" }, - "time": "2025-03-02T07:22:50+00:00" + "time": "2026-03-29T08:24:34+00:00" }, { "name": "laravel/framework", - "version": "v11.37.0", + "version": "v11.57.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "6cb103d2024b087eae207654b3f4b26646119ba5" + "reference": "4fc41929c95024795d83a54309aa4e9922f74263" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/6cb103d2024b087eae207654b3f4b26646119ba5", - "reference": "6cb103d2024b087eae207654b3f4b26646119ba5", + "url": "https://api.github.com/repos/laravel/framework/zipball/4fc41929c95024795d83a54309aa4e9922f74263", + "reference": "4fc41929c95024795d83a54309aa4e9922f74263", "shasum": "" }, "require": { - "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12|^0.13|^0.14", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", "dragonmantank/cron-expression": "^3.4", @@ -2493,12 +2406,12 @@ "guzzlehttp/uri-template": "^1.0", "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", "laravel/serializable-closure": "^1.3|^2.0", - "league/commonmark": "^2.6", + "league/commonmark": "^2.7", "league/flysystem": "^3.25.1", "league/flysystem-local": "^3.25.1", "league/uri": "^7.5.1", "monolog/monolog": "^3.0", - "nesbot/carbon": "^2.72.2|^3.4", + "nesbot/carbon": "^2.72.6|^3.8.4", "nunomaduro/termwind": "^2.0", "php": "^8.2", "psr/container": "^1.1.1|^2.0.1", @@ -2573,17 +2486,18 @@ "fakerphp/faker": "^1.24", "guzzlehttp/promises": "^2.0.3", "guzzlehttp/psr7": "^2.4", + "laravel/pint": "^1.18", "league/flysystem-aws-s3-v3": "^3.25.1", "league/flysystem-ftp": "^3.25.1", "league/flysystem-path-prefixing": "^3.25.1", "league/flysystem-read-only": "^3.25.1", "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", - "orchestra/testbench-core": "^9.6", + "orchestra/testbench-core": "^9.18.0", "pda/pheanstalk": "^5.0.6", "php-http/discovery": "^1.15", - "phpstan/phpstan": "^1.11.5", - "phpunit/phpunit": "^10.5.35|^11.3.6", + "phpstan/phpstan": "2.1.41", + "phpunit/phpunit": "^10.5.35|^11.3.6|^12.0.1", "predis/predis": "^2.3", "resend/resend-php": "^0.10.0", "symfony/cache": "^7.0.3", @@ -2615,7 +2529,7 @@ "mockery/mockery": "Required to use mocking (^1.6).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", - "phpunit/phpunit": "Required to use assertions and run tests (^10.5|^11.0).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1).", "predis/predis": "Required to use the predis connector (^2.3).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", @@ -2673,38 +2587,38 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-01-02T20:10:21+00:00" + "time": "2026-09-29T15:33:27+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.2", + "version": "v0.3.26", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "0e0535747c6b8d6d10adca8b68293cf4517abb0f" + "reference": "2d1e9bf6bab8d3f383c254db7f2b4ea8816d55e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/0e0535747c6b8d6d10adca8b68293cf4517abb0f", - "reference": "0e0535747c6b8d6d10adca8b68293cf4517abb0f", + "url": "https://api.github.com/repos/laravel/prompts/zipball/2d1e9bf6bab8d3f383c254db7f2b4ea8816d55e0", + "reference": "2d1e9bf6bab8d3f383c254db7f2b4ea8816d55e0", "shasum": "" }, "require": { "composer-runtime-api": "^2.2", "ext-mbstring": "*", "php": "^8.1", - "symfony/console": "^6.2|^7.0" + "symfony/console": "^6.2|^7.0|^8.0" }, "conflict": { "illuminate/console": ">=10.17.0 <10.25.0", "laravel/framework": ">=10.17.0 <10.25.0" }, "require-dev": { - "illuminate/collections": "^10.0|^11.0", + "illuminate/collections": "^10.0|^11.0|^12.0|^13.0", "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3|^3.4", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-mockery": "^1.1" + "pestphp/pest": "^2.3|^3.4|^4.0", + "phpstan/phpstan": "^1.12.28", + "phpstan/phpstan-mockery": "^1.1.3" }, "suggest": { "ext-pcntl": "Required for the spinner to be animated." @@ -2729,34 +2643,33 @@ ], "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { - "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.2" + "source": "https://github.com/laravel/prompts/tree/v0.3.26" }, - "time": "2024-11-12T14:59:47+00:00" + "time": "2026-10-09T14:45:13+00:00" }, { "name": "laravel/serializable-closure", - "version": "v2.0.1", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "613b2d4998f85564d40497e05e89cb6d9bd1cbe8" + "reference": "2d5869a838bbcf37e0d8b0568fc41914e81374b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/613b2d4998f85564d40497e05e89cb6d9bd1cbe8", - "reference": "613b2d4998f85564d40497e05e89cb6d9bd1cbe8", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/2d5869a838bbcf37e0d8b0568fc41914e81374b5", + "reference": "2d5869a838bbcf37e0d8b0568fc41914e81374b5", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "illuminate/support": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0|^12.0|^13.0", "nesbot/carbon": "^2.67|^3.0", - "pestphp/pest": "^2.36", + "pestphp/pest": "^2.36|^3.0|^4.0", "phpstan/phpstan": "^2.0", - "symfony/var-dumper": "^6.2.0|^7.0.0" + "symfony/var-dumper": "^6.2.0|^7.0.0|^8.0.0" }, "type": "library", "extra": { @@ -2793,37 +2706,37 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2024-12-16T15:26:28+00:00" + "time": "2026-09-22T14:32:34+00:00" }, { "name": "laravel/tinker", - "version": "v2.10.0", + "version": "v2.11.1", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "ba4d51eb56de7711b3a37d63aa0643e99a339ae5" + "reference": "c9f80cc835649b5c1842898fb043f8cc098dd741" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/ba4d51eb56de7711b3a37d63aa0643e99a339ae5", - "reference": "ba4d51eb56de7711b3a37d63aa0643e99a339ae5", + "url": "https://api.github.com/repos/laravel/tinker/zipball/c9f80cc835649b5c1842898fb043f8cc098dd741", + "reference": "c9f80cc835649b5c1842898fb043f8cc098dd741", "shasum": "" }, "require": { - "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", "php": "^7.2.5|^8.0", "psy/psysh": "^0.11.1|^0.12.0", - "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0|^8.0" }, "require-dev": { "mockery/mockery": "~1.3.3|^1.4.2", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.5.8|^9.3.3" + "phpunit/phpunit": "^8.5.8|^9.3.3|^10.0" }, "suggest": { - "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0)." + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0)." }, "type": "library", "extra": { @@ -2857,35 +2770,35 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.10.0" + "source": "https://github.com/laravel/tinker/tree/v2.11.1" }, - "time": "2024-09-23T13:32:56+00:00" + "time": "2026-02-06T14:12:35+00:00" }, { "name": "laravel/ui", - "version": "v4.6.0", + "version": "v4.6.3", "source": { "type": "git", "url": "https://github.com/laravel/ui.git", - "reference": "a34609b15ae0c0512a0cf47a21695a2729cb7f93" + "reference": "ff27db15416c1ed8ad9848f5692e47595dd5de27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/ui/zipball/a34609b15ae0c0512a0cf47a21695a2729cb7f93", - "reference": "a34609b15ae0c0512a0cf47a21695a2729cb7f93", + "url": "https://api.github.com/repos/laravel/ui/zipball/ff27db15416c1ed8ad9848f5692e47595dd5de27", + "reference": "ff27db15416c1ed8ad9848f5692e47595dd5de27", "shasum": "" }, "require": { - "illuminate/console": "^9.21|^10.0|^11.0", - "illuminate/filesystem": "^9.21|^10.0|^11.0", - "illuminate/support": "^9.21|^10.0|^11.0", - "illuminate/validation": "^9.21|^10.0|^11.0", + "illuminate/console": "^9.21|^10.0|^11.0|^12.0|^13.0", + "illuminate/filesystem": "^9.21|^10.0|^11.0|^12.0|^13.0", + "illuminate/support": "^9.21|^10.0|^11.0|^12.0|^13.0", + "illuminate/validation": "^9.21|^10.0|^11.0|^12.0|^13.0", "php": "^8.0", - "symfony/console": "^6.0|^7.0" + "symfony/console": "^6.0|^7.0|^8.0" }, "require-dev": { - "orchestra/testbench": "^7.35|^8.15|^9.0", - "phpunit/phpunit": "^9.3|^10.4|^11.0" + "orchestra/testbench": "^7.35|^8.15|^9.0|^10.0|^11.0", + "phpunit/phpunit": "^9.3|^10.4|^11.5|^12.5|^13.0" }, "type": "library", "extra": { @@ -2920,22 +2833,22 @@ "ui" ], "support": { - "source": "https://github.com/laravel/ui/tree/v4.6.0" + "source": "https://github.com/laravel/ui/tree/v4.6.3" }, - "time": "2024-11-21T15:06:41+00:00" + "time": "2026-03-17T13:41:52+00:00" }, { "name": "league/commonmark", - "version": "2.6.1", + "version": "2.10.4", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "d990688c91cedfb69753ffc2512727ec646df2ad" + "reference": "40821b7606d8d946bac57dbd2290076c722e3a65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d990688c91cedfb69753ffc2512727ec646df2ad", - "reference": "d990688c91cedfb69753ffc2512727ec646df2ad", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/40821b7606d8d946bac57dbd2290076c722e3a65", + "reference": "40821b7606d8d946bac57dbd2290076c722e3a65", "shasum": "" }, "require": { @@ -2957,14 +2870,14 @@ "github/gfm": "0.29.0", "michelf/php-markdown": "^1.4 || ^2.0", "nyholm/psr7": "^1.5", - "phpstan/phpstan": "^1.8.2", - "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "phpstan/phpstan": "^2.0.0", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0 || ^12.0.0 || ^13.0.0", "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0 | ^7.0", - "symfony/process": "^5.4 | ^6.0 | ^7.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0 || ^8.0", "unleashedtech/php-coding-standard": "^3.1.1", - "vimeo/psalm": "^4.24.0 || ^5.0.0" + "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" }, "suggest": { "symfony/yaml": "v2.3+ required if using the Front Matter extension" @@ -2972,7 +2885,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.7-dev" + "dev-main": "2.11-dev" } }, "autoload": { @@ -3029,7 +2942,7 @@ "type": "tidelift" } ], - "time": "2024-12-29T14:10:59+00:00" + "time": "2026-10-17T19:59:50+00:00" }, { "name": "league/config", @@ -3115,16 +3028,16 @@ }, { "name": "league/csv", - "version": "9.20.1", + "version": "9.28.0", "source": { "type": "git", "url": "https://github.com/thephpleague/csv.git", - "reference": "491d1e79e973a7370c7571dc0fe4a7241f4936ee" + "reference": "6582ace29ae09ba5b07049d40ea13eb19c8b5073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/csv/zipball/491d1e79e973a7370c7571dc0fe4a7241f4936ee", - "reference": "491d1e79e973a7370c7571dc0fe4a7241f4936ee", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/6582ace29ae09ba5b07049d40ea13eb19c8b5073", + "reference": "6582ace29ae09ba5b07049d40ea13eb19c8b5073", "shasum": "" }, "require": { @@ -3134,19 +3047,23 @@ "require-dev": { "ext-dom": "*", "ext-xdebug": "*", - "friendsofphp/php-cs-fixer": "^3.64.0", - "phpbench/phpbench": "^1.3.1", - "phpstan/phpstan": "^1.12.11", + "friendsofphp/php-cs-fixer": "^3.92.3", + "phpbench/phpbench": "^1.4.3", + "phpstan/phpstan": "^1.12.32", "phpstan/phpstan-deprecation-rules": "^1.2.1", - "phpstan/phpstan-phpunit": "^1.4.1", - "phpstan/phpstan-strict-rules": "^1.6.1", - "phpunit/phpunit": "^10.5.16 || ^11.4.3", - "symfony/var-dumper": "^6.4.8 || ^7.1.8" + "phpstan/phpstan-phpunit": "^1.4.2", + "phpstan/phpstan-strict-rules": "^1.6.2", + "phpunit/phpunit": "^10.5.16 || ^11.5.22 || ^12.5.4", + "symfony/var-dumper": "^6.4.8 || ^7.4.0 || ^8.0" }, "suggest": { "ext-dom": "Required to use the XMLConverter and the HTMLConverter classes", "ext-iconv": "Needed to ease transcoding CSV using iconv stream filters", - "ext-mbstring": "Needed to ease transcoding CSV using mb stream filters" + "ext-mbstring": "Needed to ease transcoding CSV using mb stream filters", + "ext-mysqli": "Requiered to use the package with the MySQLi extension", + "ext-pdo": "Required to use the package with the PDO extension", + "ext-pgsql": "Requiered to use the package with the PgSQL extension", + "ext-sqlite3": "Required to use the package with the SQLite3 extension" }, "type": "library", "extra": { @@ -3159,7 +3076,7 @@ "src/functions_include.php" ], "psr-4": { - "League\\Csv\\": "src/" + "League\\Csv\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -3198,20 +3115,20 @@ "type": "github" } ], - "time": "2024-12-18T10:11:15+00:00" + "time": "2025-12-27T15:18:42+00:00" }, { "name": "league/flysystem", - "version": "3.29.1", + "version": "3.36.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" + "reference": "f7fb152932f30072d573510cbd4dd657d6475b25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", - "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/f7fb152932f30072d573510cbd4dd657d6475b25", + "reference": "f7fb152932f30072d573510cbd4dd657d6475b25", "shasum": "" }, "require": { @@ -3235,13 +3152,13 @@ "composer/semver": "^3.0", "ext-fileinfo": "*", "ext-ftp": "*", - "ext-mongodb": "^1.3", + "ext-mongodb": "^1.3|^2", "ext-zip": "*", "friendsofphp/php-cs-fixer": "^3.5", "google/cloud-storage": "^1.23", "guzzlehttp/psr7": "^2.6", "microsoft/azure-storage-blob": "^1.1", - "mongodb/mongodb": "^1.2", + "mongodb/mongodb": "^1.2|^2", "phpseclib/phpseclib": "^3.0.36", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.5.11|^10.0", @@ -3279,22 +3196,22 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.29.1" + "source": "https://github.com/thephpleague/flysystem/tree/3.36.0" }, - "time": "2024-10-08T08:58:34+00:00" + "time": "2026-09-02T08:00:27+00:00" }, { "name": "league/flysystem-local", - "version": "3.29.0", + "version": "3.35.3", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", - "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27" + "reference": "a099b24dce160f3b2239043d13d47c4a1a214ea4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27", - "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/a099b24dce160f3b2239043d13d47c4a1a214ea4", + "reference": "a099b24dce160f3b2239043d13d47c4a1a214ea4", "shasum": "" }, "require": { @@ -3328,22 +3245,22 @@ "local" ], "support": { - "source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.35.3" }, - "time": "2024-08-09T21:24:39+00:00" + "time": "2026-08-12T13:29:21+00:00" }, { "name": "league/mime-type-detection", - "version": "1.16.0", + "version": "1.17.0", "source": { "type": "git", "url": "https://github.com/thephpleague/mime-type-detection.git", - "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + "reference": "f5f47eff7c48ed1003069a2ca67f316fb4021c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", - "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/f5f47eff7c48ed1003069a2ca67f316fb4021c76", + "reference": "f5f47eff7c48ed1003069a2ca67f316fb4021c76", "shasum": "" }, "require": { @@ -3353,7 +3270,7 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "phpstan/phpstan": "^0.12.68", - "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0 || ^11.0 || ^12.0" }, "type": "library", "autoload": { @@ -3374,7 +3291,7 @@ "description": "Mime-type detection for Flysystem", "support": { "issues": "https://github.com/thephpleague/mime-type-detection/issues", - "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.17.0" }, "funding": [ { @@ -3386,37 +3303,43 @@ "type": "tidelift" } ], - "time": "2024-09-21T08:32:55+00:00" + "time": "2026-07-09T11:49:27+00:00" }, { "name": "league/uri", - "version": "7.5.1", + "version": "7.9.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "81fb5145d2644324614cc532b28efd0215bda430" + "reference": "fcc872a3d872aa13f935e0cd1887b9abb06da07f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", - "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/fcc872a3d872aa13f935e0cd1887b9abb06da07f", + "reference": "fcc872a3d872aa13f935e0cd1887b9abb06da07f", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.5", - "php": "^8.1" + "ext-mbstring": "*", + "league/uri-interfaces": "^7.9.0", + "php": "^8.1", + "psr/http-factory": "^1" }, "conflict": { "league/uri-schemes": "^1.0" }, "suggest": { "ext-bcmath": "to improve IPV4 host parsing", + "ext-dom": "to convert the URI into an HTML anchor tag", "ext-fileinfo": "to create Data URI from file contennts", "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", - "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", - "league/uri-components": "Needed to easily manipulate URI objects components", + "ext-uri": "to use the PHP native URI class", + "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain", + "league/uri-components": "to provide additional tools to manipulate URI objects components", + "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP", "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -3444,6 +3367,7 @@ "description": "URI manipulation library", "homepage": "https://uri.thephpleague.com", "keywords": [ + "URN", "data-uri", "file-uri", "ftp", @@ -3456,9 +3380,11 @@ "psr-7", "query-string", "querystring", + "rfc2141", "rfc3986", "rfc3987", "rfc6570", + "rfc8141", "uri", "uri-template", "url", @@ -3468,7 +3394,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri/tree/7.5.1" + "source": "https://github.com/thephpleague/uri/tree/7.9.0" }, "funding": [ { @@ -3476,26 +3402,25 @@ "type": "github" } ], - "time": "2024-12-08T08:40:02+00:00" + "time": "2026-10-16T15:19:33+00:00" }, { "name": "league/uri-interfaces", - "version": "7.5.0", + "version": "7.9.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + "reference": "eb5f6d24e6a4fe0a8e9c78ded4eb1dfff1404f58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", - "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/eb5f6d24e6a4fe0a8e9c78ded4eb1dfff1404f58", + "reference": "eb5f6d24e6a4fe0a8e9c78ded4eb1dfff1404f58", "shasum": "" }, "require": { "ext-filter": "*", "php": "^8.1", - "psr/http-factory": "^1", "psr/http-message": "^1.1 || ^2.0" }, "suggest": { @@ -3503,6 +3428,7 @@ "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -3527,7 +3453,7 @@ "homepage": "https://nyamsprod.com" } ], - "description": "Common interfaces and classes for URI representation and interaction", + "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI", "homepage": "https://uri.thephpleague.com", "keywords": [ "data-uri", @@ -3552,7 +3478,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.9.0" }, "funding": [ { @@ -3560,28 +3486,28 @@ "type": "github" } ], - "time": "2024-12-08T08:18:47+00:00" + "time": "2026-10-16T15:19:33+00:00" }, { "name": "masterminds/html5", - "version": "2.10.0", + "version": "2.11.0", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "fcf91eb64359852f00d921887b219479b4f21251" + "reference": "a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251", - "reference": "fcf91eb64359852f00d921887b219479b4f21251", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7", + "reference": "a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7", "shasum": "" }, "require": { "ext-dom": "*", - "php": ">=5.3.0" + "php": ">=7.4" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" + "phpunit/phpunit": "^6 || ^7 || ^8 || ^9 || ^10" }, "type": "library", "extra": { @@ -3625,29 +3551,29 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.10.0" + "source": "https://github.com/Masterminds/html5-php/tree/2.11.0" }, - "time": "2025-07-25T09:04:22+00:00" + "time": "2026-08-18T06:18:41+00:00" }, { "name": "mews/purifier", - "version": "3.4.2", + "version": "3.4.4", "source": { "type": "git", "url": "https://github.com/mewebstudio/Purifier.git", - "reference": "d4d3830267eeda7b385d61dd680ace14dcf142df" + "reference": "b2705cc6c832ce7229373418e191d71b6c037841" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mewebstudio/Purifier/zipball/d4d3830267eeda7b385d61dd680ace14dcf142df", - "reference": "d4d3830267eeda7b385d61dd680ace14dcf142df", + "url": "https://api.github.com/repos/mewebstudio/Purifier/zipball/b2705cc6c832ce7229373418e191d71b6c037841", + "reference": "b2705cc6c832ce7229373418e191d71b6c037841", "shasum": "" }, "require": { "ezyang/htmlpurifier": "^4.16.0", - "illuminate/config": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/filesystem": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/support": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/config": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/filesystem": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/support": "^5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^7.2|^8.0" }, "require-dev": { @@ -3703,22 +3629,22 @@ ], "support": { "issues": "https://github.com/mewebstudio/Purifier/issues", - "source": "https://github.com/mewebstudio/Purifier/tree/3.4.2" + "source": "https://github.com/mewebstudio/Purifier/tree/3.4.4" }, - "time": "2024-03-20T16:18:22+00:00" + "time": "2026-04-15T16:41:08+00:00" }, { "name": "monolog/monolog", - "version": "3.8.1", + "version": "3.12.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4" + "reference": "d7059e4c691d05ea1222b5124bed0f961be46e15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/aef6ee73a77a66e404dd6540934a9ef1b3c855b4", - "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/d7059e4c691d05ea1222b5124bed0f961be46e15", + "reference": "d7059e4c691d05ea1222b5124bed0f961be46e15", "shasum": "" }, "require": { @@ -3736,7 +3662,7 @@ "graylog2/gelf-php": "^1.4.2 || ^2.0", "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", - "mongodb/mongodb": "^1.8", + "mongodb/mongodb": "^1.8 || ^2.0", "php-amqplib/php-amqplib": "~2.4 || ^3", "php-console/php-console": "^3.1.8", "phpstan/phpstan": "^2", @@ -3744,6 +3670,7 @@ "phpstan/phpstan-strict-rules": "^2", "phpunit/phpunit": "^10.5.17 || ^11.0.7", "predis/predis": "^1.1 || ^2", + "psr/clock": "^1.0", "rollbar/rollbar": "^4.0", "ruflin/elastica": "^7 || ^8", "symfony/mailer": "^5.4 || ^6", @@ -3762,6 +3689,7 @@ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "psr/clock": "Required to pass a clock to the Logger and control the timestamp of log records", "rollbar/rollbar": "Allow sending log messages to Rollbar", "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, @@ -3796,7 +3724,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.8.1" + "source": "https://github.com/Seldaek/monolog/tree/3.12.1" }, "funding": [ { @@ -3808,20 +3736,20 @@ "type": "tidelift" } ], - "time": "2024-12-05T17:15:07+00:00" + "time": "2026-09-29T19:21:12+00:00" }, { "name": "nesbot/carbon", - "version": "3.8.4", + "version": "3.15.0", "source": { "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "129700ed449b1f02d70272d2ac802357c8c30c58" + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "217d38553209bdb44e01590d9e9a2e4df8354cce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/129700ed449b1f02d70272d2ac802357c8c30c58", - "reference": "129700ed449b1f02d70272d2ac802357c8c30c58", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/217d38553209bdb44e01590d9e9a2e4df8354cce", + "reference": "217d38553209bdb44e01590d9e9a2e4df8354cce", "shasum": "" }, "require": { @@ -3829,9 +3757,10 @@ "ext-json": "*", "php": "^8.1", "psr/clock": "^1.0", - "symfony/clock": "^6.3 || ^7.0", + "symfony/clock": "^6.3.12 || ^7.0 || ^8.0", "symfony/polyfill-mbstring": "^1.0", - "symfony/translation": "^4.4.18 || ^5.2.1|| ^6.0 || ^7.0" + "symfony/polyfill-time": "^1.0", + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0 || ^8.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -3839,14 +3768,13 @@ "require-dev": { "doctrine/dbal": "^3.6.3 || ^4.0", "doctrine/orm": "^2.15.2 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.57.2", + "friendsofphp/php-cs-fixer": "^v3.87.1", "kylekatarnls/multi-tester": "^2.5.3", - "ondrejmirtes/better-reflection": "^6.25.0.4", - "phpmd/phpmd": "^2.15.0", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.11.2", - "phpunit/phpunit": "^10.5.20", - "squizlabs/php_codesniffer": "^3.9.0" + "phpmd/phpmd": "^3.0@dev", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.22", + "phpunit/phpunit": "^10.5.53", + "squizlabs/php_codesniffer": "^3.13.4 || ^4.0.0" }, "bin": [ "bin/carbon" @@ -3889,16 +3817,16 @@ } ], "description": "An API extension for DateTime that supports 281 different languages.", - "homepage": "https://carbon.nesbot.com", + "homepage": "https://carbonphp.github.io/carbon/", "keywords": [ "date", "datetime", "time" ], "support": { - "docs": "https://carbon.nesbot.com/docs", - "issues": "https://github.com/briannesbitt/Carbon/issues", - "source": "https://github.com/briannesbitt/Carbon" + "docs": "https://carbonphp.github.io/carbon/guide/getting-started/introduction.html", + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" }, "funding": [ { @@ -3914,38 +3842,43 @@ "type": "tidelift" } ], - "time": "2024-12-27T09:25:35+00:00" + "time": "2026-10-18T18:27:53+00:00" }, { "name": "nette/schema", - "version": "v1.3.2", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "da801d52f0354f70a638673c4a0f04e16529431d" + "reference": "af9fa8a86bfca9b02b10346220db26e62ef942ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", - "reference": "da801d52f0354f70a638673c4a0f04e16529431d", + "url": "https://api.github.com/repos/nette/schema/zipball/af9fa8a86bfca9b02b10346220db26e62ef942ec", + "reference": "af9fa8a86bfca9b02b10346220db26e62ef942ec", "shasum": "" }, "require": { "nette/utils": "^4.0", - "php": "8.1 - 8.4" + "php": "8.1 - 8.6" }, "require-dev": { - "nette/tester": "^2.5.2", - "phpstan/phpstan-nette": "^1.0", + "nette/phpstan-rules": "^1.0.7", + "nette/tester": "^2.6", + "phpstan/extension-installer": "^1.4@stable", + "phpstan/phpstan": "^2.3@stable", "tracy/tracy": "^2.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.4-dev" } }, "autoload": { + "psr-4": { + "Nette\\": "src" + }, "classmap": [ "src/" ] @@ -3960,54 +3893,56 @@ { "name": "David Grudl", "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" } ], - "description": "📐 Nette Schema: validating data structures against a given Schema.", - "homepage": "https://nette.org", + "description": "📐 Nette Schema: validates and normalizes data such as configuration or API input against a schema described in a few readable lines of PHP, with precise error messages.", + "homepage": "https://doc.nette.org/schema", "keywords": [ - "config", - "nette" + "configuration", + "data validation", + "nette", + "normalization", + "schema", + "validation" ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.2" + "source": "https://github.com/nette/schema/tree/v1.4.0" }, - "time": "2024-10-06T23:10:23+00:00" + "time": "2026-10-22T02:12:50+00:00" }, { "name": "nette/utils", - "version": "v4.0.5", + "version": "v4.1.6", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96" + "reference": "6bf24518accf32cf845bca305e0b92078700fd01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/736c567e257dbe0fcf6ce81b4d6dbe05c6899f96", - "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96", + "url": "https://api.github.com/repos/nette/utils/zipball/6bf24518accf32cf845bca305e0b92078700fd01", + "reference": "6bf24518accf32cf845bca305e0b92078700fd01", "shasum": "" }, "require": { - "php": "8.0 - 8.4" + "php": "8.2 - 8.6" }, "conflict": { "nette/finder": "<3", "nette/schema": "<1.2.2" }, "require-dev": { - "jetbrains/phpstorm-attributes": "dev-master", + "jetbrains/phpstorm-attributes": "^1.2", + "nette/phpstan-rules": "^1.0", "nette/tester": "^2.5", - "phpstan/phpstan": "^1.0", + "phpstan/extension-installer": "^1.4@stable", + "phpstan/phpstan": "^2.1@stable", "tracy/tracy": "^2.9" }, "suggest": { "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-iconv": "to use Strings::chr(), ord() and reverse()", "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", "ext-json": "to use Nette\\Utils\\Json", "ext-mbstring": "to use Strings::lower() etc...", @@ -4016,10 +3951,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { + "psr-4": { + "Nette\\": "src" + }, "classmap": [ "src/" ] @@ -4060,26 +3998,25 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.5" + "source": "https://github.com/nette/utils/tree/v4.1.6" }, - "time": "2024-08-07T15:39:19+00:00" + "time": "2026-10-20T17:07:56+00:00" }, { "name": "nikic/php-parser", - "version": "v5.4.0", + "version": "v5.9.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + "reference": "9e33da9553fe7786f0962b35f4e4ecf01be89def" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/9e33da9553fe7786f0962b35f4e4ecf01be89def", + "reference": "9e33da9553fe7786f0962b35f4e4ecf01be89def", "shasum": "" }, "require": { - "ext-ctype": "*", "ext-json": "*", "ext-tokenizer": "*", "php": ">=7.4" @@ -4094,7 +4031,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -4118,37 +4055,37 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.9.0" }, - "time": "2024-12-30T11:07:19+00:00" + "time": "2026-09-13T18:51:52+00:00" }, { "name": "nunomaduro/termwind", - "version": "v2.3.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda" + "reference": "712a31b768f5daea284c2169a7d227031001b9a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda", - "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/712a31b768f5daea284c2169a7d227031001b9a8", + "reference": "712a31b768f5daea284c2169a7d227031001b9a8", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.1.8" + "symfony/console": "^7.4.4 || ^8.0.4" }, "require-dev": { - "illuminate/console": "^11.33.2", - "laravel/pint": "^1.18.2", + "illuminate/console": "^11.47.0", + "laravel/pint": "^1.27.1", "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0", - "phpstan/phpstan": "^1.12.11", - "phpstan/phpstan-strict-rules": "^1.6.1", - "symfony/var-dumper": "^7.1.8", + "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.3.2", + "phpstan/phpstan": "^1.12.32", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.3.5 || ^8.0.4", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -4180,7 +4117,7 @@ "email": "enunomaduro@gmail.com" } ], - "description": "Its like Tailwind CSS, but for the console.", + "description": "It's like Tailwind CSS, but for the console.", "keywords": [ "cli", "console", @@ -4191,7 +4128,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.0" + "source": "https://github.com/nunomaduro/termwind/tree/v2.4.0" }, "funding": [ { @@ -4207,7 +4144,7 @@ "type": "github" } ], - "time": "2024-11-21T10:39:51+00:00" + "time": "2026-02-16T23:10:27+00:00" }, { "name": "nyholm/psr7", @@ -4289,21 +4226,21 @@ }, { "name": "onelogin/php-saml", - "version": "4.3.0", + "version": "4.3.2", "source": { "type": "git", "url": "https://github.com/SAML-Toolkits/php-saml.git", - "reference": "bf5efce9f2df5d489d05e78c27003a0fc8bc50f0" + "reference": "26b3a47349415e5b7aa300ba4ab7fc316c65f19e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SAML-Toolkits/php-saml/zipball/bf5efce9f2df5d489d05e78c27003a0fc8bc50f0", - "reference": "bf5efce9f2df5d489d05e78c27003a0fc8bc50f0", + "url": "https://api.github.com/repos/SAML-Toolkits/php-saml/zipball/26b3a47349415e5b7aa300ba4ab7fc316c65f19e", + "reference": "26b3a47349415e5b7aa300ba4ab7fc316c65f19e", "shasum": "" }, "require": { "php": ">=7.3", - "robrichards/xmlseclibs": "^3.1" + "robrichards/xmlseclibs": "^3.1.5" }, "require-dev": { "pdepend/pdepend": "^2.8.0", @@ -4349,20 +4286,20 @@ "type": "github" } ], - "time": "2025-05-25T14:28:00+00:00" + "time": "2026-05-07T22:38:04+00:00" }, { "name": "phpoption/phpoption", - "version": "1.9.3", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + "reference": "67b192b6a42ec03944b972d6e633ddec78ad2c6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/67b192b6a42ec03944b972d6e633ddec78ad2c6d", + "reference": "67b192b6a42ec03944b972d6e633ddec78ad2c6d", "shasum": "" }, "require": { @@ -4370,7 +4307,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "phpunit/phpunit": "^8.5.54 || ^9.6.36 || ^10.5.64 || ^11.5.56 || ^12.5.33" }, "type": "library", "extra": { @@ -4412,7 +4349,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + "source": "https://github.com/schmittjoh/php-option/tree/1.10.0" }, "funding": [ { @@ -4424,20 +4361,20 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:41:07+00:00" + "time": "2026-08-24T00:54:40+00:00" }, { "name": "phpseclib/phpseclib", - "version": "2.0.48", + "version": "2.0.55", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "eaa7be704b8b93a6913b69eb7f645a59d7731b61" + "reference": "d73c9e019a895be83b18a2ccccfa7e2b0a648743" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/eaa7be704b8b93a6913b69eb7f645a59d7731b61", - "reference": "eaa7be704b8b93a6913b69eb7f645a59d7731b61", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d73c9e019a895be83b18a2ccccfa7e2b0a648743", + "reference": "d73c9e019a895be83b18a2ccccfa7e2b0a648743", "shasum": "" }, "require": { @@ -4445,7 +4382,7 @@ }, "require-dev": { "phing/phing": "~2.7", - "phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0|^8.5|^9.4", "squizlabs/php_codesniffer": "~2.0" }, "suggest": { @@ -4518,7 +4455,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/2.0.48" + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.55" }, "funding": [ { @@ -4534,33 +4471,33 @@ "type": "tidelift" } ], - "time": "2024-12-14T21:03:54+00:00" + "time": "2026-06-14T19:53:12+00:00" }, { "name": "propaganistas/laravel-phone", - "version": "5.3.3", + "version": "5.3.6", "source": { "type": "git", "url": "https://github.com/Propaganistas/Laravel-Phone.git", - "reference": "2172362ae5714ddc397d9df96a44b82bd125631a" + "reference": "89f26e8336cf8f8041609148b4fef752f0bd720e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Propaganistas/Laravel-Phone/zipball/2172362ae5714ddc397d9df96a44b82bd125631a", - "reference": "2172362ae5714ddc397d9df96a44b82bd125631a", + "url": "https://api.github.com/repos/Propaganistas/Laravel-Phone/zipball/89f26e8336cf8f8041609148b4fef752f0bd720e", + "reference": "89f26e8336cf8f8041609148b4fef752f0bd720e", "shasum": "" }, "require": { - "giggsey/libphonenumber-for-php-lite": "^8.13.35", - "illuminate/contracts": "^10.0|^11.0", - "illuminate/support": "^10.0|^11.0", - "illuminate/validation": "^10.0|^11.0", + "giggsey/libphonenumber-for-php-lite": "^8.13.35|^9.0.0", + "illuminate/contracts": "^10.0|^11.0|^12.0", + "illuminate/support": "^10.0|^11.0|^12.0", + "illuminate/validation": "^10.0|^11.0|^12.0", "php": "^8.1" }, "require-dev": { "laravel/pint": "^1.14", "orchestra/testbench": "*", - "phpunit/phpunit": "^10.5" + "phpunit/phpunit": "^10.5|^11.5.3" }, "type": "library", "extra": { @@ -4597,7 +4534,7 @@ ], "support": { "issues": "https://github.com/Propaganistas/Laravel-Phone/issues", - "source": "https://github.com/Propaganistas/Laravel-Phone/tree/5.3.3" + "source": "https://github.com/Propaganistas/Laravel-Phone/tree/5.3.6" }, "funding": [ { @@ -4605,7 +4542,7 @@ "type": "github" } ], - "time": "2024-12-27T11:45:47+00:00" + "time": "2025-03-21T09:07:26+00:00" }, { "name": "psr/cache", @@ -5070,16 +5007,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.7", + "version": "v0.12.24", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "d73fa3c74918ef4522bb8a3bf9cab39161c4b57c" + "reference": "ca0fdcf8a7617afa3adfdf1b5fef573dffb69ca1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/d73fa3c74918ef4522bb8a3bf9cab39161c4b57c", - "reference": "d73fa3c74918ef4522bb8a3bf9cab39161c4b57c", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/ca0fdcf8a7617afa3adfdf1b5fef573dffb69ca1", + "reference": "ca0fdcf8a7617afa3adfdf1b5fef573dffb69ca1", "shasum": "" }, "require": { @@ -5087,18 +5024,19 @@ "ext-tokenizer": "*", "nikic/php-parser": "^5.0 || ^4.0", "php": "^8.0 || ^7.4", - "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", - "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + "symfony/console": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" }, "conflict": { "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.2" + "bamarni/composer-bin-plugin": "^1.2", + "composer/class-map-generator": "^1.6" }, "suggest": { + "composer/class-map-generator": "Improved tab completion performance with better class discovery.", "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", - "ext-pdo-sqlite": "The doc command requires SQLite to work.", "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." }, "bin": [ @@ -5129,12 +5067,11 @@ "authors": [ { "name": "Justin Hileman", - "email": "justin@justinhileman.info", - "homepage": "http://justinhileman.com" + "email": "justin@justinhileman.info" } ], "description": "An interactive shell for modern PHP.", - "homepage": "http://psysh.org", + "homepage": "https://psysh.org", "keywords": [ "REPL", "console", @@ -5143,9 +5080,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.7" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.24" }, - "time": "2024-12-10T01:58:33+00:00" + "time": "2026-06-29T15:41:09+00:00" }, { "name": "ralouphie/getallheaders", @@ -5193,16 +5130,16 @@ }, { "name": "ramsey/collection", - "version": "2.0.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", - "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", "shasum": "" }, "require": { @@ -5210,25 +5147,22 @@ }, "require-dev": { "captainhook/plugin-composer": "^5.3", - "ergebnis/composer-normalize": "^2.28.3", - "fakerphp/faker": "^1.21", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", "hamcrest/hamcrest-php": "^2.0", - "jangregor/phpstan-prophecy": "^1.0", - "mockery/mockery": "^1.5", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpcsstandards/phpcsutils": "^1.0.0-rc1", - "phpspec/prophecy-phpunit": "^2.0", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5", - "psalm/plugin-mockery": "^1.1", - "psalm/plugin-phpunit": "^0.18.4", - "ramsey/coding-standard": "^2.0.3", - "ramsey/conventional-commits": "^1.3", - "vimeo/psalm": "^5.4" + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" }, "type": "library", "extra": { @@ -5266,37 +5200,26 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/2.0.0" + "source": "https://github.com/ramsey/collection/tree/2.1.1" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", - "type": "tidelift" - } - ], - "time": "2022-12-31T21:50:55+00:00" + "time": "2025-03-22T05:38:12+00:00" }, { "name": "ramsey/uuid", - "version": "4.7.6", + "version": "4.9.4", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + "reference": "75d73f48d02797c2c285a7e9f348fadc0102ffe2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/75d73f48d02797c2c285a7e9f348fadc0102ffe2", + "reference": "75d73f48d02797c2c285a7e9f348fadc0102ffe2", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", - "ext-json": "*", + "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14 || ^0.15 || ^0.16 || ^0.17 || ^0.18 || ^0.19 || ^0.20 || ^1.0", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -5304,26 +5227,23 @@ "rhumsaa/uuid": "self.version" }, "require-dev": { - "captainhook/captainhook": "^5.10", + "captainhook/captainhook": "^5.25", "captainhook/plugin-composer": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "doctrine/annotations": "^1.8", - "ergebnis/composer-normalize": "^2.15", - "mockery/mockery": "^1.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", "paragonie/random-lib": "^2", - "php-mock/php-mock": "^2.2", - "php-mock/php-mock-mockery": "^1.3", - "php-parallel-lint/php-parallel-lint": "^1.1", - "phpbench/phpbench": "^1.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^8.5 || ^9", - "ramsey/composer-repl": "^1.4", - "slevomat/coding-standard": "^8.4", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.9" + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" }, "suggest": { "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", @@ -5358,32 +5278,22 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.6" + "source": "https://github.com/ramsey/uuid/tree/4.9.4" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", - "type": "tidelift" - } - ], - "time": "2024-04-27T21:32:50+00:00" + "time": "2026-09-16T11:39:30+00:00" }, { "name": "robrichards/xmlseclibs", - "version": "3.1.3", + "version": "3.1.5", "source": { "type": "git", "url": "https://github.com/robrichards/xmlseclibs.git", - "reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07" + "reference": "03062be78178cbb5e8f605cd255dc32a14981f92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/2bdfd742624d739dfadbd415f00181b4a77aaf07", - "reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07", + "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/03062be78178cbb5e8f605cd255dc32a14981f92", + "reference": "03062be78178cbb5e8f605cd255dc32a14981f92", "shasum": "" }, "require": { @@ -5410,31 +5320,39 @@ ], "support": { "issues": "https://github.com/robrichards/xmlseclibs/issues", - "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.3" + "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.5" }, - "time": "2024-11-20T21:13:56+00:00" + "time": "2026-03-13T10:31:56+00:00" }, { "name": "sabberworm/php-css-parser", - "version": "v8.9.0", + "version": "v9.5.0", "source": { "type": "git", "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", - "reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9" + "reference": "f284e63b6e891e0c28631e54ba06c3ed102a9ef3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d8e916507b88e389e26d4ab03c904a082aa66bb9", - "reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/f284e63b6e891e0c28631e54ba06c3ed102a9ef3", + "reference": "f284e63b6e891e0c28631e54ba06c3ed102a9ef3", "shasum": "" }, "require": { "ext-iconv": "*", - "php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0 || ~8.6.0" }, "require-dev": { - "phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41", - "rawr/cross-data-providers": "^2.0.0" + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/extension-installer": "1.4.3", + "phpstan/phpstan": "1.12.33 || 2.2.9", + "phpstan/phpstan-phpunit": "1.4.2 || 2.0.18", + "phpstan/phpstan-strict-rules": "1.6.2 || 2.0.12", + "phpunit/phpunit": "8.5.54", + "rawr/phpunit-data-provider": "3.3.1", + "rector/rector": "1.2.10 || 2.6.2", + "rector/type-perfect": "1.0.0 || 2.1.4", + "squizlabs/php_codesniffer": "4.0.4" }, "suggest": { "ext-mbstring": "for parsing UTF-8 CSS" @@ -5442,10 +5360,14 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "9.0.x-dev" + "dev-main": "9.6.x-dev" } }, "autoload": { + "files": [ + "src/Rule/Rule.php", + "src/RuleSet/RuleContainer.php" + ], "psr-4": { "Sabberworm\\CSS\\": "src/" } @@ -5476,49 +5398,57 @@ ], "support": { "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", - "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.9.0" + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.5.0" }, - "time": "2025-07-11T13:20:48+00:00" + "time": "2026-09-20T15:02:00+00:00" }, { "name": "sentry/sentry", - "version": "4.10.0", + "version": "4.34.0", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "2af937d47d8aadb8dab0b1d7b9557e495dd12856" + "reference": "3d8f4e56becb10ede64e2ac6f8077f6434715461" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/2af937d47d8aadb8dab0b1d7b9557e495dd12856", - "reference": "2af937d47d8aadb8dab0b1d7b9557e495dd12856", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/3d8f4e56becb10ede64e2ac6f8077f6434715461", + "reference": "3d8f4e56becb10ede64e2ac6f8077f6434715461", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "guzzlehttp/psr7": "^1.8.4|^2.1.1", + "guzzlehttp/psr7": "^1.8.4|^2.1.1|^3.0.0", "jean85/pretty-package-versions": "^1.5|^2.0.4", "php": "^7.2|^8.0", "psr/log": "^1.0|^2.0|^3.0", - "symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0" + "symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0|^8.0" }, "conflict": { "raven/raven": "*" }, "require-dev": { + "carthage-software/mago": "1.30.0", "friendsofphp/php-cs-fixer": "^3.4", - "guzzlehttp/promises": "^2.0.3", - "guzzlehttp/psr7": "^1.8.4|^2.1.1", + "guzzlehttp/guzzle": "^7.0|^8.0", + "guzzlehttp/promises": "^2.0.3|^3.0.0", "monolog/monolog": "^1.6|^2.0|^3.0", - "phpbench/phpbench": "^1.0", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^8.5|^9.6", - "symfony/phpunit-bridge": "^5.2|^6.0|^7.0", - "vimeo/psalm": "^4.17" + "nyholm/psr7": "^1.8", + "open-telemetry/api": "^1.1", + "open-telemetry/context": "^1.1", + "open-telemetry/exporter-otlp": "^1.1", + "open-telemetry/gen-otlp-protobuf": "^1.2.1", + "open-telemetry/sdk": "^1.1", + "open-telemetry/sem-conv": "^1.27", + "phpstan/phpstan": "^2.2", + "phpunit/phpunit": "^8.5.52|^9.6.34", + "spiral/roadrunner-http": "^3.6", + "spiral/roadrunner-worker": "^3.6" }, "suggest": { + "ext-excimer": "Enable Sentry profiling with the Excimer PHP extension.", "monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler." }, "type": "library", @@ -5555,7 +5485,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/4.10.0" + "source": "https://github.com/getsentry/sentry-php/tree/4.34.0" }, "funding": [ { @@ -5567,39 +5497,42 @@ "type": "custom" } ], - "time": "2024-11-06T07:44:19+00:00" + "time": "2026-10-08T11:25:58+00:00" }, { "name": "sentry/sentry-laravel", - "version": "4.10.2", + "version": "4.29.0", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-laravel.git", - "reference": "0e2e5bc4311da51349487afcf67b8fca937f6d94" + "reference": "4b3deab3d8818490220e1da8e2d7cca971f74410" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/0e2e5bc4311da51349487afcf67b8fca937f6d94", - "reference": "0e2e5bc4311da51349487afcf67b8fca937f6d94", + "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/4b3deab3d8818490220e1da8e2d7cca971f74410", + "reference": "4b3deab3d8818490220e1da8e2d7cca971f74410", "shasum": "" }, "require": { - "illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0", + "illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0 | ^13.0", "nyholm/psr7": "^1.0", "php": "^7.2 | ^8.0", - "sentry/sentry": "^4.10", - "symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0" + "sentry/sentry": "^4.34.0", + "symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0 | ^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.11", "guzzlehttp/guzzle": "^7.2", + "laravel/ai": "^0.1.5 | ^1.0", "laravel/folio": "^1.1", - "laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0", - "livewire/livewire": "^2.0 | ^3.0", + "laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0 | ^13.0", + "laravel/octane": "^2.15", + "laravel/pennant": "^1.0", + "livewire/livewire": "^2.0 | ^3.0 | ^4.0", "mockery/mockery": "^1.3", - "orchestra/testbench": "^4.7 | ^5.1 | ^6.0 | ^7.0 | ^8.0 | ^9.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.4 | ^9.3 | ^10.4" + "orchestra/testbench": "^4.7 | ^5.1 | ^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0", + "phpstan/phpstan": "^1.10 | ^2.2", + "phpunit/phpunit": "^8.5 | ^9.6 | ^10.4 | ^11.5" }, "type": "library", "extra": { @@ -5644,7 +5577,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-laravel/issues", - "source": "https://github.com/getsentry/sentry-laravel/tree/4.10.2" + "source": "https://github.com/getsentry/sentry-laravel/tree/4.29.0" }, "funding": [ { @@ -5656,26 +5589,25 @@ "type": "custom" } ], - "time": "2024-12-17T11:38:58+00:00" + "time": "2026-10-08T12:31:48+00:00" }, { "name": "symfony/clock", - "version": "v7.2.0", + "version": "v8.1.9", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + "reference": "945ea3b64d6da9c1c2c354fe5c07b27455df6442" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "url": "https://api.github.com/repos/symfony/clock/zipball/945ea3b64d6da9c1c2c354fe5c07b27455df6442", + "reference": "945ea3b64d6da9c1c2c354fe5c07b27455df6442", "shasum": "" }, "require": { - "php": ">=8.2", - "psr/clock": "^1.0", - "symfony/polyfill-php83": "^1.28" + "php": ">=8.4.1", + "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -5714,7 +5646,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.2.0" + "source": "https://github.com/symfony/clock/tree/v8.1.9" }, "funding": [ { @@ -5725,32 +5657,37 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2026-10-12T14:32:04+00:00" }, { "name": "symfony/console", - "version": "v7.2.1", + "version": "v7.4.21", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3" + "reference": "21f1bc2296f7ff6043241a8dcbc09559b3732820" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3", - "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3", + "url": "https://api.github.com/repos/symfony/console/zipball/21f1bc2296f7ff6043241a8dcbc09559b3732820", + "reference": "21f1bc2296f7ff6043241a8dcbc09559b3732820", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0" + "symfony/string": "^7.2|^8.0" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -5764,16 +5701,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -5807,7 +5744,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.1" + "source": "https://github.com/symfony/console/tree/v7.4.21" }, "funding": [ { @@ -5818,29 +5755,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-11T03:49:26+00:00" + "time": "2026-10-12T18:45:38+00:00" }, { "name": "symfony/css-selector", - "version": "v7.2.0", + "version": "v8.1.6", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" + "reference": "08e2905152a39cf3fd1745d83f8c483e258887d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", - "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/08e2905152a39cf3fd1745d83f8c483e258887d9", + "reference": "08e2905152a39cf3fd1745d83f8c483e258887d9", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.4.1" }, "type": "library", "autoload": { @@ -5872,7 +5813,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.2.0" + "source": "https://github.com/symfony/css-selector/tree/v8.1.6" }, "funding": [ { @@ -5883,25 +5824,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2026-08-23T10:06:25+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d", "shasum": "" }, "require": { @@ -5914,7 +5859,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -5939,7 +5884,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1" }, "funding": [ { @@ -5950,40 +5895,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { "name": "symfony/error-handler", - "version": "v7.2.1", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "6150b89186573046167796fa5f3f76601d5145f8" + "reference": "82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/6150b89186573046167796fa5f3f76601d5145f8", - "reference": "6150b89186573046167796fa5f3f76601d5145f8", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0", + "reference": "82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/polyfill-php85": "^1.32", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/deprecation-contracts": "<2.5", "symfony/http-kernel": "<6.4" }, "require-dev": { + "symfony/console": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0" + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -6014,7 +5966,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.2.1" + "source": "https://github.com/symfony/error-handler/tree/v7.4.20" }, "funding": [ { @@ -6025,33 +5977,38 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-07T08:50:44+00:00" + "time": "2026-09-22T18:56:40+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.2.0", + "version": "v8.1.5", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" + "reference": "7458da64220376b2e0dc2d8451bf43382c1ad297" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7458da64220376b2e0dc2d8451bf43382c1ad297", + "reference": "7458da64220376b2e0dc2d8451bf43382c1ad297", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<6.4", + "symfony/security-http": "<7.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -6060,13 +6017,14 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/stopwatch": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -6094,7 +6052,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.1.5" }, "funding": [ { @@ -6105,25 +6063,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2026-08-21T17:47:34+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.1", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" + "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c7de7a00ffb67842132da02ea92988a39ccd9f4e", + "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e", "shasum": "" }, "require": { @@ -6137,7 +6099,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -6170,7 +6132,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.1" }, "funding": [ { @@ -6181,32 +6143,36 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { "name": "symfony/finder", - "version": "v7.2.2", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "url": "https://api.github.com/repos/symfony/finder/zipball/2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "symfony/filesystem": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -6234,7 +6200,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.2" + "source": "https://github.com/symfony/finder/tree/v7.4.20" }, "funding": [ { @@ -6245,32 +6211,35 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2026-09-26T06:31:10+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.2.2", + "version": "v7.4.21", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "62d1a43796ca3fea3f83a8470dfe63a4af3bc588" + "reference": "58c89144c7a36dd89c3d01917e9fa3a72d8aaf31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/62d1a43796ca3fea3f83a8470dfe63a4af3bc588", - "reference": "62d1a43796ca3fea3f83a8470dfe63a4af3bc588", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/58c89144c7a36dd89c3d01917e9fa3a72d8aaf31", + "reference": "58c89144c7a36dd89c3d01917e9fa3a72d8aaf31", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "^1.1" }, "conflict": { "doctrine/dbal": "<3.6", @@ -6279,12 +6248,13 @@ "require-dev": { "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0" + "symfony/cache": "^6.4.12|^7.1.5|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/rate-limiter": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -6312,7 +6282,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.2.2" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.21" }, "funding": [ { @@ -6323,34 +6293,38 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2026-10-08T16:56:12+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.2.2", + "version": "v7.4.21", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "3c432966bd8c7ec7429663105f5a02d7e75b4306" + "reference": "4779fce7dedacb8801b2b61c703ef99159502331" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3c432966bd8c7ec7429663105f5a02d7e75b4306", - "reference": "3c432966bd8c7ec7429663105f5a02d7e75b4306", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/4779fce7dedacb8801b2b61c703ef99159502331", + "reference": "4779fce7dedacb8801b2b61c703ef99159502331", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^7.3|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -6360,6 +6334,7 @@ "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", "symfony/doctrine-bridge": "<6.4", + "symfony/flex": "<2.10", "symfony/form": "<6.4", "symfony/http-client": "<6.4", "symfony/http-client-contracts": "<2.5", @@ -6377,28 +6352,28 @@ }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/css-selector": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4.1|^7.0.1|^8.0", + "symfony/dom-crawler": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^7.1", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^7.1", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^7.1|^8.0", + "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/serializer": "^7.1|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/translation": "^6.4|^7.0|^8.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", - "twig/twig": "^3.12" + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0", + "twig/twig": "^3.12|^4.0" }, "type": "library", "autoload": { @@ -6426,7 +6401,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.2" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.21" }, "funding": [ { @@ -6437,25 +6412,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-31T14:59:40+00:00" + "time": "2026-10-14T06:44:08+00:00" }, { "name": "symfony/mailer", - "version": "v7.2.0", + "version": "v7.4.19", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "e4d358702fb66e4c8a2af08e90e7271a62de39cc" + "reference": "6f6f2441bef07a42d2617b9b3aadf04a321aa514" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/e4d358702fb66e4c8a2af08e90e7271a62de39cc", - "reference": "e4d358702fb66e4c8a2af08e90e7271a62de39cc", + "url": "https://api.github.com/repos/symfony/mailer/zipball/6f6f2441bef07a42d2617b9b3aadf04a321aa514", + "reference": "6f6f2441bef07a42d2617b9b3aadf04a321aa514", "shasum": "" }, "require": { @@ -6463,8 +6442,8 @@ "php": ">=8.2", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/mime": "^7.2", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/mime": "^7.2|^8.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -6475,10 +6454,10 @@ "symfony/twig-bridge": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/twig-bridge": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/twig-bridge": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -6506,7 +6485,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.2.0" + "source": "https://github.com/symfony/mailer/tree/v7.4.19" }, "funding": [ { @@ -6517,48 +6496,53 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-25T15:21:05+00:00" + "time": "2026-09-15T06:01:15+00:00" }, { "name": "symfony/mime", - "version": "v7.2.1", + "version": "v7.4.19", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283" + "reference": "f8ac7d0a800bcabbcd1f7de56594cf05e6cd5693" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/7f9617fcf15cb61be30f8b252695ed5e2bfac283", - "reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283", + "url": "https://api.github.com/repos/symfony/mime/zipball/f8ac7d0a800bcabbcd1f7de56594cf05e6cd5693", + "reference": "f8ac7d0a800bcabbcd1f7de56594cf05e6cd5693", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "egulias/email-validator": "~3.0.0", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", "symfony/mailer": "<6.4", "symfony/serializer": "<6.4.3|>7.0,<7.0.3" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/serializer": "^6.4.3|^7.0.3" + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4.44|^7.4.17|^8.1.5" }, "type": "library", "autoload": { @@ -6590,7 +6574,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.2.1" + "source": "https://github.com/symfony/mime/tree/v7.4.19" }, "funding": [ { @@ -6601,29 +6585,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-07T08:50:44+00:00" + "time": "2026-09-04T10:45:44+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.2.0", + "version": "v8.1.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" + "reference": "88f9c561f678a02d54b897014049fa839e33ff82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/88f9c561f678a02d54b897014049fa839e33ff82", + "reference": "88f9c561f678a02d54b897014049fa839e33ff82", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4.1", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -6657,7 +6645,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" + "source": "https://github.com/symfony/options-resolver/tree/v8.1.0" }, "funding": [ { @@ -6668,25 +6656,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-20T11:17:29+00:00" + "time": "2026-05-29T05:06:50+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { @@ -6736,7 +6728,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0" }, "funding": [ { @@ -6747,25 +6739,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5cac8f4db97208823aa353f59a01faad2da52c75", + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75", "shasum": "" }, "require": { @@ -6814,7 +6810,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.43.0" }, "funding": [ { @@ -6825,25 +6821,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.31.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" + "reference": "533d68cf99c8f8ee2e8893c59ed59192e92cfd74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", - "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/533d68cf99c8f8ee2e8893c59ed59192e92cfd74", + "reference": "533d68cf99c8f8ee2e8893c59ed59192e92cfd74", "shasum": "" }, "require": { @@ -6897,7 +6897,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.43.0" }, "funding": [ { @@ -6908,25 +6908,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-09-23T14:40:04+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/ebd57ccc7edb93d632e184efbe7693d2517bab3b", + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b", "shasum": "" }, "require": { @@ -6978,7 +6982,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.43.0" }, "funding": [ { @@ -6989,28 +6993,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-09-23T22:02:09+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", "shasum": "" }, "require": { + "ext-iconv": "*", "php": ">=7.2" }, "provide": { @@ -7058,7 +7067,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0" }, "funding": [ { @@ -7069,25 +7078,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-09-24T15:19:04+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.31.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "reference": "9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74", + "reference": "9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74", "shasum": "" }, "require": { @@ -7138,7 +7151,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.43.0" }, "funding": [ { @@ -7149,25 +7162,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-09-25T15:50:05+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.31.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + "reference": "80ccff923a8d61f73ebe9da0aa94e25232f004ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/80ccff923a8d61f73ebe9da0aa94e25232f004ce", + "reference": "80ccff923a8d61f73ebe9da0aa94e25232f004ce", "shasum": "" }, "require": { @@ -7214,7 +7231,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.43.0" }, "funding": [ { @@ -7225,25 +7242,192 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-09-25T15:50:05+00:00" }, { - "name": "symfony/polyfill-uuid", - "version": "v1.31.0", + "name": "symfony/polyfill-php85", + "version": "v1.43.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + "url": "https://github.com/symfony/polyfill-php85.git", + "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/86a42cbcc07adc331481a5ab310a4024bfc227f6", + "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php85\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php85/tree/v1.43.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-09-25T15:46:47+00:00" + }, + { + "name": "symfony/polyfill-time", + "version": "v1.42.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-time.git", + "reference": "ac9f1ed802dd58f37e720388130c088434aa09fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-time/zipball/ac9f1ed802dd58f37e720388130c088434aa09fc", + "reference": "ac9f1ed802dd58f37e720388130c088434aa09fc", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Time\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Philippe Nyamagana Butera", + "email": "nyamsprod@gmail.com" + }, + { + "name": "Tim Düsterhus", + "email": "tim@tideways-gmbh.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Time API added to PHP 8.6", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "duration", + "polyfill", + "portable", + "shim", + "time" + ], + "support": { + "source": "https://github.com/symfony/polyfill-time/tree/v1.42.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-08-07T13:08:13+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.43.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "b23ff8245cc5c4479ea2be3d0132d2e6dd433993" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/b23ff8245cc5c4479ea2be3d0132d2e6dd433993", + "reference": "b23ff8245cc5c4479ea2be3d0132d2e6dd433993", "shasum": "" }, "require": { @@ -7293,7 +7477,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.43.0" }, "funding": [ { @@ -7304,25 +7488,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-09-24T05:20:52+00:00" }, { "name": "symfony/process", - "version": "v7.2.0", + "version": "v7.4.21", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" + "reference": "e5247f4a5e0797d232ad8e8e6803aeb341843c83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", - "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "url": "https://api.github.com/repos/symfony/process/zipball/e5247f4a5e0797d232ad8e8e6803aeb341843c83", + "reference": "e5247f4a5e0797d232ad8e8e6803aeb341843c83", "shasum": "" }, "require": { @@ -7354,7 +7542,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.0" + "source": "https://github.com/symfony/process/tree/v7.4.21" }, "funding": [ { @@ -7365,45 +7553,49 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-06T14:24:19+00:00" + "time": "2026-10-08T16:56:12+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.2.0", + "version": "v8.1.9", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f" + "reference": "cfa8f3ac693fec234a91d8745b45ed9a81a0b799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/cfa8f3ac693fec234a91d8745b45ed9a81a0b799", + "reference": "cfa8f3ac693fec234a91d8745b45ed9a81a0b799", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4.1", "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^6.4|^7.0" + "symfony/http-foundation": "^7.4|^8.0" }, "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-kernel": "<6.4" + "php-http/discovery": "<1.15" }, "require-dev": { "nyholm/psr7": "^1.1", "php-http/discovery": "^1.15", "psr/log": "^1.1.4|^2|^3", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0" + "symfony/browser-kit": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/runtime": "^7.4|^8.0" }, "type": "symfony-bridge", "autoload": { @@ -7437,7 +7629,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.2.0" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v8.1.9" }, "funding": [ { @@ -7448,25 +7640,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-26T08:57:56+00:00" + "time": "2026-10-07T08:21:34+00:00" }, { "name": "symfony/routing", - "version": "v7.2.0", + "version": "v7.4.21", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "e10a2450fa957af6c448b9b93c9010a4e4c0725e" + "reference": "7a344cf871532d081875bfdd18f3dff8dca36c5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/e10a2450fa957af6c448b9b93c9010a4e4c0725e", - "reference": "e10a2450fa957af6c448b9b93c9010a4e4c0725e", + "url": "https://api.github.com/repos/symfony/routing/zipball/7a344cf871532d081875bfdd18f3dff8dca36c5b", + "reference": "7a344cf871532d081875bfdd18f3dff8dca36c5b", "shasum": "" }, "require": { @@ -7480,11 +7676,11 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -7518,7 +7714,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.2.0" + "source": "https://github.com/symfony/routing/tree/v7.4.21" }, "funding": [ { @@ -7529,25 +7725,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-25T11:08:51+00:00" + "time": "2026-10-11T18:40:59+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.1", + "version": "v3.7.3", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/15e6a07ec2a2c75ceb1b21dd98105ee8456d2257", + "reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257", "shasum": "" }, "require": { @@ -7565,7 +7765,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -7601,7 +7801,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.7.3" }, "funding": [ { @@ -7612,44 +7812,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2026-07-27T15:39:01+00:00" }, { "name": "symfony/string", - "version": "v7.2.0", + "version": "v8.1.9", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" + "reference": "07fb208558f941eab50ec49c89c2a6a93fb11f01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", + "url": "https://api.github.com/repos/symfony/string/zipball/07fb208558f941eab50ec49c89c2a6a93fb11f01", + "reference": "07fb208558f941eab50ec49c89c2a6a93fb11f01", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4.1", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.1", - "symfony/error-handler": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -7688,7 +7891,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.0" + "source": "https://github.com/symfony/string/tree/v8.1.9" }, "funding": [ { @@ -7699,60 +7902,58 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-13T13:31:26+00:00" + "time": "2026-10-03T15:16:03+00:00" }, { "name": "symfony/translation", - "version": "v7.2.2", + "version": "v8.1.5", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "e2674a30132b7cc4d74540d6c2573aa363f05923" + "reference": "d9e1caba0d6b6f9a26710af8a2f88d37f001215a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/e2674a30132b7cc4d74540d6c2573aa363f05923", - "reference": "e2674a30132b7cc4d74540d6c2573aa363f05923", + "url": "https://api.github.com/repos/symfony/translation/zipball/d9e1caba0d6b6f9a26710af8a2f88d37f001215a", + "reference": "d9e1caba0d6b6f9a26710af8a2f88d37f001215a", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5|^3.0" + "php": ">=8.4.1", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation-contracts": "^3.6.1" }, "conflict": { - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", + "nikic/php-parser": "<5.0", "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<6.4", - "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<6.4", - "symfony/yaml": "<6.4" + "symfony/service-contracts": "<2.5" }, "provide": { "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { - "nikic/php-parser": "^4.18|^5.0", + "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^6.4|^7.0", + "symfony/routing": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -7783,7 +7984,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.2.2" + "source": "https://github.com/symfony/translation/tree/v8.1.5" }, "funding": [ { @@ -7794,25 +7995,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-07T08:18:10+00:00" + "time": "2026-08-21T17:47:34+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.5.1", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" + "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/ccb206b98faccc511ebae8e5fad50f2dc0b30621", + "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621", "shasum": "" }, "require": { @@ -7825,7 +8030,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -7861,7 +8066,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.7.1" }, "funding": [ { @@ -7872,25 +8077,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { "name": "symfony/uid", - "version": "v7.2.0", + "version": "v7.4.21", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "2d294d0c48df244c71c105a169d0190bfb080426" + "reference": "3e706a245b5343ea93be9cafe84525bfb54e60fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/2d294d0c48df244c71c105a169d0190bfb080426", - "reference": "2d294d0c48df244c71c105a169d0190bfb080426", + "url": "https://api.github.com/repos/symfony/uid/zipball/3e706a245b5343ea93be9cafe84525bfb54e60fc", + "reference": "3e706a245b5343ea93be9cafe84525bfb54e60fc", "shasum": "" }, "require": { @@ -7898,7 +8107,7 @@ "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -7935,7 +8144,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.2.0" + "source": "https://github.com/symfony/uid/tree/v7.4.21" }, "funding": [ { @@ -7946,41 +8155,45 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2026-10-12T14:31:36+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.2.0", + "version": "v7.4.21", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c" + "reference": "55d06b02f49eca9bff61828548988e6f8763e8a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c6a22929407dec8765d6e2b6ff85b800b245879c", - "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/55d06b02f49eca9bff61828548988e6f8763e8a6", + "reference": "55d06b02f49eca9bff61828548988e6f8763e8a6", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { "symfony/console": "<6.4" }, "require-dev": { - "ext-iconv": "*", - "symfony/console": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0", - "twig/twig": "^3.12" + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "twig/twig": "^3.12|^4.0" }, "bin": [ "Resources/bin/var-dump-server" @@ -8018,7 +8231,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.2.0" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.21" }, "funding": [ { @@ -8029,32 +8242,36 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-08T15:48:14+00:00" + "time": "2026-10-13T05:48:33+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", - "version": "v2.3.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", - "reference": "0d72ac1c00084279c1816675284073c5a337c20d" + "reference": "f0292ccf0ec75843d65027214426b6b163b48b41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", - "reference": "0d72ac1c00084279c1816675284073c5a337c20d", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/f0292ccf0ec75843d65027214426b6b163b48b41", + "reference": "f0292ccf0ec75843d65027214426b6b163b48b41", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "php": "^7.4 || ^8.0", - "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0 || ^8.0" }, "require-dev": { "phpstan/phpstan": "^2.0", @@ -8087,30 +8304,30 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "support": { "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", - "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.4.0" }, - "time": "2024-12-21T16:25:41+00:00" + "time": "2025-12-02T11:56:42+00:00" }, { "name": "uwil/admin-secure-laravel", - "version": "5.0.0", + "version": "5.1.1", "source": { "type": "git", "url": "git@lab.s-web.fr:ldc-web/projets/ldc-web-admin-secure-laravel.git", - "reference": "7d9c052db4318752a312dc9763bc8c31ea053aa2" + "reference": "c54dad85ee051e103f50dc8f19d457703bc5ff03" }, "dist": { "type": "zip", - "url": "https://lab.s-web.fr/api/v4/projects/20/packages/composer/archives/uwil/admin-secure-laravel.zip?sha=7d9c052db4318752a312dc9763bc8c31ea053aa2", - "reference": "7d9c052db4318752a312dc9763bc8c31ea053aa2", + "url": "https://lab.s-web.fr/api/v4/projects/20/packages/composer/archives/uwil/admin-secure-laravel.zip?sha=c54dad85ee051e103f50dc8f19d457703bc5ff03", + "reference": "c54dad85ee051e103f50dc8f19d457703bc5ff03", "shasum": "" }, "require": { "dxw/cidr": "^3.2", - "illuminate/support": "~11|~12", - "laravel/framework": "~11|~12", + "illuminate/support": "~11|~12|~13", + "laravel/framework": "~11|~12|~13", "php": "^8.3", - "symfony/options-resolver": "^7.0" + "symfony/options-resolver": "^7.0|^8.0" }, "require-dev": { "larastan/larastan": "^2.9", @@ -8221,31 +8438,31 @@ }, { "name": "uwil/laravel-common", - "version": "4.1.1", + "version": "4.2.0", "source": { "type": "git", "url": "git@lab.s-web.fr:ldc-web/projets/laravel-common.git", - "reference": "7c08c4f545307bdba8bd09835b59982094b06e49" + "reference": "6be63873dfa17ce81ff85d5d04d54e34e38df828" }, "dist": { "type": "zip", - "url": "https://lab.s-web.fr/api/v4/projects/215/packages/composer/archives/uwil/laravel-common.zip?sha=7c08c4f545307bdba8bd09835b59982094b06e49", - "reference": "7c08c4f545307bdba8bd09835b59982094b06e49", + "url": "https://lab.s-web.fr/api/v4/projects/215/packages/composer/archives/uwil/laravel-common.zip?sha=6be63873dfa17ce81ff85d5d04d54e34e38df828", + "reference": "6be63873dfa17ce81ff85d5d04d54e34e38df828", "shasum": "" }, "require": { - "illuminate/support": "~11|~12", - "kwaadpepper/image-resizer": "^3.0", - "laravel/framework": "~11|~12", + "illuminate/support": "~11|~12|~13", + "kwaadpepper/image-resizer": "^4.0", + "laravel/framework": "~11|~12|~13", "mews/purifier": "^3.4", - "php": "^8.3", + "php": "^8.4", "sentry/sentry-laravel": "^4.10" }, "require-dev": { - "larastan/larastan": "^2.9", - "orchestra/testbench": "^9.0", - "phpunit/php-code-coverage": "^11.0", - "phpunit/phpunit": "^11.0", + "jonpurvis/fuzz": "^1.1", + "larastan/larastan": "^3.12", + "orchestra/testbench": "^10.0", + "pestphp/pest": "^4.0", "slevomat/coding-standard": "^8.3", "squizlabs/php_codesniffer": "^3.7" }, @@ -8285,26 +8502,26 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.6.1", + "version": "v5.7.0", "source": { "type": "git", - "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" + "url": "https://github.com/phpdotenv/phpdotenv.git", + "reference": "301c07936b16d88628b126b01d082ba153cf4c40" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", - "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "url": "https://api.github.com/repos/phpdotenv/phpdotenv/zipball/301c07936b16d88628b126b01d082ba153cf4c40", + "reference": "301c07936b16d88628b126b01d082ba153cf4c40", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.3", + "graham-campbell/result-type": "^1.2", "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.3", - "symfony/polyfill-ctype": "^1.24", - "symfony/polyfill-mbstring": "^1.24", - "symfony/polyfill-php80": "^1.24" + "phpoption/phpoption": "^1.10", + "symfony/polyfill-ctype": "^1.26", + "symfony/polyfill-mbstring": "^1.26", + "symfony/polyfill-php80": "^1.26" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", @@ -8345,7 +8562,7 @@ "homepage": "https://github.com/vlucas" } ], - "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "description": "Loads environment variables from `.env` to `$_ENV` and `$_SERVER` automagically, and optionally to `getenv()`.", "keywords": [ "dotenv", "env", @@ -8353,7 +8570,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.7.0" }, "funding": [ { @@ -8365,27 +8582,27 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:52:34+00:00" + "time": "2026-08-24T18:07:49+00:00" }, { "name": "voku/portable-ascii", - "version": "2.0.3", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + "reference": "8e1051fe39379367aecf014f41744ce7539a856f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/8e1051fe39379367aecf014f41744ce7539a856f", + "reference": "8e1051fe39379367aecf014f41744ce7539a856f", "shasum": "" }, "require": { - "php": ">=7.0.0" + "php": ">=7.1.0" }, "require-dev": { - "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + "phpunit/phpunit": "~8.5 || ~9.6 || ~10.5 || ~11.5" }, "suggest": { "ext-intl": "Use Intl for transliterator_transliterate() support" @@ -8415,7 +8632,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + "source": "https://github.com/voku/portable-ascii/tree/2.1.1" }, "funding": [ { @@ -8439,65 +8656,7 @@ "type": "tidelift" } ], - "time": "2024-11-21T01:49:47+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" + "time": "2026-04-26T05:33:54+00:00" } ], "packages-dev": [ @@ -8549,16 +8708,16 @@ }, { "name": "brianium/paratest", - "version": "v7.4.8", + "version": "v7.20.0", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "cf16fcbb9b8107a7df6b97e497fc91e819774d8b" + "reference": "81c80677c9ec0ed4ef16b246167f11dec81a6e3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/cf16fcbb9b8107a7df6b97e497fc91e819774d8b", - "reference": "cf16fcbb9b8107a7df6b97e497fc91e819774d8b", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/81c80677c9ec0ed4ef16b246167f11dec81a6e3d", + "reference": "81c80677c9ec0ed4ef16b246167f11dec81a6e3d", "shasum": "" }, "require": { @@ -8566,27 +8725,27 @@ "ext-pcre": "*", "ext-reflection": "*", "ext-simplexml": "*", - "fidry/cpu-core-counter": "^1.2.0", - "jean85/pretty-package-versions": "^2.0.6", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0", - "phpunit/php-code-coverage": "^10.1.16", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-timer": "^6.0.0", - "phpunit/phpunit": "^10.5.36", - "sebastian/environment": "^6.1.0", - "symfony/console": "^6.4.7 || ^7.1.5", - "symfony/process": "^6.4.7 || ^7.1.5" + "fidry/cpu-core-counter": "^1.3.0", + "jean85/pretty-package-versions": "^2.1.1", + "php": "~8.3.0 || ~8.4.0 || ~8.5.0", + "phpunit/php-code-coverage": "^12.5.3 || ^13.0.1", + "phpunit/php-file-iterator": "^6.0.1 || ^7", + "phpunit/php-timer": "^8 || ^9", + "phpunit/phpunit": "^12.5.14 || ^13.0.5", + "sebastian/environment": "^8.0.3 || ^9", + "symfony/console": "^7.4.7 || ^8.0.7", + "symfony/process": "^7.4.5 || ^8.0.5" }, "require-dev": { - "doctrine/coding-standard": "^12.0.0", + "doctrine/coding-standard": "^14.0.0", + "ext-pcntl": "*", "ext-pcov": "*", "ext-posix": "*", - "phpstan/phpstan": "^1.12.6", - "phpstan/phpstan-deprecation-rules": "^1.2.1", - "phpstan/phpstan-phpunit": "^1.4.0", - "phpstan/phpstan-strict-rules": "^1.6.1", - "squizlabs/php_codesniffer": "^3.10.3", - "symfony/filesystem": "^6.4.3 || ^7.1.5" + "phpstan/phpstan": "^2.1.44", + "phpstan/phpstan-deprecation-rules": "^2.0.4", + "phpstan/phpstan-phpunit": "^2.0.16", + "phpstan/phpstan-strict-rules": "^2.0.10", + "symfony/filesystem": "^7.4.6 || ^8.0.6" }, "bin": [ "bin/paratest", @@ -8626,7 +8785,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.4.8" + "source": "https://github.com/paratestphp/paratest/tree/v7.20.0" }, "funding": [ { @@ -8638,20 +8797,20 @@ "type": "paypal" } ], - "time": "2024-10-15T12:45:19+00:00" + "time": "2026-03-29T15:46:14+00:00" }, { "name": "composer/semver", - "version": "3.4.3", + "version": "3.5.1", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + "reference": "528948210cc46f967a4b98e83b19e76f2b504993" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "url": "https://api.github.com/repos/composer/semver/zipball/528948210cc46f967a4b98e83b19e76f2b504993", + "reference": "528948210cc46f967a4b98e83b19e76f2b504993", "shasum": "" }, "require": { @@ -8693,7 +8852,7 @@ "homepage": "http://robbast.nl" } ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", + "description": "Version comparison library that offers utilities, version constraint parsing and validation.", "keywords": [ "semantic", "semver", @@ -8703,7 +8862,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.3" + "source": "https://github.com/composer/semver/tree/3.5.1" }, "funding": [ { @@ -8713,39 +8872,35 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2024-09-19T14:15:21+00:00" + "time": "2026-10-05T13:12:12+00:00" }, { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.0.0", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "4be43904336affa5c2f70744a348312336afd0da" + "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", - "reference": "4be43904336affa5c2f70744a348312336afd0da", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/963f0c67bffde0eac41b56be71ac0e8ba132f0bd", + "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0 || ^2.0", + "composer-plugin-api": "^2.2", "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" }, "require-dev": { - "composer/composer": "*", + "composer/composer": "^2.2", "ext-json": "*", "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", "yoast/phpunit-polyfills": "^1.0" }, "type": "composer-plugin", @@ -8764,9 +8919,9 @@ "authors": [ { "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" + "email": "opensource@frenck.dev", + "homepage": "https://frenck.dev", + "role": "Open source developer" }, { "name": "Contributors", @@ -8774,7 +8929,6 @@ } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", "keywords": [ "PHPCodeSniffer", "PHP_CodeSniffer", @@ -8795,36 +8949,55 @@ ], "support": { "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", "source": "https://github.com/PHPCSStandards/composer-installer" }, - "time": "2023-01-05T11:28:13+00:00" + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2026-05-06T08:26:05+00:00" }, { "name": "dragon-code/contracts", - "version": "2.23.0", + "version": "2.25.0", "source": { "type": "git", "url": "https://github.com/TheDragonCode/contracts.git", - "reference": "44dbad923f152e0dc2699fbac2d33b65dd6a8f7d" + "reference": "13d1254801026be5ba33cf1309a414953869175f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TheDragonCode/contracts/zipball/44dbad923f152e0dc2699fbac2d33b65dd6a8f7d", - "reference": "44dbad923f152e0dc2699fbac2d33b65dd6a8f7d", + "url": "https://api.github.com/repos/TheDragonCode/contracts/zipball/13d1254801026be5ba33cf1309a414953869175f", + "reference": "13d1254801026be5ba33cf1309a414953869175f", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "psr/http-message": "^1.0.1 || ^2.0", - "symfony/http-kernel": "^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/http-kernel": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0", "symfony/polyfill-php80": "^1.23" }, "conflict": { "andrey-helldar/contracts": "*" }, "require-dev": { - "illuminate/database": "^10.0 || ^11.0", - "phpdocumentor/reflection-docblock": "^5.0" + "illuminate/database": "^10.0 || ^11.0 || ^12.0 || ^13.0", + "phpdocumentor/reflection-docblock": "^5.0 || ^6.0" }, "type": "library", "autoload": { @@ -8856,29 +9029,26 @@ "url": "https://boosty.to/dragon-code", "type": "boosty" }, - { - "url": "https://www.donationalerts.com/r/dragon_code", - "type": "donationalerts" - }, { "url": "https://yoomoney.ru/to/410012608840929", "type": "yoomoney" } ], - "time": "2024-03-11T20:15:12+00:00" + "abandoned": true, + "time": "2026-03-17T21:50:20+00:00" }, { "name": "dragon-code/pretty-array", - "version": "v4.1.0", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/TheDragonCode/pretty-array.git", - "reference": "6c84e2454491b414efbd37985c322712cdf9012f" + "reference": "b94034d92172a5d14a578822d68b2a8f8b5388e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TheDragonCode/pretty-array/zipball/6c84e2454491b414efbd37985c322712cdf9012f", - "reference": "6c84e2454491b414efbd37985c322712cdf9012f", + "url": "https://api.github.com/repos/TheDragonCode/pretty-array/zipball/b94034d92172a5d14a578822d68b2a8f8b5388e0", + "reference": "b94034d92172a5d14a578822d68b2a8f8b5388e0", "shasum": "" }, "require": { @@ -8889,7 +9059,7 @@ "php": "^8.0" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^10.2" + "phpunit/phpunit": "^9.6 || ^10.0 || ^11.0 || ^12.0" }, "suggest": { "symfony/thanks": "Give thanks (in the form of a GitHub) to your fellow PHP package maintainers" @@ -8908,7 +9078,7 @@ { "name": "Andrey Helldar", "email": "helldar@dragon-code.pro", - "homepage": "https://github.com/andrey-helldar" + "homepage": "https://dragon-code.pro" } ], "description": "Simple conversion of an array to a pretty view", @@ -8929,33 +9099,26 @@ "url": "https://boosty.to/dragon-code", "type": "boosty" }, - { - "url": "https://github.com/sponsors/TheDragonCode", - "type": "github" - }, - { - "url": "https://opencollective.com/dragon-code", - "type": "open_collective" - }, { "url": "https://yoomoney.ru/to/410012608840929", "type": "yoomoney" } ], - "time": "2023-06-02T11:37:44+00:00" + "abandoned": "symfony/var-exporter", + "time": "2025-02-24T15:35:24+00:00" }, { "name": "dragon-code/support", - "version": "6.15.1", + "version": "6.17.1", "source": { "type": "git", "url": "https://github.com/TheDragonCode/support.git", - "reference": "dd68d435d64873797a82b318021d49ba05e917bf" + "reference": "82a465953267989883d64b921e9725600a5073b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TheDragonCode/support/zipball/dd68d435d64873797a82b318021d49ba05e917bf", - "reference": "dd68d435d64873797a82b318021d49ba05e917bf", + "url": "https://api.github.com/repos/TheDragonCode/support/zipball/82a465953267989883d64b921e9725600a5073b5", + "reference": "82a465953267989883d64b921e9725600a5073b5", "shasum": "" }, "require": { @@ -8967,15 +9130,14 @@ "ext-mbstring": "*", "php": "^8.1", "psr/http-message": "^1.0.1 || ^2.0", - "symfony/polyfill-php81": "^1.25", "voku/portable-ascii": "^1.4.8 || ^2.0.1" }, "conflict": { "andrey-helldar/support": "*" }, "require-dev": { - "illuminate/contracts": "^9.0 || ^10.0 || ^11.0", - "phpunit/phpunit": "^9.6 || ^11.0", + "illuminate/contracts": "^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0", + "phpunit/phpunit": "^9.6 || ^11.0 || ^12.0", "symfony/var-dumper": "^6.0 || ^7.0" }, "suggest": { @@ -9032,16 +9194,13 @@ "url": "https://boosty.to/dragon-code", "type": "boosty" }, - { - "url": "https://www.donationalerts.com/r/dragon_code", - "type": "donationalerts" - }, { "url": "https://yoomoney.ru/to/410012608840929", "type": "yoomoney" } ], - "time": "2024-12-18T12:33:59+00:00" + "abandoned": "illuminate/support", + "time": "2026-04-03T15:06:29+00:00" }, { "name": "fakerphp/faker", @@ -9108,30 +9267,31 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.2.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "8520451a140d3f46ac33042715115e290cf5785f" + "reference": "d384a7d0d6e67aa497327260ca95023e92dc2032" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", - "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/d384a7d0d6e67aa497327260ca95023e92dc2032", + "reference": "d384a7d0d6e67aa497327260ca95023e92dc2032", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "fidry/makefile": "^0.2.0", + "fidry/makefile": "^0.2.0 || ^1.1.2", "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^1.9.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", - "phpstan/phpstan-phpunit": "^1.2.2", - "phpstan/phpstan-strict-rules": "^1.4.4", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "symfony/polyfill-mbstring": "^1.33", "webmozarts/strict-phpunit": "^7.5" }, "type": "library", @@ -9157,7 +9317,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.4.1" }, "funding": [ { @@ -9165,20 +9325,20 @@ "type": "github" } ], - "time": "2024-08-06T10:04:20+00:00" + "time": "2026-09-29T22:11:39+00:00" }, { "name": "filp/whoops", - "version": "2.16.0", + "version": "2.18.7", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "befcdc0e5dce67252aa6322d82424be928214fa2" + "reference": "50670ba239926c50f2073e868f6672f775cd57ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/befcdc0e5dce67252aa6322d82424be928214fa2", - "reference": "befcdc0e5dce67252aa6322d82424be928214fa2", + "url": "https://api.github.com/repos/filp/whoops/zipball/50670ba239926c50f2073e868f6672f775cd57ec", + "reference": "50670ba239926c50f2073e868f6672f775cd57ec", "shasum": "" }, "require": { @@ -9187,8 +9347,8 @@ }, "require-dev": { "mockery/mockery": "^1.0", - "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", - "symfony/var-dumper": "^4.0 || ^5.0" + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3 || ^10.5.58", + "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0" }, "suggest": { "symfony/var-dumper": "Pretty print complex values better with var-dumper available", @@ -9228,7 +9388,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.16.0" + "source": "https://github.com/filp/whoops/tree/2.18.7" }, "funding": [ { @@ -9236,24 +9396,26 @@ "type": "github" } ], - "time": "2024-09-25T12:00:00+00:00" + "time": "2026-10-18T13:17:38+00:00" }, { "name": "hamcrest/hamcrest-php", - "version": "v2.0.1", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + "reference": "b61cd040da1a4925bc90a51c074f5297e7c0fa52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b61cd040da1a4925bc90a51c074f5297e7c0fa52", + "reference": "b61cd040da1a4925bc90a51c074f5297e7c0fa52", "shasum": "" }, "require": { - "php": "^5.3|^7.0|^8.0" + "ext-ctype": "*", + "ext-dom": "*", + "php": "^7.4|^8.0" }, "replace": { "cordoval/hamcrest-php": "*", @@ -9261,13 +9423,15 @@ "kodova/hamcrest-php": "*" }, "require-dev": { - "phpunit/php-file-iterator": "^1.4 || ^2.0", - "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -9285,22 +9449,22 @@ ], "support": { "issues": "https://github.com/hamcrest/hamcrest-php/issues", - "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + "source": "https://github.com/hamcrest/hamcrest-php/tree/v3.0.0" }, - "time": "2020-07-09T08:09:16+00:00" + "time": "2026-03-17T11:56:53+00:00" }, { "name": "laravel-lang/attributes", - "version": "2.11.4", + "version": "2.16.4", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/attributes.git", - "reference": "5f8abba8adaca2f6b5527843a515652bef0ff007" + "reference": "4a0de72632bb1862532977fd76ed6be9c1cc65af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/attributes/zipball/5f8abba8adaca2f6b5527843a515652bef0ff007", - "reference": "5f8abba8adaca2f6b5527843a515652bef0ff007", + "url": "https://api.github.com/repos/Laravel-Lang/attributes/zipball/4a0de72632bb1862532977fd76ed6be9c1cc65af", + "reference": "4a0de72632bb1862532977fd76ed6be9c1cc65af", "shasum": "" }, "require": { @@ -9310,7 +9474,7 @@ }, "require-dev": { "laravel-lang/status-generator": "^1.19 || ^2.0", - "phpunit/phpunit": "^10.0", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", "symfony/var-dumper": "^6.0 || ^7.0" }, "type": "library", @@ -9340,7 +9504,7 @@ "homepage": "https://github.com/Laravel-Lang" } ], - "description": "List of 126 languages for form field names", + "description": "Translation of form element names", "keywords": [ "attributes", "fields", @@ -9354,9 +9518,19 @@ ], "support": { "issues": "https://github.com/Laravel-Lang/attributes/issues", - "source": "https://github.com/Laravel-Lang/attributes/tree/2.11.4" + "source": "https://github.com/Laravel-Lang/attributes/tree/2.16.4" }, - "time": "2025-01-06T14:39:45+00:00" + "funding": [ + { + "url": "https://boosty.to/dragon-code", + "type": "boosty" + }, + { + "url": "https://yoomoney.ru/to/410012608840929", + "type": "yoomoney" + } + ], + "time": "2026-05-30T12:11:05+00:00" }, { "name": "laravel-lang/common", @@ -9441,16 +9615,16 @@ }, { "name": "laravel-lang/http-statuses", - "version": "3.8.5", + "version": "3.13.2", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/http-statuses.git", - "reference": "d5ddb3c6cfafadb3a2e9d2d5d96d8d11a9130544" + "reference": "2d33c7b4f5b268224c559c27c1220764b5391ae2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Lang/http-statuses/zipball/d5ddb3c6cfafadb3a2e9d2d5d96d8d11a9130544", - "reference": "d5ddb3c6cfafadb3a2e9d2d5d96d8d11a9130544", + "url": "https://api.github.com/repos/Laravel-Lang/http-statuses/zipball/2d33c7b4f5b268224c559c27c1220764b5391ae2", + "reference": "2d33c7b4f5b268224c559c27c1220764b5391ae2", "shasum": "" }, "require": { @@ -9460,7 +9634,7 @@ }, "require-dev": { "laravel-lang/status-generator": "^1.19 || ^2.0", - "phpunit/phpunit": "^10.0", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", "symfony/var-dumper": "^6.0 || ^7.0" }, "type": "library", @@ -9490,7 +9664,7 @@ "homepage": "https://github.com/Laravel-Lang" } ], - "description": "List of 126 languages for HTTP statuses", + "description": "Translation of HTTP statuses", "keywords": [ "http", "lang", @@ -9502,13 +9676,23 @@ ], "support": { "issues": "https://github.com/Laravel-Lang/http-statuses/issues", - "source": "https://github.com/Laravel-Lang/http-statuses/tree/3.8.5" + "source": "https://github.com/Laravel-Lang/http-statuses/tree/3.13.2" }, - "time": "2024-09-30T19:56:37+00:00" + "funding": [ + { + "url": "https://boosty.to/dragon-code", + "type": "boosty" + }, + { + "url": "https://yoomoney.ru/to/410012608840929", + "type": "yoomoney" + } + ], + "time": "2026-05-30T12:11:06+00:00" }, { "name": "laravel-lang/lang", - "version": "13.12.0", + "version": "13.12.1", "source": { "type": "git", "url": "https://github.com/Laravel-Lang/lang.git", @@ -9675,29 +9859,28 @@ }, { "name": "mockery/mockery", - "version": "1.6.12", + "version": "1.6.15", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + "reference": "967a801bd188989a5669bd280f252d51c0fdc9ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", - "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "url": "https://api.github.com/repos/mockery/mockery/zipball/967a801bd188989a5669bd280f252d51c0fdc9ee", + "reference": "967a801bd188989a5669bd280f252d51c0fdc9ee", "shasum": "" }, "require": { - "hamcrest/hamcrest-php": "^2.0.1", - "lib-pcre": ">=7.0", + "hamcrest/hamcrest-php": "^2.0 || ^3.0", "php": ">=7.3" }, "conflict": { "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.6.17", - "symplify/easy-coding-standard": "^12.1.14" + "phpunit/phpunit": "^9.6.36", + "symplify/easy-coding-standard": "^13.2.17" }, "type": "library", "autoload": { @@ -9754,24 +9937,24 @@ "security": "https://github.com/mockery/mockery/security/advisories", "source": "https://github.com/mockery/mockery" }, - "time": "2024-05-16T03:13:13+00:00" + "time": "2026-08-19T19:37:52+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.12.1", + "version": "1.14.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" + "reference": "8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae", + "reference": "8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.0" }, "conflict": { "doctrine/collections": "<1.6.8", @@ -9806,50 +9989,48 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.14.0" }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" + "url": "https://github.com/mnapoli", + "type": "github" } ], - "time": "2024-11-08T17:47:46+00:00" + "time": "2026-08-11T10:17:44+00:00" }, { "name": "nunomaduro/collision", - "version": "v8.5.0", + "version": "v8.9.5", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "f5c101b929c958e849a633283adff296ed5f38f5" + "reference": "fb53eacd509a1d303858e2d20cfebf2d630254ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f5c101b929c958e849a633283adff296ed5f38f5", - "reference": "f5c101b929c958e849a633283adff296ed5f38f5", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/fb53eacd509a1d303858e2d20cfebf2d630254ec", + "reference": "fb53eacd509a1d303858e2d20cfebf2d630254ec", "shasum": "" }, "require": { - "filp/whoops": "^2.16.0", - "nunomaduro/termwind": "^2.1.0", + "filp/whoops": "^2.18.4", + "nunomaduro/termwind": "^2.4.0", "php": "^8.2.0", - "symfony/console": "^7.1.5" + "symfony/console": "^7.4.14 || ^8.1.1" }, "conflict": { - "laravel/framework": "<11.0.0 || >=12.0.0", - "phpunit/phpunit": "<10.5.1 || >=12.0.0" + "laravel/framework": "<11.48.0 || >=14.0.0", + "phpunit/phpunit": "<11.5.50 || >=14.0.0" }, "require-dev": { - "larastan/larastan": "^2.9.8", - "laravel/framework": "^11.28.0", - "laravel/pint": "^1.18.1", - "laravel/sail": "^1.36.0", - "laravel/sanctum": "^4.0.3", - "laravel/tinker": "^2.10.0", - "orchestra/testbench-core": "^9.5.3", - "pestphp/pest": "^2.36.0 || ^3.4.0", - "sebastian/environment": "^6.1.0 || ^7.2.0" + "brianium/paratest": "^7.8.5", + "larastan/larastan": "^3.10.0", + "laravel/framework": "^11.48.0 || ^12.56.0 || ^13.20.0", + "laravel/pint": "^1.29.3", + "orchestra/testbench-core": "^9.12.0 || ^10.12.1 || ^11.3.5", + "pestphp/pest": "^3.8.5 || ^4.7.5 || ^5.0.0", + "sebastian/environment": "^7.2.1 || ^8.1.2 || ^9.3.2" }, "type": "library", "extra": { @@ -9886,6 +10067,7 @@ "cli", "command-line", "console", + "dev", "error", "handling", "laravel", @@ -9911,7 +10093,7 @@ "type": "patreon" } ], - "time": "2024-10-15T16:06:32+00:00" + "time": "2026-07-15T19:09:14+00:00" }, { "name": "phar-io/manifest", @@ -10033,30 +10215,30 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.33.0", + "version": "2.3.6", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140" + "reference": "1427af4647235b4a73b13940b1f1258d3584f36e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1427af4647235b4a73b13940b1f1258d3584f36e", + "reference": "1427af4647235b4a73b13940b1f1258d3584f36e", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^5.3.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", "symfony/process": "^5.2" }, "type": "library", @@ -10074,41 +10256,39 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.6" }, - "time": "2024-10-13T11:25:22+00:00" + "time": "2026-09-27T20:07:45+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "10.1.16", + "version": "12.5.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77" + "reference": "7440368d94738d54f2c1de24dbd3871793bbb0dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7440368d94738d54f2c1de24dbd3871793bbb0dd", + "reference": "7440368d94738d54f2c1de24dbd3871793bbb0dd", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-text-template": "^3.0.1", - "sebastian/code-unit-reverse-lookup": "^3.0.0", - "sebastian/complexity": "^3.2.0", - "sebastian/environment": "^6.1.0", - "sebastian/lines-of-code": "^2.0.2", - "sebastian/version": "^4.0.1", - "theseer/tokenizer": "^1.2.3" + "nikic/php-parser": "^5.9.0", + "php": ">=8.3", + "phpunit/php-text-template": "^5.0.1", + "sebastian/complexity": "^5.0", + "sebastian/environment": "^8.1.2", + "sebastian/lines-of-code": "^4.0.1", + "sebastian/version": "^6.0", + "theseer/tokenizer": "^2.0.1" }, "require-dev": { - "phpunit/phpunit": "^10.1" + "phpunit/phpunit": "^12.5.37" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -10117,7 +10297,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1.x-dev" + "dev-main": "12.5.x-dev" } }, "autoload": { @@ -10146,40 +10326,52 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" } ], - "time": "2024-08-22T04:31:57+00:00" + "time": "2026-10-03T14:03:50+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "4.1.0", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + "reference": "a248d1640ab059b075f53a2ef0f9856e864e06b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a248d1640ab059b075f53a2ef0f9856e864e06b5", + "reference": "a248d1640ab059b075f53a2ef0f9856e864e06b5", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.5.33" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -10207,36 +10399,48 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", + "type": "tidelift" } ], - "time": "2023-08-31T06:24:48+00:00" + "time": "2026-08-25T14:40:53+00:00" }, { "name": "phpunit/php-invoker", - "version": "4.0.0", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/12b54e689b07a25a9b41e57736dfab6ec9ae5406", + "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.0" }, "suggest": { "ext-pcntl": "*" @@ -10244,7 +10448,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -10270,7 +10474,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0" }, "funding": [ { @@ -10278,32 +10483,32 @@ "type": "github" } ], - "time": "2023-02-03T06:56:09+00:00" + "time": "2025-02-07T04:58:58+00:00" }, { "name": "phpunit/php-text-template", - "version": "3.0.1", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + "reference": "babab73b7ef9fae406f2eb3ee11323a61caa63d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/babab73b7ef9fae406f2eb3ee11323a61caa63d5", + "reference": "babab73b7ef9fae406f2eb3ee11323a61caa63d5", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.5.37" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -10330,40 +10535,52 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-text-template", + "type": "tidelift" } ], - "time": "2023-08-31T14:07:24+00:00" + "time": "2026-10-03T04:51:29+00:00" }, { "name": "phpunit/php-timer", - "version": "6.0.0", + "version": "8.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", + "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "8.0-dev" } }, "autoload": { @@ -10389,7 +10606,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0" }, "funding": [ { @@ -10397,52 +10615,49 @@ "type": "github" } ], - "time": "2023-02-03T06:57:52+00:00" + "time": "2025-02-07T04:59:38+00:00" }, { "name": "phpunit/phpunit", - "version": "10.5.40", + "version": "12.5.40", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "e6ddda95af52f69c1e0c7b4f977cccb58048798c" + "reference": "76bd3198f16aeb375a4d5f3626471445aed0966e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e6ddda95af52f69c1e0c7b4f977cccb58048798c", - "reference": "e6ddda95af52f69c1e0c7b4f977cccb58048798c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/76bd3198f16aeb375a4d5f3626471445aed0966e", + "reference": "76bd3198f16aeb375a4d5f3626471445aed0966e", "shasum": "" }, "require": { "ext-dom": "*", + "ext-filter": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", - "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.1", + "myclabs/deep-copy": "^1.14.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", - "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.16", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-invoker": "^4.0.0", - "phpunit/php-text-template": "^3.0.1", - "phpunit/php-timer": "^6.0.0", - "sebastian/cli-parser": "^2.0.1", - "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.3", - "sebastian/diff": "^5.1.1", - "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.2", - "sebastian/global-state": "^6.0.2", - "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.0", - "sebastian/type": "^4.0.0", - "sebastian/version": "^4.0.1" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" + "php": ">=8.3", + "phpunit/php-code-coverage": "^12.5.8", + "phpunit/php-file-iterator": "^6.0.2", + "phpunit/php-invoker": "^6.0.0", + "phpunit/php-text-template": "^5.0.1", + "phpunit/php-timer": "^8.0.0", + "sebastian/cli-parser": "^4.2.1", + "sebastian/comparator": "^7.1.8", + "sebastian/diff": "^7.0.1", + "sebastian/environment": "^8.1.2", + "sebastian/exporter": "^7.0.3", + "sebastian/global-state": "^8.0.3", + "sebastian/object-enumerator": "^7.0.0", + "sebastian/recursion-context": "^7.0.1", + "sebastian/type": "^6.0.4", + "sebastian/version": "^6.0.1", + "staabm/side-effects-detector": "^1.0.5" }, "bin": [ "phpunit" @@ -10450,7 +10665,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.5-dev" + "dev-main": "12.5-dev" } }, "autoload": { @@ -10482,45 +10697,42 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.40" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.40" }, "funding": [ { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" + "url": "https://phpunit.de/sponsoring.html", + "type": "other" } ], - "time": "2024-12-21T05:49:06+00:00" + "time": "2026-10-16T05:55:07+00:00" }, { "name": "respect/stringifier", - "version": "0.2.0", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/Respect/Stringifier.git", - "reference": "e55af3c8aeaeaa2abb5fa47a58a8e9688cc23b59" + "reference": "e88515f675b373596d5dcdd9dc6103b8504c7ca5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Respect/Stringifier/zipball/e55af3c8aeaeaa2abb5fa47a58a8e9688cc23b59", - "reference": "e55af3c8aeaeaa2abb5fa47a58a8e9688cc23b59", + "url": "https://api.github.com/repos/Respect/Stringifier/zipball/e88515f675b373596d5dcdd9dc6103b8504c7ca5", + "reference": "e88515f675b373596d5dcdd9dc6103b8504c7ca5", "shasum": "" }, "require": { - "php": ">=7.1" + "php": "^8.1" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.8", "malukenho/docheader": "^0.1.7", - "phpunit/phpunit": "^6.4" + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-strict-rules": "^1.5", + "phpunit/phpunit": "^10.0", + "respect/coding-standard": "^4.0", + "squizlabs/php_codesniffer": "^3.7" }, "type": "library", "autoload": { @@ -10528,7 +10740,9 @@ "src/stringify.php" ], "psr-4": { - "Respect\\Stringifier\\": "src/" + "Respect\\Stringifier\\": "src/", + "Respect\\Stringifier\\Test\\": "tests/src/", + "Respect\\Stringifier\\Test\\Unit\\": "tests/unit" } }, "notification-url": "https://packagist.org/downloads/", @@ -10542,7 +10756,6 @@ } ], "description": "Converts any value to a string", - "homepage": "http://respect.github.io/Stringifier/", "keywords": [ "respect", "stringifier", @@ -10550,32 +10763,32 @@ ], "support": { "issues": "https://github.com/Respect/Stringifier/issues", - "source": "https://github.com/Respect/Stringifier/tree/0.2.0" + "source": "https://github.com/Respect/Stringifier/tree/1.0.0" }, - "time": "2017-12-29T19:39:25+00:00" + "time": "2023-04-12T20:15:44+00:00" }, { "name": "respect/validation", - "version": "2.4.0", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/Respect/Validation.git", - "reference": "48b38bd91e0badbc2c4381dce726b09fd68850d9" + "reference": "48254ed1079fc0879eb03fb2b600f92bb4ecb787" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Respect/Validation/zipball/48b38bd91e0badbc2c4381dce726b09fd68850d9", - "reference": "48b38bd91e0badbc2c4381dce726b09fd68850d9", + "url": "https://api.github.com/repos/Respect/Validation/zipball/48254ed1079fc0879eb03fb2b600f92bb4ecb787", + "reference": "48254ed1079fc0879eb03fb2b600f92bb4ecb787", "shasum": "" }, "require": { "php": ">=8.1", - "respect/stringifier": "^0.2.0", + "respect/stringifier": "^0.2.0 || ^1.0", "symfony/polyfill-mbstring": "^1.2" }, "require-dev": { - "egulias/email-validator": "^3.0", - "giggsey/libphonenumber-for-php-lite": "^8.13", + "egulias/email-validator": "^3.0 || ^4.0", + "giggsey/libphonenumber-for-php-lite": "^8.13 || ^9.0", "malukenho/docheader": "^1.0", "mikey179/vfsstream": "^1.6", "phpstan/phpstan": "^1.9", @@ -10618,34 +10831,34 @@ ], "support": { "issues": "https://github.com/Respect/Validation/issues", - "source": "https://github.com/Respect/Validation/tree/2.4.0" + "source": "https://github.com/Respect/Validation/tree/2.5.0" }, - "time": "2025-01-07T00:34:58+00:00" + "time": "2026-07-22T15:21:03+00:00" }, { "name": "sebastian/cli-parser", - "version": "2.0.1", + "version": "4.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + "reference": "7d05781b13f7dec9043a629a21d086ed74582a15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/7d05781b13f7dec9043a629a21d086ed74582a15", + "reference": "7d05781b13f7dec9043a629a21d086ed74582a15", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "4.2-dev" } }, "autoload": { @@ -10669,155 +10882,59 @@ "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - } - ], - "time": "2024-03-02T07:12:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ + }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" - }, - "funding": [ + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:58:43+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser", + "type": "tidelift" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:59:15+00:00" + "time": "2026-05-17T05:29:34+00:00" }, { "name": "sebastian/comparator", - "version": "5.0.3", + "version": "7.1.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" + "reference": "7c65c1e79836812819705b473a90c12399542485" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", - "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/7c65c1e79836812819705b473a90c12399542485", + "reference": "7c65c1e79836812819705b473a90c12399542485", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" + "php": ">=8.3", + "sebastian/diff": "^7.0", + "sebastian/exporter": "^7.0.3" }, "require-dev": { - "phpunit/phpunit": "^10.5" + "phpunit/phpunit": "^12.5.25" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "7.1-dev" } }, "autoload": { @@ -10857,41 +10974,53 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2024-10-18T14:56:07+00:00" + "time": "2026-05-21T04:45:25+00:00" }, { "name": "sebastian/complexity", - "version": "3.2.0", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" + "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/bad4316aba5303d0221f43f8cee37eb58d384bbb", + "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.2-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -10915,7 +11044,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0" }, "funding": [ { @@ -10923,33 +11052,33 @@ "type": "github" } ], - "time": "2023-12-21T08:37:17+00:00" + "time": "2025-02-07T04:55:25+00:00" }, { "name": "sebastian/diff", - "version": "5.1.1", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + "reference": "cd4cabe39f8a4e8ee6818ba99f10a05561ea4ad6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/cd4cabe39f8a4e8ee6818ba99f10a05561ea4ad6", + "reference": "cd4cabe39f8a4e8ee6818ba99f10a05561ea4ad6", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" + "phpunit/phpunit": "^12.5.33", + "symfony/process": "^7.4.17" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -10982,35 +11111,47 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + "source": "https://github.com/sebastianbergmann/diff/tree/7.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/diff", + "type": "tidelift" } ], - "time": "2024-03-02T07:15:17+00:00" + "time": "2026-08-25T15:35:54+00:00" }, { "name": "sebastian/environment", - "version": "6.1.0", + "version": "8.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + "reference": "9d32c685773823b1983e256ae4ecd48a10d6e439" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/9d32c685773823b1983e256ae4ecd48a10d6e439", + "reference": "9d32c685773823b1983e256ae4ecd48a10d6e439", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.5.26" }, "suggest": { "ext-posix": "*" @@ -11018,7 +11159,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-main": "8.1-dev" } }, "autoload": { @@ -11046,42 +11187,54 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + "source": "https://github.com/sebastianbergmann/environment/tree/8.1.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" } ], - "time": "2024-03-23T08:47:14+00:00" + "time": "2026-05-25T13:40:20+00:00" }, { "name": "sebastian/exporter", - "version": "5.1.2", + "version": "7.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + "reference": "c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23", + "reference": "c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" + "php": ">=8.3", + "sebastian/recursion-context": "^7.0.1" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -11124,43 +11277,55 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" + "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T07:17:12+00:00" + "time": "2026-05-20T04:37:17+00:00" }, { "name": "sebastian/global-state", - "version": "6.0.2", + "version": "8.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + "reference": "b164d3274d6537ab462591c5755f76a8f5b1aae9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b164d3274d6537ab462591c5755f76a8f5b1aae9", + "reference": "b164d3274d6537ab462591c5755f76a8f5b1aae9", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.3", + "sebastian/object-reflector": "^5.0", + "sebastian/recursion-context": "^7.0.1" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.5.28" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "8.0-dev" } }, "autoload": { @@ -11186,41 +11351,53 @@ "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" } ], - "time": "2024-03-02T07:19:19+00:00" + "time": "2026-06-01T15:10:33+00:00" }, { "name": "sebastian/lines-of-code", - "version": "2.0.2", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + "reference": "d543b8ef219dcd8da262cbb958639a96bedba10e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d543b8ef219dcd8da262cbb958639a96bedba10e", + "reference": "d543b8ef219dcd8da262cbb958639a96bedba10e", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.7.0", + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -11244,42 +11421,54 @@ "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/lines-of-code", + "type": "tidelift" } ], - "time": "2023-12-21T08:38:20+00:00" + "time": "2026-05-19T16:22:07+00:00" }, { "name": "sebastian/object-enumerator", - "version": "5.0.0", + "version": "7.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1effe8e9b8e068e9ae228e542d5d11b5d16db894", + "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.3", + "sebastian/object-reflector": "^5.0", + "sebastian/recursion-context": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -11301,7 +11490,8 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0" }, "funding": [ { @@ -11309,32 +11499,32 @@ "type": "github" } ], - "time": "2023-02-03T07:08:32+00:00" + "time": "2025-02-07T04:57:48+00:00" }, { "name": "sebastian/object-reflector", - "version": "3.0.0", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + "reference": "4bfa827c969c98be1e527abd576533293c634f6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/4bfa827c969c98be1e527abd576533293c634f6a", + "reference": "4bfa827c969c98be1e527abd576533293c634f6a", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -11356,7 +11546,8 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0" }, "funding": [ { @@ -11364,32 +11555,32 @@ "type": "github" } ], - "time": "2023-02-03T07:06:18+00:00" + "time": "2025-02-07T04:58:17+00:00" }, { "name": "sebastian/recursion-context", - "version": "5.0.0", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/0b01998a7d5b1f122911a66bebcb8d46f0c82d8c", + "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -11419,40 +11610,53 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2023-02-03T07:05:40+00:00" + "time": "2025-08-13T04:44:59+00:00" }, { "name": "sebastian/type", - "version": "4.0.0", + "version": "6.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + "reference": "82ff822c2edc46724be9f7411d3163021f602773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/82ff822c2edc46724be9f7411d3163021f602773", + "reference": "82ff822c2edc46724be9f7411d3163021f602773", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -11475,37 +11679,50 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/6.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" } ], - "time": "2023-02-03T07:10:45+00:00" + "time": "2026-05-20T06:45:45+00:00" }, { "name": "sebastian/version", - "version": "4.0.1", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + "reference": "9e935a16187e14f39b0e79910dabd614972cdb26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/9e935a16187e14f39b0e79910dabd614972cdb26", + "reference": "9e935a16187e14f39b0e79910dabd614972cdb26", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -11528,44 +11745,57 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/6.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/version", + "type": "tidelift" } ], - "time": "2023-02-07T11:34:05+00:00" + "time": "2026-10-04T05:50:08+00:00" }, { "name": "slevomat/coding-standard", - "version": "8.15.0", + "version": "8.31.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "7d1d957421618a3803b593ec31ace470177d7817" + "reference": "0a40807a48873948bfa7ffce2a4e69ba40cf5e76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7d1d957421618a3803b593ec31ace470177d7817", - "reference": "7d1d957421618a3803b593ec31ace470177d7817", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/0a40807a48873948bfa7ffce2a4e69ba40cf5e76", + "reference": "0a40807a48873948bfa7ffce2a4e69ba40cf5e76", "shasum": "" }, "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", - "php": "^7.2 || ^8.0", - "phpstan/phpdoc-parser": "^1.23.1", - "squizlabs/php_codesniffer": "^3.9.0" + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.2.1", + "php": "^7.4 || ^8.0", + "phpstan/phpdoc-parser": "^2.3.3", + "squizlabs/php_codesniffer": "^4.0.1" }, "require-dev": { - "phing/phing": "2.17.4", - "php-parallel-lint/php-parallel-lint": "1.3.2", - "phpstan/phpstan": "1.10.60", - "phpstan/phpstan-deprecation-rules": "1.1.4", - "phpstan/phpstan-phpunit": "1.3.16", - "phpstan/phpstan-strict-rules": "1.5.2", - "phpunit/phpunit": "8.5.21|9.6.8|10.5.11" + "phing/phing": "3.0.1|3.1.2", + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/phpstan": "2.2.7", + "phpstan/phpstan-deprecation-rules": "2.0.5", + "phpstan/phpstan-phpunit": "2.0.18", + "phpstan/phpstan-strict-rules": "2.0.12", + "phpunit/phpunit": "9.6.34|10.5.63|11.4.4|11.5.56|12.5.33" }, "type": "phpcodesniffer-standard", "extra": { @@ -11589,7 +11819,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.15.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.31.1" }, "funding": [ { @@ -11601,20 +11831,20 @@ "type": "tidelift" } ], - "time": "2024-03-09T15:20:58+00:00" + "time": "2026-07-31T10:42:43+00:00" }, { "name": "spatie/backtrace", - "version": "1.7.1", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "0f2477c520e3729de58e061b8192f161c99f770b" + "reference": "8ffe78be5ed355b5009e3dd989d183433e9a5adc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/0f2477c520e3729de58e061b8192f161c99f770b", - "reference": "0f2477c520e3729de58e061b8192f161c99f770b", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/8ffe78be5ed355b5009e3dd989d183433e9a5adc", + "reference": "8ffe78be5ed355b5009e3dd989d183433e9a5adc", "shasum": "" }, "require": { @@ -11625,7 +11855,7 @@ "laravel/serializable-closure": "^1.3 || ^2.0", "phpunit/phpunit": "^9.3 || ^11.4.3", "spatie/phpunit-snapshot-assertions": "^4.2 || ^5.1.6", - "symfony/var-dumper": "^5.1 || ^6.0 || ^7.0" + "symfony/var-dumper": "^5.1|^6.0|^7.0|^8.0" }, "type": "library", "autoload": { @@ -11652,7 +11882,8 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.7.1" + "issues": "https://github.com/spatie/backtrace/issues", + "source": "https://github.com/spatie/backtrace/tree/1.8.2" }, "funding": [ { @@ -11664,34 +11895,34 @@ "type": "other" } ], - "time": "2024-12-02T13:28:15+00:00" + "time": "2026-03-11T13:48:28+00:00" }, { "name": "spatie/error-solutions", - "version": "1.1.2", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/spatie/error-solutions.git", - "reference": "d239a65235a1eb128dfa0a4e4c4ef032ea11b541" + "reference": "e495d7178ca524f2dd0fe6a1d99a1e608e1c9936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/error-solutions/zipball/d239a65235a1eb128dfa0a4e4c4ef032ea11b541", - "reference": "d239a65235a1eb128dfa0a4e4c4ef032ea11b541", + "url": "https://api.github.com/repos/spatie/error-solutions/zipball/e495d7178ca524f2dd0fe6a1d99a1e608e1c9936", + "reference": "e495d7178ca524f2dd0fe6a1d99a1e608e1c9936", "shasum": "" }, "require": { "php": "^8.0" }, "require-dev": { - "illuminate/broadcasting": "^10.0|^11.0", - "illuminate/cache": "^10.0|^11.0", - "illuminate/support": "^10.0|^11.0", - "livewire/livewire": "^2.11|^3.3.5", + "illuminate/broadcasting": "^10.0|^11.0|^12.0", + "illuminate/cache": "^10.0|^11.0|^12.0", + "illuminate/support": "^10.0|^11.0|^12.0", + "livewire/livewire": "^2.11|^3.5.20", "openai-php/client": "^0.10.1", - "orchestra/testbench": "^7.0|8.22.3|^9.0", - "pestphp/pest": "^2.20", - "phpstan/phpstan": "^1.11", + "orchestra/testbench": "8.22.3|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "phpstan/phpstan": "^2.1", "psr/simple-cache": "^3.0", "psr/simple-cache-implementation": "^3.0", "spatie/ray": "^1.28", @@ -11730,7 +11961,7 @@ ], "support": { "issues": "https://github.com/spatie/error-solutions/issues", - "source": "https://github.com/spatie/error-solutions/tree/1.1.2" + "source": "https://github.com/spatie/error-solutions/tree/1.1.3" }, "funding": [ { @@ -11738,30 +11969,30 @@ "type": "github" } ], - "time": "2024-12-11T09:51:56+00:00" + "time": "2025-02-14T12:29:50+00:00" }, { "name": "spatie/flare-client-php", - "version": "1.10.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/spatie/flare-client-php.git", - "reference": "140a42b2c5d59ac4ecf8f5b493386a4f2eb28272" + "reference": "53f41b08a27cc039e1a8ed2be9a202e924f31bad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/140a42b2c5d59ac4ecf8f5b493386a4f2eb28272", - "reference": "140a42b2c5d59ac4ecf8f5b493386a4f2eb28272", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/53f41b08a27cc039e1a8ed2be9a202e924f31bad", + "reference": "53f41b08a27cc039e1a8ed2be9a202e924f31bad", "shasum": "" }, "require": { - "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0", + "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^8.0", "spatie/backtrace": "^1.6.1", - "symfony/http-foundation": "^5.2|^6.0|^7.0", - "symfony/mime": "^5.2|^6.0|^7.0", - "symfony/process": "^5.2|^6.0|^7.0", - "symfony/var-dumper": "^5.2|^6.0|^7.0" + "symfony/http-foundation": "^5.2|^6.0|^7.0|^8.0", + "symfony/mime": "^5.2|^6.0|^7.0|^8.0", + "symfony/process": "^5.2|^6.0|^7.0|^8.0", + "symfony/var-dumper": "^5.2|^6.0|^7.0|^8.0" }, "require-dev": { "dms/phpunit-arraysubset-asserts": "^0.5.0", @@ -11799,7 +12030,7 @@ ], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", - "source": "https://github.com/spatie/flare-client-php/tree/1.10.0" + "source": "https://github.com/spatie/flare-client-php/tree/1.11.1" }, "funding": [ { @@ -11807,41 +12038,44 @@ "type": "github" } ], - "time": "2024-12-02T14:30:06+00:00" + "time": "2026-05-15T09:31:32+00:00" }, { "name": "spatie/ignition", - "version": "1.15.0", + "version": "1.16.0", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2" + "reference": "b59385bb7aa24dae81bcc15850ebecfda7b40838" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/e3a68e137371e1eb9edc7f78ffa733f3b98991d2", - "reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2", + "url": "https://api.github.com/repos/spatie/ignition/zipball/b59385bb7aa24dae81bcc15850ebecfda7b40838", + "reference": "b59385bb7aa24dae81bcc15850ebecfda7b40838", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", "php": "^8.0", - "spatie/error-solutions": "^1.0", - "spatie/flare-client-php": "^1.7", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "spatie/backtrace": "^1.7.1", + "spatie/error-solutions": "^1.1.2", + "spatie/flare-client-php": "^1.9", + "symfony/console": "^5.4.42|^6.0|^7.0|^8.0", + "symfony/http-foundation": "^5.4.42|^6.0|^7.0|^8.0", + "symfony/mime": "^5.4.42|^6.0|^7.0|^8.0", + "symfony/var-dumper": "^5.4.42|^6.0|^7.0|^8.0" }, "require-dev": { - "illuminate/cache": "^9.52|^10.0|^11.0", + "illuminate/cache": "^9.52|^10.0|^11.0|^12.0|^13.0", "mockery/mockery": "^1.4", - "pestphp/pest": "^1.20|^2.0", + "pestphp/pest": "^1.20|^2.0|^3.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "psr/simple-cache-implementation": "*", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", + "symfony/cache": "^5.4.38|^6.0|^7.0|^8.0", + "symfony/process": "^5.4.35|^6.0|^7.0|^8.0", "vlucas/phpdotenv": "^5.5" }, "suggest": { @@ -11890,42 +12124,43 @@ "type": "github" } ], - "time": "2024-06-12T14:55:22+00:00" + "time": "2026-03-17T10:51:08+00:00" }, { "name": "spatie/laravel-ignition", - "version": "2.9.0", + "version": "2.12.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "62042df15314b829d0f26e02108f559018e2aad0" + "reference": "0d49228686542bf718ad1a978ab3eb1d5a0dcd41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/62042df15314b829d0f26e02108f559018e2aad0", - "reference": "62042df15314b829d0f26e02108f559018e2aad0", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/0d49228686542bf718ad1a978ab3eb1d5a0dcd41", + "reference": "0d49228686542bf718ad1a978ab3eb1d5a0dcd41", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "illuminate/support": "^10.0|^11.0", - "php": "^8.1", - "spatie/ignition": "^1.15", - "symfony/console": "^6.2.3|^7.0", - "symfony/var-dumper": "^6.2.3|^7.0" + "illuminate/support": "^11.0|^12.0|^13.0", + "nesbot/carbon": "^2.72|^3.0", + "php": "^8.2", + "spatie/ignition": "^1.16", + "symfony/console": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "require-dev": { - "livewire/livewire": "^2.11|^3.3.5", - "mockery/mockery": "^1.5.1", - "openai-php/client": "^0.8.1", - "orchestra/testbench": "8.22.3|^9.0", - "pestphp/pest": "^2.34", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan-deprecation-rules": "^1.1.1", - "phpstan/phpstan-phpunit": "^1.3.16", - "vlucas/phpdotenv": "^5.5" + "livewire/livewire": "^3.7.0|^4.0|dev-josh/v3-laravel-13-support", + "mockery/mockery": "^1.6.12", + "openai-php/client": "^0.10.3|^0.19", + "orchestra/testbench": "^v9.16.0|^10.6|^11.0", + "pestphp/pest": "^3.7|^4.0", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.8", + "vlucas/phpdotenv": "^5.6.2" }, "suggest": { "openai-php/client": "Require get solutions from OpenAI", @@ -11981,41 +12216,41 @@ "type": "github" } ], - "time": "2024-12-02T08:43:31+00:00" + "time": "2026-10-19T16:31:25+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.11.2", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "1368f4a58c3c52114b86b1abe8f4098869cb0079" + "reference": "bbdc3d0532623e21838b7041a4364383a8126f96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/1368f4a58c3c52114b86b1abe8f4098869cb0079", - "reference": "1368f4a58c3c52114b86b1abe8f4098869cb0079", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/bbdc3d0532623e21838b7041a4364383a8126f96", + "reference": "bbdc3d0532623e21838b7041a4364383a8126f96", "shasum": "" }, "require": { + "ext-libxml": "*", "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": ">=5.4.0" + "php": ">=7.2.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + "phpunit/phpunit": "^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31" + }, + "suggest": { + "ext-iconv": "For accurate character length calculation when the checked files contain multi-byte characters.", + "ext-pcntl": "For parallel processing support via the --parallel CLI option." }, "bin": [ "bin/phpcbf", "bin/phpcs" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -12034,7 +12269,7 @@ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "description": "PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.", "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ "phpcs", @@ -12059,105 +12294,85 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2024-12-11T16:04:26+00:00" + "time": "2026-08-06T02:45:27+00:00" }, { - "name": "symfony/polyfill-php81", - "version": "v1.31.0", + "name": "staabm/side-effects-detector", + "version": "1.0.5", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", "shasum": "" }, "require": { - "php": ">=7.2" + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" }, "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, "classmap": [ - "Resources/stubs" + "lib/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", + "description": "A static analysis tool to detect side effects in PHP code", "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" + "static analysis" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/staabm", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-10-20T05:08:20+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/7989e43bf381af0eac72e4f0ca5bcbfa81658be4", + "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" + "php": "^8.1" }, "type": "library", "autoload": { @@ -12179,7 +12394,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/2.0.1" }, "funding": [ { @@ -12187,20 +12402,20 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-12-08T11:19:18+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.3", + "php": "^8.5", "ext-curl": "*", "ext-dom": "*", "ext-json": "*" }, - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform-dev": {}, + "plugin-api-version": "2.9.0" } From 4eaebf86c0b9d549fe271201528931180d244116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 22 Oct 2026 15:58:06 +0200 Subject: [PATCH 3/8] fix: Claim factory --- database/factories/ClaimFactory.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/database/factories/ClaimFactory.php b/database/factories/ClaimFactory.php index edcc7a4..8b30407 100644 --- a/database/factories/ClaimFactory.php +++ b/database/factories/ClaimFactory.php @@ -8,7 +8,6 @@ use App\Enums\Claims\ClaimType; use App\Models\Brand; use App\Models\Claim; use App\Models\ClaimSubject; -use App\Models\Customer; use Illuminate\Database\Eloquent\Factories\Factory; class ClaimFactory extends Factory @@ -40,9 +39,6 @@ class ClaimFactory extends Factory 'status' => collect(ClaimStatus::toArray())->random()->value, 'brand_id' => $this->faker->randomElement(Brand::query()->get()->modelKeys()), 'subject_id' => $this->faker->randomElement(ClaimSubject::query()->get()->modelKeys()), - 'customer_id' => $this->faker->boolean(50) - ? $this->faker->randomElement(Customer::query()->get()->modelKeys()) - : null, ]; } } From c235055b62d66acbc617fed08074cef191780e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 22 Oct 2026 15:58:19 +0200 Subject: [PATCH 4/8] build: docker file bump --- Dockerfile | 9 +++++++-- manifest.yaml | 11 ++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6481cbb..f8c9751 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,9 @@ +ARG PHP_8_5_TAG=latest + FROM composer:2.8 AS vendor +WORKDIR /app + ARG GITLAB_USER ARG GITLAB_PASSWORD @@ -8,7 +12,7 @@ COPY database/ database/ COPY composer.json composer.json COPY composer.lock composer.lock -RUN composer config gitlab-token.lab.s-web.fr ${GITLAB_USER} ${GITLAB_PASSWORD} +RUN composer config gitlab-token.lab.s-web.fr "${GITLAB_USER}" "${GITLAB_PASSWORD}" RUN composer install \ --ignore-platform-reqs \ --no-interaction \ @@ -32,7 +36,8 @@ RUN npm config set @uwil:registry https://lab.s-web.fr/api/v4/groups/ldc-web/-/p RUN npm config set -- '//lab.s-web.fr/api/v4/groups/ldc-web/-/packages/npm/:_authToken' "${GITLAB_PASSWORD}" RUN npm ci --no-audit --no-fund --loglevel=error && npm run prod -FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-8.3:170625-101047 +ARG PHP_8_5_TAG +FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/uwil-production-8.5:${PHP_8_5_TAG} ARG USER=www-data diff --git a/manifest.yaml b/manifest.yaml index cb127df..db1dff2 100644 --- a/manifest.yaml +++ b/manifest.yaml @@ -11,8 +11,8 @@ data: APP_URL: "https://${APP_DOMAIN}" APP_K8S_INTERNAL_URL: "${APP_APP_K8S_INTERNAL_URL}" LOG_CHANNEL: "k8s" - DB_HOST: "${APP_DB_HOST}" - DB_PORT: "${APP_DB_PORT}" + DB_HOST: "${APP_GLOBAL_OVH_MYSQL_HOST}" + DB_PORT: "${APP_GLOBAL_OVH_MYSQL_PORT}" DB_DATABASE: "${APP_DB_DATABASE}" DB_USERNAME: "${APP_DB_USERNAME}" DB_PASSWORD: "${APP_DB_PASSWORD}" @@ -83,7 +83,12 @@ spec: lifecycle: preStop: exec: - command: ["/bin/sh","-c","kill -s TERM 1; while test $(ps ax | grep -v grep | grep bash | wc -l) -gt 0; do sleep 2s; done"] + command: + [ + "/bin/sh", + "-c", + "kill -s TERM 1; while test $(ps ax | grep -v grep | grep bash | wc -l) -gt 0; do sleep 2s; done", + ] resources: limits: cpu: "${APP_CI_CPU_LIMIT}" From 132c25a75eb2188b4f0af91838c30ce646d4de04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 22 Oct 2026 16:01:21 +0200 Subject: [PATCH 5/8] chore: replace deprecated constant mysql in config --- config/database.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/database.php b/config/database.php index 17ec10e..f69b1f0 100644 --- a/config/database.php +++ b/config/database.php @@ -1,6 +1,7 @@ true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ - PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + Mysql::ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], From ea1d6c6bba2b8cb0822830853030ec8949ee0784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 22 Oct 2026 16:01:36 +0200 Subject: [PATCH 6/8] chore : vscode config intellephnese php version --- .vscode/settings.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index c774b95..7948528 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,5 @@ { - "phpcs.executablePath": "vendor/bin/phpcs", "workbench.colorCustomizations": { "activityBar.activeBackground": "#8dc952", "activityBar.activeBorder": "#3d7fc2", @@ -22,5 +21,5 @@ "commandCenter.border": "#15202b99" }, "peacock.remoteColor": "#73b137", - "intelephense.environment.phpVersion": "8.2" + "intelephense.environment.phpVersion": "8.5" } From cc6ad2e6e148dd08218e169d0fc6f9fdba6887ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 22 Oct 2026 16:37:28 +0200 Subject: [PATCH 7/8] chore: phpcs fix --- app/Console/Commands/UserCreate.php | 36 ++++++++++----------- app/Http/Controllers/Bo/ClaimController.php | 4 +-- config/sentry.php | 2 -- phpcs.xml | 3 -- 4 files changed, 20 insertions(+), 25 deletions(-) diff --git a/app/Console/Commands/UserCreate.php b/app/Console/Commands/UserCreate.php index d656d86..05f86e3 100644 --- a/app/Console/Commands/UserCreate.php +++ b/app/Console/Commands/UserCreate.php @@ -31,14 +31,14 @@ class UserCreate extends Command * * @var string|null */ - protected $first_name; + protected $firstName; /** * The last name of the new user. * * @var string|null */ - protected $last_name; + protected $lastName; /** * The email of the new user. @@ -61,10 +61,10 @@ class UserCreate extends Command */ public function handle(): void { - $this->first_name = null; + $this->firstName = null; $this->addFirstName(); - $this->last_name = null; + $this->lastName = null; $this->addLastName(); $this->email = null; @@ -74,8 +74,8 @@ class UserCreate extends Command $this->addRole(); $user = new User([ - 'first_name' => $this->first_name, - 'last_name' => $this->last_name, + 'first_name' => $this->firstName, + 'last_name' => $this->lastName, 'email' => $this->email, 'role' => $this->role, 'published' => true, @@ -93,22 +93,22 @@ class UserCreate extends Command */ private function addFirstName(): void { - while (is_null($this->first_name)) { + while (is_null($this->firstName)) { try { $tmp = $this->ask('Type the wanted user first name', 'Admin'); $validator = Validator::make(['first_name' => $tmp], [ 'first_name' => 'required|min:3|max:255' ]); $validator->validate(); - $this->first_name = $tmp; + $this->firstName = $tmp; } catch (ValidationException $e) { $this->error(sprintf( 'Please provide a valid first name %s', \implode(',', collect($e->errors())->flatten()->all()) )); continue; - } //end try - }; //end while + } + } } /** @@ -118,22 +118,22 @@ class UserCreate extends Command */ private function addLastName(): void { - while (is_null($this->last_name)) { + while (is_null($this->lastName)) { try { $tmp = $this->ask('Type the wanted user last name', 'Saïtama'); $validator = Validator::make(['last_name' => $tmp], [ 'last_name' => 'required|min:3|max:255' ]); $validator->validate(); - $this->last_name = $tmp; + $this->lastName = $tmp; } catch (ValidationException $e) { $this->error(sprintf( 'Please provide a valid last_name %s', \implode(',', collect($e->errors())->flatten()->all()) )); continue; - } //end try - }; //end while + } + } } /** @@ -157,8 +157,8 @@ class UserCreate extends Command \implode(',', collect($e->errors())->flatten()->all()) )); continue; - } //end try - }; //end while + } + } } /** @@ -199,7 +199,7 @@ class UserCreate extends Command \implode(',', collect($e->errors())->flatten()->all()) )); continue; - } //end try - }; //end while + } + } } } diff --git a/app/Http/Controllers/Bo/ClaimController.php b/app/Http/Controllers/Bo/ClaimController.php index 516b953..8a7ea9e 100644 --- a/app/Http/Controllers/Bo/ClaimController.php +++ b/app/Http/Controllers/Bo/ClaimController.php @@ -220,7 +220,7 @@ class ClaimController extends Controller // Return conversation. $claimMessageModels = ClaimMessage::getAllModelsFromClaim($claim->getKey()); return response()->json($claimMessageModels); - } //end if + } return response()->json([], 500); }); } @@ -293,6 +293,6 @@ class ClaimController extends Controller return $pdf->download('export.pdf'); } return $this->returnExportZip($format, $claims, $pdf->output()); - }; //end if + } } } diff --git a/config/sentry.php b/config/sentry.php index 2e47564..7ecd5b4 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -51,10 +51,8 @@ return [ 'missing_routes' => false, ], - // @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii. 'send_default_pii' => env('SENTRY_SEND_DEFAULT_PII', false), - // @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#traces-sample-rate. 'traces_sample_rate' => env('SENTRY_TRACES_SAMPLE_RATE') === null ? null : (float) env('SENTRY_TRACES_SAMPLE_RATE'), 'before_send' => [\App\Lib\Helpers\ExceptionsHelper::class, 'sentryEventHandler'], diff --git a/phpcs.xml b/phpcs.xml index 9cca483..06cc447 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -113,9 +113,6 @@ - - - From b01f0fb9dd6ff696d93f721bc6880fa027de7f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 22 Oct 2026 16:40:39 +0200 Subject: [PATCH 8/8] chore: add missing phpstan --- composer.json | 1 + composer.lock | 196 +++++++++++++++++++++++++++++++++++++++++++++++++- phpstan.neon | 12 ++++ 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 phpstan.neon diff --git a/composer.json b/composer.json index 49c6598..2ef6463 100644 --- a/composer.json +++ b/composer.json @@ -48,6 +48,7 @@ "require-dev": { "brianium/paratest": "^7.2", "fakerphp/faker": "^1.9.1", + "larastan/larastan": "^3.13", "laravel-lang/common": "^4.0", "mockery/mockery": "^1.4.4", "nunomaduro/collision": "^8.1", diff --git a/composer.lock b/composer.lock index 6d0b4c5..e577121 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "5c57f125ee6389ff10d80f29bd887be6", + "content-hash": "d68ae6bf9f312e10a5634838a46574f1", "packages": [ { "name": "24slides/laravel-saml2", @@ -9453,6 +9453,136 @@ }, "time": "2026-03-17T11:56:53+00:00" }, + { + "name": "iamcal/sql-parser", + "version": "v0.7", + "source": { + "type": "git", + "url": "https://github.com/iamcal/SQLParser.git", + "reference": "610392f38de49a44dab08dc1659960a29874c4b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/iamcal/SQLParser/zipball/610392f38de49a44dab08dc1659960a29874c4b8", + "reference": "610392f38de49a44dab08dc1659960a29874c4b8", + "shasum": "" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^1.0", + "phpunit/phpunit": "^5|^6|^7|^8|^9" + }, + "type": "library", + "autoload": { + "psr-4": { + "iamcal\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Cal Henderson", + "email": "cal@iamcal.com" + } + ], + "description": "MySQL schema parser", + "support": { + "issues": "https://github.com/iamcal/SQLParser/issues", + "source": "https://github.com/iamcal/SQLParser/tree/v0.7" + }, + "time": "2026-01-28T22:20:33+00:00" + }, + { + "name": "larastan/larastan", + "version": "v3.13.0", + "source": { + "type": "git", + "url": "https://github.com/larastan/larastan.git", + "reference": "24ee69a7705ffc7c2cd8a3c96a5f498a4c2de5e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/larastan/larastan/zipball/24ee69a7705ffc7c2cd8a3c96a5f498a4c2de5e3", + "reference": "24ee69a7705ffc7c2cd8a3c96a5f498a4c2de5e3", + "shasum": "" + }, + "require": { + "iamcal/sql-parser": "^0.7.0", + "illuminate/console": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/container": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/contracts": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/database": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/http": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/pipeline": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/support": "^11.44.2 || ^12.4.1 || ^13", + "php": "^8.2", + "phpstan/phpstan": "^2.3.0" + }, + "require-dev": { + "doctrine/coding-standard": "^14", + "laravel/framework": "^11.44.2 || ^12.7.2 || ^13", + "mockery/mockery": "^1.6.12", + "nikic/php-parser": "^5.4", + "orchestra/canvas": "^v9.2.2 || ^10.0.1 || ^11", + "orchestra/testbench-core": "^9.12.0 || ^10.1 || ^11", + "phpstan/phpstan-deprecation-rules": "^2.0.1", + "phpunit/phpunit": "^10.5.35 || ^11.5.15 || ^12.5.8 || ^13.3.0" + }, + "suggest": { + "orchestra/testbench": "Using Larastan for analysing a package needs Testbench", + "phpmyadmin/sql-parser": "Install to enable Larastan's optional phpMyAdmin-based SQL parser automatically" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Larastan\\Larastan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Can Vural", + "email": "can9119@gmail.com" + } + ], + "description": "Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel", + "keywords": [ + "PHPStan", + "code analyse", + "code analysis", + "larastan", + "laravel", + "package", + "php", + "static analysis" + ], + "support": { + "issues": "https://github.com/larastan/larastan/issues", + "source": "https://github.com/larastan/larastan/tree/v3.13.0" + }, + "funding": [ + { + "url": "https://github.com/canvural", + "type": "github" + } + ], + "time": "2026-10-07T14:14:28+00:00" + }, { "name": "laravel-lang/attributes", "version": "2.16.4", @@ -10260,6 +10390,70 @@ }, "time": "2026-09-27T20:07:45+00:00" }, + { + "name": "phpstan/phpstan", + "version": "2.3.1", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6155239b488e95d26d1ebd95c6b4bb294d7f09db", + "reference": "6155239b488e95d26d1ebd95c6b4bb294d7f09db", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ondřej Mirtes" + }, + { + "name": "Markus Staab" + }, + { + "name": "Vincent Langlet" + } + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2026-10-08T21:09:11+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "12.5.8", diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..bf6f26d --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,12 @@ +includes: + - vendor/larastan/larastan/extension.neon + - vendor/nesbot/carbon/extension.neon + +parameters: + paths: + - app/ + + level: 10 + + # Enforce strict types analysis + treatPhpDocTypesAsCertain: false