From 894d675e2af4f1a802e502748f8d5bb659d9c795 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 2 Feb 2024 05:55:59 +1100 Subject: [PATCH 1/7] Fixes for email templates --- app/Providers/AppServiceProvider.php | 2 -- app/Services/Email/EmailDefaults.php | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 21f1c52f77f5..53f49f4f854c 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -78,7 +78,6 @@ class AppServiceProvider extends ServiceProvider ->middleware('client'); }); - /* Ensure we don't have stale state in jobs */ Queue::before(function (JobProcessing $event) { App::forgetInstance('truthsource'); @@ -107,7 +106,6 @@ class AppServiceProvider extends ServiceProvider return $this; }); - Mailer::macro('mailgun_config', function (string $secret, string $domain, string $endpoint = 'api.mailgun.net') { // @phpstan-ignore /** @phpstan-ignore-next-line **/ Mailer::setSymfonyTransport(app('mail.manager')->createSymfonyTransport([ diff --git a/app/Services/Email/EmailDefaults.php b/app/Services/Email/EmailDefaults.php index 6598bac40d9f..8eb8765ca69b 100644 --- a/app/Services/Email/EmailDefaults.php +++ b/app/Services/Email/EmailDefaults.php @@ -177,7 +177,7 @@ class EmailDefaults $breaks = ["
","
","
"]; $this->email->email_object->text_body = str_ireplace($breaks, "\r\n", $this->email->email_object->body); $this->email->email_object->text_body = strip_tags($this->email->email_object->text_body); - $this->email->email_object->text_body = str_replace('$view_button', '$view_url', $this->email->email_object->text_body); + $this->email->email_object->text_body = str_replace(['$view_button','$viewButton'], '$view_url', $this->email->email_object->text_body); if ($this->template == 'email.template.custom') { $this->email->email_object->body = (str_replace('$body', $this->email->email_object->body, str_replace(["\r","\n"], "", $this->email->email_object->settings->email_style_custom))); From 9c5253cd1ba13c44ce4569fabfd768330000fb36 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 2 Feb 2024 07:24:05 +1100 Subject: [PATCH 2/7] Fixes for logic around contact passwords - handling blank email strings --- app/Repositories/ClientContactRepository.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/Repositories/ClientContactRepository.php b/app/Repositories/ClientContactRepository.php index 9419c4012745..7e1ce9d20706 100644 --- a/app/Repositories/ClientContactRepository.php +++ b/app/Repositories/ClientContactRepository.php @@ -82,10 +82,14 @@ class ClientContactRepository extends BaseRepository $update_contact->fill($contact); - if (array_key_exists('password', $contact) && strlen($contact['password']) > 1) { + if (array_key_exists('password', $contact) && strlen($contact['password']) > 1 && strlen($update_contact->email) > 3) { //updating on a blank contact email will cause large table scanning $update_contact->password = Hash::make($contact['password']); - $client->company->client_contacts()->where('email', $update_contact->email)->update(['password' => $update_contact->password]); + $client->company->client_contacts()->where('email', $update_contact->email)->cursor() + ->each(function ($saveable_contact) use ($update_contact){ + $saveable_contact->password = $update_contact->password; + $saveable_contact->save(); + }); } if (array_key_exists('email', $contact)) { From 31aa5eb8c9b46f05d73c8e7080e26e7356471be4 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 2 Feb 2024 07:33:44 +1100 Subject: [PATCH 3/7] Minor fixes --- app/Repositories/ClientContactRepository.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Repositories/ClientContactRepository.php b/app/Repositories/ClientContactRepository.php index 7e1ce9d20706..f00bd4d0cc20 100644 --- a/app/Repositories/ClientContactRepository.php +++ b/app/Repositories/ClientContactRepository.php @@ -85,7 +85,9 @@ class ClientContactRepository extends BaseRepository if (array_key_exists('password', $contact) && strlen($contact['password']) > 1 && strlen($update_contact->email) > 3) { //updating on a blank contact email will cause large table scanning $update_contact->password = Hash::make($contact['password']); - $client->company->client_contacts()->where('email', $update_contact->email)->cursor() + $client->company + ->client_contacts() + ->where('email', $update_contact->email)->cursor() ->each(function ($saveable_contact) use ($update_contact){ $saveable_contact->password = $update_contact->password; $saveable_contact->save(); From bea52e641e1b8232ae451ca44cc2fbbcd59a2acf Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 3 Feb 2024 22:26:43 +1100 Subject: [PATCH 4/7] Fixes for display of unsubscribe link --- app/Jobs/Util/Import.php | 24 +++++++++-------- app/Listeners/User/UpdateUserLastLogin.php | 1 - app/Mail/Admin/EntityCreatedObject.php | 7 ++--- app/Mail/Engine/BaseEmailEngine.php | 27 +++++++------------ app/Mail/Engine/PaymentEmailEngine.php | 2 ++ app/Mail/User/UserLoggedIn.php | 20 +++++--------- app/Repositories/ClientContactRepository.php | 15 ++++++----- app/Utils/Traits/Inviteable.php | 8 +++++- .../views/email/admin/generic_text.blade.php | 12 ++++++--- .../views/email/template/client.blade.php | 4 +-- resources/views/email/template/text.blade.php | 4 +-- routes/client.php | 9 +++++++ 12 files changed, 71 insertions(+), 62 deletions(-) diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index afed2928261f..894c6046d764 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -1091,15 +1091,15 @@ class Import implements ShouldQueue { Invoice::unguard(); - $rules = [ - '*.client_id' => ['required'], - ]; + // $rules = [ + // '*.client_id' => ['required'], + // ]; - $validator = Validator::make($data, $rules); + // // $validator = Validator::make($data, $rules); - if ($validator->fails()) { - throw new MigrationValidatorFailed(json_encode($validator->errors())); - } + // if ($validator->fails()) { + // throw new MigrationValidatorFailed(json_encode($validator->errors())); + // } $invoice_repository = new InvoiceMigrationRepository(); @@ -1145,6 +1145,8 @@ class Import implements ShouldQueue $key = "invoices_{$resource['id']}"; + nlog($invoice->id); + $this->ids['invoices'][$key] = [ 'old' => $resource['id'], 'new' => $invoice->id, @@ -2056,7 +2058,7 @@ class Import implements ShouldQueue public function failed($exception = null) { - info('the job failed'); + nlog('the job failed'); config(['queue.failed.driver' => null]); @@ -2067,11 +2069,11 @@ class Import implements ShouldQueue LightLogs::create($job_failure) ->queue(); - info(print_r($exception->getMessage(), 1)); + nlog(print_r($exception->getMessage(), 1)); - if (Ninja::isHosted()) { + // if (Ninja::isHosted()) { app('sentry')->captureException($exception); - } + // } } diff --git a/app/Listeners/User/UpdateUserLastLogin.php b/app/Listeners/User/UpdateUserLastLogin.php index bc0404e29f36..56b3a1ff6864 100644 --- a/app/Listeners/User/UpdateUserLastLogin.php +++ b/app/Listeners/User/UpdateUserLastLogin.php @@ -63,7 +63,6 @@ class UpdateUserLastLogin implements ShouldQueue $ip = array_key_exists('ip', $event->event_vars) ? $event->event_vars['ip'] : 'IP address not resolved'; $key = "user_logged_in_{$user->id}{$event->company->db}"; - if ($user->ip != $ip && is_null(Cache::get($key)) && $user->user_logged_in_notification) { $nmo = new NinjaMailerObject(); $nmo->mailable = new UserLoggedIn($user, $user->account->companies->first(), $ip); diff --git a/app/Mail/Admin/EntityCreatedObject.php b/app/Mail/Admin/EntityCreatedObject.php index c58108013652..baab3068db25 100644 --- a/app/Mail/Admin/EntityCreatedObject.php +++ b/app/Mail/Admin/EntityCreatedObject.php @@ -73,7 +73,8 @@ class EntityCreatedObject ); $mail_obj->markdown = 'email.admin.generic'; - + $mail_obj->text_view = 'email.template.text'; + $content = ctrans( $this->template_body, [ @@ -92,7 +93,7 @@ class EntityCreatedObject 'logo' => $this->company->present()->logo(), 'settings' => $this->company->settings, 'whitelabel' => $this->company->account->isPaid() ? true : false, - 'text_body' => $content, + 'text_body' => str_replace(['$view_button','$viewButton','$viewLink','$view_url'], '$view_url', $content), ]; } else { $this->entity->load('client.country', 'client.company'); @@ -179,7 +180,7 @@ class EntityCreatedObject 'logo' => $this->company->present()->logo(), 'settings' => $settings, 'whitelabel' => $this->company->account->isPaid() ? true : false, - 'text_body' => $content, + 'text_body' => str_replace(['$view_button','$viewButton','$view_link','$view_button'], '$view_url', $content), ]; } } diff --git a/app/Mail/Engine/BaseEmailEngine.php b/app/Mail/Engine/BaseEmailEngine.php index ebb90796fbc1..a850dc804e21 100644 --- a/app/Mail/Engine/BaseEmailEngine.php +++ b/app/Mail/Engine/BaseEmailEngine.php @@ -123,6 +123,15 @@ class BaseEmailEngine implements EngineInterface public function setTextBody($text) { + + if (! empty($this->variables)) { + + $text = str_replace(['$paymentLink', '$viewButton', '$view_button', '$viewLink', '$view_link'], '$view_url', $text); + $text = str_replace(array_keys($this->variables), array_values($this->variables), $text); + $text = str_replace(array_keys($this->variables), array_values($this->variables), $text); + + } + $this->text_body = $text; return $this; @@ -189,22 +198,4 @@ class BaseEmailEngine implements EngineInterface return $this->text_body; } - private function replaceEntities($content) - { - $find = [ - '

', - '

', - '
', - '<\div>', - ]; - - $replace = [ - '', - '\n\n', - '', - '\n\n', - ]; - - return str_replace($find, $replace, $content); - } } diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php index 0b89106304db..ade3c995603a 100644 --- a/app/Mail/Engine/PaymentEmailEngine.php +++ b/app/Mail/Engine/PaymentEmailEngine.php @@ -31,6 +31,7 @@ class PaymentEmailEngine extends BaseEmailEngine public $client; + /** @var \App\Models\Payment $payment */ public $payment; public $template_data; @@ -91,6 +92,7 @@ class PaymentEmailEngine extends BaseEmailEngine ->setVariables($this->makeValues()) ->setSubject($subject_template) ->setBody($body_template) + ->setTextBody($body_template) ->setFooter('') ->setViewLink('') ->setViewText(''); diff --git a/app/Mail/User/UserLoggedIn.php b/app/Mail/User/UserLoggedIn.php index a7137166cacb..dd2a329f0080 100644 --- a/app/Mail/User/UserLoggedIn.php +++ b/app/Mail/User/UserLoggedIn.php @@ -12,31 +12,21 @@ namespace App\Mail\User; -use Illuminate\Bus\Queueable; +use App\Models\User; +use App\Models\Company; use Illuminate\Mail\Mailable; -use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\App; class UserLoggedIn extends Mailable { - // use Queueable, SerializesModels; - - public $company; - - public $user; - - public $ip; /** * Create a new message instance. * * @return void */ - public function __construct($user, $company, $ip) + public function __construct(public User $user, public Company $company, public string $ip) { - $this->company = $company; - $this->user = $user; - $this->ip = $ip; } /** @@ -48,11 +38,13 @@ class UserLoggedIn extends Mailable { App::setLocale($this->company->getLocale()); + $text = ctrans('texts.new_login_description', ['email' => $this->user->email, 'ip' => $this->ip, 'time' => now()]); + return $this->from(config('mail.from.address'), config('mail.from.name')) ->subject(ctrans('texts.new_login_detected')) ->text('email.admin.generic_text', [ 'title' => ctrans('texts.new_login_detected'), - 'body' => strip_tags(ctrans('texts.new_login_description', ['email' => $this->user->email, 'ip' => $this->ip, 'time' => now()])), + 'body' => $text, ]) ->view('email.admin.notification') ->with([ diff --git a/app/Repositories/ClientContactRepository.php b/app/Repositories/ClientContactRepository.php index f00bd4d0cc20..4a508fc18964 100644 --- a/app/Repositories/ClientContactRepository.php +++ b/app/Repositories/ClientContactRepository.php @@ -85,13 +85,14 @@ class ClientContactRepository extends BaseRepository if (array_key_exists('password', $contact) && strlen($contact['password']) > 1 && strlen($update_contact->email) > 3) { //updating on a blank contact email will cause large table scanning $update_contact->password = Hash::make($contact['password']); - $client->company - ->client_contacts() - ->where('email', $update_contact->email)->cursor() - ->each(function ($saveable_contact) use ($update_contact){ - $saveable_contact->password = $update_contact->password; - $saveable_contact->save(); - }); + ClientContact::withTrashed() + ->where('company_id', $client->id) + ->where('client_id', $client->company_id) + ->where('email', $update_contact->email)->cursor() + ->each(function ($saveable_contact) use ($update_contact){ + $saveable_contact->password = $update_contact->password; + $saveable_contact->save(); + }); } if (array_key_exists('email', $contact)) { diff --git a/app/Utils/Traits/Inviteable.php b/app/Utils/Traits/Inviteable.php index 735937d81fa8..fef8239788a3 100644 --- a/app/Utils/Traits/Inviteable.php +++ b/app/Utils/Traits/Inviteable.php @@ -49,7 +49,9 @@ trait Inviteable public function getPaymentLink() { + if (Ninja::isHosted()) { + /**@var \App\Models\Company $company */ $domain = $this->company->domain(); } else { $domain = config('ninja.app_url'); @@ -105,7 +107,11 @@ trait Inviteable switch ($this->company->portal_mode) { case 'subdomain': - return $domain.'/client/'.$entity_type.'/'.$this->key; + + if(Ninja::isHosted()) + return 'https://router.invoiceninja.com/route/'.encrypt($domain.'/client/'.$entity_type.'/'.$this->key); + else + return $domain.'/client/'.$entity_type.'/'.$this->key; break; case 'iframe': return $domain.'/client/'.$entity_type.'/'.$this->key; diff --git a/resources/views/email/admin/generic_text.blade.php b/resources/views/email/admin/generic_text.blade.php index 1fdebc4f23ab..8b540769fb71 100644 --- a/resources/views/email/admin/generic_text.blade.php +++ b/resources/views/email/admin/generic_text.blade.php @@ -1,9 +1,15 @@ -{!! $title !!} +{{ $title }} @isset($body) -{!! $body !!} +{{ strip_tags(str_replace("
", "\r\n", $body)) }} @endisset @isset($content) -{!! $content !!} +{{ strip_tags(str_replace("
", "\r\n", $content)) }} +@endisset + +@isset($whitelabel) +@if(!$whitelabel) +{{ ctrans('texts.ninja_email_footer', ['site' => 'https://invoiceninja.com']) }} +@endif @endisset \ No newline at end of file diff --git a/resources/views/email/template/client.blade.php b/resources/views/email/template/client.blade.php index 2986b35345fb..1076ab9d32a9 100644 --- a/resources/views/email/template/client.blade.php +++ b/resources/views/email/template/client.blade.php @@ -233,7 +233,7 @@ - @isset($email_preferences) + @if(isset($email_preferences) && $email_preferences)
- @endisset + @endif diff --git a/resources/views/email/template/text.blade.php b/resources/views/email/template/text.blade.php index 5af56ef5ff4e..302642f32281 100644 --- a/resources/views/email/template/text.blade.php +++ b/resources/views/email/template/text.blade.php @@ -1,7 +1,7 @@ -{!! $text_body !!} +{{ strip_tags(str_replace("
", "\r\n", $text_body)) }} + @isset($whitelabel) @if(!$whitelabel) - {{ ctrans('texts.ninja_email_footer', ['site' => 'https://invoiceninja.com']) }} @endif @endisset diff --git a/routes/client.php b/routes/client.php index 1394734d5977..3bf5d6798365 100644 --- a/routes/client.php +++ b/routes/client.php @@ -141,6 +141,15 @@ Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'clie Route::get('unsubscribe/{entity}/{invitation_key}', [App\Http\Controllers\ClientPortal\InvitationController::class, 'unsubscribe'])->name('unsubscribe'); }); + +Route::get('route/{hash}', function ($hash) { + + return redirect(decrypt($hash)); + +}); + + + Route::get('phantom/{entity}/{invitation_key}', [Phantom::class, 'displayInvitation'])->middleware(['invite_db', 'phantom_secret'])->name('phantom_view'); Route::get('blade/', [Phantom::class, 'blade'])->name('blade'); From 886e6b3de87a016aaa128a7d6492dc52781efdf5 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 3 Feb 2024 22:31:24 +1100 Subject: [PATCH 5/7] Improvements for email handling --- app/Mail/Engine/PaymentEmailEngine.php | 2 +- app/Mail/TemplateEmail.php | 2 +- resources/views/email/template/client.blade.php | 2 +- routes/client.php | 3 --- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php index ade3c995603a..58614d8ea1ef 100644 --- a/app/Mail/Engine/PaymentEmailEngine.php +++ b/app/Mail/Engine/PaymentEmailEngine.php @@ -208,7 +208,7 @@ class PaymentEmailEngine extends BaseEmailEngine $data['$payment.date'] = ['value' => $this->translateDate($this->payment->date, $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.payment_date')]; $data['$transaction_reference'] = ['value' => $this->payment->transaction_reference, 'label' => ctrans('texts.transaction_reference')]; $data['$reference'] = ['value' => '', 'label' => ctrans('texts.reference')]; - $data['$public_notes'] = ['value' => $this->payment->public_notes, 'label' => ctrans('texts.notes')]; + $data['$public_notes'] = ['value' => '', 'label' => ctrans('texts.notes')]; $data['$payment1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'payment1', $this->payment->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'payment1')]; $data['$payment2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'payment2', $this->payment->custom_value2, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'payment2')]; diff --git a/app/Mail/TemplateEmail.php b/app/Mail/TemplateEmail.php index 7ccd29cac206..90352e00b68e 100644 --- a/app/Mail/TemplateEmail.php +++ b/app/Mail/TemplateEmail.php @@ -139,7 +139,7 @@ class TemplateEmail extends Mailable 'whitelabel' => $this->client->user->account->isPaid() ? true : false, 'logo' => $this->company->present()->logo($settings), 'links' => $this->build_email->getAttachmentLinks(), - 'email_preferences' => (Ninja::isHosted() && in_array($settings->email_sending_method, ['default', 'mailgun'])) ? URL::signedRoute('client.email_preferences', ['entity' => $this->invitation->getEntityString(), 'invitation_key' => $this->invitation->key]) : false, + 'email_preferences' => (Ninja::isHosted() && in_array($settings->email_sending_method, ['default', 'mailgun'])) ? $this->company->domain() . URL::signedRoute('client.email_preferences', ['entity' => $this->invitation->getEntityString(), 'invitation_key' => $this->invitation->key], absolute: false) : false, ]); foreach ($this->build_email->getAttachments() as $file) { diff --git a/resources/views/email/template/client.blade.php b/resources/views/email/template/client.blade.php index 1076ab9d32a9..f13a3572b40a 100644 --- a/resources/views/email/template/client.blade.php +++ b/resources/views/email/template/client.blade.php @@ -240,7 +240,7 @@ style="padding-top: 10px;padding-bottom: 10px; background-color: #242424; border: 1px solid #c2c2c2; border-top-color: #242424; border-bottom-color: #242424;">

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

diff --git a/routes/client.php b/routes/client.php index 3bf5d6798365..0e3fdd729a89 100644 --- a/routes/client.php +++ b/routes/client.php @@ -141,15 +141,12 @@ Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'clie Route::get('unsubscribe/{entity}/{invitation_key}', [App\Http\Controllers\ClientPortal\InvitationController::class, 'unsubscribe'])->name('unsubscribe'); }); - Route::get('route/{hash}', function ($hash) { return redirect(decrypt($hash)); }); - - Route::get('phantom/{entity}/{invitation_key}', [Phantom::class, 'displayInvitation'])->middleware(['invite_db', 'phantom_secret'])->name('phantom_view'); Route::get('blade/', [Phantom::class, 'blade'])->name('blade'); From 73df9cc4949fee8d70eecb3e7770225f25d0832b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 4 Feb 2024 11:15:53 +1100 Subject: [PATCH 6/7] Small improvement for document imports --- .../TaskScheduler/StoreSchedulerRequest.php | 2 +- app/Jobs/Util/Import.php | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php b/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php index e204c36bcddb..78481ef80717 100644 --- a/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php +++ b/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php @@ -49,7 +49,7 @@ class StoreSchedulerRequest extends Request 'parameters.entity_id' => ['bail', 'sometimes', 'string'], 'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report','in:ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,activity,client,contact,client_contact,credit,document,expense,invoice,invoice_item,quote,quote_item,recurring_invoice,payment,product,task'], 'parameters.date_key' => ['bail','sometimes', 'string'], - 'parameters.status' => ['bail','sometimes', 'string'], + 'parameters.status' => ['bail','sometimes', 'nullable', 'string'], ]; return $rules; diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index 894c6046d764..cf65f4576284 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -1145,8 +1145,6 @@ class Import implements ShouldQueue $key = "invoices_{$resource['id']}"; - nlog($invoice->id); - $this->ids['invoices'][$key] = [ 'old' => $resource['id'], 'new' => $invoice->id, @@ -1352,11 +1350,11 @@ class Import implements ShouldQueue '*.client_id' => ['required'], ]; - $validator = Validator::make($data, $rules); + // $validator = Validator::make($data, $rules); - if ($validator->fails()) { - throw new MigrationValidatorFailed(json_encode($validator->errors())); - } + // if ($validator->fails()) { + // throw new MigrationValidatorFailed(json_encode($validator->errors())); + // } $payment_repository = new PaymentMigrationRepository(new CreditRepository()); @@ -1527,18 +1525,19 @@ class Import implements ShouldQueue } } - if (!$entity) { - continue; - } + // throw new Exception("Resource invoice/quote document not available."); } - if (array_key_exists('expense_id', $resource) && $resource['expense_id'] && array_key_exists('expenses', $this->ids)) { $expense_id = $this->transformId('expenses', $resource['expense_id']); $entity = Expense::query()->where('id', $expense_id)->withTrashed()->first(); } + if (!$entity) { + continue; + } + $file_url = $resource['url']; $file_name = $resource['name']; $file_path = sys_get_temp_dir().'/'.$file_name; From 764fa89ee39ff8f593af1c229bf6aab4ac01b0ac Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 4 Feb 2024 11:16:10 +1100 Subject: [PATCH 7/7] v5.8.22 --- VERSION.txt | 2 +- config/ninja.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 0fe15a58a412..694a2b5eb39c 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.8.21 \ No newline at end of file +5.8.22 \ No newline at end of file diff --git a/config/ninja.php b/config/ninja.php index a88e422fcaf3..3a3e2c684ccf 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -17,8 +17,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => env('APP_VERSION', '5.8.21'), - 'app_tag' => env('APP_TAG', '5.8.21'), + 'app_version' => env('APP_VERSION', '5.8.22'), + 'app_tag' => env('APP_TAG', '5.8.22'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false),