diff --git a/.env.example b/.env.example index 17130c14603f..ea1f4a320728 100644 --- a/.env.example +++ b/.env.example @@ -68,4 +68,7 @@ MICROSOFT_REDIRECT_URI= APPLE_CLIENT_ID= APPLE_CLIENT_SECRET= -APPLE_REDIRECT_URI= \ No newline at end of file +APPLE_REDIRECT_URI= + +NORDIGEN_SECRET_ID= +NORDIGEN_SECRET_KEY= diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 9d7067b6bdb2..e67e83be858b 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -97,6 +97,9 @@ class Kernel extends ConsoleKernel /* Fires webhooks for overdue Invoice */ $schedule->job(new InvoiceCheckLateWebhook)->dailyAt('07:00')->withoutOverlapping()->name('invoice-overdue-job')->onOneServer(); + /* Pulls in bank transactions from third party services */ + $schedule->job(new BankTransactionSync)->everyFourHours()->withoutOverlapping()->name('bank-trans-sync-job')->onOneServer(); + if (Ninja::isSelfHost()) { $schedule->call(function () { Account::query()->whereNotNull('id')->update(['is_scheduler_running' => true]); @@ -107,9 +110,6 @@ class Kernel extends ConsoleKernel if (Ninja::isHosted()) { $schedule->job(new AdjustEmailQuota)->dailyAt('23:30')->withoutOverlapping(); - /* Pulls in bank transactions from third party services */ - $schedule->job(new BankTransactionSync)->everyFourHours()->withoutOverlapping()->name('bank-trans-sync-job')->onOneServer(); - /* Checks ACH verification status and updates state to authorize when verified */ $schedule->job(new CheckACHStatus)->everySixHours()->withoutOverlapping()->name('ach-status-job')->onOneServer(); @@ -120,7 +120,7 @@ class Kernel extends ConsoleKernel $schedule->command('ninja:s3-cleanup')->dailyAt('23:15')->withoutOverlapping()->name('s3-cleanup-job')->onOneServer(); } - if (config('queue.default') == 'database' && Ninja::isSelfHost() && config('ninja.internal_queue_enabled') && ! config('ninja.is_docker')) { + if (config('queue.default') == 'database' && Ninja::isSelfHost() && config('ninja.internal_queue_enabled') && !config('ninja.is_docker')) { $schedule->command('queue:work database --stop-when-empty --memory=256')->everyMinute()->withoutOverlapping(); $schedule->command('queue:restart')->everyFiveMinutes()->withoutOverlapping(); @@ -134,7 +134,7 @@ class Kernel extends ConsoleKernel */ protected function commands() { - $this->load(__DIR__.'/Commands'); + $this->load(__DIR__ . '/Commands'); require base_path('routes/console.php'); } diff --git a/app/Helpers/Bank/Nordigen/Nordigen.php b/app/Helpers/Bank/Nordigen/Nordigen.php new file mode 100644 index 000000000000..24bc0dc58aa9 --- /dev/null +++ b/app/Helpers/Bank/Nordigen/Nordigen.php @@ -0,0 +1,126 @@ +test_mode = config('ninja.nordigen.test_mode'); + + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) + throw new \Exception('missing nordigen credentials'); + + $this->client = new \Nordigen\NordigenPHP\API\NordigenClient(config('ninja.nordigen.secret_id'), config('ninja.nordigen.secret_key')); + + $this->client->createAccessToken(); // access_token is valid 24h -> so we dont have to implement a refresh-cycle + } + + // metadata-section for frontend + public function getInstitutions() + { + if ($this->test_mode) + return [$this->client->institution->getInstitution($this->sandbox_institutionId)]; + + return $this->client->institution->getInstitutions(); + } + + // requisition-section + public function createRequisition(string $redirect, string $initutionId, string $reference) + { + if ($this->test_mode && $initutionId != $this->sandbox_institutionId) + throw new \Exception('invalid institutionId while in test-mode'); + + return $this->client->requisition->createRequisition($redirect, $initutionId, null, $reference); + } + + public function getRequisition(string $requisitionId) + { + try { + return $this->client->requisition->getRequisition($requisitionId); + } catch (\Exception $e) { + if (strpos($e->getMessage(), "Invalid Requisition ID") !== false) + return false; + + throw $e; + } + } + + // TODO: return null on not found + public function getAccount(string $account_id) + { + try { + $out = new \stdClass(); + + $out->data = $this->client->account($account_id)->getAccountDetails()["account"]; + $out->metadata = $this->client->account($account_id)->getAccountMetaData(); + $out->balances = $this->client->account($account_id)->getAccountBalances()["balances"]; + $out->institution = $this->client->institution->getInstitution($out->metadata["institution_id"]); + + $it = new AccountTransformer(); + return $it->transform($out); + } catch (\Exception $e) { + if (strpos($e->getMessage(), "Invalid Account ID") !== false) + return false; + + throw $e; + } + } + + public function isAccountActive(string $account_id) + { + try { + $account = $this->client->account($account_id)->getAccountMetaData(); + + if ($account["status"] != "READY") { + nlog('nordigen account was not in status ready. accountId: ' . $account_id . ' status: ' . $account["status"]); + return false; + } + + return true; + } catch (\Exception $e) { + if (strpos($e->getMessage(), "Invalid Account ID") !== false) + return false; + + throw $e; + } + } + + /** + * this method returns booked transactions from the bank_account, pending transactions are not part of the result + * @todo @turbo124 should we include pending transactions within the integration-process and mark them with a specific category?! + */ + public function getTransactions(string $accountId, string $dateFrom = null) + { + $transactionResponse = $this->client->account($accountId)->getAccountTransactions($dateFrom); + + $it = new TransactionTransformer(); + return $it->transform($transactionResponse); + } +} diff --git a/app/Helpers/Bank/Nordigen/Transformer/AccountTransformer.php b/app/Helpers/Bank/Nordigen/Transformer/AccountTransformer.php new file mode 100644 index 000000000000..f0aa77379478 --- /dev/null +++ b/app/Helpers/Bank/Nordigen/Transformer/AccountTransformer.php @@ -0,0 +1,121 @@ + stdClass Object +( + [data] => stdClass Object + ( + [resourceId] => XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + [iban] => DE0286055592XXXXXXXXXX + [currency] => EUR + [ownerName] => Max Mustermann + [product] => GiroKomfort + [bic] => WELADE8LXXX + [usage] => PRIV + ) + [metadata] => stdClass Object + ( + [id] => XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + [created] => 2022-12-05T18:41:53.986028Z + [last_accessed] => 2023-10-29T08:35:34.003611Z + [iban] => DE0286055592XXXXXXXXXX + [institution_id] => STADT_KREISSPARKASSE_LEIPZIG_WELADE8LXXX + [status] => READY + [owner_name] => Max Mustermann + ) + [balances] => [ + { + [balanceAmount]: { + [amount] => 9825.64 + [currency] => EUR + }, + [balanceType] => closingBooked + [referenceDate] => 2023-12-01 + }, + { + [balanceAmount[: { + [amount] => 10325.64 + [currency] => EUR + }, + [balanceType] => interimAvailable + [creditLimitIncluded]: true, + [referenceDate] => 2023-12-01 + } + ] + [institution] => stdClass Object + ( + [id] => STADT_KREISSPARKASSE_LEIPZIG_WELADE8LXXX + [name] => Stadt- und Kreissparkasse Leipzig + [bic] => WELADE8LXXX + [transaction_total_days] => 360 + [countries] => [ + "DE" + ], + [logo] => https://storage.googleapis.com/gc-prd-institution_icons-production/DE/PNG/sparkasse.png + [supported_payments] => { + [single-payment] => [ + "SCT", + "ISCT" + ] + }, + [supported_features] => [ + "card_accounts", + "payments", + "pending_transactions" + ], + [identification_codes] => [] + ) + + ) + */ + + +class AccountTransformer implements AccountTransformerInterface +{ + + public function transform($nordigen_account) + { + + if (!property_exists($nordigen_account, 'data') || !property_exists($nordigen_account, 'metadata') || !property_exists($nordigen_account, 'balances') || !property_exists($nordigen_account, 'institution')) + throw new \Exception('invalid dataset'); + + $used_balance = $nordigen_account->balances[0]; + // prefer entry with closingBooked + foreach ($nordigen_account->balances as $entry) { + if ($entry["balanceType"] === 'closingBooked') { // available: closingBooked, interimAvailable + $used_balance = $entry; + break; + } + } + + return [ + 'id' => $nordigen_account->metadata["id"], + 'account_type' => "bank", + 'account_name' => $nordigen_account->data["iban"], + 'account_status' => $nordigen_account->metadata["status"], + 'account_number' => '**** ' . substr($nordigen_account->data["iban"], -7), + 'provider_account_id' => $nordigen_account->metadata["id"], + 'provider_id' => $nordigen_account->institution["id"], + 'provider_name' => $nordigen_account->institution["name"], + 'nickname' => $nordigen_account->data["ownerName"] ? $nordigen_account->data["ownerName"] : '', + 'current_balance' => (int) $used_balance ? $used_balance["balanceAmount"]["amount"] : 0, + 'account_currency' => $used_balance ? $used_balance["balanceAmount"]["currency"] : '', + ]; + + } +} + + diff --git a/app/Helpers/Bank/Nordigen/Transformer/TransactionTransformer.php b/app/Helpers/Bank/Nordigen/Transformer/TransactionTransformer.php new file mode 100644 index 000000000000..30e511d67aec --- /dev/null +++ b/app/Helpers/Bank/Nordigen/Transformer/TransactionTransformer.php @@ -0,0 +1,149 @@ +transformTransaction($transaction); + } + + return $data; + } + + public function transformTransaction($transaction) + { + + if (!array_key_exists('transactionId', $transaction) || !array_key_exists('transactionAmount', $transaction)) + throw new \Exception('invalid dataset'); + + // description could be in varios places + $description = ''; + if (array_key_exists('remittanceInformationStructured', $transaction)) + $description = $transaction["remittanceInformationStructured"]; + else if (array_key_exists('remittanceInformationStructuredArray', $transaction)) + $description = implode('\n', $transaction["remittanceInformationStructuredArray"]); + else if (array_key_exists('remittanceInformationUnstructured', $transaction)) + $description = $transaction["remittanceInformationUnstructured"]; + else if (array_key_exists('remittanceInformationUnstructuredArray', $transaction)) + $description = implode('\n', $transaction["remittanceInformationUnstructuredArray"]); + else + Log::warning("Missing description for the following transaction: " . json_encode($transaction)); + + // participant + $participant = array_key_exists('debtorAccount', $transaction) && array_key_exists('iban', $transaction["debtorAccount"]) ? + $transaction['debtorAccount']['iban'] : + (array_key_exists('creditorAccount', $transaction) && array_key_exists('iban', $transaction["creditorAccount"]) ? + $transaction['creditorAccount']['iban'] : null); + $participant_name = array_key_exists('debtorName', $transaction) ? + $transaction['debtorName'] : + (array_key_exists('creditorName', $transaction) ? + $transaction['creditorName'] : null); + + return [ + 'transaction_id' => $transaction["transactionId"], + 'amount' => abs((int) $transaction["transactionAmount"]["amount"]), + 'currency_id' => $this->convertCurrency($transaction["transactionAmount"]["currency"]), + 'category_id' => null, // nordigen has no categories + 'category_type' => array_key_exists('additionalInformation', $transaction) ? $transaction["additionalInformation"] : null, // TODO: institution specific keys like: GUTSCHRIFT, ABSCHLUSS, MONATSABSCHLUSS etc + 'date' => $transaction["bookingDate"], + 'description' => $description, + 'participant' => $participant, + 'participant_name' => $participant_name, + 'base_type' => (int) $transaction["transactionAmount"]["amount"] <= 0 ? 'DEBIT' : 'CREDIT', + ]; + + } + + private function convertCurrency(string $code) + { + + $currencies = Cache::get('currencies'); + + if (!$currencies) { + $this->buildCache(true); + } + + $currency = $currencies->filter(function ($item) use ($code) { + return $item->code == $code; + })->first(); + + if ($currency) + return $currency->id; + + return 1; + + } + +} + + diff --git a/app/Http/Controllers/Bank/NordigenController.php b/app/Http/Controllers/Bank/NordigenController.php new file mode 100644 index 000000000000..803947c9388c --- /dev/null +++ b/app/Http/Controllers/Bank/NordigenController.php @@ -0,0 +1,304 @@ +all(); + $context = $request->getTokenContent(); + $lang = $data['lang'] ?? 'en'; + $context["lang"] = $lang; + + if (!$context) + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'failed_reason' => "token-invalid", + "redirectUrl" => config("ninja.app_url") . "?action=nordigen_connect&status=failed&reason=token-invalid", + ]); + + $context["redirect"] = $data["redirect"]; + if ($context["context"] != "nordigen" || array_key_exists("requisitionId", $context)) + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'failed_reason' => "token-invalid", + "redirectUrl" => ($context["redirect"]) . "?action=nordigen_connect&status=failed&reason=token-invalid", + ]); + + $company = $request->getCompany(); + $account = $company->account; + + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'failed_reason' => "account-config-invalid", + "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=account-config-invalid", + ]); + + if (!(Ninja::isSelfHost() || (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise'))) + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'failed_reason' => "not-available", + "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=not-available", + ]); + + $nordigen = new Nordigen(); + + // show bank_selection_screen, when institution_id is not present + if (!array_key_exists("institution_id", $data)) + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'institutions' => $nordigen->getInstitutions(), + 'redirectUrl' => $context["redirect"] . "?action=nordigen_connect&status=user-aborted" + ]); + + // redirect to requisition flow + try { + $requisition = $nordigen->createRequisition(config('ninja.app_url') . '/nordigen/confirm', $data['institution_id'], $request->token); + } catch (NordigenException $e) { // TODO: property_exists returns null in these cases... => why => therefore we just get unknown error everytime $responseBody is typeof GuzzleHttp\Psr7\Stream + $responseBody = (string) $e->getResponse()->getBody(); + + if (str_contains($responseBody, '"institution_id"')) // provided institution_id was wrong + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'failed_reason' => "institution-invalid", + "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=institution-invalid", + ]); + else if (str_contains($responseBody, '"reference"')) // this error can occur, when a reference was used double or is invalid => therefor we suggest the frontend to use another token + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'failed_reason' => "token-invalid", + "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=token-invalid", + ]); + else { + nlog("Unknown Error from nordigen: " . $e); + nlog($responseBody); + + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'failed_reason' => "unknown", + "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=unknown", + ]); + } + } + + // save cache + $context["requisitionId"] = $requisition["id"]; + Cache::put($request->token, $context, 3600); + + return response()->redirectTo($requisition["link"]); + } + + /** + * VIEW: Confirm Nordigen Bank Integration (redirect after nordigen flow) + * @param ConnectNordigenBankIntegrationRequest $request + */ + public function confirm(ConfirmNordigenBankIntegrationRequest $request) + { + $data = $request->all(); + $context = $request->getTokenContent(); + if (!array_key_exists('lang', $data) && $context['lang'] != 'en') + return redirect()->route('nordigen.confirm', array_merge(["lang" => $context['lang']], $request->query())); // redirect is required in order for the bank-ui to display everything properly + $lang = $data['lang'] ?? 'en'; + + if (!$context || $context["context"] != "nordigen" || !array_key_exists("requisitionId", $context)) + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'failed_reason' => "ref-invalid", + "redirectUrl" => ($context && array_key_exists("redirect", $context) ? $context["redirect"] : config('ninja.app_url')) . "?action=nordigen_connect&status=failed&reason=ref-invalid", + ]); + + $company = $request->getCompany(); + $account = $company->account; + + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'failed_reason' => "account-config-invalid", + "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=account-config-invalid", + ]); + + if (!(Ninja::isSelfHost() || (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise'))) + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'failed_reason' => "not-available", + "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=not-available", + ]); + + // fetch requisition + $nordigen = new Nordigen(); + $requisition = $nordigen->getRequisition($context["requisitionId"]); + + // check validity of requisition + if (!$requisition) + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'failed_reason' => "requisition-not-found", + "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=requisition-not-found", + ]); + if ($requisition["status"] != "LN") + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'failed_reason' => "requisition-invalid-status", + "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=requisition-invalid-status&status=" . $requisition["status"], + ]); + if (sizeof($requisition["accounts"]) == 0) + return view('bank.nordigen.handler', [ + 'lang' => $lang, + 'company' => $company, + 'account' => $company->account, + 'failed_reason' => "requisition-no-accounts", + "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=requisition-no-accounts", + ]); + + // connect new accounts + $bank_integration_ids = []; + foreach ($requisition["accounts"] as $nordigenAccountId) { + + $nordigen_account = $nordigen->getAccount($nordigenAccountId); + + $existing_bank_integration = BankIntegration::withTrashed()->where('nordigen_account_id', $nordigen_account['id'])->where('company_id', $company->id)->first(); + + if (!$existing_bank_integration) { + + $bank_integration = new BankIntegration(); + $bank_integration->integration_type = BankIntegration::INTEGRATION_TYPE_NORDIGEN; + $bank_integration->company_id = $company->id; + $bank_integration->account_id = $company->account_id; + $bank_integration->user_id = $company->owner()->id; + $bank_integration->nordigen_account_id = $nordigen_account['id']; + $bank_integration->bank_account_type = $nordigen_account['account_type']; + $bank_integration->bank_account_name = $nordigen_account['account_name']; + $bank_integration->bank_account_status = $nordigen_account['account_status']; + $bank_integration->bank_account_number = $nordigen_account['account_number']; + $bank_integration->nordigen_institution_id = $nordigen_account['provider_id']; + $bank_integration->provider_name = $nordigen_account['provider_name']; + $bank_integration->nickname = $nordigen_account['nickname']; + $bank_integration->balance = $nordigen_account['current_balance']; + $bank_integration->currency = $nordigen_account['account_currency']; + $bank_integration->disabled_upstream = false; + $bank_integration->auto_sync = true; + $bank_integration->from_date = now()->subDays(90); // default max-fetch interval of nordigen is 90 days + + $bank_integration->save(); + + array_push($bank_integration_ids, $bank_integration->id); + + } else { + + // resetting metadata for account status + $existing_bank_integration->balance = $account['current_balance']; + $existing_bank_integration->bank_account_status = $account['account_status']; + $existing_bank_integration->disabled_upstream = false; + $existing_bank_integration->auto_sync = true; + $existing_bank_integration->from_date = now()->subDays(90); // default max-fetch interval of nordigen is 90 days + $existing_bank_integration->deleted_at = null; + + $existing_bank_integration->save(); + + array_push($bank_integration_ids, $existing_bank_integration->id); + } + + } + + // perform update in background + $company->account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->each(function ($bank_integration) { + ProcessBankTransactionsNordigen::dispatch($bank_integration); + }); + + // prevent rerun of this method with same ref + Cache::delete($data["ref"]); + + // Successfull Response => Redirect + return response()->redirectTo($context["redirect"] . "?action=nordigen_connect&status=success&bank_integrations=" . implode(',', $bank_integration_ids)); + } + + /** + * Process Nordigen Institutions GETTER. + * + * + * @OA\Post( + * path="/api/v1/nordigen/institutions", + * operationId="nordigenRefreshWebhook", + * tags={"nordigen"}, + * summary="Getting available institutions from nordigen", + * description="Used to determine the available institutions for sending and creating a new connect-link", + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Response( + * response=200, + * description="", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/Credit"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + public function institutions(Request $request) + { + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) + return response()->json(['message' => 'Not yet authenticated with Nordigen Bank Integration service'], 400); + + $nordigen = new Nordigen(); + return response()->json($nordigen->getInstitutions()); + } + +} diff --git a/app/Http/Controllers/Bank/YodleeController.php b/app/Http/Controllers/Bank/YodleeController.php index 6b353f8e3841..e6a154060d51 100644 --- a/app/Http/Controllers/Bank/YodleeController.php +++ b/app/Http/Controllers/Bank/YodleeController.php @@ -16,7 +16,7 @@ use App\Helpers\Bank\Yodlee\Yodlee; use App\Http\Controllers\BaseController; use App\Http\Requests\Yodlee\YodleeAdminRequest; use App\Http\Requests\Yodlee\YodleeAuthRequest; -use App\Jobs\Bank\ProcessBankTransactions; +use App\Jobs\Bank\ProcessBankTransactionsYodlee; use App\Models\BankIntegration; use Illuminate\Http\Request; @@ -44,7 +44,7 @@ class YodleeController extends BaseController $company->push(); } - + $yodlee = new Yodlee($token); if ($request->has('window_closed') && $request->input("window_closed") == "true") { @@ -90,6 +90,7 @@ class YodleeController extends BaseController $bank_integration->balance = $account['current_balance']; $bank_integration->currency = $account['account_currency']; $bank_integration->from_date = now()->subYear(); + $bank_integration->auto_sync = true; $bank_integration->save(); @@ -97,47 +98,45 @@ class YodleeController extends BaseController } - $company->account->bank_integrations->each(function ($bank_integration) use ($company) { - ProcessBankTransactions::dispatch($company->account->bank_integration_account_id, $bank_integration); + $company->account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->each(function ($bank_integration) use ($company) { // TODO: filter to yodlee only + ProcessBankTransactionsYodlee::dispatch($company->account->id, $bank_integration); }); } - /** - * Process Yodlee Refresh Webhook. - * - * - * @OA\Post( - * path="/api/v1/yodlee/refresh", - * operationId="yodleeRefreshWebhook", - * tags={"yodlee"}, - * summary="Processing webhooks from Yodlee", - * description="Notifies the system when a data point can be refreshed", - * @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"), - * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), - * @OA\Parameter(ref="#/components/parameters/include"), - * @OA\Response( - * response=200, - * description="", - * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), - * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), - * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), - * @OA\JsonContent(ref="#/components/schemas/Credit"), - * ), - * @OA\Response( - * response=422, - * description="Validation error", - * @OA\JsonContent(ref="#/components/schemas/ValidationError"), - * - * ), - * @OA\Response( - * response="default", - * description="Unexpected Error", - * @OA\JsonContent(ref="#/components/schemas/Error"), - * ), - * ) - */ - + * Process Yodlee Refresh Webhook. + * + * + * @OA\Post( + * path="/api/v1/yodlee/refresh", + * operationId="yodleeRefreshWebhook", + * tags={"yodlee"}, + * summary="Processing webhooks from Yodlee", + * description="Notifies the system when a data point can be refreshed", + * @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Response( + * response=200, + * description="", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/Credit"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ /* { "event":{ @@ -174,12 +173,12 @@ class YodleeController extends BaseController // nlog($request->all()); return response()->json(['message' => 'Success'], 200); - + // // return response()->json(['message' => 'Unauthorized'], 403); } - + /* { "event":{ @@ -208,12 +207,12 @@ class YodleeController extends BaseController nlog($request->all()); return response()->json(['message' => 'Success'], 200); - + // // return response()->json(['message' => 'Unauthorized'], 403); } - + /* { "event":{ @@ -244,7 +243,7 @@ class YodleeController extends BaseController // nlog($request->all()); return response()->json(['message' => 'Success'], 200); - + // // return response()->json(['message' => 'Unauthorized'], 403); @@ -278,7 +277,7 @@ class YodleeController extends BaseController return response()->json(['message' => 'Success'], 200); - + // // return response()->json(['message' => 'Unauthorized'], 403); @@ -290,19 +289,19 @@ class YodleeController extends BaseController $user = auth()->user(); $bank_integration = BankIntegration::query() - ->withTrashed() - ->where('company_id', $user->company()->id) - ->where('account_id', $account_number) - ->exists(); + ->withTrashed() + ->where('company_id', $user->company()->id) + ->where('account_id', $account_number) + ->exists(); - if(!$bank_integration) { + if (!$bank_integration) { return response()->json(['message' => 'Account does not exist.'], 400); } $yodlee = new Yodlee($user->account->bank_integration_account_id); $summary = $yodlee->getAccountSummary($account_number); - + $transformed_summary = AccountSummary::from($summary[0]); return response()->json($transformed_summary, 200); diff --git a/app/Http/Controllers/BankIntegrationController.php b/app/Http/Controllers/BankIntegrationController.php index b2d3a33a9ae8..bf61c52bc7a4 100644 --- a/app/Http/Controllers/BankIntegrationController.php +++ b/app/Http/Controllers/BankIntegrationController.php @@ -14,6 +14,7 @@ namespace App\Http\Controllers; use App\Factory\BankIntegrationFactory; use App\Filters\BankIntegrationFilters; use App\Helpers\Bank\Yodlee\Yodlee; +use App\Helpers\Bank\Nordigen\Nordigen; use App\Http\Requests\BankIntegration\AdminBankIntegrationRequest; use App\Http\Requests\BankIntegration\BulkBankIntegrationRequest; use App\Http\Requests\BankIntegration\CreateBankIntegrationRequest; @@ -22,10 +23,14 @@ use App\Http\Requests\BankIntegration\EditBankIntegrationRequest; use App\Http\Requests\BankIntegration\ShowBankIntegrationRequest; use App\Http\Requests\BankIntegration\StoreBankIntegrationRequest; use App\Http\Requests\BankIntegration\UpdateBankIntegrationRequest; -use App\Jobs\Bank\ProcessBankTransactions; +use App\Jobs\Bank\ProcessBankTransactionsYodlee; +use App\Jobs\Bank\ProcessBankTransactionsNordigen; +use App\Models\Account; use App\Models\BankIntegration; +use App\Models\User; use App\Repositories\BankIntegrationRepository; use App\Transformers\BankIntegrationTransformer; +use App\Utils\Ninja; use App\Utils\Traits\MakesHash; use Illuminate\Http\JsonResponse; use Illuminate\Http\Response; @@ -168,13 +173,13 @@ class BankIntegrationController extends BaseController $action = request()->input('action'); $ids = request()->input('ids'); - + BankIntegration::withTrashed()->whereIn('id', $this->transformKeys($ids)) - ->company() - ->cursor() - ->each(function ($bank_integration, $key) use ($action) { - $this->bank_integration_repo->{$action}($bank_integration); - }); + ->company() + ->cursor() + ->each(function ($bank_integration, $key) use ($action) { + $this->bank_integration_repo->{$action}($bank_integration); + }); /* Need to understand which permission are required for the given bulk action ie. view / edit */ @@ -189,27 +194,45 @@ class BankIntegrationController extends BaseController */ public function refreshAccounts(AdminBankIntegrationRequest $request) { - // As yodlee is the first integration we don't need to perform switches yet, however - // if we add additional providers we can reuse this class - - /** @var \App\Models\User $user */ $user = auth()->user(); $user_account = $user->account; - $bank_account_id = $user_account->bank_integration_account_id; + $this->refreshAccountsYodlee($user); - if (!$bank_account_id) { - return response()->json(['message' => 'Not yet authenticated with Bank Integration service'], 400); - } + $this->refreshAccountsNordigen($user); - $yodlee = new Yodlee($bank_account_id); + if (Cache::get("throttle_polling:{$user_account->key}")) + return response()->json(BankIntegration::query()->company(), 200); + + // Processing transactions for each bank account + if (Ninja::isHosted() && $user->account->bank_integration_account_id) + $user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_YODLEE)->each(function ($bank_integration) use ($user_account) { + ProcessBankTransactionsYodlee::dispatch($user_account->id, $bank_integration); + }); + + if (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key') && (Ninja::isSelfHost() || (Ninja::isHosted() && $user_account->isPaid() && $user_account->plan == 'enterprise'))) + $user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->each(function ($bank_integration) { + ProcessBankTransactionsNordigen::dispatch($bank_integration); + }); + + Cache::put("throttle_polling:{$user_account->key}", true, 300); + + return response()->json(BankIntegration::query()->company(), 200); + } + + private function refreshAccountsYodlee(User $user) + { + if (!Ninja::isHosted() || !$user->account->bank_integration_account_id) + return; + + $yodlee = new Yodlee($user->account->bank_integration_account_id); $accounts = $yodlee->getAccounts(); foreach ($accounts as $account) { - if ($bi = BankIntegration::withTrashed()->where('bank_account_id', $account['id'])->where('company_id', $user->company()->id)->first()) { + if ($bi = BankIntegration::withTrashed()->where("integration_type", BankIntegration::INTEGRATION_TYPE_YODLEE)->where('bank_account_id', $account['id'])->where('company_id', $user->company()->id)->first()) { $bi->balance = $account['current_balance']; $bi->currency = $account['account_currency']; $bi->save(); @@ -229,22 +252,35 @@ class BankIntegrationController extends BaseController $bank_integration->balance = $account['current_balance']; $bank_integration->currency = $account['account_currency']; $bank_integration->auto_sync = true; - + $bank_integration->save(); } } - - if (Cache::get("throttle_polling:{$user_account->key}")) { - return response()->json(BankIntegration::query()->company(), 200); - } + } - $user_account->bank_integrations->each(function ($bank_integration) use ($user_account) { - ProcessBankTransactions::dispatch($user_account->bank_integration_account_id, $bank_integration); + private function refreshAccountsNordigen(User $user) + { + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) + return; + + $nordigen = new Nordigen(); + + BankIntegration::where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->whereNotNull('nordigen_account_id')->each(function (BankIntegration $bank_integration) use ($nordigen) { + $account = $nordigen->getAccount($bank_integration->nordigen_account_id); + if (!$account) { + $bank_integration->disabled_upstream = true; + + $bank_integration->save(); + return; + } + + $bank_integration->disabled_upstream = false; + $bank_integration->bank_account_status = $account['account_status']; + $bank_integration->balance = $account['current_balance']; + $bank_integration->currency = $account['account_currency']; + + $bank_integration->save(); }); - - Cache::put("throttle_polling:{$user_account->key}", true, 300); - - return response()->json(BankIntegration::query()->company(), 200); } /** @@ -262,23 +298,27 @@ class BankIntegrationController extends BaseController $account = $user->account; - $bank_account_id = $account->bank_integration_account_id; + $bank_integration = BankIntegration::withTrashed()->where('bank_account_id', $acc_id)->orWhere('nordigen_account_id', $acc_id)->company()->firstOrFail(); // @turbo124 please check - if (!$bank_account_id) { + if ($bank_integration->integration_type == BankIntegration::INTEGRATION_TYPE_YODLEE) + $this->removeAccountYodlee($account, $bank_integration); + // we dont remove Accounts from nordigen, because they could be used within other companies + + $this->bank_integration_repo->delete($bank_integration); + + return $this->itemResponse($bank_integration->fresh()); + } + + private function removeAccountYodlee(Account $account, BankIntegration $bank_integration) + { + if (!$account->bank_integration_account_id) { return response()->json(['message' => 'Not yet authenticated with Bank Integration service'], 400); } - $bi = BankIntegration::withTrashed()->where('bank_account_id', $acc_id)->company()->firstOrFail(); - - $yodlee = new Yodlee($bank_account_id); - $res = $yodlee->deleteAccount($acc_id); - - $this->bank_integration_repo->delete($bi); - - return $this->itemResponse($bi->fresh()); + $yodlee = new Yodlee($account->bank_integration_account_id); + $yodlee->deleteAccount($bank_integration->bank_account_id); } - /** * Return the remote list of accounts stored on the third party provider * and update our local cache. @@ -288,12 +328,20 @@ class BankIntegrationController extends BaseController */ public function getTransactions(AdminBankIntegrationRequest $request) { - /** @var \App\Models\User $user */ - $user = auth()->user(); + /** @var \App\Models\Account $account */ + $account = auth()->user()->account; - $user->account->bank_integrations->each(function ($bank_integration) use ($user) { - (new ProcessBankTransactions($user->account->bank_integration_account_id, $bank_integration))->handle(); - }); + if (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise') { + $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->cursor()->each(function ($bank_integration) use ($account) { + (new ProcessBankTransactionsYodlee($account->id, $bank_integration))->handle(); + }); + } + + if (config("ninja.nordigen.secret_id") && config("ninja.nordigen.secret_key") && (Ninja::isSelfHost() || (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise'))) { + $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->cursor()->each(function ($bank_integration) { + (new ProcessBankTransactionsNordigen($bank_integration))->handle(); + }); + } return response()->json(['message' => 'Fetching transactions....'], 200); } diff --git a/app/Http/Requests/Nordigen/ConfirmNordigenBankIntegrationRequest.php b/app/Http/Requests/Nordigen/ConfirmNordigenBankIntegrationRequest.php new file mode 100644 index 000000000000..c5c02b9eb441 --- /dev/null +++ b/app/Http/Requests/Nordigen/ConfirmNordigenBankIntegrationRequest.php @@ -0,0 +1,58 @@ + 'required|string', // nordigen redirects only with the ref-property + 'lang' => 'string', + ]; + } + public function getTokenContent() + { + $input = $this->all(); + + $data = Cache::get($input['ref']); + + return $data; + } + + public function getCompany() + { + MultiDB::findAndSetDbByCompanyKey($this->getTokenContent()['company_key']); + + return Company::where('company_key', $this->getTokenContent()['company_key'])->firstOrFail(); + } +} diff --git a/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php b/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php new file mode 100644 index 000000000000..1ba76062c593 --- /dev/null +++ b/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php @@ -0,0 +1,75 @@ + 'string', + 'institution_id' => 'string', + 'redirect' => 'string', + ]; + } + + // @turbo124 @todo please check for validity, when request from frontend + public function prepareForValidation() + { + $input = $this->all(); + + if (!array_key_exists('redirect', $input)) { + $context = $this->getTokenContent(); + + $input["redirect"] = isset($context["is_react"]) && $context['is_react'] ? config('ninja.react_url') . "/#/settings/bank_accounts" : config('ninja.app_url'); + + $this->replace($input); + } + } + public function getTokenContent() + { + if ($this->state) { + $this->token = $this->state; + } + + $data = Cache::get($this->token); + + return $data; + } + + public function getCompany() + { + MultiDB::findAndSetDbByCompanyKey($this->getTokenContent()['company_key']); + + return Company::where('company_key', $this->getTokenContent()['company_key'])->firstOrFail(); + } +} diff --git a/app/Jobs/Bank/MatchBankTransactions.php b/app/Jobs/Bank/MatchBankTransactions.php index b0453fb4c7c8..3403f1057e81 100644 --- a/app/Jobs/Bank/MatchBankTransactions.php +++ b/app/Jobs/Bank/MatchBankTransactions.php @@ -58,7 +58,7 @@ class MatchBankTransactions implements ShouldQueue private $categories; private float $available_balance = 0; - + private float $applied_amount = 0; private array $attachable_invoices = []; @@ -94,7 +94,6 @@ class MatchBankTransactions implements ShouldQueue } $bank_categories = Cache::get('bank_categories'); - if (!$bank_categories && $yodlee) { $_categories = $yodlee->getTransactionCategories(); $this->categories = collect($_categories->transactionCategory); @@ -135,11 +134,11 @@ class MatchBankTransactions implements ShouldQueue return $collection->toArray(); } - private function checkPayable($invoices) :bool + private function checkPayable($invoices): bool { foreach ($invoices as $invoice) { $invoice->service()->markSent(); - + if (!$invoice->isPayable()) { return false; } @@ -158,12 +157,12 @@ class MatchBankTransactions implements ShouldQueue $_expenses = explode(",", $input['expense_id']); - foreach($_expenses as $_expense) { - + foreach ($_expenses as $_expense) { + $expense = Expense::withTrashed() - ->where('id', $this->decodePrimaryKey($_expense)) - ->where('company_id', $this->bt->company_id) - ->first(); + ->where('id', $this->decodePrimaryKey($_expense)) + ->where('company_id', $this->bt->company_id) + ->first(); if ($expense && !$expense->transaction_id) { $expense->transaction_id = $this->bt->id; @@ -178,7 +177,7 @@ class MatchBankTransactions implements ShouldQueue $this->bts->push($this->bt->id); } } - + return $this; } @@ -202,7 +201,7 @@ class MatchBankTransactions implements ShouldQueue } $payment = Payment::withTrashed()->find($input['payment_id']); - + if ($payment && !$payment->transaction_id) { $payment->transaction_id = $this->bt->id; $payment->saveQuietly(); @@ -218,7 +217,7 @@ class MatchBankTransactions implements ShouldQueue return $this; } - private function matchInvoicePayment($input) :self + private function matchInvoicePayment($input): self { $this->bt = BankTransaction::withTrashed()->find($input['id']); @@ -227,10 +226,10 @@ class MatchBankTransactions implements ShouldQueue } $_invoices = Invoice::query() - ->withTrashed() - ->where('company_id', $this->bt->company_id) - ->whereIn('id', $this->getInvoices($input['invoice_ids'])); - + ->withTrashed() + ->where('company_id', $this->bt->company_id) + ->whereIn('id', $this->getInvoices($input['invoice_ids'])); + $amount = $this->bt->amount; if ($_invoices && $this->checkPayable($_invoices)) { @@ -242,7 +241,7 @@ class MatchBankTransactions implements ShouldQueue return $this; } - private function matchExpense($input) :self + private function matchExpense($input): self { //if there is a category id, pull it from Yodlee and insert - or just reuse!! $this->bt = BankTransaction::query()->withTrashed()->find($input['id']); @@ -274,7 +273,7 @@ class MatchBankTransactions implements ShouldQueue if (array_key_exists('vendor_id', $input)) { $this->bt->vendor_id = $input['vendor_id']; } - + $this->bt->status_id = BankTransaction::STATUS_CONVERTED; $this->bt->save(); @@ -283,7 +282,7 @@ class MatchBankTransactions implements ShouldQueue return $this; } - private function createPayment($invoices, float $amount) :void + private function createPayment($invoices, float $amount): void { $this->available_balance = $amount; @@ -320,7 +319,7 @@ class MatchBankTransactions implements ShouldQueue if (!$this->invoice) { return; } - + /* Create Payment */ $payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id); @@ -333,7 +332,7 @@ class MatchBankTransactions implements ShouldQueue $payment->currency_id = $this->bt->currency_id; $payment->is_manual = false; $payment->date = $this->bt->date ? Carbon::parse($this->bt->date) : now(); - + /* Bank Transfer! */ $payment_type_id = 1; @@ -341,7 +340,7 @@ class MatchBankTransactions implements ShouldQueue $payment->saveQuietly(); $payment->service()->applyNumber()->save(); - + if ($payment->client->getSetting('send_email_on_mark_paid')) { $payment->service()->sendEmail(); } @@ -360,24 +359,24 @@ class MatchBankTransactions implements ShouldQueue $this->invoice->next_send_date = null; $this->invoice - ->service() - ->applyNumber() - ->deletePdf() - ->save(); + ->service() + ->applyNumber() + ->deletePdf() + ->save(); $payment->ledger() - ->updatePaymentBalance($amount * -1); + ->updatePaymentBalance($amount * -1); $this->invoice - ->client - ->service() - ->updateBalanceAndPaidToDate($this->applied_amount*-1, $amount) - ->save(); + ->client + ->service() + ->updateBalanceAndPaidToDate($this->applied_amount * -1, $amount) + ->save(); $this->invoice = $this->invoice - ->service() - ->workFlow() - ->save(); + ->service() + ->workFlow() + ->save(); /* Update Invoice balance */ event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); @@ -389,13 +388,13 @@ class MatchBankTransactions implements ShouldQueue $this->bt->save(); } - private function resolveCategory($input) :?int + private function resolveCategory($input): ?int { - if (array_key_exists('ninja_category_id', $input) && (int)$input['ninja_category_id'] > 1) { + if (array_key_exists('ninja_category_id', $input) && (int) $input['ninja_category_id'] > 1) { $this->bt->ninja_category_id = $input['ninja_category_id']; $this->bt->save(); - return (int)$input['ninja_category_id']; + return (int) $input['ninja_category_id']; } $category = $this->categories->firstWhere('highLevelCategoryId', $this->bt->category_id); @@ -414,7 +413,7 @@ class MatchBankTransactions implements ShouldQueue return $ec->id; } - + return null; } diff --git a/app/Jobs/Bank/ProcessBankTransactionsNordigen.php b/app/Jobs/Bank/ProcessBankTransactionsNordigen.php new file mode 100644 index 000000000000..da9ac7f98571 --- /dev/null +++ b/app/Jobs/Bank/ProcessBankTransactionsNordigen.php @@ -0,0 +1,177 @@ +bank_integration = $bank_integration; + $this->from_date = $bank_integration->from_date ?: now()->subDays(90); + $this->company = $this->bank_integration->company; + } + + /** + * Execute the job. + * + * + * @return void + */ + public function handle() + { + if ($this->bank_integration->integration_type != BankIntegration::INTEGRATION_TYPE_NORDIGEN) + throw new \Exception("Invalid BankIntegration Type"); + + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) + throw new \Exception("Missing credentials for bank_integration service nordigen"); + + $this->nordigen = new Nordigen(); + + set_time_limit(0); + + nlog("Nordigen: Processing transactions for account: {$this->bank_integration->account->key}"); + + // UPDATE ACCOUNT + try { + $this->updateAccount(); + } catch (\Exception $e) { + nlog("Nordigen: {$this->bank_integration->nordigen_account_id} - exited abnormally => " . $e->getMessage()); + + $content = [ + "Processing transactions for account: {$this->bank_integration->nordigen_account_id} failed", + "Exception Details => ", + $e->getMessage(), + ]; + + $this->bank_integration->company->notification(new GenericNinjaAdminNotification($content))->ninja(); + + throw $e; + } + if (!$this->nordigen_account) + return; + + // UPDATE TRANSACTIONS + try { + $this->processTransactions(); + } catch (\Exception $e) { + nlog("Nordigen: {$this->bank_integration->nordigen_account_id} - exited abnormally => " . $e->getMessage()); + + $content = [ + "Processing transactions for account: {$this->bank_integration->nordigen_account_id} failed", + "Exception Details => ", + $e->getMessage(), + ]; + + $this->bank_integration->company->notification(new GenericNinjaAdminNotification($content))->ninja(); + + throw $e; + } + + // Perform Matching + BankMatchingService::dispatch($this->company->id, $this->company->db); + } + + private function updateAccount() + { + if (!$this->nordigen->isAccountActive($this->bank_integration->nordigen_account_id)) { + $this->bank_integration->disabled_upstream = true; + $this->bank_integration->save(); + $this->stop_loop = false; + nlog("Nordigen: account inactive: " . $this->bank_integration->nordigen_account_id); + // @turbo124 @todo send email for expired account + return; + } + + $this->nordigen_account = $this->nordigen->getAccount($this->bank_integration->nordigen_account_id); + + $this->bank_integration->disabled_upstream = false; + $this->bank_integration->bank_account_status = $this->nordigen_account['account_status']; + $this->bank_integration->balance = $this->nordigen_account['current_balance']; + + $this->bank_integration->save(); + } + + private function processTransactions() + { + //Get transaction count object + $transactions = $this->nordigen->getTransactions($this->bank_integration->nordigen_account_id, $this->from_date); + + //if no transactions, update the from_date and move on + if (count($transactions) == 0) { + + $this->bank_integration->from_date = now()->subDays(5); + $this->bank_integration->disabled_upstream = false; + $this->bank_integration->save(); + + return; + } + + //Harvest the company + + MultiDB::setDb($this->company->db); + + /*Get the user */ + $user_id = $this->company->owner()->id; + + /* Unguard the model to perform batch inserts */ + BankTransaction::unguard(); + + $now = now(); + + foreach ($transactions as $transaction) { + + if (BankTransaction::where('transaction_id', $transaction['transaction_id'])->where('company_id', $this->company->id)->where('bank_integration_id', $this->bank_integration->id)->withTrashed()->exists()) + continue; + + //this should be much faster to insert than using ::create() + \DB::table('bank_transactions')->insert( + array_merge($transaction, [ + 'company_id' => $this->company->id, + 'user_id' => $user_id, + 'bank_integration_id' => $this->bank_integration->id, + 'created_at' => $now, + 'updated_at' => $now, + ]) + ); + + } + + $this->bank_integration->from_date = now()->subDays(5); + $this->bank_integration->save(); + } +} diff --git a/app/Jobs/Bank/ProcessBankTransactions.php b/app/Jobs/Bank/ProcessBankTransactionsYodlee.php similarity index 84% rename from app/Jobs/Bank/ProcessBankTransactions.php rename to app/Jobs/Bank/ProcessBankTransactionsYodlee.php index 2d621799dea9..efa9f1cadaf9 100644 --- a/app/Jobs/Bank/ProcessBankTransactions.php +++ b/app/Jobs/Bank/ProcessBankTransactionsYodlee.php @@ -14,6 +14,7 @@ namespace App\Jobs\Bank; use App\Helpers\Bank\Yodlee\Transformer\AccountTransformer; use App\Helpers\Bank\Yodlee\Yodlee; use App\Libraries\MultiDB; +use App\Models\Account; use App\Models\BankIntegration; use App\Models\BankTransaction; use App\Models\Company; @@ -26,7 +27,7 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\SerializesModels; -class ProcessBankTransactions implements ShouldQueue +class ProcessBankTransactionsYodlee implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; @@ -61,21 +62,24 @@ class ProcessBankTransactions implements ShouldQueue */ public function handle() { + if ($this->bank_integration->integration_type != BankIntegration::INTEGRATION_TYPE_YODLEE) + throw new \Exception("Invalid BankIntegration Type"); + set_time_limit(0); //Loop through everything until we are up to date $this->from_date = $this->from_date ?: '2021-01-01'; - nlog("Processing transactions for account: {$this->bank_integration->account->key}"); + nlog("Yodlee: Processing transactions for account: {$this->bank_integration->account->key}"); do { try { $this->processTransactions(); - } catch(\Exception $e) { - nlog("{$this->bank_integration_account_id} - exited abnormally => ". $e->getMessage()); + } catch (\Exception $e) { + nlog("Yodlee: {$this->bank_integration->bank_account_id} - exited abnormally => " . $e->getMessage()); $content = [ - "Processing transactions for account: {$this->bank_integration->account->key} failed", + "Processing transactions for account: {$this->bank_integration->bank_account_id} failed", "Exception Details => ", $e->getMessage(), ]; @@ -103,21 +107,21 @@ class ProcessBankTransactions implements ShouldQueue try { $account_summary = $yodlee->getAccountSummary($this->bank_integration->bank_account_id); - if($account_summary) { + if ($account_summary) { $at = new AccountTransformer(); $account = $at->transform($account_summary); - if($account[0]['current_balance']) { + if ($account[0]['current_balance']) { $this->bank_integration->balance = $account[0]['current_balance']; $this->bank_integration->currency = $account[0]['account_currency']; $this->bank_integration->bank_account_status = $account[0]['account_status']; $this->bank_integration->save(); } - + } - } catch(\Exception $e) { - nlog("YODLEE: unable to update account summary for {$this->bank_integration->bank_account_id} => ". $e->getMessage()); + } catch (\Exception $e) { + nlog("YODLEE: unable to update account summary for {$this->bank_integration->bank_account_id} => " . $e->getMessage()); } $data = [ @@ -151,14 +155,14 @@ class ProcessBankTransactions implements ShouldQueue /*Get the user */ $user_id = $this->company->owner()->id; - + /* Unguard the model to perform batch inserts */ BankTransaction::unguard(); $now = now(); - + foreach ($transactions as $transaction) { - if (BankTransaction::query()->where('transaction_id', $transaction['transaction_id'])->where('company_id', $this->company->id)->withTrashed()->exists()) { + if (BankTransaction::query()->where('transaction_id', $transaction['transaction_id'])->where('company_id', $this->company->id)->where('bank_integration_id', $this->bank_integration->id)->withTrashed()->exists()) { // @turbo124 was not scoped to bank_integration_id => from my pov this should be present, because when an account was historized (is_deleted) a transaction can occur multiple (in the archived bank_integration and in the new one continue; } @@ -189,7 +193,7 @@ class ProcessBankTransactions implements ShouldQueue { return [new WithoutOverlapping($this->bank_integration_account_id)]; } - + public function backoff() { return [rand(10, 15), rand(30, 40), rand(60, 79), rand(160, 200), rand(3000, 5000)]; diff --git a/app/Jobs/Ninja/BankTransactionSync.php b/app/Jobs/Ninja/BankTransactionSync.php index ae7dc4d7b33a..b7c849681dab 100644 --- a/app/Jobs/Ninja/BankTransactionSync.php +++ b/app/Jobs/Ninja/BankTransactionSync.php @@ -11,9 +11,11 @@ namespace App\Jobs\Ninja; -use App\Jobs\Bank\ProcessBankTransactions; +use App\Jobs\Bank\ProcessBankTransactionsYodlee; +use App\Jobs\Bank\ProcessBankTransactionsNordigen; use App\Libraries\MultiDB; use App\Models\Account; +use App\Models\BankIntegration; use App\Utils\Ninja; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; @@ -43,20 +45,52 @@ class BankTransactionSync implements ShouldQueue */ public function handle() { - //multiDB environment, need to - foreach (MultiDB::$dbs as $db) { - MultiDB::setDB($db); + if (config('ninja.db.multi_db_enabled')) { - nlog("syncing transactions"); + foreach (MultiDB::$dbs as $db) { + MultiDB::setDB($db); - $a = Account::with('bank_integrations')->whereNotNull('bank_integration_account_id')->cursor()->each(function ($account) { - // $queue = Ninja::isHosted() ? 'bank' : 'default'; + $this->processYodlee(); + $this->processNordigen(); + } + + } else { + $this->processYodlee(); + $this->processNordigen(); + } + + nlog("syncing transactions - done"); + } + + private function processYodlee() + { + if (Ninja::isHosted()) { // @turbo124 @todo I migrated the schedule for the job within the kernel to execute on all platforms and use the same expression here to determine if yodlee can run or not. Please chek/verify + nlog("syncing transactions - yodlee"); + + Account::with('bank_integrations')->whereNotNull('bank_integration_account_id')->cursor()->each(function ($account) { if ($account->isPaid() && $account->plan == 'enterprise') { - $account->bank_integrations()->where('auto_sync', true)->cursor()->each(function ($bank_integration) use ($account) { - (new ProcessBankTransactions($account->bank_integration_account_id, $bank_integration))->handle(); + $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->cursor()->each(function ($bank_integration) use ($account) { + (new ProcessBankTransactionsYodlee($account->id, $bank_integration))->handle(); }); } + + }); + } + } + private function processNordigen() + { + if (config("ninja.nordigen.secret_id") && config("ninja.nordigen.secret_key")) { // @turbo124 check condition, when to execute this should be placed here (isSelfHosted || isPro/isEnterprise) + nlog("syncing transactions - nordigen"); + + Account::with('bank_integrations')->cursor()->each(function ($account) { + + if ((Ninja::isSelfHost() || (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise'))) { + $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->cursor()->each(function ($bank_integration) { + (new ProcessBankTransactionsNordigen($bank_integration))->handle(); + }); + } + }); } } diff --git a/app/Models/Account.php b/app/Models/Account.php index 81522d60beed..45985a007492 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -233,7 +233,7 @@ class Account extends BaseModel public function hasFeature($feature) { $plan_details = $this->getPlanDetails(); - $self_host = ! Ninja::isNinja(); + $self_host = !Ninja::isNinja(); switch ($feature) { case self::FEATURE_TASKS: @@ -254,35 +254,35 @@ class Account extends BaseModel case self::FEATURE_API: case self::FEATURE_CLIENT_PORTAL_PASSWORD: case self::FEATURE_CUSTOM_URL: - return $self_host || ! empty($plan_details); + return $self_host || !empty($plan_details); - // Pro; No trial allowed, unless they're trialing enterprise with an active pro plan + // Pro; No trial allowed, unless they're trialing enterprise with an active pro plan case self::FEATURE_MORE_CLIENTS: - return $self_host || ! empty($plan_details) && (! $plan_details['trial'] || ! empty($this->getPlanDetails(false, false))); + return $self_host || !empty($plan_details) && (!$plan_details['trial'] || !empty($this->getPlanDetails(false, false))); - // White Label + // White Label case self::FEATURE_WHITE_LABEL: - if (! $self_host && $plan_details && ! $plan_details['expires']) { + if (!$self_host && $plan_details && !$plan_details['expires']) { return false; } - // Fallthrough - // no break + // Fallthrough + // no break case self::FEATURE_REMOVE_CREATED_BY: - return ! empty($plan_details); // A plan is required even for self-hosted users + return !empty($plan_details); // A plan is required even for self-hosted users - // Enterprise; No Trial allowed; grandfathered for old pro users - case self::FEATURE_USERS:// Grandfathered for old Pro users + // Enterprise; No Trial allowed; grandfathered for old pro users + case self::FEATURE_USERS: // Grandfathered for old Pro users if ($plan_details && $plan_details['trial']) { // Do they have a non-trial plan? $plan_details = $this->getPlanDetails(false, false); } - return $self_host || ! empty($plan_details) && ($plan_details['plan'] == self::PLAN_ENTERPRISE); + return $self_host || !empty($plan_details) && ($plan_details['plan'] == self::PLAN_ENTERPRISE); - // Enterprise; No Trial allowed + // Enterprise; No Trial allowed case self::FEATURE_DOCUMENTS: case self::FEATURE_USER_PERMISSIONS: - return $self_host || ! empty($plan_details) && $plan_details['plan'] == self::PLAN_ENTERPRISE && ! $plan_details['trial']; + return $self_host || !empty($plan_details) && $plan_details['plan'] == self::PLAN_ENTERPRISE && !$plan_details['trial']; default: return false; @@ -291,12 +291,12 @@ class Account extends BaseModel public function isPaid(): bool { - return Ninja::isNinja() ? ($this->isPaidHostedClient() && ! $this->isTrial()) : $this->hasFeature(self::FEATURE_WHITE_LABEL); + return Ninja::isNinja() ? ($this->isPaidHostedClient() && !$this->isTrial()) : $this->hasFeature(self::FEATURE_WHITE_LABEL); } public function isPaidHostedClient(): bool { - if (! Ninja::isNinja()) { + if (!Ninja::isNinja()) { return false; } @@ -310,7 +310,7 @@ class Account extends BaseModel public function isFreeHostedClient(): bool { - if (! Ninja::isNinja()) { + if (!Ninja::isNinja()) { return false; } @@ -323,7 +323,7 @@ class Account extends BaseModel public function isEnterpriseClient(): bool { - if (! Ninja::isNinja()) { + if (!Ninja::isNinja()) { return false; } @@ -359,7 +359,7 @@ class Account extends BaseModel public function isTrial(): bool { - if (! Ninja::isNinja()) { + if (!Ninja::isNinja()) { return false; } @@ -370,7 +370,7 @@ class Account extends BaseModel public function startTrial($plan): void { - if (! Ninja::isNinja()) { + if (!Ninja::isNinja()) { return; } @@ -389,7 +389,7 @@ class Account extends BaseModel $price = $this->plan_price; $trial_plan = $this->trial_plan; - if ((! $plan || $plan == self::PLAN_FREE) && (! $trial_plan || ! $include_trial)) { + if ((!$plan || $plan == self::PLAN_FREE) && (!$trial_plan || !$include_trial)) { return null; } @@ -398,7 +398,7 @@ class Account extends BaseModel $trial_started = false; //14 day trial - $duration = 60*60*24*14; + $duration = 60 * 60 * 24 * 14; if ($trial_plan && $include_trial) { $trial_started = $this->trial_started; @@ -411,7 +411,7 @@ class Account extends BaseModel $plan_active = false; $plan_expires = false; - + if ($plan) { if ($this->plan_expires == null) { $plan_active = true; @@ -423,22 +423,22 @@ class Account extends BaseModel } } - if (! $include_inactive && ! $plan_active && ! $trial_active) { + if (!$include_inactive && !$plan_active && !$trial_active) { return null; } // Should we show plan details or trial details? - if (($plan && ! $trial_plan) || ! $include_trial) { + if (($plan && !$trial_plan) || !$include_trial) { $use_plan = true; - } elseif (! $plan && $trial_plan) { + } elseif (!$plan && $trial_plan) { $use_plan = false; } else { // There is both a plan and a trial - if (! empty($plan_active) && empty($trial_active)) { + if (!empty($plan_active) && empty($trial_active)) { $use_plan = true; - } elseif (empty($plan_active) && ! empty($trial_active)) { + } elseif (empty($plan_active) && !empty($trial_active)) { $use_plan = false; - } elseif (! empty($plan_active) && ! empty($trial_active)) { + } elseif (!empty($plan_active) && !empty($trial_active)) { // Both are active; use whichever is a better plan if ($plan == self::PLAN_ENTERPRISE) { $use_plan = true; @@ -508,21 +508,21 @@ class Account extends BaseModel public function emailsSent() { - if (is_null(Cache::get("email_quota".$this->key))) { + if (is_null(Cache::get("email_quota" . $this->key))) { return 0; } - return Cache::get("email_quota".$this->key); + return Cache::get("email_quota" . $this->key); } - public function emailQuotaExceeded() :bool + public function emailQuotaExceeded(): bool { - if (is_null(Cache::get("email_quota".$this->key))) { + if (is_null(Cache::get("email_quota" . $this->key))) { return false; } try { - if (Cache::get("email_quota".$this->key) > $this->getDailyEmailLimit()) { + if (Cache::get("email_quota" . $this->key) > $this->getDailyEmailLimit()) { if (is_null(Cache::get("throttle_notified:{$this->key}"))) { App::forgetInstance('translator'); $t = app('translator'); @@ -544,14 +544,14 @@ class Account extends BaseModel return true; } - } catch(\Exception $e) { + } catch (\Exception $e) { \Sentry\captureMessage("I encountered an error with email quotas for account {$this->key} - defaulting to SEND"); } return false; } - public function gmailCredentialNotification() :bool + public function gmailCredentialNotification(): bool { nlog("checking if gmail credential notification has already been sent"); @@ -560,7 +560,7 @@ class Account extends BaseModel } nlog("Sending notification"); - + try { if (is_null(Cache::get("gmail_credentials_notified:{$this->key}"))) { App::forgetInstance('translator'); @@ -582,7 +582,7 @@ class Account extends BaseModel } return true; - } catch(\Exception $e) { + } catch (\Exception $e) { \Sentry\captureMessage("I encountered an error with sending with gmail for account {$this->key}"); } @@ -610,7 +610,7 @@ class Account extends BaseModel if ($plan_expires->gt(now())) { $diff = $plan_expires->diffInDays(); - + if ($diff > 14) { return 0; } diff --git a/app/Models/BankIntegration.php b/app/Models/BankIntegration.php index 67a816f800f6..5be2f2313b1d 100644 --- a/app/Models/BankIntegration.php +++ b/app/Models/BankIntegration.php @@ -20,6 +20,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property int $account_id * @property int $company_id * @property int $user_id + * @property string $integration_type * @property string $provider_name * @property int $provider_id * @property int $bank_account_id @@ -30,6 +31,8 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property float $balance * @property int|null $currency * @property string $nickname + * @property string $nordigen_account_id + * @property string $nordigen_institution_id * @property string|null $from_date * @property bool $is_deleted * @property int|null $created_at @@ -60,7 +63,7 @@ class BankIntegration extends BaseModel { use SoftDeletes; use Filterable; - + protected $fillable = [ 'bank_account_name', 'provider_name', @@ -73,6 +76,10 @@ class BankIntegration extends BaseModel 'auto_sync', ]; + const INTEGRATION_TYPE_YODLEE = 'YODLEE'; + + const INTEGRATION_TYPE_NORDIGEN = 'NORDIGEN'; + public function getEntityType() { return self::class; diff --git a/app/Models/BankTransaction.php b/app/Models/BankTransaction.php index c3a7321e5c50..d39c83a62985 100644 --- a/app/Models/BankTransaction.php +++ b/app/Models/BankTransaction.php @@ -34,6 +34,8 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property string|null $date * @property int $bank_account_id * @property string|null $description + * @property string|null $participant + * @property string|null $participant_name * @property string $invoice_ids * @property int|null $expense_id * @property int|null $vendor_id @@ -68,7 +70,7 @@ class BankTransaction extends BaseModel use SoftDeletes; use MakesHash; use Filterable; - + const STATUS_UNMATCHED = 1; const STATUS_MATCHED = 2; @@ -84,10 +86,12 @@ class BankTransaction extends BaseModel 'base_type', 'expense_id', 'vendor_id', - 'amount' + 'amount', + 'participant', + 'participant_name' ]; - + public function getInvoiceIds() { $collection = collect(); @@ -162,7 +166,7 @@ class BankTransaction extends BaseModel // return $this->belongsTo(Expense::class)->withTrashed(); // } - public function service() :BankService + public function service(): BankService { return new BankService($this); } diff --git a/app/Observers/ProductObserver.php b/app/Observers/ProductObserver.php index 7e24377dc571..1d5e88af646c 100644 --- a/app/Observers/ProductObserver.php +++ b/app/Observers/ProductObserver.php @@ -28,8 +28,8 @@ class ProductObserver public function created(Product $product) { $subscriptions = Webhook::where('company_id', $product->company_id) - ->where('event_id', Webhook::EVENT_CREATE_PRODUCT) - ->exists(); + ->where('event_id', Webhook::EVENT_CREATE_PRODUCT) + ->exists(); if ($subscriptions) { WebhookHandler::dispatch(Webhook::EVENT_CREATE_PRODUCT, $product, $product->company)->delay(0); @@ -49,15 +49,15 @@ class ProductObserver if ($product->getOriginal('deleted_at') && !$product->deleted_at) { $event = Webhook::EVENT_RESTORE_PRODUCT; } - + if ($product->is_deleted) { $event = Webhook::EVENT_DELETE_PRODUCT; } - - + + $subscriptions = Webhook::where('company_id', $product->company_id) - ->where('event_id', $event) - ->exists(); + ->where('event_id', $event) + ->exists(); if ($subscriptions) { WebhookHandler::dispatch($event, $product, $product->company)->delay(0); @@ -75,10 +75,10 @@ class ProductObserver if ($product->is_deleted) { return; } - + $subscriptions = Webhook::where('company_id', $product->company_id) - ->where('event_id', Webhook::EVENT_ARCHIVE_PRODUCT) - ->exists(); + ->where('event_id', Webhook::EVENT_ARCHIVE_PRODUCT) + ->exists(); if ($subscriptions) { WebhookHandler::dispatch(Webhook::EVENT_ARCHIVE_PRODUCT, $product, $product->company)->delay(0); diff --git a/app/Repositories/BaseRepository.php b/app/Repositories/BaseRepository.php index ee20a4fef641..22e2d9cd93d3 100644 --- a/app/Repositories/BaseRepository.php +++ b/app/Repositories/BaseRepository.php @@ -41,7 +41,7 @@ class BaseRepository */ private function getEventClass($entity, $type) { - return 'App\Events\\'.ucfirst(class_basename($entity)).'\\'.ucfirst(class_basename($entity)).'Was'.$type; + return 'App\Events\\' . ucfirst(class_basename($entity)) . '\\' . ucfirst(class_basename($entity)) . 'Was' . $type; } /** @@ -67,7 +67,7 @@ class BaseRepository */ public function restore($entity) { - if (! $entity->trashed()) { + if (!$entity->trashed()) { return; } @@ -104,7 +104,7 @@ class BaseRepository $className = $this->getEventClass($entity, 'Deleted'); - if (class_exists($className) && ! ($entity instanceof Company)) { + if (class_exists($className) && !($entity instanceof Company)) { event(new $className($entity, $entity->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); } } @@ -112,7 +112,7 @@ class BaseRepository /* Returns an invoice if defined as a key in the $resource array*/ public function getInvitation($invitation, $resource) { - if (is_array($invitation) && ! array_key_exists('key', $invitation)) { + if (is_array($invitation) && !array_key_exists('key', $invitation)) { return false; } @@ -163,7 +163,7 @@ class BaseRepository $state['starting_amount'] = $model->balance; - if (! $model->id) { + if (!$model->id) { $company_defaults = $client->setCompanyDefaults($data, lcfirst($resource)); $data['exchange_rate'] = $company_defaults['exchange_rate']; $model->uses_inclusive_taxes = $client->getSetting('inclusive_taxes'); @@ -199,7 +199,7 @@ class BaseRepository }); } } - + $model->saveQuietly(); /* Model now persisted, now lets do some child tasks */ @@ -233,7 +233,7 @@ class BaseRepository foreach ($data['invitations'] as $invitation) { //if no invitations are present - create one. - if (! $this->getInvitation($invitation, $resource)) { + if (!$this->getInvitation($invitation, $resource)) { if (isset($invitation['id'])) { unset($invitation['id']); } @@ -245,9 +245,9 @@ class BaseRepository $invitation_class = sprintf('App\\Models\\%sInvitation', $resource); $new_invitation = $invitation_class::withTrashed() - ->where('client_contact_id', $contact->id) - ->where($lcfirst_resource_id, $model->id) - ->first(); + ->where('client_contact_id', $contact->id) + ->where($lcfirst_resource_id, $model->id) + ->first(); if ($new_invitation && $new_invitation->trashed()) { $new_invitation->restore(); @@ -279,7 +279,7 @@ class BaseRepository $model = $model->service()->applyNumber()->save(); /* Handle attempts where the deposit is greater than the amount/balance of the invoice */ - if ((int)$model->balance != 0 && $model->partial > $model->amount && $model->amount > 0) { + if ((int) $model->balance != 0 && $model->partial > $model->amount && $model->amount > 0) { $model->partial = min($model->amount, $model->balance); } @@ -293,14 +293,14 @@ class BaseRepository if ($model->status_id != Invoice::STATUS_DRAFT) { $model->service()->updateStatus()->save(); $model->client->service()->calculateBalance($model); - + // $diff = $state['finished_amount'] - $state['starting_amount']; // nlog("{$diff} - {$state['finished_amount']} - {$state['starting_amount']}"); // if(floatval($state['finished_amount']) != floatval($state['starting_amount'])) // $model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount']), "Update adjustment for invoice {$model->number}"); } - if (! $model->design_id) { + if (!$model->design_id) { $model->design_id = intval($this->decodePrimaryKey($client->getSetting('invoice_design_id'))); } @@ -316,7 +316,7 @@ class BaseRepository } /** If the client does not have tax_data - then populate this now */ - if($client->country_id == 840 && !$client->tax_data && $model->company->calculate_taxes && !$model->company->account->isFreeHostedClient()) { + if ($client->country_id == 840 && !$client->tax_data && $model->company->calculate_taxes && !$model->company->account->isFreeHostedClient()) { UpdateTaxData::dispatch($client, $client->company); } @@ -325,7 +325,7 @@ class BaseRepository if ($model instanceof Credit) { $model = $model->calc()->getCredit(); - if (! $model->design_id) { + if (!$model->design_id) { $model->design_id = $this->decodePrimaryKey($client->getSetting('credit_design_id')); } @@ -345,7 +345,7 @@ class BaseRepository } if ($model instanceof Quote) { - if (! $model->design_id) { + if (!$model->design_id) { $model->design_id = intval($this->decodePrimaryKey($client->getSetting('quote_design_id'))); } @@ -359,7 +359,7 @@ class BaseRepository } if ($model instanceof RecurringInvoice) { - if (! $model->design_id) { + if (!$model->design_id) { $model->design_id = intval($this->decodePrimaryKey($client->getSetting('invoice_design_id'))); } diff --git a/app/Transformers/BankIntegrationTransformer.php b/app/Transformers/BankIntegrationTransformer.php index 7757ee7559e7..8496b23e11ac 100644 --- a/app/Transformers/BankIntegrationTransformer.php +++ b/app/Transformers/BankIntegrationTransformer.php @@ -50,20 +50,21 @@ class BankIntegrationTransformer extends EntityTransformer { return [ 'id' => (string) $this->encodePrimaryKey($bank_integration->id), - 'provider_name' => (string)$bank_integration->provider_name ?: '', + 'provider_name' => (string) $bank_integration->provider_name ?: '', 'provider_id' => (int) $bank_integration->provider_id ?: 0, 'bank_account_id' => (int) $bank_integration->bank_account_id ?: 0, 'bank_account_name' => (string) $bank_integration->bank_account_name ?: '', 'bank_account_number' => (string) $bank_integration->bank_account_number ?: '', - 'bank_account_status' => (string)$bank_integration->bank_account_status ?: '', - 'bank_account_type' => (string)$bank_integration->bank_account_type ?: '', - 'balance' => (float)$bank_integration->balance ?: 0, - 'currency' => (string)$bank_integration->currency ?: '', - 'nickname' => (string)$bank_integration->nickname ?: '', - 'from_date' => (string)$bank_integration->from_date ?: '', + 'bank_account_status' => (string) $bank_integration->bank_account_status ?: '', + 'bank_account_type' => (string) $bank_integration->bank_account_type ?: '', + 'nordigen_institution_id' => (string) $bank_integration->nordigen_institution_id ?: '', + 'balance' => (float) $bank_integration->balance ?: 0, + 'currency' => (string) $bank_integration->currency ?: '', + 'nickname' => (string) $bank_integration->nickname ?: '', + 'from_date' => (string) $bank_integration->from_date ?: '', 'is_deleted' => (bool) $bank_integration->is_deleted, 'disabled_upstream' => (bool) $bank_integration->disabled_upstream, - 'auto_sync' => (bool)$bank_integration->auto_sync, + 'auto_sync' => (bool) $bank_integration->auto_sync, 'created_at' => (int) $bank_integration->created_at, 'updated_at' => (int) $bank_integration->updated_at, 'archived_at' => (int) $bank_integration->deleted_at, diff --git a/app/Transformers/BankTransactionTransformer.php b/app/Transformers/BankTransactionTransformer.php index 401d5a0a1eb8..15654f9654e1 100644 --- a/app/Transformers/BankTransactionTransformer.php +++ b/app/Transformers/BankTransactionTransformer.php @@ -63,11 +63,13 @@ class BankTransactionTransformer extends EntityTransformer 'bank_account_id' => (int) $bank_transaction->bank_account_id, 'status_id' => (string) $bank_transaction->status_id, 'description' => (string) $bank_transaction->description ?: '', + 'participant' => (string) $bank_transaction->participant ?: '', + 'participant_name' => (string) $bank_transaction->participant_name ?: '', 'base_type' => (string) $bank_transaction->base_type ?: '', 'invoice_ids' => (string) $bank_transaction->invoice_ids ?: '', - 'expense_id'=> (string) $bank_transaction->expense_id ?: '', - 'payment_id'=> (string) $this->encodePrimaryKey($bank_transaction->payment_id) ?: '', - 'vendor_id'=> (string) $this->encodePrimaryKey($bank_transaction->vendor_id) ?: '', + 'expense_id' => (string) $bank_transaction->expense_id ?: '', + 'payment_id' => (string) $this->encodePrimaryKey($bank_transaction->payment_id) ?: '', + 'vendor_id' => (string) $this->encodePrimaryKey($bank_transaction->vendor_id) ?: '', 'bank_transaction_rule_id' => (string) $this->encodePrimaryKey($bank_transaction->bank_transaction_rule_id) ?: '', 'is_deleted' => (bool) $bank_transaction->is_deleted, 'created_at' => (int) $bank_transaction->created_at, diff --git a/composer.json b/composer.json index 1ef66cdd1760..5998d27257f8 100644 --- a/composer.json +++ b/composer.json @@ -72,6 +72,7 @@ "microsoft/microsoft-graph": "^1.69", "mollie/mollie-api-php": "^2.36", "nelexa/zip": "^4.0", + "nordigen/nordigen-php": "^1.1", "nwidart/laravel-modules": "^10.0", "omnipay/paypal": "^3.0", "payfast/payfast-php-sdk": "^1.1", @@ -172,11 +173,11 @@ } }, "repositories": [ - { - "type": "vcs", - "url": "https://github.com/turbo124/apple" - } + { + "type": "vcs", + "url": "https://github.com/turbo124/apple" + } ], "minimum-stability": "dev", "prefer-stable": true -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index 7d2e2f95858e..5496e6fcbe81 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": "28b57fe6eac3d71c607125cda9a6a537", + "content-hash": "e9ac8b1951e155ece9b20e57a92fd09e", "packages": [ { "name": "afosto/yaac", @@ -33,9 +33,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "authors": [ { "name": "Afosto Team", @@ -44,14 +42,7 @@ ], "description": "Yet Another ACME client: a decoupled LetsEncrypt client", "homepage": "https://afosto.com", - "keywords": [ - "ACME", - "acmev2", - "afosto", - "encrypt", - "lets", - "v2" - ], + "keywords": ["ACME", "acmev2", "afosto", "encrypt", "lets", "v2"], "support": { "issues": "https://github.com/afosto/yaac/issues", "source": "https://github.com/afosto/yaac/tree/v1.5.2" @@ -94,17 +85,10 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "Core logic and the utilities for the Apimatic's PHP SDK", "homepage": "https://github.com/apimatic/core-lib-php", - "keywords": [ - "apimatic", - "core", - "corelib", - "php" - ], + "keywords": ["apimatic", "core", "corelib", "php"], "support": { "issues": "https://github.com/apimatic/core-lib-php/issues", "source": "https://github.com/apimatic/core-lib-php/tree/0.3.3" @@ -135,9 +119,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "Definition of the behavior of apimatic/core, apimatic/unirest-php and Apimatic's PHP SDK", "homepage": "https://github.com/apimatic/core-interfaces-php", "keywords": [ @@ -183,9 +165,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], + "license": ["OSL-3.0"], "authors": [ { "name": "Christian Weiske", @@ -240,9 +220,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Mashape", @@ -259,13 +237,7 @@ ], "description": "Unirest PHP", "homepage": "https://github.com/apimatic/unirest-php", - "keywords": [ - "client", - "curl", - "http", - "https", - "rest" - ], + "keywords": ["client", "curl", "http", "https", "rest"], "support": { "email": "opensource@apimatic.io", "issues": "https://github.com/apimatic/unirest-php/issues", @@ -303,9 +275,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Marc Aschmann", @@ -314,10 +284,7 @@ ], "description": "A PHP wrapper for Ansible.", "homepage": "https://github.com/maschmann/php-ansible", - "keywords": [ - "ansible", - "php" - ], + "keywords": ["ansible", "php"], "support": { "issues": "https://github.com/maschmann/php-ansible/issues", "source": "https://github.com/maschmann/php-ansible/tree/v4.1.0" @@ -345,14 +312,10 @@ }, "type": "library", "autoload": { - "classmap": [ - "lib" - ] + "classmap": ["lib"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "proprietary" - ], + "license": ["proprietary"], "description": "Official PHP SDK for Authorize.Net", "homepage": "http://developer.authorize.net", "keywords": [ @@ -402,9 +365,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Claudin J. Daniel", @@ -455,14 +416,10 @@ }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "authors": [ { "name": "AWS SDK Common Runtime Team", @@ -471,12 +428,7 @@ ], "description": "AWS Common Runtime for PHP", "homepage": "https://github.com/awslabs/aws-crt-php", - "keywords": [ - "amazon", - "aws", - "crt", - "sdk" - ], + "keywords": ["amazon", "aws", "crt", "sdk"], "support": { "issues": "https://github.com/awslabs/aws-crt-php/issues", "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.4" @@ -542,17 +494,13 @@ } }, "autoload": { - "files": [ - "src/functions.php" - ], + "files": ["src/functions.php"], "psr-4": { "Aws\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "authors": [ { "name": "Amazon Web Services", @@ -613,9 +561,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], + "license": ["BSD-2-Clause"], "authors": [ { "name": "Ben Scholzen 'DASPRiD'", @@ -658,9 +604,7 @@ "friendsofphp/php-cs-fixer": "^3.6", "phpunit/phpunit": "^9.5" }, - "bin": [ - "snappdf" - ], + "bin": ["snappdf"], "type": "library", "autoload": { "psr-4": { @@ -668,9 +612,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Benjamin Beganović", @@ -717,9 +659,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Braintree", @@ -762,9 +702,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "Arbitrary-precision arithmetic library", "keywords": [ "Arbitrary-precision", @@ -820,9 +758,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "KyleKatarn", @@ -830,13 +766,7 @@ } ], "description": "Types to use Carbon in Doctrine", - "keywords": [ - "carbon", - "date", - "datetime", - "doctrine", - "time" - ], + "keywords": ["carbon", "date", "datetime", "doctrine", "time"], "support": { "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0" @@ -893,9 +823,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Checkout.com", @@ -949,15 +877,11 @@ "type": "library", "autoload": { "psr-4": { - "CleverIt\\UBL\\Invoice\\": [ - "src/" - ] + "CleverIt\\UBL\\Invoice\\": ["src/"] } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Bram van Eijk | CleverIT", @@ -1006,17 +930,13 @@ }, "type": "library", "autoload": { - "files": [ - "src/functions_include.php" - ], + "files": ["src/functions_include.php"], "psr-4": { "Clue\\StreamFilter\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Christian Lück", @@ -1087,9 +1007,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jordi Boggiano", @@ -1098,13 +1016,7 @@ } ], "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", - "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" - ], + "keywords": ["cabundle", "cacert", "certificate", "ssl", "tls"], "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", @@ -1154,9 +1066,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], + "license": ["BSD-2-Clause"], "authors": [ { "name": "Ben Scholzen 'DASPRiD'", @@ -1166,10 +1076,7 @@ } ], "description": "PHP 7.1 enum implementation", - "keywords": [ - "enum", - "map" - ], + "keywords": ["enum", "map"], "support": { "issues": "https://github.com/DASPRiD/Enum/issues", "source": "https://github.com/DASPRiD/Enum/tree/1.0.5" @@ -1212,9 +1119,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Dragonfly Development Inc.", @@ -1239,12 +1144,7 @@ ], "description": "Given a deep data structure, access data by dot notation.", "homepage": "https://github.com/dflydev/dflydev-dot-access-data", - "keywords": [ - "access", - "data", - "dot", - "notation" - ], + "keywords": ["access", "data", "dot", "notation"], "support": { "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2" @@ -1289,9 +1189,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Guilherme Blanco", @@ -1316,11 +1214,7 @@ ], "description": "Docblock Annotations Parser", "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], + "keywords": ["annotations", "docblock", "parser"], "support": { "issues": "https://github.com/doctrine/annotations/issues", "source": "https://github.com/doctrine/annotations/tree/2.0.1" @@ -1362,9 +1256,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Guilherme Blanco", @@ -1460,9 +1352,7 @@ "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." }, - "bin": [ - "bin/doctrine-dbal" - ], + "bin": ["bin/doctrine-dbal"], "type": "library", "autoload": { "psr-4": { @@ -1470,9 +1360,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Guilherme Blanco", @@ -1569,9 +1457,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", "homepage": "https://www.doctrine-project.org/", "support": { @@ -1613,9 +1499,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Guilherme Blanco", @@ -1703,9 +1587,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Guilherme Blanco", @@ -1796,9 +1678,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Marco Pivetta", @@ -1808,10 +1688,7 @@ ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], + "keywords": ["constructor", "instantiate"], "support": { "issues": "https://github.com/doctrine/instantiator/issues", "source": "https://github.com/doctrine/instantiator/tree/2.0.0" @@ -1863,9 +1740,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Guilherme Blanco", @@ -1882,13 +1757,7 @@ ], "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], + "keywords": ["annotations", "docblock", "lexer", "parser", "php"], "support": { "issues": "https://github.com/doctrine/lexer/issues", "source": "https://github.com/doctrine/lexer/tree/3.0.0" @@ -1943,9 +1812,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Chris Tankersley", @@ -1954,10 +1821,7 @@ } ], "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", - "keywords": [ - "cron", - "schedule" - ], + "keywords": ["cron", "schedule"], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" @@ -2008,9 +1872,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Eduardo Gulias Davis" @@ -2082,9 +1944,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jeroen van den Enden", @@ -2093,13 +1953,7 @@ ], "description": "Endroid QR Code", "homepage": "https://github.com/endroid/qr-code", - "keywords": [ - "code", - "endroid", - "php", - "qr", - "qrcode" - ], + "keywords": ["code", "endroid", "php", "qr", "qrcode"], "support": { "issues": "https://github.com/endroid/qr-code/issues", "source": "https://github.com/endroid/qr-code/tree/5.0.3" @@ -2145,9 +1999,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "eWAY", @@ -2156,12 +2008,7 @@ ], "description": "eWAY Rapid PHP library", "homepage": "https://www.eway.com.au", - "keywords": [ - "eway", - "payment processing", - "payments", - "rapid" - ], + "keywords": ["eway", "payment processing", "payments", "rapid"], "support": { "issues": "https://github.com/eWAYPayment/eway-rapid-php/issues", "source": "https://github.com/eWAYPayment/eway-rapid-php/tree/v1.4.1" @@ -2197,20 +2044,14 @@ }, "type": "library", "autoload": { - "files": [ - "library/HTMLPurifier.composer.php" - ], + "files": ["library/HTMLPurifier.composer.php"], "psr-0": { "HTMLPurifier": "library/" }, - "exclude-from-classmap": [ - "/library/HTMLPurifier/Language/" - ] + "exclude-from-classmap": ["/library/HTMLPurifier/Language/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1-or-later" - ], + "license": ["LGPL-2.1-or-later"], "authors": [ { "name": "Edward Z. Yang", @@ -2220,9 +2061,7 @@ ], "description": "Standards compliant HTML filter written in PHP", "homepage": "http://htmlpurifier.org/", - "keywords": [ - "html" - ], + "keywords": ["html"], "support": { "issues": "https://github.com/ezyang/htmlpurifier/issues", "source": "https://github.com/ezyang/htmlpurifier/tree/v4.17.0" @@ -2277,20 +2116,14 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "François Zaninotto" } ], "description": "Faker is a PHP library that generates fake data for you.", - "keywords": [ - "data", - "faker", - "fixtures" - ], + "keywords": ["data", "faker", "fixtures"], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", "source": "https://github.com/FakerPHP/Faker/tree/v1.23.0" @@ -2333,9 +2166,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Neuman Vong", @@ -2350,10 +2181,7 @@ ], "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", "homepage": "https://github.com/firebase/php-jwt", - "keywords": [ - "jwt", - "php" - ], + "keywords": ["jwt", "php"], "support": { "issues": "https://github.com/firebase/php-jwt/issues", "source": "https://github.com/firebase/php-jwt/tree/v6.10.0" @@ -2395,9 +2223,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fruitcake", @@ -2410,11 +2236,7 @@ ], "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", "homepage": "https://github.com/fruitcake/php-cors", - "keywords": [ - "cors", - "laravel", - "symfony" - ], + "keywords": ["cors", "laravel", "symfony"], "support": { "issues": "https://github.com/fruitcake/php-cors/issues", "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" @@ -2464,9 +2286,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "GoCardless and contributors", @@ -2475,11 +2295,7 @@ ], "description": "GoCardless Pro PHP Client Library", "homepage": "https://gocardless.com/", - "keywords": [ - "api", - "direct debit", - "gocardless" - ], + "keywords": ["api", "direct debit", "gocardless"], "support": { "issues": "https://github.com/gocardless/gocardless-pro-php/issues", "source": "https://github.com/gocardless/gocardless-pro-php/tree/v4.28.0" @@ -2523,23 +2339,14 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Asmir Mustafic" } ], "description": "Convert XSD (XML Schema) definitions into PHP classes", - "keywords": [ - "converter", - "jms", - "php", - "serializer", - "xml", - "xsd" - ], + "keywords": ["converter", "jms", "php", "serializer", "xml", "xsd"], "support": { "issues": "https://github.com/goetas-webservices/xsd2php-runtime/issues", "source": "https://github.com/goetas-webservices/xsd2php-runtime/tree/v0.2.16" @@ -2590,25 +2397,17 @@ } }, "autoload": { - "files": [ - "src/aliases.php" - ], + "files": ["src/aliases.php"], "psr-4": { "Google\\": "src/" }, - "classmap": [ - "src/aliases.php" - ] + "classmap": ["src/aliases.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "description": "Client library for Google APIs", "homepage": "http://developers.google.com/api-client-library/php", - "keywords": [ - "google" - ], + "keywords": ["google"], "support": { "issues": "https://github.com/googleapis/google-api-php-client/issues", "source": "https://github.com/googleapis/google-api-php-client/tree/v2.15.1" @@ -2637,22 +2436,16 @@ }, "type": "library", "autoload": { - "files": [ - "autoload.php" - ], + "files": ["autoload.php"], "psr-4": { "Google\\Service\\": "src" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "description": "Client library for Google APIs", "homepage": "http://developers.google.com/api-client-library/php", - "keywords": [ - "google" - ], + "keywords": ["google"], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.328.0" @@ -2700,16 +2493,10 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "description": "Google Auth Library for PHP", "homepage": "http://github.com/google/google-auth-library-php", - "keywords": [ - "Authentication", - "google", - "oauth2" - ], + "keywords": ["Authentication", "google", "oauth2"], "support": { "docs": "https://googleapis.github.io/google-auth-library-php/main/", "issues": "https://github.com/googleapis/google-auth-library-php/issues", @@ -2745,9 +2532,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Graham Campbell", @@ -2812,9 +2597,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Benjamin Zikarsky", @@ -2878,17 +2661,13 @@ } }, "autoload": { - "files": [ - "src/functions_include.php" - ], + "files": ["src/functions_include.php"], "psr-4": { "GuzzleHttp\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Graham Campbell", @@ -2992,9 +2771,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Graham Campbell", @@ -3018,9 +2795,7 @@ } ], "description": "Guzzle promises library", - "keywords": [ - "promise" - ], + "keywords": ["promise"], "support": { "issues": "https://github.com/guzzle/promises/issues", "source": "https://github.com/guzzle/promises/tree/2.0.2" @@ -3086,9 +2861,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Graham Campbell", @@ -3193,9 +2966,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Graham Campbell", @@ -3219,10 +2990,7 @@ } ], "description": "A polyfill class for uri_template of PHP", - "keywords": [ - "guzzlehttp", - "uri-template" - ], + "keywords": ["guzzlehttp", "uri-template"], "support": { "issues": "https://github.com/guzzle/uri-template/issues", "source": "https://github.com/guzzle/uri-template/tree/v1.0.3" @@ -3271,17 +3039,13 @@ }, "type": "library", "autoload": { - "files": [ - "src/functions.php" - ], + "files": ["src/functions.php"], "psr-4": { "JsonMachine\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "authors": [ { "name": "Filip Halaxa", @@ -3333,9 +3097,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ivan Akimov", @@ -3394,9 +3156,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "hedii", @@ -3455,9 +3215,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Daniel Erling", @@ -3467,10 +3225,7 @@ ], "description": "Get mimetypes by fileextensions and visa versa", "homepage": "https://github.com/horstoeko/mimedb", - "keywords": [ - "file extension", - "mimetype" - ], + "keywords": ["file extension", "mimetype"], "support": { "issues": "https://github.com/horstoeko/mimedb/issues", "source": "https://github.com/horstoeko/mimedb/tree/v1.0.5" @@ -3510,9 +3265,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Daniel Erling", @@ -3522,9 +3275,7 @@ ], "description": "A library for string manipulation utilities", "homepage": "https://github.com/horstoeko/stringmanagement", - "keywords": [ - "stringmanagement" - ], + "keywords": ["stringmanagement"], "support": { "issues": "https://github.com/horstoeko/stringmanagement/issues", "source": "https://github.com/horstoeko/stringmanagement/tree/v1.0.11" @@ -3579,9 +3330,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Daniel Erling", @@ -3640,9 +3389,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -3650,12 +3397,7 @@ } ], "description": "An HTTP Factory using Guzzle PSR7", - "keywords": [ - "factory", - "http", - "psr-17", - "psr-7" - ], + "keywords": ["factory", "http", "psr-17", "psr-7"], "support": { "issues": "https://github.com/http-interop/http-factory-guzzle/issues", "source": "https://github.com/http-interop/http-factory-guzzle/tree/1.2.0" @@ -3699,9 +3441,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "imdhemy", @@ -3750,9 +3490,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "imdhemy", @@ -3813,9 +3551,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "imdhemy", @@ -3877,9 +3613,7 @@ "dev-master": "2.4-dev" }, "laravel": { - "providers": [ - "Intervention\\Image\\ImageServiceProvider" - ], + "providers": ["Intervention\\Image\\ImageServiceProvider"], "aliases": { "Image": "Intervention\\Image\\Facades\\Image" } @@ -3891,9 +3625,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Oliver Vogel", @@ -3967,9 +3699,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Benjamin Beganović", @@ -3979,10 +3709,7 @@ ], "description": "Simplified database records management", "homepage": "https://github.com/invoiceninja/inspector", - "keywords": [ - "inspector", - "invoiceninja" - ], + "keywords": ["inspector", "invoiceninja"], "support": { "issues": "https://github.com/invoiceninja/inspector/issues", "source": "https://github.com/invoiceninja/inspector/tree/v2.0" @@ -4026,9 +3753,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Alessandro Lai", @@ -4036,12 +3761,7 @@ } ], "description": "A library to get pretty versions strings of installed dependencies", - "keywords": [ - "composer", - "package", - "release", - "versions" - ], + "keywords": ["composer", "package", "release", "versions"], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5" @@ -4086,9 +3806,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Johannes M. Schmitt", @@ -4100,12 +3818,7 @@ } ], "description": "Class/method/property metadata management in PHP", - "keywords": [ - "annotations", - "metadata", - "xml", - "yaml" - ], + "keywords": ["annotations", "metadata", "xml", "yaml"], "support": { "issues": "https://github.com/schmittjoh/metadata/issues", "source": "https://github.com/schmittjoh/metadata/tree/2.8.0" @@ -4174,9 +3887,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Johannes M. Schmitt", @@ -4241,9 +3952,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "josemmo", @@ -4253,12 +3962,7 @@ ], "description": "Librería para la generación, firma y envío de facturas electrónicas", "homepage": "https://github.com/josemmo/Facturae-PHP", - "keywords": [ - "face", - "faceb2b", - "facturae", - "xades" - ], + "keywords": ["face", "faceb2b", "facturae", "xades"], "support": { "issues": "https://github.com/josemmo/Facturae-PHP/issues", "source": "https://github.com/josemmo/Facturae-PHP/tree/v1.7.9" @@ -4285,15 +3989,11 @@ "type": "library", "autoload": { "psr-4": { - "kmukku\\phpIso11649\\": [ - "src/" - ] + "kmukku\\phpIso11649\\": ["src/"] } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Keijo Mukku", @@ -4343,9 +4043,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jeffrey Way", @@ -4353,11 +4051,7 @@ } ], "description": "Simple view presenters", - "keywords": [ - "laravel", - "presenter", - "view" - ], + "keywords": ["laravel", "presenter", "view"], "support": { "issues": "https://github.com/laracasts/Presenter/issues", "source": "https://github.com/laracasts/Presenter/tree/0.2.6" @@ -4545,9 +4239,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Taylor Otwell", @@ -4556,10 +4248,7 @@ ], "description": "The Laravel Framework.", "homepage": "https://laravel.com", - "keywords": [ - "framework", - "laravel" - ], + "keywords": ["framework", "laravel"], "support": { "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" @@ -4606,17 +4295,13 @@ } }, "autoload": { - "files": [ - "src/helpers.php" - ], + "files": ["src/helpers.php"], "psr-4": { "Laravel\\Prompts\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "support": { "issues": "https://github.com/laravel/prompts/issues", "source": "https://github.com/laravel/prompts/tree/v0.1.13" @@ -4658,9 +4343,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Taylor Otwell", @@ -4672,11 +4355,7 @@ } ], "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", - "keywords": [ - "closure", - "laravel", - "serializable" - ], + "keywords": ["closure", "laravel", "serializable"], "support": { "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" @@ -4723,9 +4402,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Taylor Otwell", @@ -4733,11 +4410,7 @@ } ], "description": "Slack Notification Channel for laravel.", - "keywords": [ - "laravel", - "notifications", - "slack" - ], + "keywords": ["laravel", "notifications", "slack"], "support": { "issues": "https://github.com/laravel/slack-notification-channel/issues", "source": "https://github.com/laravel/slack-notification-channel/tree/v2.5.0" @@ -4793,9 +4466,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Taylor Otwell", @@ -4804,10 +4475,7 @@ ], "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.", "homepage": "https://laravel.com", - "keywords": [ - "laravel", - "oauth" - ], + "keywords": ["laravel", "oauth"], "support": { "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" @@ -4850,9 +4518,7 @@ "dev-master": "2.x-dev" }, "laravel": { - "providers": [ - "Laravel\\Tinker\\TinkerServiceProvider" - ] + "providers": ["Laravel\\Tinker\\TinkerServiceProvider"] } }, "autoload": { @@ -4861,9 +4527,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Taylor Otwell", @@ -4871,12 +4535,7 @@ } ], "description": "Powerful REPL for the Laravel framework.", - "keywords": [ - "REPL", - "Tinker", - "laravel", - "psysh" - ], + "keywords": ["REPL", "Tinker", "laravel", "psysh"], "support": { "issues": "https://github.com/laravel/tinker/issues", "source": "https://github.com/laravel/tinker/tree/v2.8.2" @@ -4914,9 +4573,7 @@ "dev-master": "4.x-dev" }, "laravel": { - "providers": [ - "Laravel\\Ui\\UiServiceProvider" - ] + "providers": ["Laravel\\Ui\\UiServiceProvider"] } }, "autoload": { @@ -4926,9 +4583,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Taylor Otwell", @@ -4936,10 +4591,7 @@ } ], "description": "Laravel UI utilities and presets.", - "keywords": [ - "laravel", - "ui" - ], + "keywords": ["laravel", "ui"], "support": { "source": "https://github.com/laravel/ui/tree/v4.3.0" }, @@ -4947,34 +4599,34 @@ }, { "name": "lcobucci/clock", - "version": "3.0.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/lcobucci/clock.git", - "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc" + "reference": "6f28b826ea01306b07980cb8320ab30b966cd715" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/039ef98c6b57b101d10bd11d8fdfda12cbd996dc", - "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/6f28b826ea01306b07980cb8320ab30b966cd715", + "reference": "6f28b826ea01306b07980cb8320ab30b966cd715", "shasum": "" }, "require": { - "php": "~8.1.0 || ~8.2.0", + "php": "~8.2.0 || ~8.3.0", "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" }, "require-dev": { - "infection/infection": "^0.26", - "lcobucci/coding-standard": "^9.0", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-deprecation-rules": "^1.1.1", - "phpstan/phpstan-phpunit": "^1.3.2", - "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^9.5.27" + "infection/infection": "^0.27", + "lcobucci/coding-standard": "^11.0.0", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan": "^1.10.25", + "phpstan/phpstan-deprecation-rules": "^1.1.3", + "phpstan/phpstan-phpunit": "^1.3.13", + "phpstan/phpstan-strict-rules": "^1.5.1", + "phpunit/phpunit": "^10.2.3" }, "type": "library", "autoload": { @@ -4983,9 +4635,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Luís Cobucci", @@ -4995,7 +4645,7 @@ "description": "Yet another clock abstraction", "support": { "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.0.0" + "source": "https://github.com/lcobucci/clock/tree/3.2.0" }, "funding": [ { @@ -5007,7 +4657,7 @@ "type": "patreon" } ], - "time": "2022-12-19T15:00:24+00:00" + "time": "2023-11-17T17:00:27+00:00" }, { "name": "lcobucci/jwt", @@ -5052,9 +4702,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Luís Cobucci", @@ -5063,10 +4711,7 @@ } ], "description": "A simple library to work with JSON Web Token and JSON Web Signature", - "keywords": [ - "JWS", - "jwt" - ], + "keywords": ["JWS", "jwt"], "support": { "issues": "https://github.com/lcobucci/jwt/issues", "source": "https://github.com/lcobucci/jwt/tree/4.3.0" @@ -5139,9 +4784,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Colin O'Dell", @@ -5227,9 +4870,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Colin O'Dell", @@ -5315,17 +4956,13 @@ } }, "autoload": { - "files": [ - "src/functions_include.php" - ], + "files": ["src/functions_include.php"], "psr-4": { "League\\Csv\\": "src" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ignace Nyamagana Butera", @@ -5411,9 +5048,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Frank de Jonge", @@ -5481,9 +5116,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Frank de Jonge", @@ -5543,9 +5176,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Frank de Jonge", @@ -5553,13 +5184,7 @@ } ], "description": "Local filesystem adapter for Flysystem.", - "keywords": [ - "Flysystem", - "file", - "files", - "filesystem", - "local" - ], + "keywords": ["Flysystem", "file", "files", "filesystem", "local"], "support": { "issues": "https://github.com/thephpleague/flysystem-local/issues", "source": "https://github.com/thephpleague/flysystem-local/tree/3.23.0" @@ -5621,9 +5246,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Phil Sturgeon", @@ -5634,12 +5257,7 @@ ], "description": "Handle the output of complex data structures ready for API output.", "homepage": "http://fractal.thephpleague.com/", - "keywords": [ - "api", - "json", - "league", - "rest" - ], + "keywords": ["api", "json", "league", "rest"], "support": { "issues": "https://github.com/thephpleague/fractal/issues", "source": "https://github.com/thephpleague/fractal/tree/0.20.1" @@ -5676,9 +5294,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Frank de Jonge", @@ -5746,9 +5362,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ben Corlett", @@ -5808,9 +5422,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Adrian Macneil", @@ -5823,12 +5435,7 @@ ], "description": "Omnipay payment processing library", "homepage": "https://omnipay.thephpleague.com/", - "keywords": [ - "checkout", - "creditcard", - "omnipay", - "payment" - ], + "keywords": ["checkout", "creditcard", "omnipay", "payment"], "support": { "issues": "https://github.com/thephpleague/omnipay/issues", "source": "https://github.com/thephpleague/omnipay/tree/v3.2.1" @@ -5875,26 +5482,20 @@ "type": "library", "extra": { "laravel": { - "providers": [ - "Livewire\\LivewireServiceProvider" - ], + "providers": ["Livewire\\LivewireServiceProvider"], "aliases": { "Livewire": "Livewire\\Livewire" } } }, "autoload": { - "files": [ - "src/helpers.php" - ], + "files": ["src/helpers.php"], "psr-4": { "Livewire\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Caleb Porzio", @@ -5953,9 +5554,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Paul Duncan", @@ -5975,10 +5574,7 @@ } ], "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", - "keywords": [ - "stream", - "zip" - ], + "keywords": ["stream", "zip"], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.0" @@ -6025,9 +5621,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Mark Baker", @@ -6036,10 +5630,7 @@ ], "description": "PHP Class for working with complex numbers", "homepage": "https://github.com/MarkBaker/PHPComplex", - "keywords": [ - "complex", - "mathematics" - ], + "keywords": ["complex", "mathematics"], "support": { "issues": "https://github.com/MarkBaker/PHPComplex/issues", "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2" @@ -6080,9 +5671,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Mark Baker", @@ -6091,11 +5680,7 @@ ], "description": "PHP Class for working with matrices", "homepage": "https://github.com/MarkBaker/PHPMatrix", - "keywords": [ - "mathematics", - "matrix", - "vector" - ], + "keywords": ["mathematics", "matrix", "vector"], "support": { "issues": "https://github.com/MarkBaker/PHPMatrix/issues", "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1" @@ -6136,9 +5721,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Microsoft Graph Client Tooling", @@ -6192,9 +5775,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], + "license": ["BSD-2-Clause"], "authors": [ { "name": "Mollie B.V.", @@ -6303,9 +5884,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Mathias Verraes", @@ -6323,11 +5902,7 @@ ], "description": "PHP implementation of Fowler's Money pattern", "homepage": "http://moneyphp.org", - "keywords": [ - "Value Object", - "money", - "vo" - ], + "keywords": ["Value Object", "money", "vo"], "support": { "issues": "https://github.com/moneyphp/money/issues", "source": "https://github.com/moneyphp/money/tree/v4.3.0" @@ -6402,9 +5977,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jordi Boggiano", @@ -6414,11 +5987,7 @@ ], "description": "Sends your logs to files, sockets, inboxes, databases and various web services", "homepage": "https://github.com/Seldaek/monolog", - "keywords": [ - "log", - "logging", - "psr-3" - ], + "keywords": ["log", "logging", "psr-3"], "support": { "issues": "https://github.com/Seldaek/monolog/issues", "source": "https://github.com/Seldaek/monolog/tree/3.5.0" @@ -6457,9 +6026,7 @@ "composer/xdebug-handler": "^3.0.3", "phpunit/phpunit": "^8.5.33" }, - "bin": [ - "bin/jp.php" - ], + "bin": ["bin/jp.php"], "type": "library", "extra": { "branch-alias": { @@ -6467,17 +6034,13 @@ } }, "autoload": { - "files": [ - "src/JmesPath.php" - ], + "files": ["src/JmesPath.php"], "psr-4": { "JmesPath\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Graham Campbell", @@ -6491,10 +6054,7 @@ } ], "description": "Declaratively specify how to extract elements from a JSON document", - "keywords": [ - "json", - "jsonpath" - ], + "keywords": ["json", "jsonpath"], "support": { "issues": "https://github.com/jmespath/jmespath.php/issues", "source": "https://github.com/jmespath/jmespath.php/tree/2.7.0" @@ -6548,9 +6108,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ne-Lexa", @@ -6613,9 +6171,7 @@ "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", "squizlabs/php_codesniffer": "^3.4" }, - "bin": [ - "bin/carbon" - ], + "bin": ["bin/carbon"], "type": "library", "extra": { "branch-alias": { @@ -6623,14 +6179,10 @@ "dev-master": "2.x-dev" }, "laravel": { - "providers": [ - "Carbon\\Laravel\\ServiceProvider" - ] + "providers": ["Carbon\\Laravel\\ServiceProvider"] }, "phpstan": { - "includes": [ - "extension.neon" - ] + "includes": ["extension.neon"] } }, "autoload": { @@ -6639,9 +6191,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Brian Nesbitt", @@ -6655,11 +6205,7 @@ ], "description": "An API extension for DateTime that supports 281 different languages.", "homepage": "https://carbon.nesbot.com", - "keywords": [ - "date", - "datetime", - "time" - ], + "keywords": ["date", "datetime", "time"], "support": { "docs": "https://carbon.nesbot.com/docs", "issues": "https://github.com/briannesbitt/Carbon/issues", @@ -6711,16 +6257,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], + "license": ["BSD-3-Clause", "GPL-2.0-only", "GPL-3.0-only"], "authors": [ { "name": "David Grudl", @@ -6733,10 +6273,7 @@ ], "description": "📐 Nette Schema: validating data structures against a given Schema.", "homepage": "https://nette.org", - "keywords": [ - "config", - "nette" - ], + "keywords": ["config", "nette"], "support": { "issues": "https://github.com/nette/schema/issues", "source": "https://github.com/nette/schema/tree/v1.2.5" @@ -6785,16 +6322,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], + "license": ["BSD-3-Clause", "GPL-2.0-only", "GPL-3.0-only"], "authors": [ { "name": "David Grudl", @@ -6851,9 +6382,7 @@ "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, - "bin": [ - "bin/php-parse" - ], + "bin": ["bin/php-parse"], "type": "library", "extra": { "branch-alias": { @@ -6866,25 +6395,68 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Nikita Popov" } ], "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], + "keywords": ["parser", "php"], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" }, "time": "2023-12-10T21:03:43+00:00" }, + { + "name": "nordigen/nordigen-php", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/nordigen/nordigen-php.git", + "reference": "1770384ceb8042c7275cb0e404d8b7131bdccc56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nordigen/nordigen-php/zipball/1770384ceb8042c7275cb0e404d8b7131bdccc56", + "reference": "1770384ceb8042c7275cb0e404d8b7131bdccc56", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "guzzlehttp/guzzle": "^7.3", + "php": ">=7.4" + }, + "require-dev": { + "blastcloud/guzzler": "^2.0", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Nordigen\\NordigenPHP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Nordigen Solutions", + "email": "support@nordigen.com", + "homepage": "https://nordigen.com" + } + ], + "description": "Nordigen official API client for PHP", + "homepage": "https://nordigen.com", + "keywords": ["Open Banking", "api", "nordigen", "psd2"], + "support": { + "issues": "https://github.com/nordigen/nordigen-php/issues", + "source": "https://github.com/nordigen/nordigen-php/tree/1.1.1" + }, + "time": "2023-06-22T10:53:06+00:00" + }, { "name": "nunomaduro/termwind", "version": "v1.15.1", @@ -6919,23 +6491,17 @@ "type": "library", "extra": { "laravel": { - "providers": [ - "Termwind\\Laravel\\TermwindServiceProvider" - ] + "providers": ["Termwind\\Laravel\\TermwindServiceProvider"] } }, "autoload": { - "files": [ - "src/Functions.php" - ], + "files": ["src/Functions.php"], "psr-4": { "Termwind\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nuno Maduro", @@ -6943,14 +6509,7 @@ } ], "description": "Its like Tailwind CSS, but for the console.", - "keywords": [ - "cli", - "console", - "css", - "package", - "php", - "style" - ], + "keywords": ["cli", "console", "css", "package", "php", "style"], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", "source": "https://github.com/nunomaduro/termwind/tree/v1.15.1" @@ -7013,17 +6572,13 @@ } }, "autoload": { - "files": [ - "src/helpers.php" - ], + "files": ["src/helpers.php"], "psr-4": { "Nwidart\\Modules\\": "src" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Widart", @@ -7033,13 +6588,7 @@ } ], "description": "Laravel Module management", - "keywords": [ - "laravel", - "module", - "modules", - "nwidart", - "rad" - ], + "keywords": ["laravel", "module", "modules", "nwidart", "rad"], "support": { "issues": "https://github.com/nWidart/laravel-modules/issues", "source": "https://github.com/nWidart/laravel-modules/tree/10.0.4" @@ -7099,9 +6648,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Tobias Nyholm", @@ -7114,10 +6661,7 @@ ], "description": "A fast PHP7 implementation of PSR-7", "homepage": "https://tnyholm.se", - "keywords": [ - "psr-17", - "psr-7" - ], + "keywords": ["psr-17", "psr-7"], "support": { "issues": "https://github.com/Nyholm/psr7/issues", "source": "https://github.com/Nyholm/psr7/tree/1.8.1" @@ -7176,14 +6720,10 @@ "psr-4": { "Omnipay\\Common\\": "src/Common" }, - "classmap": [ - "src/Omnipay.php" - ] + "classmap": ["src/Omnipay.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Adrian Macneil", @@ -7261,9 +6801,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Adrian Macneil", @@ -7319,9 +6857,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Paragon Initiative Enterprises", @@ -7384,9 +6920,7 @@ }, "type": "library", "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Paragon Initiative Enterprises", @@ -7395,12 +6929,7 @@ } ], "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" - ], + "keywords": ["csprng", "polyfill", "pseudorandom", "random"], "support": { "email": "info@paragonie.com", "issues": "https://github.com/paragonie/random_compat/issues", @@ -7435,14 +6964,10 @@ }, "type": "library", "autoload": { - "files": [ - "autoload.php" - ] + "files": ["autoload.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], + "license": ["ISC"], "authors": [ { "name": "Paragon Initiative Enterprises", @@ -7523,9 +7048,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Payfast", @@ -7533,12 +7056,7 @@ } ], "description": "Payfast PHP Library", - "keywords": [ - "api", - "onsite", - "payfast", - "php" - ], + "keywords": ["api", "onsite", "payfast", "php"], "support": { "issues": "https://github.com/Payfast/payfast-php-sdk/issues", "source": "https://github.com/Payfast/payfast-php-sdk/tree/v1.1.5" @@ -7592,9 +7110,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Márk Sági-Kazár", @@ -7603,12 +7119,7 @@ ], "description": "Common HTTP Client implementations and tools for HTTPlug", "homepage": "http://httplug.io", - "keywords": [ - "client", - "common", - "http", - "httplug" - ], + "keywords": ["client", "common", "http", "httplug"], "support": { "issues": "https://github.com/php-http/client-common/issues", "source": "https://github.com/php-http/client-common/tree/2.7.1" @@ -7661,14 +7172,10 @@ "psr-4": { "Http\\Discovery\\": "src/" }, - "exclude-from-classmap": [ - "src/Composer/Plugin.php" - ] + "exclude-from-classmap": ["src/Composer/Plugin.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Márk Sági-Kazár", @@ -7734,9 +7241,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Tobias Nyholm", @@ -7745,10 +7250,7 @@ ], "description": "Guzzle 7 HTTP Adapter", "homepage": "http://httplug.io", - "keywords": [ - "Guzzle", - "http" - ], + "keywords": ["Guzzle", "http"], "support": { "issues": "https://github.com/php-http/guzzle7-adapter/issues", "source": "https://github.com/php-http/guzzle7-adapter/tree/1.0.0" @@ -7786,9 +7288,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Eric GELOEN", @@ -7802,10 +7302,7 @@ ], "description": "HTTPlug, the HTTP client abstraction for PHP", "homepage": "http://httplug.io", - "keywords": [ - "client", - "http" - ], + "keywords": ["client", "http"], "support": { "issues": "https://github.com/php-http/httplug/issues", "source": "https://github.com/php-http/httplug/tree/2.4.0" @@ -7851,17 +7348,13 @@ }, "type": "library", "autoload": { - "files": [ - "src/filters.php" - ], + "files": ["src/filters.php"], "psr-4": { "Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Márk Sági-Kazár", @@ -7870,11 +7363,7 @@ ], "description": "HTTP Message related tools", "homepage": "http://php-http.org", - "keywords": [ - "http", - "message", - "psr-7" - ], + "keywords": ["http", "message", "psr-7"], "support": { "issues": "https://github.com/php-http/message/issues", "source": "https://github.com/php-http/message/tree/1.16.0" @@ -7911,9 +7400,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Márk Sági-Kazár", @@ -7922,13 +7409,7 @@ ], "description": "Factory interfaces for PSR-7 HTTP Message", "homepage": "http://php-http.org", - "keywords": [ - "factory", - "http", - "message", - "stream", - "uri" - ], + "keywords": ["factory", "http", "message", "stream", "uri"], "support": { "issues": "https://github.com/php-http/message-factory/issues", "source": "https://github.com/php-http/message-factory/tree/1.1.0" @@ -7964,9 +7445,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Joel Wurtz", @@ -7979,9 +7458,7 @@ ], "description": "Promise used for asynchronous HTTP requests", "homepage": "http://httplug.io", - "keywords": [ - "promise" - ], + "keywords": ["promise"], "support": { "issues": "https://github.com/php-http/promise/issues", "source": "https://github.com/php-http/promise/tree/1.2.1" @@ -8021,9 +7498,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Raphael Stolt", @@ -8033,11 +7508,7 @@ ], "description": "Implementation of JSON Pointer (http://tools.ietf.org/html/rfc6901)", "homepage": "https://github.com/raphaelstolt/php-jsonpointer", - "keywords": [ - "json", - "json pointer", - "json traversal" - ], + "keywords": ["json", "json pointer", "json traversal"], "support": { "issues": "https://github.com/raphaelstolt/php-jsonpointer/issues", "source": "https://github.com/raphaelstolt/php-jsonpointer/tree/master" @@ -8073,9 +7544,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jaap van Otterdijk", @@ -8139,9 +7608,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Mike van Riel", @@ -8219,9 +7686,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Maarten Balliauw", @@ -8297,9 +7762,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "authors": [ { "name": "Johannes M. Schmitt", @@ -8313,12 +7776,7 @@ } ], "description": "Option Type for PHP", - "keywords": [ - "language", - "option", - "php", - "type" - ], + "keywords": ["language", "option", "php", "type"], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" @@ -8366,17 +7824,13 @@ }, "type": "library", "autoload": { - "files": [ - "phpseclib/bootstrap.php" - ], + "files": ["phpseclib/bootstrap.php"], "psr-4": { "phpseclib3\\": "phpseclib/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jim Wigginton", @@ -8476,15 +7930,11 @@ "type": "library", "autoload": { "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] + "PHPStan\\PhpDocParser\\": ["src/"] } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", @@ -8521,9 +7971,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Antonio Carlos Ribeiro", @@ -8576,9 +8024,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Till Krüss", @@ -8588,11 +8034,7 @@ ], "description": "A flexible and feature-complete Redis client for PHP.", "homepage": "http://github.com/predis/predis", - "keywords": [ - "nosql", - "predis", - "redis" - ], + "keywords": ["nosql", "predis", "redis"], "support": { "issues": "https://github.com/predis/predis/issues", "source": "https://github.com/predis/predis/tree/v2.2.2" @@ -8634,9 +8076,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -8644,11 +8084,7 @@ } ], "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], + "keywords": ["cache", "psr", "psr-6"], "support": { "source": "https://github.com/php-fig/cache/tree/3.0.0" }, @@ -8678,9 +8114,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -8689,13 +8123,7 @@ ], "description": "Common interface for reading the clock.", "homepage": "https://github.com/php-fig/clock", - "keywords": [ - "clock", - "now", - "psr", - "psr-20", - "time" - ], + "keywords": ["clock", "now", "psr", "psr-20", "time"], "support": { "issues": "https://github.com/php-fig/clock/issues", "source": "https://github.com/php-fig/clock/tree/1.0.0" @@ -8731,9 +8159,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -8784,9 +8210,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -8794,11 +8218,7 @@ } ], "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], + "keywords": ["events", "psr", "psr-14"], "support": { "issues": "https://github.com/php-fig/event-dispatcher/issues", "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" @@ -8835,9 +8255,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -8846,12 +8264,7 @@ ], "description": "Common interface for HTTP clients", "homepage": "https://github.com/php-fig/http-client", - "keywords": [ - "http", - "http-client", - "psr", - "psr-18" - ], + "keywords": ["http", "http-client", "psr", "psr-18"], "support": { "source": "https://github.com/php-fig/http-client" }, @@ -8887,9 +8300,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -8941,9 +8352,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -8994,9 +8403,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -9005,11 +8412,7 @@ ], "description": "Common interface for logging libraries", "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], + "keywords": ["log", "psr", "psr-3"], "support": { "source": "https://github.com/php-fig/log/tree/3.0.0" }, @@ -9044,9 +8447,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -9054,13 +8455,7 @@ } ], "description": "Common interfaces for simple caching", - "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" - ], + "keywords": ["cache", "caching", "psr", "psr-16", "simple-cache"], "support": { "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" }, @@ -9100,9 +8495,7 @@ "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." }, - "bin": [ - "bin/psysh" - ], + "bin": ["bin/psysh"], "type": "library", "extra": { "branch-alias": { @@ -9114,17 +8507,13 @@ } }, "autoload": { - "files": [ - "src/functions.php" - ], + "files": ["src/functions.php"], "psr-4": { "Psy\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Justin Hileman", @@ -9134,12 +8523,7 @@ ], "description": "An interactive shell for modern PHP.", "homepage": "http://psysh.org", - "keywords": [ - "REPL", - "console", - "interactive", - "shell" - ], + "keywords": ["REPL", "console", "interactive", "shell"], "support": { "issues": "https://github.com/bobthecow/psysh/issues", "source": "https://github.com/bobthecow/psysh/tree/v0.11.22" @@ -9184,9 +8568,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "Library for interacting with the Pusher REST API", "keywords": [ "events", @@ -9230,14 +8612,10 @@ }, "type": "library", "autoload": { - "files": [ - "src/getallheaders.php" - ] + "files": ["src/getallheaders.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ralph Khattar", @@ -9305,9 +8683,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ben Ramsey", @@ -9316,14 +8692,7 @@ } ], "description": "A PHP library for representing and manipulating collections.", - "keywords": [ - "array", - "collection", - "hash", - "map", - "queue", - "set" - ], + "keywords": ["array", "collection", "hash", "map", "queue", "set"], "support": { "issues": "https://github.com/ramsey/collection/issues", "source": "https://github.com/ramsey/collection/tree/2.0.0" @@ -9399,23 +8768,15 @@ } }, "autoload": { - "files": [ - "src/functions.php" - ], + "files": ["src/functions.php"], "psr-4": { "Ramsey\\Uuid\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", - "keywords": [ - "guid", - "identifier", - "uuid" - ], + "keywords": ["guid", "identifier", "uuid"], "support": { "issues": "https://github.com/ramsey/uuid/issues", "source": "https://github.com/ramsey/uuid/tree/4.7.5" @@ -9457,18 +8818,14 @@ }, "type": "library", "autoload": { - "files": [ - "Deprecated.php" - ], + "files": ["Deprecated.php"], "psr-4": { "Razorpay\\Api\\": "src/", "Razorpay\\Tests\\": "tests/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Abhay Rana", @@ -9484,12 +8841,7 @@ ], "description": "Razorpay PHP Client Library", "homepage": "https://docs.razorpay.com", - "keywords": [ - "api", - "client", - "php", - "razorpay" - ], + "keywords": ["api", "client", "php", "razorpay"], "support": { "email": "contact@razorpay.com", "issues": "https://github.com/Razorpay/razorpay-php/issues", @@ -9534,20 +8886,14 @@ }, "type": "library", "autoload": { - "files": [ - "library/Deprecated.php" - ], + "files": ["library/Deprecated.php"], "psr-4": { "WpOrg\\Requests\\": "src/" }, - "classmap": [ - "library/Requests.php" - ] + "classmap": ["library/Requests.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], + "license": ["ISC"], "authors": [ { "name": "Ryan McCue", @@ -9611,17 +8957,13 @@ }, "type": "library", "autoload": { - "files": [ - "lib/functions.php" - ], + "files": ["lib/functions.php"], "psr-4": { "Sabre\\Uri\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Evert Pot", @@ -9632,11 +8974,7 @@ ], "description": "Functions for making sense out of URIs.", "homepage": "http://sabre.io/uri/", - "keywords": [ - "rfc3986", - "uri", - "url" - ], + "keywords": ["rfc3986", "uri", "url"], "support": { "forum": "https://groups.google.com/group/sabredav-discuss", "issues": "https://github.com/sabre-io/uri/issues", @@ -9681,9 +9019,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Evert Pot", @@ -9699,12 +9035,7 @@ ], "description": "sabre/xml is an XML library that you may not hate.", "homepage": "https://sabre.io/xml/", - "keywords": [ - "XMLReader", - "XMLWriter", - "dom", - "xml" - ], + "keywords": ["XMLReader", "XMLWriter", "dom", "xml"], "support": { "forum": "https://groups.google.com/group/sabredav-discuss", "issues": "https://github.com/sabre-io/xml/issues", @@ -9733,9 +9064,7 @@ }, "type": "metapackage", "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Sentry", @@ -9825,17 +9154,13 @@ }, "type": "library", "autoload": { - "files": [ - "src/functions.php" - ], + "files": ["src/functions.php"], "psr-4": { "Sentry\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Sentry", @@ -9924,9 +9249,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Sentry", @@ -9981,14 +9304,10 @@ }, "type": "library", "autoload": { - "classmap": [ - "fpdf.php" - ] + "classmap": ["fpdf.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Olivier Plathey", @@ -9998,10 +9317,7 @@ ], "description": "FPDF is a PHP class which allows to generate PDF files with pure PHP. F from FPDF stands for Free: you may use it for any kind of usage and modify it to suit your needs.", "homepage": "http://www.fpdf.org", - "keywords": [ - "fpdf", - "pdf" - ], + "keywords": ["fpdf", "pdf"], "support": { "source": "https://github.com/Setasign/FPDF/tree/1.8.6" }, @@ -10045,9 +9361,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jan Slabon", @@ -10062,11 +9376,7 @@ ], "description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.", "homepage": "https://www.setasign.com/fpdi", - "keywords": [ - "fpdf", - "fpdi", - "pdf" - ], + "keywords": ["fpdf", "fpdi", "pdf"], "support": { "issues": "https://github.com/Setasign/FPDI/issues", "source": "https://github.com/Setasign/FPDI/tree/v2.6.0" @@ -10115,9 +9425,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Shopify Inc.", @@ -10169,9 +9477,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0" - ], + "license": ["LGPL-3.0"], "authors": [ { "name": "Sebastien MALOT", @@ -10180,13 +9486,7 @@ ], "description": "Pdf parser library. Can read and extract information from pdf file.", "homepage": "https://www.pdfparser.org", - "keywords": [ - "extract", - "parse", - "parser", - "pdf", - "text" - ], + "keywords": ["extract", "parse", "parser", "pdf", "text"], "support": { "issues": "https://github.com/smalot/pdfparser/issues", "source": "https://github.com/smalot/pdfparser/tree/v2.7.0" @@ -10226,9 +9526,7 @@ "SocialiteProviders\\Apple\\": "" } }, - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ahilan", @@ -10302,9 +9600,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Andy Wendt", @@ -10365,9 +9661,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Brian Faust", @@ -10443,9 +9737,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ruben Van Assche", @@ -10455,11 +9747,7 @@ ], "description": "Create unified resources and data transfer objects", "homepage": "https://github.com/spatie/laravel-data", - "keywords": [ - "laravel", - "laravel-data", - "spatie" - ], + "keywords": ["laravel", "laravel-data", "spatie"], "support": { "issues": "https://github.com/spatie/laravel-data/issues", "source": "https://github.com/spatie/laravel-data/tree/3.10.1" @@ -10504,9 +9792,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Freek Van der Herten", @@ -10516,10 +9802,7 @@ ], "description": "Tools for creating Laravel packages", "homepage": "https://github.com/spatie/laravel-package-tools", - "keywords": [ - "laravel-package-tools", - "spatie" - ], + "keywords": ["laravel-package-tools", "spatie"], "support": { "issues": "https://github.com/spatie/laravel-package-tools/issues", "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.1" @@ -10585,9 +9868,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "A PHP library to create Swiss QR bills", "support": { "issues": "https://github.com/sprain/php-swiss-qr-bill/issues", @@ -10634,9 +9915,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Square Developer Platform", @@ -10646,11 +9925,7 @@ ], "description": "Use Square APIs to manage and run business including payment, customer, product, inventory, and employee management.", "homepage": "https://squareup.com/developers", - "keywords": [ - "api", - "sdk", - "square" - ], + "keywords": ["api", "sdk", "square"], "support": { "issues": "https://github.com/square/square-php-sdk/issues", "source": "https://github.com/square/square-php-sdk/tree/30.0.0.20230816" @@ -10694,9 +9969,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Stripe and contributors", @@ -10705,11 +9978,7 @@ ], "description": "Stripe PHP Library", "homepage": "https://stripe.com/", - "keywords": [ - "api", - "payment processing", - "stripe" - ], + "keywords": ["api", "payment processing", "stripe"], "support": { "issues": "https://github.com/stripe/stripe-php/issues", "source": "https://github.com/stripe/stripe-php/tree/v12.8.0" @@ -10765,14 +10034,10 @@ "psr-4": { "Symfony\\Component\\Console\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -10785,12 +10050,7 @@ ], "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], + "keywords": ["cli", "command-line", "console", "terminal"], "support": { "source": "https://github.com/symfony/console/tree/v6.4.1" }, @@ -10812,34 +10072,30 @@ }, { "name": "symfony/css-selector", - "version": "v6.4.0", + "version": "v7.0.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "d036c6c0d0b09e24a14a35f8292146a658f986e4" + "reference": "bb51d46e53ef8d50d523f0c5faedba056a27943e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/d036c6c0d0b09e24a14a35f8292146a658f986e4", - "reference": "d036c6c0d0b09e24a14a35f8292146a658f986e4", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/bb51d46e53ef8d50d523f0c5faedba056a27943e", + "reference": "bb51d46e53ef8d50d523f0c5faedba056a27943e", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\CssSelector\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -10857,7 +10113,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.4.0" + "source": "https://github.com/symfony/css-selector/tree/v7.0.0" }, "funding": [ { @@ -10873,7 +10129,7 @@ "type": "tidelift" } ], - "time": "2023-10-31T08:40:20+00:00" + "time": "2023-10-31T17:59:56+00:00" }, { "name": "symfony/deprecation-contracts", @@ -10903,14 +10159,10 @@ } }, "autoload": { - "files": [ - "function.php" - ] + "files": ["function.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -10970,22 +10222,16 @@ "symfony/http-kernel": "^6.4|^7.0", "symfony/serializer": "^5.4|^6.0|^7.0" }, - "bin": [ - "Resources/bin/patch-type-declarations" - ], + "bin": ["Resources/bin/patch-type-declarations"], "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\ErrorHandler\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -11019,24 +10265,24 @@ }, { "name": "symfony/event-dispatcher", - "version": "v6.4.0", + "version": "v7.0.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6" + "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d76d2632cfc2206eecb5ad2b26cd5934082941b6", - "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c459b40ffe67c49af6fd392aac374c9edf8a027e", + "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -11045,27 +10291,23 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", + "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/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0|^7.0" + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -11079,7 +10321,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/v6.4.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.0" }, "funding": [ { @@ -11095,7 +10337,7 @@ "type": "tidelift" } ], - "time": "2023-07-27T06:52:43+00:00" + "time": "2023-07-27T16:29:09+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -11131,9 +10373,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -11197,14 +10437,10 @@ "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -11261,14 +10497,10 @@ "psr-4": { "Symfony\\Component\\Finder\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -11351,14 +10583,10 @@ "psr-4": { "Symfony\\Component\\HttpClient\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -11371,9 +10599,7 @@ ], "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", - "keywords": [ - "http" - ], + "keywords": ["http"], "support": { "source": "https://github.com/symfony/http-client/tree/v6.4.0" }, @@ -11424,14 +10650,10 @@ "psr-4": { "Symfony\\Contracts\\HttpClient\\": "" }, - "exclude-from-classmap": [ - "/Test/" - ] + "exclude-from-classmap": ["/Test/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -11509,14 +10731,10 @@ "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -11622,14 +10840,10 @@ "psr-4": { "Symfony\\Component\\HttpKernel\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -11663,39 +10877,35 @@ }, { "name": "symfony/intl", - "version": "v6.4.0", + "version": "v7.0.0", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "41d16f0294b9ca6e5540728580c65cfa3848fbf5" + "reference": "a2bf3df1fe6ca7ed9aaf2d3f7d7a33b5529b021d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/41d16f0294b9ca6e5540728580c65cfa3848fbf5", - "reference": "41d16f0294b9ca6e5540728580c65cfa3848fbf5", + "url": "https://api.github.com/repos/symfony/intl/zipball/a2bf3df1fe6ca7ed9aaf2d3f7d7a33b5529b021d", + "reference": "a2bf3df1fe6ca7ed9aaf2d3f7d7a33b5529b021d", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/filesystem": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Intl\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Bernhard Schussek", @@ -11725,7 +10935,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v6.4.0" + "source": "https://github.com/symfony/intl/tree/v7.0.0" }, "funding": [ { @@ -11741,7 +10951,7 @@ "type": "tidelift" } ], - "time": "2023-10-28T23:12:08+00:00" + "time": "2023-10-28T23:12:22+00:00" }, { "name": "symfony/mailer", @@ -11784,14 +10994,10 @@ "psr-4": { "Symfony\\Component\\Mailer\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -11853,14 +11059,10 @@ "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\Mailgun\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -11933,14 +11135,10 @@ "psr-4": { "Symfony\\Component\\Mime\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -11953,10 +11151,7 @@ ], "description": "Allows manipulating MIME messages", "homepage": "https://symfony.com", - "keywords": [ - "mime", - "mime-type" - ], + "keywords": ["mime", "mime-type"], "support": { "source": "https://github.com/symfony/mime/tree/v6.4.0" }, @@ -11978,20 +11173,20 @@ }, { "name": "symfony/options-resolver", - "version": "v6.4.0", + "version": "v7.0.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "22301f0e7fdeaacc14318928612dee79be99860e" + "reference": "700ff4096e346f54cb628ea650767c8130f1001f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22301f0e7fdeaacc14318928612dee79be99860e", - "reference": "22301f0e7fdeaacc14318928612dee79be99860e", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f", + "reference": "700ff4096e346f54cb628ea650767c8130f1001f", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -11999,14 +11194,10 @@ "psr-4": { "Symfony\\Component\\OptionsResolver\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -12019,13 +11210,9 @@ ], "description": "Provides an improved replacement for the array_replace PHP function", "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], + "keywords": ["config", "configuration", "options"], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.4.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.0.0" }, "funding": [ { @@ -12041,7 +11228,7 @@ "type": "tidelift" } ], - "time": "2023-08-08T10:16:24+00:00" + "time": "2023-08-08T10:20:21+00:00" }, { "name": "symfony/polyfill-ctype", @@ -12077,17 +11264,13 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Gert de Pagter", @@ -12100,12 +11283,7 @@ ], "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], + "keywords": ["compatibility", "ctype", "polyfill", "portable"], "support": { "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" }, @@ -12156,17 +11334,13 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -12237,23 +11411,15 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Intl\\Icu\\": "" }, - "classmap": [ - "Resources/stubs" - ], - "exclude-from-classmap": [ - "/Tests/" - ] + "classmap": ["Resources/stubs"], + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -12326,17 +11492,13 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Intl\\Idn\\": "" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Laurent Bassin", @@ -12411,20 +11573,14 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, - "classmap": [ - "Resources/stubs" - ] + "classmap": ["Resources/stubs"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -12498,17 +11654,13 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -12575,17 +11727,13 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Php72\\": "" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -12598,12 +11746,7 @@ ], "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], + "keywords": ["compatibility", "polyfill", "portable", "shim"], "support": { "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0" }, @@ -12651,20 +11794,14 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, - "classmap": [ - "Resources/stubs" - ] + "classmap": ["Resources/stubs"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ion Bazan", @@ -12681,12 +11818,7 @@ ], "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], + "keywords": ["compatibility", "polyfill", "portable", "shim"], "support": { "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" }, @@ -12735,20 +11867,14 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Php83\\": "" }, - "classmap": [ - "Resources/stubs" - ] + "classmap": ["Resources/stubs"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -12761,12 +11887,7 @@ ], "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], + "keywords": ["compatibility", "polyfill", "portable", "shim"], "support": { "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0" }, @@ -12820,17 +11941,13 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Uuid\\": "" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Grégoire Pineau", @@ -12843,12 +11960,7 @@ ], "description": "Symfony polyfill for uuid functions", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "uuid" - ], + "keywords": ["compatibility", "polyfill", "portable", "uuid"], "support": { "source": "https://github.com/symfony/polyfill-uuid/tree/v1.28.0" }, @@ -12899,14 +12011,10 @@ "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\Postmark\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -12960,14 +12068,10 @@ "psr-4": { "Symfony\\Component\\Process\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -13042,14 +12146,10 @@ "psr-4": { "Symfony\\Bridge\\PsrHttpMessage\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -13062,12 +12162,7 @@ ], "description": "PSR HTTP message bridge", "homepage": "http://symfony.com", - "keywords": [ - "http", - "http-message", - "psr-17", - "psr-7" - ], + "keywords": ["http", "http-message", "psr-17", "psr-7"], "support": { "issues": "https://github.com/symfony/psr-http-message-bridge/issues", "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.3.1" @@ -13126,14 +12221,10 @@ "psr-4": { "Symfony\\Component\\Routing\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -13146,12 +12237,7 @@ ], "description": "Maps an HTTP request to a set of configuration variables", "homepage": "https://symfony.com", - "keywords": [ - "router", - "routing", - "uri", - "url" - ], + "keywords": ["router", "routing", "uri", "url"], "support": { "source": "https://github.com/symfony/routing/tree/v6.4.1" }, @@ -13206,14 +12292,10 @@ "psr-4": { "Symfony\\Contracts\\Service\\": "" }, - "exclude-from-classmap": [ - "/Test/" - ] + "exclude-from-classmap": ["/Test/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -13255,20 +12337,20 @@ }, { "name": "symfony/string", - "version": "v6.4.0", + "version": "v7.0.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809" + "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/b45fcf399ea9c3af543a92edf7172ba21174d809", - "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809", + "url": "https://api.github.com/repos/symfony/string/zipball/92bd2bfbba476d4a1838e5e12168bef2fd1e6620", + "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -13278,28 +12360,22 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { - "files": [ - "Resources/functions.php" - ], + "files": ["Resources/functions.php"], "psr-4": { "Symfony\\Component\\String\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -13321,7 +12397,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.0" + "source": "https://github.com/symfony/string/tree/v7.0.0" }, "funding": [ { @@ -13337,7 +12413,7 @@ "type": "tidelift" } ], - "time": "2023-11-28T20:41:49+00:00" + "time": "2023-11-29T08:40:23+00:00" }, { "name": "symfony/translation", @@ -13389,20 +12465,14 @@ }, "type": "library", "autoload": { - "files": [ - "Resources/functions.php" - ], + "files": ["Resources/functions.php"], "psr-4": { "Symfony\\Component\\Translation\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -13465,14 +12535,10 @@ "psr-4": { "Symfony\\Contracts\\Translation\\": "" }, - "exclude-from-classmap": [ - "/Test/" - ] + "exclude-from-classmap": ["/Test/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -13538,14 +12604,10 @@ "psr-4": { "Symfony\\Component\\Uid\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Grégoire Pineau", @@ -13562,11 +12624,7 @@ ], "description": "Provides an object-oriented API to generate and represent UIDs", "homepage": "https://symfony.com", - "keywords": [ - "UID", - "ulid", - "uuid" - ], + "keywords": ["UID", "ulid", "uuid"], "support": { "source": "https://github.com/symfony/uid/tree/v6.4.0" }, @@ -13643,14 +12701,10 @@ "psr-4": { "Symfony\\Component\\Validator\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -13713,25 +12767,17 @@ "symfony/uid": "^5.4|^6.0|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "bin": [ - "Resources/bin/var-dump-server" - ], + "bin": ["Resources/bin/var-dump-server"], "type": "library", "autoload": { - "files": [ - "Resources/functions/dump.php" - ], + "files": ["Resources/functions/dump.php"], "psr-4": { "Symfony\\Component\\VarDumper\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -13744,10 +12790,7 @@ ], "description": "Provides mechanisms for walking through any arbitrary PHP variable", "homepage": "https://symfony.com", - "keywords": [ - "debug", - "dump" - ], + "keywords": ["debug", "dump"], "support": { "source": "https://github.com/symfony/var-dumper/tree/v6.4.0" }, @@ -13792,22 +12835,16 @@ "require-dev": { "symfony/console": "^5.4|^6.0|^7.0" }, - "bin": [ - "Resources/bin/yaml-lint" - ], + "bin": ["Resources/bin/yaml-lint"], "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Yaml\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -13874,9 +12911,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Tijs Verkoyen", @@ -13917,9 +12952,7 @@ "type": "library", "extra": { "laravel": { - "providers": [ - "Turbo124\\Beacon\\CollectorServiceProvider" - ], + "providers": ["Turbo124\\Beacon\\CollectorServiceProvider"], "aliases": { "Beacon": "Turbo124\\Beacon\\CollectorFacade" } @@ -13931,9 +12964,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "David Bomba", @@ -13943,12 +12974,7 @@ ], "description": "Application level data collector package for laravel", "homepage": "https://github.com/turbo124/beacon", - "keywords": [ - "beacon", - "light logs", - "lightlogs", - "turbo124" - ], + "keywords": ["beacon", "light logs", "lightlogs", "turbo124"], "support": { "source": "https://github.com/turbo124/beacon/tree/v1.5.2" }, @@ -13981,14 +13007,10 @@ "psr-4": { "Twig\\Extra\\Intl\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -13999,10 +13021,7 @@ ], "description": "A Twig extension for Intl", "homepage": "https://twig.symfony.com", - "keywords": [ - "intl", - "twig" - ], + "keywords": ["intl", "twig"], "support": { "source": "https://github.com/twigphp/intl-extra/tree/v3.8.0" }, @@ -14049,9 +13068,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Fabien Potencier", @@ -14071,9 +13088,7 @@ ], "description": "Twig, the flexible, fast, and secure template language for PHP", "homepage": "https://twig.symfony.com", - "keywords": [ - "templating" - ], + "keywords": ["templating"], "support": { "issues": "https://github.com/twigphp/Twig/issues", "source": "https://github.com/twigphp/Twig/tree/v3.8.0" @@ -14121,9 +13136,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Twilio API Team", @@ -14132,11 +13145,7 @@ ], "description": "A PHP wrapper for Twilio's API", "homepage": "https://github.com/twilio/twilio-php", - "keywords": [ - "api", - "sms", - "twilio" - ], + "keywords": ["api", "sms", "twilio"], "time": "2023-02-22T19:59:53+00:00" }, { @@ -14186,9 +13195,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Graham Campbell", @@ -14202,11 +13209,7 @@ } ], "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", - "keywords": [ - "dotenv", - "env", - "environment" - ], + "keywords": ["dotenv", "env", "environment"], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0" @@ -14253,9 +13256,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Lars Moelleken", @@ -14264,11 +13265,7 @@ ], "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", "homepage": "https://github.com/voku/portable-ascii", - "keywords": [ - "ascii", - "clean", - "php" - ], + "keywords": ["ascii", "clean", "php"], "support": { "issues": "https://github.com/voku/portable-ascii/issues", "source": "https://github.com/voku/portable-ascii/tree/2.0.1" @@ -14334,9 +13331,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Bernhard Schussek", @@ -14344,11 +13339,7 @@ } ], "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], + "keywords": ["assert", "check", "validate"], "support": { "issues": "https://github.com/webmozarts/assert/issues", "source": "https://github.com/webmozarts/assert/tree/1.11.0" @@ -14388,14 +13379,10 @@ "psr-0": { "Webpatser\\Countries": "src/" }, - "classmap": [ - "src/commands" - ] + "classmap": ["src/commands"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Christoph Kempen", @@ -14410,12 +13397,7 @@ ], "description": "Laravel Countries is a bundle for Laravel, providing Almost ISO 3166_2, 3166_3, currency, Capital and more for all countries.", "homepage": "https://github.com/webpatser/laravel-countries", - "keywords": [ - "countries", - "iso_3166_2", - "iso_3166_3", - "laravel" - ], + "keywords": ["countries", "iso_3166_2", "iso_3166_3", "laravel"], "support": { "issues": "https://github.com/webpatser/laravel-countries/issues", "source": "https://github.com/webpatser/laravel-countries" @@ -14447,14 +13429,10 @@ } }, "autoload": { - "classmap": [ - "wepay.php" - ] + "classmap": ["wepay.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "authors": [ { "name": "WePay", @@ -14462,11 +13440,7 @@ } ], "description": "WePay APIv2 SDK for PHP", - "keywords": [ - "payment", - "sdk", - "wepay" - ], + "keywords": ["payment", "sdk", "wepay"], "support": { "issues": "https://github.com/wepay/PHP-SDK/issues", "source": "https://github.com/wepay/PHP-SDK/tree/master" @@ -14501,9 +13475,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "The officially supported client for Postmark (http://postmarkapp.com)", "support": { "issues": "https://github.com/ActiveCampaign/postmark-php/issues", @@ -14547,26 +13519,20 @@ "dev-master": "3.8-dev" }, "laravel": { - "providers": [ - "Barryvdh\\Debugbar\\ServiceProvider" - ], + "providers": ["Barryvdh\\Debugbar\\ServiceProvider"], "aliases": { "Debugbar": "Barryvdh\\Debugbar\\Facades\\Debugbar" } } }, "autoload": { - "files": [ - "src/helpers.php" - ], + "files": ["src/helpers.php"], "psr-4": { "Barryvdh\\Debugbar\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Barry vd. Heuvel", @@ -14654,9 +13620,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Barry vd. Heuvel", @@ -14723,15 +13687,11 @@ }, "autoload": { "psr-0": { - "Barryvdh": [ - "src/" - ] + "Barryvdh": ["src/"] } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Mike van Riel", @@ -14793,15 +13753,11 @@ "type": "library", "autoload": { "psr-4": { - "ParaTest\\": [ - "src/" - ] + "ParaTest\\": ["src/"] } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Brian Scaturro", @@ -14816,12 +13772,7 @@ ], "description": "Parallel testing for PHP", "homepage": "https://github.com/paratestphp/paratest", - "keywords": [ - "concurrent", - "parallel", - "phpunit", - "testing" - ], + "keywords": ["concurrent", "parallel", "phpunit", "testing"], "support": { "issues": "https://github.com/paratestphp/paratest/issues", "source": "https://github.com/paratestphp/paratest/tree/v7.3.1" @@ -14877,9 +13828,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jordi Boggiano", @@ -14888,9 +13837,7 @@ } ], "description": "Utilities to scan PHP code and generate class maps.", - "keywords": [ - "classmap" - ], + "keywords": ["classmap"], "support": { "issues": "https://github.com/composer/class-map-generator/issues", "source": "https://github.com/composer/class-map-generator/tree/1.1.0" @@ -14945,9 +13892,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jordi Boggiano", @@ -14956,12 +13901,7 @@ } ], "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], + "keywords": ["PCRE", "preg", "regex", "regular expression"], "support": { "issues": "https://github.com/composer/pcre/issues", "source": "https://github.com/composer/pcre/tree/3.1.1" @@ -15015,9 +13955,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nils Adermann", @@ -15036,12 +13974,7 @@ } ], "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], + "keywords": ["semantic", "semver", "validation", "versioning"], "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", @@ -15094,9 +14027,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "John Stevenson", @@ -15104,10 +14035,7 @@ } ], "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], + "keywords": ["Xdebug", "performance"], "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", @@ -15164,9 +14092,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Théo FIDRY", @@ -15174,10 +14100,7 @@ } ], "description": "Tiny utility to get the number of CPU cores.", - "keywords": [ - "CPU", - "core" - ], + "keywords": ["CPU", "core"], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", "source": "https://github.com/theofidry/cpu-core-counter/tree/1.0.0" @@ -15229,9 +14152,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Filipe Dobreira", @@ -15310,9 +14231,7 @@ "ext-dom": "For handling output formats in XML", "ext-mbstring": "For handling non-UTF8 characters." }, - "bin": [ - "php-cs-fixer" - ], + "bin": ["php-cs-fixer"], "type": "application", "autoload": { "psr-4": { @@ -15320,9 +14239,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -15385,18 +14302,12 @@ } }, "autoload": { - "classmap": [ - "hamcrest" - ] + "classmap": ["hamcrest"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "description": "This is the PHP port of Hamcrest Matchers", - "keywords": [ - "test" - ], + "keywords": ["test"], "support": { "issues": "https://github.com/hamcrest/hamcrest-php/issues", "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" @@ -15429,9 +14340,7 @@ "type": "library", "extra": { "laravel": { - "providers": [ - "Laracasts\\Cypress\\CypressServiceProvider" - ] + "providers": ["Laracasts\\Cypress\\CypressServiceProvider"] } }, "autoload": { @@ -15440,9 +14349,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jeffrey Way", @@ -15452,10 +14359,7 @@ ], "description": "Laravel Cypress Boilerplate", "homepage": "https://github.com/laracasts/cypress", - "keywords": [ - "cypress", - "laracasts" - ], + "keywords": ["cypress", "laracasts"], "support": { "issues": "https://github.com/laracasts/cypress/issues", "source": "https://github.com/laracasts/cypress/tree/3.0.1" @@ -15504,9 +14408,7 @@ "dev-master": "2.0-dev" }, "phpstan": { - "includes": [ - "extension.neon" - ] + "includes": ["extension.neon"] } }, "autoload": { @@ -15515,9 +14417,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Can Vural", @@ -15603,9 +14503,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Maxime Bouroumeau-Fuseau", @@ -15619,10 +14517,7 @@ ], "description": "Debug bar in the browser for php application", "homepage": "https://github.com/maximebf/php-debugbar", - "keywords": [ - "debug", - "debugbar" - ], + "keywords": ["debug", "debugbar"], "support": { "issues": "https://github.com/maximebf/php-debugbar/issues", "source": "https://github.com/maximebf/php-debugbar/tree/v1.19.1" @@ -15657,18 +14552,13 @@ }, "type": "library", "autoload": { - "files": [ - "library/helpers.php", - "library/Mockery.php" - ], + "files": ["library/helpers.php", "library/Mockery.php"], "psr-4": { "Mockery\\": "library/Mockery" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Pádraic Brady", @@ -15740,17 +14630,13 @@ }, "type": "library", "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], + "files": ["src/DeepCopy/deep_copy.php"], "psr-4": { "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "Create deep copies (clones) of your objects", "keywords": [ "clone", @@ -15817,17 +14703,13 @@ } }, "autoload": { - "files": [ - "./src/Adapters/Phpunit/Autoload.php" - ], + "files": ["./src/Adapters/Phpunit/Autoload.php"], "psr-4": { "NunoMaduro\\Collision\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nuno Maduro", @@ -15895,14 +14777,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Arne Blankerts", @@ -15946,14 +14824,10 @@ }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Arne Blankerts", @@ -16029,9 +14903,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-2.0-or-later" - ], + "license": ["GPL-2.0-or-later"], "authors": [ { "name": "The phpMyAdmin Team", @@ -16085,25 +14957,15 @@ "conflict": { "phpstan/phpstan-shim": "*" }, - "bin": [ - "phpstan", - "phpstan.phar" - ], + "bin": ["phpstan", "phpstan.phar"], "type": "library", "autoload": { - "files": [ - "bootstrap.php" - ] + "files": ["bootstrap.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], + "keywords": ["dev", "static analysis"], "support": { "docs": "https://phpstan.org/user-guide/getting-started", "forum": "https://github.com/phpstan/phpstan/discussions", @@ -16170,14 +15032,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16187,11 +15045,7 @@ ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], + "keywords": ["coverage", "testing", "xunit"], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", @@ -16232,14 +15086,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16249,10 +15099,7 @@ ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], + "keywords": ["filesystem", "iterator"], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", @@ -16297,14 +15144,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16314,9 +15157,7 @@ ], "description": "Invoke callables with a timeout", "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], + "keywords": ["process"], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" @@ -16356,14 +15197,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16373,9 +15210,7 @@ ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], + "keywords": ["template"], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", @@ -16416,14 +15251,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16433,9 +15264,7 @@ ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], + "keywords": ["timer"], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" @@ -16493,9 +15322,7 @@ "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" }, - "bin": [ - "phpunit" - ], + "bin": ["phpunit"], "type": "library", "extra": { "branch-alias": { @@ -16503,17 +15330,11 @@ } }, "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] + "files": ["src/Framework/Assert/Functions.php"], + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16523,11 +15344,7 @@ ], "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], + "keywords": ["phpunit", "testing", "xunit"], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", @@ -16576,14 +15393,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16632,14 +15445,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16688,14 +15497,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16747,14 +15552,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16775,11 +15576,7 @@ ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], + "keywords": ["comparator", "compare", "equality"], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", @@ -16821,14 +15618,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16879,14 +15672,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16899,12 +15688,7 @@ ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], + "keywords": ["diff", "udiff", "unidiff", "unified diff"], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", @@ -16948,14 +15732,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -16964,11 +15744,7 @@ ], "description": "Provides functionality to handle HHVM/PHP environments", "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], + "keywords": ["Xdebug", "environment", "hhvm"], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", @@ -17011,14 +15787,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -17043,10 +15815,7 @@ ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], + "keywords": ["export", "exporter"], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", @@ -17090,14 +15859,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -17106,9 +15871,7 @@ ], "description": "Snapshotting of global state", "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], + "keywords": ["global state"], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", @@ -17150,14 +15913,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -17209,14 +15968,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -17264,14 +16019,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -17319,14 +16070,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -17382,14 +16129,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -17435,14 +16178,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -17494,9 +16233,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Freek Van de Herten", @@ -17507,10 +16244,7 @@ ], "description": "A better backtrace", "homepage": "https://github.com/spatie/backtrace", - "keywords": [ - "Backtrace", - "spatie" - ], + "keywords": ["Backtrace", "spatie"], "support": { "source": "https://github.com/spatie/backtrace/tree/1.5.3" }, @@ -17565,25 +16299,16 @@ } }, "autoload": { - "files": [ - "src/helpers.php" - ], + "files": ["src/helpers.php"], "psr-4": { "Spatie\\FlareClient\\": "src" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "Send PHP errors to Flare", "homepage": "https://github.com/spatie/flare-client-php", - "keywords": [ - "exception", - "flare", - "reporting", - "spatie" - ], + "keywords": ["exception", "flare", "reporting", "spatie"], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", "source": "https://github.com/spatie/flare-client-php/tree/1.4.3" @@ -17647,9 +16372,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Spatie", @@ -17659,12 +16382,7 @@ ], "description": "A beautiful error page for PHP applications.", "homepage": "https://flareapp.io/ignition", - "keywords": [ - "error", - "flare", - "laravel", - "page" - ], + "keywords": ["error", "flare", "laravel", "page"], "support": { "docs": "https://flareapp.io/docs/ignition-for-laravel/introduction", "forum": "https://twitter.com/flareappio", @@ -17731,17 +16449,13 @@ } }, "autoload": { - "files": [ - "src/helpers.php" - ], + "files": ["src/helpers.php"], "psr-4": { "Spatie\\LaravelIgnition\\": "src" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Spatie", @@ -17751,12 +16465,7 @@ ], "description": "A beautiful error page for Laravel applications.", "homepage": "https://flareapp.io/ignition", - "keywords": [ - "error", - "flare", - "laravel", - "page" - ], + "keywords": ["error", "flare", "laravel", "page"], "support": { "docs": "https://flareapp.io/docs/ignition-for-laravel/introduction", "forum": "https://twitter.com/flareappio", @@ -17802,9 +16511,7 @@ "type": "phpstan-extension", "extra": { "phpstan": { - "includes": [ - "extension.neon" - ] + "includes": ["extension.neon"] } }, "autoload": { @@ -17813,9 +16520,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Michal Špaček", @@ -17824,9 +16529,7 @@ } ], "description": "Stripe SDK extension for PHPStan", - "keywords": [ - "static analysis" - ], + "keywords": ["static analysis"], "support": { "issues": "https://github.com/spaze/phpstan-stripe/issues", "source": "https://github.com/spaze/phpstan-stripe/tree/v3.1.0" @@ -17861,20 +16564,14 @@ } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Php81\\": "" }, - "classmap": [ - "Resources/stubs" - ] + "classmap": ["Resources/stubs"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -17887,12 +16584,7 @@ ], "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], + "keywords": ["compatibility", "polyfill", "portable", "shim"], "support": { "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" }, @@ -17914,20 +16606,20 @@ }, { "name": "symfony/stopwatch", - "version": "v6.4.0", + "version": "v7.0.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2" + "reference": "7bbfa3dd564a0ce12eb4acaaa46823c740f9cb7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", - "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/7bbfa3dd564a0ce12eb4acaaa46823c740f9cb7a", + "reference": "7bbfa3dd564a0ce12eb4acaaa46823c740f9cb7a", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/service-contracts": "^2.5|^3" }, "type": "library", @@ -17935,14 +16627,10 @@ "psr-4": { "Symfony\\Component\\Stopwatch\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -17956,7 +16644,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.4.0" + "source": "https://github.com/symfony/stopwatch/tree/v7.0.0" }, "funding": [ { @@ -17972,7 +16660,7 @@ "type": "tidelift" } ], - "time": "2023-02-16T10:14:28+00:00" + "time": "2023-07-05T13:06:06+00:00" }, { "name": "theseer/tokenizer", @@ -17996,14 +16684,10 @@ }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Arne Blankerts", @@ -18042,5 +16726,5 @@ "platform-dev": { "php": "^8.1|^8.2" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/config/ninja.php b/config/ninja.php index aade77cb0f13..b4fc5bdc2aa9 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -7,7 +7,7 @@ return [ 'license_url' => 'https://app.invoiceninja.com', 'react_url' => env('REACT_URL', 'https://app.invoicing.co'), 'production' => env('NINJA_PROD', false), - 'license' => env('NINJA_LICENSE', ''), + 'license' => env('NINJA_LICENSE', ''), 'version_url' => 'https://pdf.invoicing.co/api/version', 'app_name' => env('APP_NAME', 'Invoice Ninja'), 'app_env' => env('APP_ENV', 'selfhosted'), @@ -86,7 +86,7 @@ return [ 'password' => 'password', 'stripe' => env('STRIPE_KEYS', ''), 'paypal' => env('PAYPAL_KEYS', ''), - 'ppcp' => env('PPCP_KEYS', ''), + 'ppcp' => env('PPCP_KEYS', ''), 'paypal_rest' => env('PAYPAL_REST_KEYS', ''), 'authorize' => env('AUTHORIZE_KEYS', ''), 'checkout' => env('CHECKOUT_KEYS', ''), @@ -196,7 +196,7 @@ return [ 'ninja_default_company_id' => env('NINJA_COMPANY_ID', null), 'ninja_default_company_gateway_id' => env('NINJA_COMPANY_GATEWAY_ID', null), 'ninja_hosted_secret' => env('NINJA_HOSTED_SECRET', ''), - 'ninja_hosted_header' =>env('NINJA_HEADER', ''), + 'ninja_hosted_header' => env('NINJA_HEADER', ''), 'ninja_connect_secret' => env('NINJA_CONNECT_SECRET', ''), 'internal_queue_enabled' => env('INTERNAL_QUEUE_ENABLED', true), 'ninja_apple_api_key' => env('APPLE_API_KEY', false), @@ -218,6 +218,11 @@ return [ 'dev_mode' => env("YODLEE_DEV_MODE", false), 'config_name' => env("YODLEE_CONFIG_NAME", false), ], + 'nordigen' => [ + 'secret_id' => env('NORDIGEN_SECRET_ID', false), + 'secret_key' => env('NORDIGEN_SECRET_KEY', false), + 'test_mode' => env("NORDIGEN_TEST_MODE", false), + ], 'licenses' => env('LICENSES', false), 'google_application_credentials' => env("GOOGLE_APPLICATION_CREDENTIALS", false), 'shopify' => [ diff --git a/database/factories/BankIntegrationFactory.php b/database/factories/BankIntegrationFactory.php index 2cc88e5f7ad8..515015d36311 100644 --- a/database/factories/BankIntegrationFactory.php +++ b/database/factories/BankIntegrationFactory.php @@ -23,6 +23,7 @@ class BankIntegrationFactory extends Factory public function definition() { return [ + 'integration_type' => null, 'provider_name' => $this->faker->company(), 'provider_id' => 1, 'bank_account_name' => $this->faker->catchPhrase(), diff --git a/database/migrations/2023_11_26_082959_add_bank_integration_id.php b/database/migrations/2023_11_26_082959_add_bank_integration_id.php new file mode 100644 index 000000000000..ea3517bcd28f --- /dev/null +++ b/database/migrations/2023_11_26_082959_add_bank_integration_id.php @@ -0,0 +1,46 @@ +string('integration_type')->nullable(); + $table->string('nordigen_account_id')->nullable(); + $table->string('nordigen_institution_id')->nullable(); + }); + + // migrate old account to be used with yodlee + BankIntegration::query()->whereNull('integration_type')->whereNotNull('account_id')->cursor()->each(function ($bank_integration) { + $bank_integration->integration_type = BankIntegration::INTEGRATION_TYPE_YODLEE; + $bank_integration->save(); + }); + + // MAYBE migration of account->bank_account_id etc + Schema::table('bank_transactions', function (Blueprint $table) { + $table->string('participant')->nullable(); // iban, credit-card info or else + $table->string('participant_name')->nullable(); // name + }); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +}; diff --git a/lang/de/texts.php b/lang/de/texts.php index 3bf53d2dbd76..9e0731882600 100644 --- a/lang/de/texts.php +++ b/lang/de/texts.php @@ -96,7 +96,7 @@ $lang = array( 'powered_by' => 'Unterstützt durch', 'no_items' => 'Keine Elemente', 'recurring_invoices' => 'Wiederkehrende Rechnungen', - 'recurring_help' => '
Senden Sie Ihren Kunden automatisch die gleichen Rechnungen wöchentlich, zweimonatlich, monatlich, vierteljährlich oder jährlich zu.
+ 'recurring_help' => 'Senden Sie Ihren Kunden automatisch die gleichen Rechnungen wöchentlich, zweimonatlich, monatlich, vierteljährlich oder jährlich zu.
Verwenden Sie :MONTH, :QUARTER oder :YEAR für dynamische Daten. Grundlegende Mathematik funktioniert auch, zum Beispiel :MONTH-1.
Beispiele für dynamische Rechnungsvariablen: