From f16e8fdd1572c3ae6fecae36eb3b633fe849711b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 7 Feb 2024 07:42:46 +1100 Subject: [PATCH] Fixes for KRW currency formatting --- app/Http/Controllers/ImportController.php | 12 +- .../Transformer/Csv/TaskTransformer.php | 7 +- app/Jobs/Company/CompanyExport.php | 291 ++++++- app/Jobs/Company/CompanyImport.php | 33 +- app/Jobs/Mail/NinjaMailerJob.php | 35 +- .../Quote/QuoteCreatedNotification.php | 1 + app/Models/CompanyUser.php | 2 +- app/Models/Credit.php | 2 +- app/Models/Document.php | 2 +- app/Services/Email/Email.php | 32 +- app/Utils/HtmlEngine.php | 2 +- composer.json | 2 +- composer.lock | 708 ++++-------------- config/services.php | 4 + ..._06_204031_correction_for_krw_currency.php | 31 + database/seeders/CurrenciesSeeder.php | 2 +- phpstan.neon | 30 - phpunit.xml | 31 - resources/views/email/admin/generic.blade.php | 2 +- .../views/email/template/admin.blade.php | 8 + .../views/email/template/plain.blade.php | 6 +- resources/views/pdf-designs/tech.html | 4 +- tests/Feature/Import/CSV/TaskImportTest.php | 4 +- 23 files changed, 559 insertions(+), 692 deletions(-) create mode 100644 database/migrations/2024_02_06_204031_correction_for_krw_currency.php delete mode 100644 phpstan.neon delete mode 100644 phpunit.xml diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php index 8c0902eb7f4f..edd51d5d6fb2 100644 --- a/app/Http/Controllers/ImportController.php +++ b/app/Http/Controllers/ImportController.php @@ -244,19 +244,23 @@ class ImportController extends Controller */ public function detectDelimiter($csvfile): string { - $delimiters = [',', '.', ';']; - $bestDelimiter = ' '; + + $delimiters = [',', '.', ';', '|']; + $bestDelimiter = ','; $count = 0; + // 10-01-2024 - A better way to resolve the csv file delimiter. + $csvfile = substr($csvfile, 0, strpos($csvfile, "\n")); + foreach ($delimiters as $delimiter) { if (substr_count(strstr($csvfile, "\n", true), $delimiter) >= $count) { - $count = substr_count(strstr($csvfile, "\n", true), $delimiter); + $count = substr_count($csvfile, $delimiter); $bestDelimiter = $delimiter; } } - return $bestDelimiter; + } } diff --git a/app/Import/Transformer/Csv/TaskTransformer.php b/app/Import/Transformer/Csv/TaskTransformer.php index c46e218a1948..cfe44f7676c4 100644 --- a/app/Import/Transformer/Csv/TaskTransformer.php +++ b/app/Import/Transformer/Csv/TaskTransformer.php @@ -63,7 +63,6 @@ class TaskTransformer extends BaseTransformer $time_log = collect($task_items_data) ->map(function ($item) { - return $this->parseLog($item); })->toJson(); @@ -80,10 +79,10 @@ class TaskTransformer extends BaseTransformer $notes = $item['task.notes'] ?? ''; - if(isset($item['task.is_billable']) && is_string($item['task.is_billable']) && in_array($item['task.is_billable'], ['yes', 'true', '1'])) { + if(isset($item['task.billable']) && is_string($item['task.billable']) && in_array($item['task.billable'], ['yes', 'true', '1', 'TRUE', 'YES'])) { $is_billable = true; - } elseif(isset($item['task.is_billable']) && is_bool($item['task.is_billable'])) { - $is_billable = $item['task.is_billable']; + } elseif(isset($item['task.billable']) && is_bool($item['task.billable'])) { + $is_billable = $item['task.billable']; } else { $is_billable = false; } diff --git a/app/Jobs/Company/CompanyExport.php b/app/Jobs/Company/CompanyExport.php index 454f82347eb8..fd71232d2cc8 100644 --- a/app/Jobs/Company/CompanyExport.php +++ b/app/Jobs/Company/CompanyExport.php @@ -34,6 +34,7 @@ use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Storage; +use Hyvor\JsonExporter\File; class CompanyExport implements ShouldQueue { @@ -46,8 +47,8 @@ class CompanyExport implements ShouldQueue private $export_format = 'json'; private $export_data = []; - - + private $writer; + private $file_name; /** * Create a new job instance. * @@ -67,13 +68,23 @@ class CompanyExport implements ShouldQueue public function handle() { MultiDB::setDb($this->company->db); - nlog("starting export"); - + + + $this->file_name = date('Y-m-d') . '_' . str_replace([" ", "/"], ["_",""], $this->company->present()->name() . '_' . $this->company->company_key . '.json'); + +$this->writer = new File($this->file_name); + +$info = $this->writer->collection(''); + + + set_time_limit(0); $this->export_data['app_version'] = config('ninja.app_version'); $this->export_data['storage_url'] = Storage::url(''); - + +$info->addItems($this->export_data); + $this->export_data['activities'] = $this->company->all_activities->map(function ($activity) { $activity = $this->transformArrayOfKeys($activity, [ 'user_id', @@ -98,27 +109,21 @@ class CompanyExport implements ShouldQueue return $activity; })->makeHidden(['id'])->all(); - // $this->export_data['backups'] = $this->company->all_activities()->with('backup')->cursor()->map(function ($activity){ - // $backup = $activity->backup; +$x = $this->writer->collection('activities'); +$x->addItems($this->export_data['activities']); +$this->export_data = null; - // if(!$backup) - // return; - - // $backup->activity_id = $this->encodePrimaryKey($backup->activity_id); - - // return $backup; - - // })->all(); $this->export_data['users'] = $this->company->users()->withTrashed()->cursor()->map(function ($user) { $user->account_id = $this->encodePrimaryKey($user->account_id); - // $user->id = $this->encodePrimaryKey($user->id); - - return $user->makeVisible(['id']); })->all(); +$x = $this->writer->collection('users'); +$x->addItems($this->export_data['users']); +$this->export_data = null; + $this->export_data['client_contacts'] = $this->company->client_contacts->map(function ($client_contact) { $client_contact = $this->transformArrayOfKeys($client_contact, ['company_id', 'user_id', 'client_id']); @@ -138,6 +143,10 @@ class CompanyExport implements ShouldQueue })->all(); +$x = $this->writer->collection('client_contacts'); +$x->addItems($this->export_data['client_contacts']); +$this->export_data = null; + $this->export_data['client_gateway_tokens'] = $this->company->client_gateway_tokens->map(function ($client_gateway_token) { $client_gateway_token = $this->transformArrayOfKeys($client_gateway_token, ['company_id', 'client_id', 'company_gateway_id']); @@ -145,6 +154,10 @@ class CompanyExport implements ShouldQueue })->all(); +$x = $this->writer->collection('client_gateway_tokens'); +$x->addItems($this->export_data['client_gateway_tokens']); +$this->export_data = null; + $this->export_data['clients'] = $this->company->clients()->orderBy('number', 'DESC')->cursor()->map(function ($client) { $client = $this->transformArrayOfKeys($client, ['company_id', 'user_id', 'assigned_user_id', 'group_settings_id']); $client->tax_data = ''; @@ -152,9 +165,20 @@ class CompanyExport implements ShouldQueue })->all(); +$x = $this->writer->collection('clients'); +$x->addItems($this->export_data['clients']); +$this->export_data = null; + $this->export_data['company'] = $this->company->toArray(); $this->export_data['company']['company_key'] = $this->createHash(); + + +$x = $this->writer->collection('company'); +$x->addItems($this->export_data['company']); +$this->export_data = null; + + $this->export_data['company_gateways'] = $this->company->company_gateways()->withTrashed()->cursor()->map(function ($company_gateway) { $company_gateway = $this->transformArrayOfKeys($company_gateway, ['company_id', 'user_id']); $company_gateway->config = decrypt($company_gateway->config); @@ -162,25 +186,49 @@ class CompanyExport implements ShouldQueue return $company_gateway->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('company_gateways'); +$x->addItems($this->export_data['company_gateways']); +$this->export_data = null; + + + + $this->export_data['company_tokens'] = $this->company->tokens->map(function ($token) { $token = $this->transformArrayOfKeys($token, ['company_id', 'account_id', 'user_id']); return $token; })->all(); + +$x = $this->writer->collection('company_tokens'); +$x->addItems($this->export_data['company_tokens']); +$this->export_data = null; + + $this->export_data['company_ledger'] = $this->company->ledger->map(function ($ledger) { $ledger = $this->transformArrayOfKeys($ledger, ['activity_id', 'client_id', 'company_id', 'account_id', 'user_id','company_ledgerable_id']); return $ledger; })->all(); + +$x = $this->writer->collection('company_ledger'); +$x->addItems($this->export_data['company_ledger']); +$this->export_data = null; + + $this->export_data['company_users'] = $this->company->company_users()->without(['user','account'])->cursor()->map(function ($company_user) { $company_user = $this->transformArrayOfKeys($company_user, ['company_id', 'account_id', 'user_id']); - - // return $company_user->makeHidden(['react_settings']); return $company_user; })->all(); + +$x = $this->writer->collection('company_users'); +$x->addItems($this->export_data['company_users']); +$this->export_data = null; + + $this->export_data['credits'] = $this->company->credits()->orderBy('number', 'DESC')->cursor()->map(function ($credit) { $credit = $this->transformBasicEntities($credit); $credit = $this->transformArrayOfKeys($credit, ['recurring_id','client_id', 'vendor_id', 'project_id', 'design_id', 'subscription_id','invoice_id']); @@ -188,6 +236,10 @@ class CompanyExport implements ShouldQueue return $credit->makeVisible(['id']); })->all(); +$x = $this->writer->collection('credits'); +$x->addItems($this->export_data['credits']); +$this->export_data = null; + $this->export_data['credit_invitations'] = CreditInvitation::query()->where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($credit) { $credit = $this->transformArrayOfKeys($credit, ['company_id', 'user_id', 'client_contact_id', 'credit_id']); @@ -195,8 +247,20 @@ class CompanyExport implements ShouldQueue return $credit->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('credit_invitations'); +$x->addItems($this->export_data['credit_invitations']); +$this->export_data = null; + + $this->export_data['designs'] = $this->company->user_designs->makeHidden(['id'])->all(); + +$x = $this->writer->collection('designs'); +$x->addItems($this->export_data['designs']); +$this->export_data = null; + + $this->export_data['documents'] = $this->company->all_documents->map(function ($document) { $document = $this->transformArrayOfKeys($document, ['user_id', 'assigned_user_id', 'company_id', 'project_id', 'vendor_id','documentable_id']); $document->hashed_id = $this->encodePrimaryKey($document->id); @@ -204,12 +268,20 @@ class CompanyExport implements ShouldQueue return $document->makeVisible(['id']); })->all(); +$x = $this->writer->collection('documents'); +$x->addItems($this->export_data['documents']); +$this->export_data = null; + $this->export_data['expense_categories'] = $this->company->expense_categories()->cursor()->map(function ($expense_category) { $expense_category = $this->transformArrayOfKeys($expense_category, ['user_id', 'company_id']); return $expense_category->makeVisible(['id']); })->all(); +$x = $this->writer->collection('expense_categories'); +$x->addItems($this->export_data['expense_categories']); +$this->export_data = null; + $this->export_data['expenses'] = $this->company->expenses()->orderBy('number', 'DESC')->cursor()->map(function ($expense) { $expense = $this->transformBasicEntities($expense); @@ -218,12 +290,23 @@ class CompanyExport implements ShouldQueue return $expense->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('expenses'); +$x->addItems($this->export_data['expenses']); +$this->export_data = null; + + $this->export_data['group_settings'] = $this->company->group_settings->map(function ($gs) { $gs = $this->transformArrayOfKeys($gs, ['user_id', 'company_id']); return $gs->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('group_settings'); +$x->addItems($this->export_data['group_settings']); +$this->export_data = null; + $this->export_data['invoices'] = $this->company->invoices()->orderBy('number', 'DESC')->cursor()->map(function ($invoice) { $invoice = $this->transformBasicEntities($invoice); @@ -238,18 +321,33 @@ class CompanyExport implements ShouldQueue })->all(); +$x = $this->writer->collection('invoices'); +$x->addItems($this->export_data['invoices']); +$this->export_data = null; + $this->export_data['invoice_invitations'] = InvoiceInvitation::query()->where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($invoice) { $invoice = $this->transformArrayOfKeys($invoice, ['company_id', 'user_id', 'client_contact_id', 'invoice_id']); return $invoice->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('invoice_invitations'); +$x->addItems($this->export_data['invoice_invitations']); +$this->export_data = null; + + $this->export_data['payment_terms'] = $this->company->user_payment_terms->map(function ($term) { $term = $this->transformArrayOfKeys($term, ['user_id', 'company_id']); return $term; })->makeHidden(['id'])->all(); + +$x = $this->writer->collection('payment_terms'); +$x->addItems($this->export_data['payment_terms']); +$this->export_data = null; + $this->export_data['payments'] = $this->company->payments()->orderBy('number', 'DESC')->cursor()->map(function ($payment) { $payment = $this->transformBasicEntities($payment); @@ -260,6 +358,13 @@ class CompanyExport implements ShouldQueue return $payment->makeVisible(['id']); })->all(); + + +$x = $this->writer->collection('payments'); +$x->addItems($this->export_data['payments']); +$this->export_data = null; + + $this->export_data['products'] = $this->company->products->map(function ($product) { $product = $this->transformBasicEntities($product); $product = $this->transformArrayOfKeys($product, ['vendor_id','project_id']); @@ -267,6 +372,12 @@ class CompanyExport implements ShouldQueue return $product->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('products'); +$x->addItems($this->export_data['products']); +$this->export_data = null; + + $this->export_data['projects'] = $this->company->projects()->orderBy('number', 'DESC')->cursor()->map(function ($project) { $project = $this->transformBasicEntities($project); $project = $this->transformArrayOfKeys($project, ['client_id']); @@ -274,6 +385,12 @@ class CompanyExport implements ShouldQueue return $project->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('projects'); +$x->addItems($this->export_data['projects']); +$this->export_data = null; + + $this->export_data['quotes'] = $this->company->quotes()->orderBy('number', 'DESC')->cursor()->map(function ($quote) { $quote = $this->transformBasicEntities($quote); $quote = $this->transformArrayOfKeys($quote, ['invoice_id','recurring_id','client_id', 'vendor_id', 'project_id', 'design_id', 'subscription_id']); @@ -281,6 +398,11 @@ class CompanyExport implements ShouldQueue return $quote->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('quotes'); +$x->addItems($this->export_data['quotes']); +$this->export_data = null; + $this->export_data['quote_invitations'] = QuoteInvitation::query()->where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($quote) { $quote = $this->transformArrayOfKeys($quote, ['company_id', 'user_id', 'client_contact_id', 'quote_id']); @@ -288,6 +410,12 @@ class CompanyExport implements ShouldQueue return $quote->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('quote_invitations'); +$x->addItems($this->export_data['quote_invitations']); +$this->export_data = null; + + $this->export_data['recurring_expenses'] = $this->company->recurring_expenses()->orderBy('number', 'DESC')->cursor()->map(function ($expense) { $expense = $this->transformBasicEntities($expense); $expense = $this->transformArrayOfKeys($expense, ['vendor_id', 'invoice_id', 'client_id', 'category_id', 'project_id']); @@ -295,6 +423,13 @@ class CompanyExport implements ShouldQueue return $expense->makeVisible(['id']); })->all(); + + +$x = $this->writer->collection('recurring_expenses'); +$x->addItems($this->export_data['recurring_expenses']); +$this->export_data = null; + + $this->export_data['recurring_invoices'] = $this->company->recurring_invoices()->orderBy('number', 'DESC')->cursor()->map(function ($ri) { $ri = $this->transformBasicEntities($ri); $ri = $this->transformArrayOfKeys($ri, ['client_id', 'vendor_id', 'project_id', 'design_id', 'subscription_id']); @@ -302,6 +437,11 @@ class CompanyExport implements ShouldQueue return $ri->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('recurring_invoices'); +$x->addItems($this->export_data['recurring_invoices']); +$this->export_data = null; + $this->export_data['recurring_invoice_invitations'] = RecurringInvoiceInvitation::query()->where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($ri) { $ri = $this->transformArrayOfKeys($ri, ['company_id', 'user_id', 'client_contact_id', 'recurring_invoice_id']); @@ -309,6 +449,13 @@ class CompanyExport implements ShouldQueue return $ri; })->all(); + +$x = $this->writer->collection('recurring_invoice_invitations'); +$x->addItems($this->export_data['recurring_invoice_invitations']); +$this->export_data = null; + + + $this->export_data['subscriptions'] = $this->company->subscriptions->map(function ($subscription) { $subscription = $this->transformBasicEntities($subscription); $subscription->group_id = $this->encodePrimaryKey($subscription->group_id); @@ -323,6 +470,10 @@ class CompanyExport implements ShouldQueue })->all(); +$x = $this->writer->collection('subscriptions'); +$x->addItems($this->export_data['subscriptions']); +$this->export_data = null; + $this->export_data['system_logs'] = $this->company->system_logs->map(function ($log) { $log->client_id = $this->encodePrimaryKey($log->client_id); $log->company_id = $this->encodePrimaryKey($log->company_id); @@ -330,14 +481,26 @@ class CompanyExport implements ShouldQueue return $log; })->makeHidden(['id'])->all(); + +$x = $this->writer->collection('system_logs'); +$x->addItems($this->export_data['system_logs']); +$this->export_data = null; + + $this->export_data['tasks'] = $this->company->tasks()->orderBy('number', 'DESC')->cursor()->map(function ($task) { $task = $this->transformBasicEntities($task); $task = $this->transformArrayOfKeys($task, ['client_id', 'invoice_id', 'project_id', 'status_id']); return $task->makeHidden(['hash','meta'])->makeVisible(['id']); - // return $task->makeHidden(['hash','meta'])->makeVisible(['id']); //@release v5.7.63 })->all(); + + +$x = $this->writer->collection('tasks'); +$x->addItems($this->export_data['tasks']); +$this->export_data = null; + + $this->export_data['task_statuses'] = $this->company->task_statuses->map(function ($status) { $status->id = $this->encodePrimaryKey($status->id); $status->user_id = $this->encodePrimaryKey($status->user_id); @@ -346,6 +509,13 @@ class CompanyExport implements ShouldQueue return $status; })->all(); + + +$x = $this->writer->collection('task_statuses'); +$x->addItems($this->export_data['task_statuses']); +$this->export_data = null; + + $this->export_data['tax_rates'] = $this->company->tax_rates->map(function ($rate) { $rate->company_id = $this->encodePrimaryKey($rate->company_id); $rate->user_id = $this->encodePrimaryKey($rate->user_id); @@ -353,11 +523,24 @@ class CompanyExport implements ShouldQueue return $rate; })->makeHidden(['id'])->all(); + + +$x = $this->writer->collection('tax_rates'); +$x->addItems($this->export_data['tax_rates']); +$this->export_data = null; + + $this->export_data['vendors'] = $this->company->vendors()->orderBy('number', 'DESC')->cursor()->map(function ($vendor) { return $this->transformBasicEntities($vendor)->makeVisible(['id']); })->all(); + +$x = $this->writer->collection('vendors'); +$x->addItems($this->export_data['vendors']); +$this->export_data = null; + + $this->export_data['vendor_contacts'] = VendorContact::where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($vendor) { $vendor = $this->transformBasicEntities($vendor); $vendor = $this->transformArrayOfKeys($vendor, ['vendor_id']); @@ -365,6 +548,13 @@ class CompanyExport implements ShouldQueue return $vendor->makeVisible(['id','user_id']); })->all(); + + +$x = $this->writer->collection('vendor_contacts'); +$x->addItems($this->export_data['vendor_contacts']); +$this->export_data = null; + + $this->export_data['webhooks'] = $this->company->webhooks->map(function ($hook) { $hook->user_id = $this->encodePrimaryKey($hook->user_id); $hook->company_id = $this->encodePrimaryKey($hook->company_id); @@ -372,6 +562,12 @@ class CompanyExport implements ShouldQueue return $hook; })->makeHidden(['id'])->all(); + +$x = $this->writer->collection('webhooks'); +$x->addItems($this->export_data['webhooks']); +$this->export_data = null; + + $this->export_data['purchase_orders'] = $this->company->purchase_orders()->orderBy('number', 'DESC')->cursor()->map(function ($purchase_order) { $purchase_order = $this->transformBasicEntities($purchase_order); $purchase_order = $this->transformArrayOfKeys($purchase_order, ['expense_id','client_id', 'vendor_id', 'project_id', 'design_id', 'subscription_id','project_id']); @@ -384,6 +580,13 @@ class CompanyExport implements ShouldQueue 'company_id',]); })->all(); + +$x = $this->writer->collection('purchase_orders'); +$x->addItems($this->export_data['purchase_orders']); +$this->export_data = null; + + + $this->export_data['purchase_order_invitations'] = PurchaseOrderInvitation::query()->where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($purchase_order) { $purchase_order = $this->transformArrayOfKeys($purchase_order, ['company_id', 'user_id', 'vendor_contact_id', 'purchase_order_id']); @@ -391,26 +594,46 @@ class CompanyExport implements ShouldQueue })->all(); +$x = $this->writer->collection('purchase_order_invitations'); +$x->addItems($this->export_data['purchase_order_invitations']); +$this->export_data = null; + $this->export_data['bank_integrations'] = $this->company->bank_integrations()->withTrashed()->orderBy('id', 'ASC')->cursor()->map(function ($bank_integration) { $bank_integration = $this->transformArrayOfKeys($bank_integration, ['account_id','company_id', 'user_id']); return $bank_integration->makeVisible(['id','user_id','company_id','account_id','hashed_id']); })->all(); +$x = $this->writer->collection('bank_integrations'); +$x->addItems($this->export_data['bank_integrations']); +$this->export_data = null; + $this->export_data['bank_transactions'] = $this->company->bank_transactions()->withTrashed()->orderBy('id', 'ASC')->cursor()->map(function ($bank_transaction) { $bank_transaction = $this->transformArrayOfKeys($bank_transaction, ['company_id', 'user_id','bank_integration_id','expense_id','ninja_category_id','vendor_id']); return $bank_transaction->makeVisible(['id','user_id','company_id']); })->all(); +$x = $this->writer->collection('bank_transactions'); +$x->addItems($this->export_data['bank_transactions']); +$this->export_data = null; + $this->export_data['schedulers'] = $this->company->schedulers()->withTrashed()->orderBy('id', 'ASC')->cursor()->map(function ($scheduler) { $scheduler = $this->transformArrayOfKeys($scheduler, ['company_id', 'user_id']); return $scheduler->makeVisible(['id','user_id','company_id']); })->all(); +$x = $this->writer->collection('schedulers'); +$x->addItems($this->export_data['schedulers']); +$this->export_data = null; + //write to tmp and email to owner(); + +$this->writer->end(); + + $this->zipAndSend(); return true; @@ -446,38 +669,40 @@ class CompanyExport implements ShouldQueue private function zipAndSend() { - $file_name = date('Y-m-d').'_'.str_replace([" ", "/"], ["_",""], $this->company->present()->name() . '_' . $this->company->company_key .'.zip'); + // $file_name = date('Y-m-d').'_'.str_replace([" ", "/"], ["_",""], $this->company->present()->name() . '_' . $this->company->company_key .'.zip'); - $path = 'backups'; + $zip_path = \Illuminate\Support\Str::ascii(str_replace(".json", ".zip", $this->file_name)); + // $path = 'backups'; // Storage::makeDirectory(storage_path('backups/')); - try { - mkdir(storage_path('backups/')); - } catch(\Exception $e) { - nlog("could not create directory"); - } + // try { + // mkdir(storage_path('backups/')); + // } catch(\Exception $e) { + // nlog("could not create directory"); + // } - $zip_path = storage_path('backups/'.\Illuminate\Support\Str::ascii($file_name)); + // $zip_path = storage_path('backups/'.\Illuminate\Support\Str::ascii($file_name)); $zip = new \ZipArchive(); if ($zip->open($zip_path, \ZipArchive::CREATE) !== true) { nlog("cannot open {$zip_path}"); } - $zip->addFromString("backup.json", json_encode($this->export_data)); + $zip->addFile($this->file_name, 'backup.json'); + // $zip->addFromString("backup.json", json_encode($this->export_data)); $zip->close(); - Storage::disk(config('filesystems.default'))->put('backups/'.$file_name, file_get_contents($zip_path)); + Storage::disk(config('filesystems.default'))->put('backups/'.str_replace(".json", ".zip",$this->file_name), file_get_contents($zip_path)); if(file_exists($zip_path)) { unlink($zip_path); } if(Ninja::isSelfHost()) { - $storage_path = 'backups/'.$file_name; + $storage_path = 'backups/'.str_replace(".json", ".zip",$this->file_name); } else { - $storage_path = Storage::disk(config('filesystems.default'))->path('backups/'.$file_name); + $storage_path = Storage::disk(config('filesystems.default'))->path('backups/'.str_replace(".json", ".zip",$this->file_name)); } $url = Cache::get($this->hash); diff --git a/app/Jobs/Company/CompanyImport.php b/app/Jobs/Company/CompanyImport.php index ee3877776cfa..b240664b7c7d 100644 --- a/app/Jobs/Company/CompanyImport.php +++ b/app/Jobs/Company/CompanyImport.php @@ -278,7 +278,6 @@ class CompanyImport implements ShouldQueue throw new \Exception('No import data found, has the cache expired?'); } - // $this->backup_file = json_decode(file_get_contents($this->file_location)); $tmp_file = $this->unzipFile(); $this->file_path = $tmp_file; @@ -341,15 +340,37 @@ class CompanyImport implements ShouldQueue { $path = TempFile::filePath(Storage::disk(config('filesystems.default'))->get($this->file_location), basename($this->file_location)); + nlog($path); $zip = new ZipArchive(); - $archive = $zip->open($path); + $res = $zip->open($path, ZipArchive::OVERWRITE); - $file_path = sys_get_temp_dir().'/'.sha1(microtime()); - $zip->extractTo($file_path); - $zip->close(); - $file_location = "{$file_path}/backup.json"; +if ($res === true) { + echo 'ok'; + $zip->extractTo('test'); + $zip->close(); + + + // $file_path = sys_get_temp_dir().'/'.sha1(microtime()); + + // nlog($file_path); + +// $result = $zip->extractTo($file_path); + +$result = $zip->extractTo("."); + + nlog($result); + + $$zip->close(); + +} else { + echo 'failed, code:' . $res; +} + + + $file_location = "backup.json"; + $file_path = $file_location; if (! file_exists($file_path)) { throw new NonExistingMigrationFile('Backup file does not exist, or is corrupted.'); } diff --git a/app/Jobs/Mail/NinjaMailerJob.php b/app/Jobs/Mail/NinjaMailerJob.php index 9570e7736283..a9c0a65d2620 100644 --- a/app/Jobs/Mail/NinjaMailerJob.php +++ b/app/Jobs/Mail/NinjaMailerJob.php @@ -260,11 +260,36 @@ class NinjaMailerJob implements ShouldQueue $t->replace(Ninja::transformTranslations($this->nmo->settings)); /** Force free/trials onto specific mail driver */ - if(Ninja::isHosted() && !$this->company->account->isPaid()) - { - $this->mailer = 'mailgun'; - $this->setHostedMailgunMailer(); - return $this; + // if(Ninja::isHosted() && !$this->company->account->isPaid()) + // { + // $this->mailer = 'mailgun'; + // $this->setHostedMailgunMailer(); + // return $this; + // } + + if(Ninja::isHosted() && $this->company->account->isPaid() && $this->nmo->settings->email_sending_method == 'default') { + //check if outlook. + + try{ + $email = $this->nmo->to_user->email; + $domain = explode("@", $email)[1] ?? ""; + $dns = dns_get_record($domain, DNS_MX); + $server = $dns[0]["target"]; + if(stripos($server, "outlook.com") !== false){ + + $this->mailer = 'postmark'; + $this->client_postmark_secret = config('services.postmark-outlook.token'); + + $this->nmo + ->mailable + ->from('maildelivery@invoice.services', 'Invoice Ninja'); + + return $this; + } + } + catch(\Exception $e){ + nlog($e->getMessage()); + } } switch ($this->nmo->settings->email_sending_method) { diff --git a/app/Listeners/Quote/QuoteCreatedNotification.php b/app/Listeners/Quote/QuoteCreatedNotification.php index 9fa025c15c37..2643075e2a9a 100644 --- a/app/Listeners/Quote/QuoteCreatedNotification.php +++ b/app/Listeners/Quote/QuoteCreatedNotification.php @@ -45,6 +45,7 @@ class QuoteCreatedNotification implements ShouldQueue /* We loop through each user and determine whether they need to be notified */ + /** @var \App\Models\CompanyUser $company_user */ foreach ($event->company->company_users as $company_user) { /* The User */ $user = $company_user->user; diff --git a/app/Models/CompanyUser.php b/app/Models/CompanyUser.php index 4f8352e23bd9..c6811ddf3e3a 100644 --- a/app/Models/CompanyUser.php +++ b/app/Models/CompanyUser.php @@ -201,7 +201,7 @@ class CompanyUser extends Pivot * @return bool */ public function portalType(): bool - { + { nlog(isset($this->react_settings->react_notification_link) && $this->react_settings->react_notification_link); return isset($this->react_settings->react_notification_link) && $this->react_settings->react_notification_link; } diff --git a/app/Models/Credit.php b/app/Models/Credit.php index a4c8250069a7..bc571fc4b7c7 100644 --- a/app/Models/Credit.php +++ b/app/Models/Credit.php @@ -204,7 +204,7 @@ class Credit extends BaseModel public function getDueDateAttribute($value) { - return $this->dateMutator($value); + return $value ? $this->dateMutator($value) : null; } public function getPartialDueDateAttribute($value) diff --git a/app/Models/Document.php b/app/Models/Document.php index 2c5111c80dc8..e393ef3c4129 100644 --- a/app/Models/Document.php +++ b/app/Models/Document.php @@ -220,7 +220,7 @@ class Document extends BaseModel $img = new \Imagick(); $img->readImageBlob($file); $img->setImageCompression(true); - $img->setImageCompressionQuality(50); + $img->setImageCompressionQuality(40); return $img->getImageBlob(); diff --git a/app/Services/Email/Email.php b/app/Services/Email/Email.php index 9f71781b1993..7052dc5f56ee 100644 --- a/app/Services/Email/Email.php +++ b/app/Services/Email/Email.php @@ -486,10 +486,34 @@ class Email implements ShouldQueue { /** Force free/trials onto specific mail driver */ - if(Ninja::isHosted() && !$this->company->account->isPaid()) { - $this->mailer = 'mailgun'; - $this->setHostedMailgunMailer(); - return $this; + // if(Ninja::isHosted() && !$this->company->account->isPaid()) { + // $this->mailer = 'mailgun'; + // $this->setHostedMailgunMailer(); + // return $this; + // } + + if(Ninja::isHosted() && $this->company->account->isPaid() && $this->email_object->settings->email_sending_method == 'default') { + + try { + + $address_object = reset($this->email_object->to); + $email = $address_object->address ?? ''; + $domain = explode("@", $email)[1] ?? ""; + $dns = dns_get_record($domain, DNS_MX); + $server = $dns[0]["target"]; + if(stripos($server, "outlook.com") !== false) { + + + $this->mailer = 'postmark'; + $this->client_postmark_secret = config('services.postmark-outlook.token'); + $this->mailable + ->from('maildelivery@invoice.services', 'Invoice Ninja'); + + return $this; + } + } catch(\Exception $e) { + nlog($e->getMessage()); + } } switch ($this->email_object->settings->email_sending_method) { diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php index 42db03a65d7a..d1b3d601c872 100644 --- a/app/Utils/HtmlEngine.php +++ b/app/Utils/HtmlEngine.php @@ -384,7 +384,7 @@ class HtmlEngine $data['$total'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.total')]; $data['$amount'] = &$data['$total']; - $data['$amount_due'] = ['value' => &$data['$total']['value'], 'label' => ctrans('texts.amount_due')]; + $data['$amount_due'] = ['value' => &$data['$balance_due']['value'], 'label' => ctrans('texts.amount_due')]; $data['$quote.total'] = &$data['$total']; $data['$invoice.total'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.invoice_total')]; $data['$invoice_total_raw'] = ['value' => $this->entity_calc->getTotal(), 'label' => ctrans('texts.invoice_total')]; diff --git a/composer.json b/composer.json index c2f34cadfc27..b24086a877bd 100644 --- a/composer.json +++ b/composer.json @@ -112,6 +112,7 @@ "fakerphp/faker": "^1.14", "filp/whoops": "^2.7", "friendsofphp/php-cs-fixer": "^3.14", + "hyvor/php-json-exporter": "^0.0.3", "laracasts/cypress": "^3.0", "larastan/larastan": "^2", "mockery/mockery": "^1.4.4", @@ -119,7 +120,6 @@ "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^10.0", "spatie/laravel-ignition": "^2.0", - "spatie/laravel-open-telemetry": "^0.0.9", "spaze/phpstan-stripe": "^3.0" }, "autoload": { diff --git a/composer.lock b/composer.lock index 82bb75f38b56..8d43e5a2e3a8 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": "61931b267752ed077ff3f1545b80259b", + "content-hash": "7a990a24b596bd1ab52a5f829fcc7e27", "packages": [ { "name": "afosto/yaac", @@ -1343,16 +1343,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.298.2", + "version": "3.298.3", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "626f731c38e06ea483025334512f4c2afea1739d" + "reference": "70fde185df4a8dd99983a308b823991fb5b39060" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/626f731c38e06ea483025334512f4c2afea1739d", - "reference": "626f731c38e06ea483025334512f4c2afea1739d", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/70fde185df4a8dd99983a308b823991fb5b39060", + "reference": "70fde185df4a8dd99983a308b823991fb5b39060", "shasum": "" }, "require": { @@ -1432,9 +1432,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.298.2" + "source": "https://github.com/aws/aws-sdk-php/tree/3.298.3" }, - "time": "2024-02-02T19:05:34+00:00" + "time": "2024-02-05T19:05:28+00:00" }, { "name": "bacon/bacon-qr-code", @@ -2677,27 +2677,27 @@ }, { "name": "doctrine/lexer", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "84a527db05647743d50373e0ec53a152f2cde568" + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568", - "reference": "84a527db05647743d50373e0ec53a152f2cde568", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9.5", + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "^5.21" }, "type": "library", "autoload": { @@ -2734,7 +2734,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.0" + "source": "https://github.com/doctrine/lexer/tree/3.0.1" }, "funding": [ { @@ -2750,7 +2750,7 @@ "type": "tidelift" } ], - "time": "2022-12-15T16:57:16+00:00" + "time": "2024-02-05T11:56:58+00:00" }, { "name": "dragonmantank/cron-expression", @@ -7966,25 +7966,27 @@ }, { "name": "nikic/php-parser", - "version": "v4.18.0", + "version": "v5.0.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" + "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4a21235f7e56e713259a6f76bf4b5ea08502b9dc", + "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.0" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "bin": [ "bin/php-parse" @@ -7992,7 +7994,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -8016,9 +8018,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.0" }, - "time": "2023-12-10T21:03:43+00:00" + "time": "2024-01-07T17:17:35+00:00" }, { "name": "nordigen/nordigen-php", @@ -13389,16 +13391,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", "shasum": "" }, "require": { @@ -13412,9 +13414,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -13451,7 +13450,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" }, "funding": [ { @@ -13467,20 +13466,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", "shasum": "" }, "require": { @@ -13491,9 +13490,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -13532,7 +13528,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" }, "funding": [ { @@ -13548,20 +13544,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "e46b4da57951a16053cd751f63f4a24292788157" + "reference": "07094a28851a49107f3ab4f9120ca2975a64b6e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e46b4da57951a16053cd751f63f4a24292788157", - "reference": "e46b4da57951a16053cd751f63f4a24292788157", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/07094a28851a49107f3ab4f9120ca2975a64b6e1", + "reference": "07094a28851a49107f3ab4f9120ca2975a64b6e1", "shasum": "" }, "require": { @@ -13572,9 +13568,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -13619,7 +13612,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.29.0" }, "funding": [ { @@ -13635,20 +13628,20 @@ "type": "tidelift" } ], - "time": "2023-03-21T17:27:24+00:00" + "time": "2024-01-29T20:12:16+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" + "reference": "a287ed7475f85bf6f61890146edbc932c0fff919" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919", + "reference": "a287ed7475f85bf6f61890146edbc932c0fff919", "shasum": "" }, "require": { @@ -13661,9 +13654,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -13706,7 +13696,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0" }, "funding": [ { @@ -13722,20 +13712,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:30:37+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", "shasum": "" }, "require": { @@ -13746,9 +13736,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -13790,7 +13777,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" }, "funding": [ { @@ -13806,20 +13793,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "shasum": "" }, "require": { @@ -13833,9 +13820,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -13873,7 +13857,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" }, "funding": [ { @@ -13889,20 +13873,20 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" + "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25", + "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25", "shasum": "" }, "require": { @@ -13910,9 +13894,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -13949,7 +13930,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0" }, "funding": [ { @@ -13965,20 +13946,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", "shasum": "" }, "require": { @@ -13986,9 +13967,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -14032,7 +14010,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" }, "funding": [ { @@ -14048,20 +14026,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11" + "reference": "86fcae159633351e5fd145d1c47de6c528f8caff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/86fcae159633351e5fd145d1c47de6c528f8caff", + "reference": "86fcae159633351e5fd145d1c47de6c528f8caff", "shasum": "" }, "require": { @@ -14070,9 +14048,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -14112,7 +14087,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.29.0" }, "funding": [ { @@ -14128,20 +14103,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T06:22:46+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e" + "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/9c44518a5aff8da565c8a55dbe85d2769e6f630e", - "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/3abdd21b0ceaa3000ee950097bc3cf9efc137853", + "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853", "shasum": "" }, "require": { @@ -14155,9 +14130,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -14194,7 +14166,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.29.0" }, "funding": [ { @@ -14210,7 +14182,7 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/postmark-mailer", @@ -15943,16 +15915,16 @@ }, { "name": "barryvdh/laravel-ide-helper", - "version": "v2.13.0", + "version": "v2.14.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "81d5b223ff067a1f38e14c100997e153b837fe4a" + "reference": "485c756f6cff408d6b273274c5e86112c3973d98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/81d5b223ff067a1f38e14c100997e153b837fe4a", - "reference": "81d5b223ff067a1f38e14c100997e153b837fe4a", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/485c756f6cff408d6b273274c5e86112c3973d98", + "reference": "485c756f6cff408d6b273274c5e86112c3973d98", "shasum": "" }, "require": { @@ -15963,7 +15935,7 @@ "illuminate/console": "^8 || ^9 || ^10", "illuminate/filesystem": "^8 || ^9 || ^10", "illuminate/support": "^8 || ^9 || ^10", - "nikic/php-parser": "^4.7", + "nikic/php-parser": "^4.18 || ^5", "php": "^7.3 || ^8.0", "phpdocumentor/type-resolver": "^1.1.0" }, @@ -15976,7 +15948,7 @@ "orchestra/testbench": "^6 || ^7 || ^8", "phpunit/phpunit": "^8.5 || ^9", "spatie/phpunit-snapshot-assertions": "^3 || ^4", - "vimeo/psalm": "^3.12" + "vimeo/psalm": "^5.4" }, "suggest": { "illuminate/events": "Required for automatic helper generation (^6|^7|^8|^9|^10)." @@ -15984,7 +15956,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.12-dev" + "dev-master": "2.14-dev" }, "laravel": { "providers": [ @@ -16021,7 +15993,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.13.0" + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.14.0" }, "funding": [ { @@ -16033,7 +16005,7 @@ "type": "github" } ], - "time": "2023-02-04T13:56:40+00:00" + "time": "2024-02-05T08:16:36+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -16807,6 +16779,50 @@ }, "time": "2020-07-09T08:09:16+00:00" }, + { + "name": "hyvor/php-json-exporter", + "version": "0.0.3", + "source": { + "type": "git", + "url": "https://github.com/hyvor/php-json-exporter.git", + "reference": "9fade1856135deaa2d0fc9b3065949019703471d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hyvor/php-json-exporter/zipball/9fade1856135deaa2d0fc9b3065949019703471d", + "reference": "9fade1856135deaa2d0fc9b3065949019703471d", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "pestphp/pest": "^1.22", + "phpstan/phpstan": "^1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Hyvor\\JsonExporter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Supun", + "email": "supun@hyvor.com" + } + ], + "description": "Export large datasets to a JSON file without memory exhaustion", + "support": { + "issues": "https://github.com/hyvor/php-json-exporter/issues", + "source": "https://github.com/hyvor/php-json-exporter/tree/0.0.3" + }, + "time": "2023-04-11T15:12:18+00:00" + }, { "name": "laracasts/cypress", "version": "3.0.1", @@ -17271,274 +17287,6 @@ ], "time": "2023-10-11T15:45:01+00:00" }, - { - "name": "open-telemetry/api", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/opentelemetry-php/api.git", - "reference": "401d04c6afe349afa78250ac862db2f89dbf94f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/401d04c6afe349afa78250ac862db2f89dbf94f6", - "reference": "401d04c6afe349afa78250ac862db2f89dbf94f6", - "shasum": "" - }, - "require": { - "open-telemetry/context": "^1.0", - "php": "^7.4 || ^8.0", - "psr/log": "^1.1|^2.0|^3.0", - "symfony/polyfill-php80": "^1.26", - "symfony/polyfill-php81": "^1.26", - "symfony/polyfill-php82": "^1.26" - }, - "conflict": { - "open-telemetry/sdk": "<=1.0.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.0.x-dev" - } - }, - "autoload": { - "files": [ - "Trace/functions.php" - ], - "psr-4": { - "OpenTelemetry\\API\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "opentelemetry-php contributors", - "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" - } - ], - "description": "API for OpenTelemetry PHP.", - "keywords": [ - "Metrics", - "api", - "apm", - "logging", - "opentelemetry", - "otel", - "tracing" - ], - "support": { - "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", - "docs": "https://opentelemetry.io/docs/php", - "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", - "source": "https://github.com/open-telemetry/opentelemetry-php" - }, - "time": "2024-01-10T13:04:59+00:00" - }, - { - "name": "open-telemetry/context", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/opentelemetry-php/context.git", - "reference": "e9d254a7c89885e63fd2fde54e31e81aaaf52b7c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/context/zipball/e9d254a7c89885e63fd2fde54e31e81aaaf52b7c", - "reference": "e9d254a7c89885e63fd2fde54e31e81aaaf52b7c", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0", - "symfony/polyfill-php80": "^1.26", - "symfony/polyfill-php81": "^1.26", - "symfony/polyfill-php82": "^1.26" - }, - "suggest": { - "ext-ffi": "To allow context switching in Fibers" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.0.x-dev" - } - }, - "autoload": { - "files": [ - "fiber/initialize_fiber_handler.php" - ], - "psr-4": { - "OpenTelemetry\\Context\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "opentelemetry-php contributors", - "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" - } - ], - "description": "Context implementation for OpenTelemetry PHP.", - "keywords": [ - "Context", - "opentelemetry", - "otel" - ], - "support": { - "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", - "docs": "https://opentelemetry.io/docs/php", - "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", - "source": "https://github.com/open-telemetry/opentelemetry-php" - }, - "time": "2024-01-13T05:50:44+00:00" - }, - { - "name": "open-telemetry/sdk", - "version": "1.0.7", - "source": { - "type": "git", - "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "818263750d299df5b9612a738440e56d92e5a296" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/818263750d299df5b9612a738440e56d92e5a296", - "reference": "818263750d299df5b9612a738440e56d92e5a296", - "shasum": "" - }, - "require": { - "ext-json": "*", - "open-telemetry/api": "^1.0", - "open-telemetry/context": "^1.0", - "open-telemetry/sem-conv": "^1.0", - "php": "^7.4 || ^8.0", - "php-http/discovery": "^1.14", - "psr/http-client": "^1.0", - "psr/http-client-implementation": "^1.0", - "psr/http-factory-implementation": "^1.0", - "psr/http-message": "^1.0.1|^2.0", - "psr/log": "^1.1|^2.0|^3.0", - "symfony/polyfill-mbstring": "^1.23", - "symfony/polyfill-php80": "^1.26", - "symfony/polyfill-php81": "^1.26", - "symfony/polyfill-php82": "^1.26" - }, - "suggest": { - "ext-gmp": "To support unlimited number of synchronous metric readers", - "ext-mbstring": "To increase performance of string operations" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.0.x-dev" - } - }, - "autoload": { - "files": [ - "Common/Util/functions.php", - "Logs/Exporter/_register.php", - "Metrics/MetricExporter/_register.php", - "Propagation/_register.php", - "Trace/SpanExporter/_register.php", - "Common/Dev/Compatibility/_load.php", - "_autoload.php" - ], - "psr-4": { - "OpenTelemetry\\SDK\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "opentelemetry-php contributors", - "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" - } - ], - "description": "SDK for OpenTelemetry PHP.", - "keywords": [ - "Metrics", - "apm", - "logging", - "opentelemetry", - "otel", - "sdk", - "tracing" - ], - "support": { - "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", - "docs": "https://opentelemetry.io/docs/php", - "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", - "source": "https://github.com/open-telemetry/opentelemetry-php" - }, - "time": "2024-01-24T12:00:22+00:00" - }, - { - "name": "open-telemetry/sem-conv", - "version": "1.24.0", - "source": { - "type": "git", - "url": "https://github.com/opentelemetry-php/sem-conv.git", - "reference": "d03e6501d21c04cd1b1e66e4cbcc7c2dd2e2cfa3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/d03e6501d21c04cd1b1e66e4cbcc7c2dd2e2cfa3", - "reference": "d03e6501d21c04cd1b1e66e4cbcc7c2dd2e2cfa3", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "OpenTelemetry\\SemConv\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "opentelemetry-php contributors", - "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" - } - ], - "description": "Semantic conventions for OpenTelemetry PHP.", - "keywords": [ - "Metrics", - "apm", - "logging", - "opentelemetry", - "otel", - "semantic conventions", - "semconv", - "tracing" - ], - "support": { - "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", - "docs": "https://opentelemetry.io/docs/php", - "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", - "source": "https://github.com/open-telemetry/opentelemetry-php" - }, - "time": "2024-01-23T21:47:17+00:00" - }, { "name": "phar-io/manifest", "version": "2.0.3", @@ -19443,86 +19191,6 @@ ], "time": "2024-01-12T13:14:58+00:00" }, - { - "name": "spatie/laravel-open-telemetry", - "version": "0.0.9", - "source": { - "type": "git", - "url": "https://github.com/spatie/laravel-open-telemetry.git", - "reference": "3785efd133829ae6d1a27cccb99772c2a31295fa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-open-telemetry/zipball/3785efd133829ae6d1a27cccb99772c2a31295fa", - "reference": "3785efd133829ae6d1a27cccb99772c2a31295fa", - "shasum": "" - }, - "require": { - "illuminate/contracts": "^10.0", - "illuminate/http": "^10.0", - "open-telemetry/api": "^1.0", - "open-telemetry/sdk": "^1.0", - "php": "^8.1", - "php-http/guzzle7-adapter": "^1.0", - "spatie/laravel-package-tools": "^1.13.8" - }, - "require-dev": { - "laravel/pint": "^1.3", - "nunomaduro/collision": "^7.0", - "nunomaduro/larastan": "^2.3.4", - "orchestra/testbench": "^8.0", - "pestphp/pest": "^2.0", - "pestphp/pest-plugin-laravel": "^2.0", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan-deprecation-rules": "^1.1.1", - "phpstan/phpstan-phpunit": "^1.3.3", - "spatie/laravel-ray": "^1.31", - "spatie/pest-plugin-snapshots": "^2.0", - "spatie/phpunit-snapshot-assertions": "^5.0", - "spatie/test-time": "^1.3", - "spatie/valuestore": "^1.3.2" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Spatie\\OpenTelemetry\\OpenTelemetryServiceProvider" - ], - "aliases": { - "Measure": "Spatie\\OpenTelemetry\\Facades\\Measure" - } - } - }, - "autoload": { - "psr-4": { - "Spatie\\OpenTelemetry\\": "src", - "Spatie\\OpenTelemetry\\Database\\Factories\\": "database/factories" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "role": "Developer" - } - ], - "description": "Measure performance across jobs and services", - "homepage": "https://github.com/spatie/laravel-open-telemetry", - "keywords": [ - "laravel", - "laravel-open-telemetry", - "spatie" - ], - "support": { - "issues": "https://github.com/spatie/laravel-open-telemetry/issues", - "source": "https://github.com/spatie/laravel-open-telemetry/tree/0.0.9" - }, - "time": "2024-01-12T12:12:48+00:00" - }, { "name": "spaze/phpstan-stripe", "version": "v3.1.0", @@ -19587,16 +19255,16 @@ }, { "name": "symfony/polyfill-php81", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" + "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/c565ad1e63f30e7477fc40738343c62b40bc672d", + "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d", "shasum": "" }, "require": { @@ -19604,9 +19272,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -19646,7 +19311,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.29.0" }, "funding": [ { @@ -19662,86 +19327,7 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-php82", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php82.git", - "reference": "7716bea9c86776fb3362d6b52fe1fc9471056a49" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/7716bea9c86776fb3362d6b52fe1fc9471056a49", - "reference": "7716bea9c86776fb3362d6b52fe1fc9471056a49", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php82\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php82/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-08-25T17:27:25+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/stopwatch", diff --git a/config/services.php b/config/services.php index d73f3555c01d..b9218c37270d 100644 --- a/config/services.php +++ b/config/services.php @@ -34,6 +34,10 @@ return [ 'token' => env('POSTMARK_SECRET', ''), ], + 'postmark-outlook' => [ + 'token' => env('POSTMARK_OUTLOOK_SECRET','') + ], + 'microsoft' => [ 'client_id' => env('MICROSOFT_CLIENT_ID'), 'client_secret' => env('MICROSOFT_CLIENT_SECRET'), diff --git a/database/migrations/2024_02_06_204031_correction_for_krw_currency.php b/database/migrations/2024_02_06_204031_correction_for_krw_currency.php new file mode 100644 index 000000000000..adba8729f79b --- /dev/null +++ b/database/migrations/2024_02_06_204031_correction_for_krw_currency.php @@ -0,0 +1,31 @@ +thousand_separator = ','; + $c->decimal_separator = '.'; + $c->save(); + } + + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // + } +}; diff --git a/database/seeders/CurrenciesSeeder.php b/database/seeders/CurrenciesSeeder.php index 298deea028ab..32ebcde53256 100644 --- a/database/seeders/CurrenciesSeeder.php +++ b/database/seeders/CurrenciesSeeder.php @@ -101,7 +101,7 @@ class CurrenciesSeeder extends Seeder ['id' => 76, 'name' => 'Surinamese Dollar', 'code' => 'SRD', 'symbol' => 'SRD', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], ['id' => 77, 'name' => 'Bahraini Dinar', 'code' => 'BHD', 'symbol' => 'BD ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['id' => 78, 'name' => 'Venezuelan Bolivars', 'code' => 'VES', 'symbol' => 'Bs.', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['id' => 79, 'name' => 'South Korean Won', 'code' => 'KRW', 'symbol' => 'W ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['id' => 79, 'name' => 'South Korean Won', 'code' => 'KRW', 'symbol' => 'W ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['id' => 80, 'name' => 'Moroccan Dirham', 'code' => 'MAD', 'symbol' => 'MAD ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['id' => 81, 'name' => 'Jamaican Dollar', 'code' => 'JMD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['id' => 82, 'name' => 'Angolan Kwanza', 'code' => 'AOA', 'symbol' => 'Kz', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], diff --git a/phpstan.neon b/phpstan.neon deleted file mode 100644 index 37fd452255e5..000000000000 --- a/phpstan.neon +++ /dev/null @@ -1,30 +0,0 @@ -includes: - - ./vendor/larastan/larastan/extension.neon - - ./vendor/spaze/phpstan-stripe/extension.neon - - phpstan-baseline.neon -parameters: - level: 2 - paths: - - app - excludePaths: - - 'vendor/*' - - 'resources/*/*.php' - - 'app/Jobs/Ninja/*' - - 'app/Models/Presenters/*' - - 'app/Console/Commands/*' - - 'app/DataMapper/Analytics/*' - - 'app/PaymentDrivers/Authorize/*' - - 'app/PaymentDrivers/AuthorizePaymentDriver.php' - - 'app/Utils/Traits/*' - universalObjectCratesClasses: - - App\DataMapper\Tax\RuleInterface - - App\DataMapper\FeesAndLimits - - \Postmark\Models\DynamicResponseModel - - \Stripe\Collection - reportUnmatchedIgnoredErrors: false - ignoreErrors: - - '#Array has 2 duplicate keys with value#' - - '#Call to an undefined method#' - - '#makeHidden#' - - '#Socialite#' - - '#Access to protected property#' \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index 113938ad5e36..000000000000 --- a/phpunit.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - ./tests/Unit - - - ./tests/Integration - - - ./tests/Feature - - - ./tests/Pdf - - - - - - - - - - - - - - - diff --git a/resources/views/email/admin/generic.blade.php b/resources/views/email/admin/generic.blade.php index 84e065c488cd..9177d9147da3 100644 --- a/resources/views/email/admin/generic.blade.php +++ b/resources/views/email/admin/generic.blade.php @@ -1,4 +1,4 @@ -@component('email.template.admin', ['design' => 'light', 'settings' => $settings, 'logo' => $logo]) +@component('email.template.admin', ['design' => 'light', 'settings' => $settings, 'logo' => $logo, 'url' => $url])
@isset($greeting)

{{ $greeting }}

diff --git a/resources/views/email/template/admin.blade.php b/resources/views/email/template/admin.blade.php index 96547c9d5883..3cb45eb146be 100644 --- a/resources/views/email/template/admin.blade.php +++ b/resources/views/email/template/admin.blade.php @@ -1,6 +1,7 @@ @php $primary_color = isset($settings) ? $settings->primary_color : '#4caf50'; $email_alignment = isset($settings) && $settings?->email_alignment ? $settings->email_alignment : 'center'; + $email_preferences = isset($url) && str_contains($url ?? '', '/#/') ? config('ninja.react_url').'/#/settings/user_details/notifications' : config('ninja.app_url'); @endphp © {{ date('Y') }} Invoice Ninja, All Rights Reserved

+ + +

+ {{ ctrans('texts.email_preferences') }} +

+
+
diff --git a/resources/views/email/template/plain.blade.php b/resources/views/email/template/plain.blade.php index c66249b20235..0a2aa9a4a126 100644 --- a/resources/views/email/template/plain.blade.php +++ b/resources/views/email/template/plain.blade.php @@ -45,6 +45,6 @@ @endif @endisset -@isset($email_preferences) -

{{ ctrans('texts.unsubscribe') }}

-@endisset \ No newline at end of file +@if(isset($email_preferences) && $email_preferences) +

{{ ctrans('texts.email_preferences') }}

+@endif \ No newline at end of file diff --git a/resources/views/pdf-designs/tech.html b/resources/views/pdf-designs/tech.html index 09a2c29c062e..b5ab208eabe5 100644 --- a/resources/views/pdf-designs/tech.html +++ b/resources/views/pdf-designs/tech.html @@ -389,11 +389,11 @@ $payment_due_label: - $payment_due + $due_date $amount_due_label: - $amount_due + $balance_due diff --git a/tests/Feature/Import/CSV/TaskImportTest.php b/tests/Feature/Import/CSV/TaskImportTest.php index 4979d636f372..eb31bc6af92e 100644 --- a/tests/Feature/Import/CSV/TaskImportTest.php +++ b/tests/Feature/Import/CSV/TaskImportTest.php @@ -64,7 +64,7 @@ class TaskImportTest extends TestCase 2 => 'client.name', 4 => 'task.number', 5 => 'task.description', - 6 => 'task.is_billable', + 6 => 'task.billable', 7 => 'task.start_date', 9 => 'task.end_date', 8 => 'task.start_time', @@ -132,7 +132,7 @@ class TaskImportTest extends TestCase 3 => 'project.name', 2 => 'client.name', 5 => 'task.description', - 6 => 'task.is_billable', + 6 => 'task.billable', 7 => 'task.start_date', 9 => 'task.end_date', 8 => 'task.start_time',