1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 13:12:50 +01:00

Merge pull request #8553 from turbo124/v5-develop

v5.6.2
This commit is contained in:
David Bomba 2023-06-14 08:26:15 +10:00 committed by GitHub
commit 75cf7ac7e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 5383 additions and 57 deletions

View File

@ -1 +1 @@
5.6.1
5.6.2

View File

@ -53,8 +53,10 @@ class TranslationsExport extends Command
'fr_CA',
'he',
'hr',
'hu',
'it',
'ja',
'km_KH',
'lt',
'lv_LV',
'mk_MK',
@ -131,10 +133,11 @@ class TranslationsExport extends Command
Storage::disk('local')->makeDirectory('lang');
foreach ($this->langs as $lang) {
nlog($lang);
Storage::disk('local')->makeDirectory("lang/{$lang}");
$translations = Lang::getLoader()->load($lang, 'texts');
nlog($translations);
Storage::disk('local')->put("lang/{$lang}/{$lang}.json", json_encode(Arr::dot($translations), JSON_UNESCAPED_UNICODE));
}
}

View File

@ -87,7 +87,7 @@ class CompanyController extends BaseController
* summary="Gets a list of companies",
* description="Lists companies, search and filters allow fine grained lists to be generated.
Query parameters can be added to performed more fine grained filtering of the companies, these are handled by the CompanyFilters class which defines the methods available",
* Query parameters can be added to performed more fine grained filtering of the companies, these are handled by the CompanyFilters class which defines the methods available",
* @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
@ -114,7 +114,10 @@ class CompanyController extends BaseController
*/
public function index()
{
$companies = Company::whereAccountId(auth()->user()->company()->account->id);
/** @var \App\Models\User $user */
$user = auth()->user();
$companies = Company::whereAccountId($user->company()->account->id);
return $this->listResponse($companies);
}
@ -159,8 +162,12 @@ class CompanyController extends BaseController
*/
public function create(CreateCompanyRequest $request)
{
$cf = new \App\Factory\CompanyFactory;
$company = $cf->create(auth()->user()->company()->account->id);
/** @var \App\Models\User $user */
$user = auth()->user();
$company_factory = new \App\Factory\CompanyFactory;
$company = $company_factory->create($user->company()->account->id);
return $this->itemResponse($company);
}
@ -206,15 +213,18 @@ class CompanyController extends BaseController
{
$this->forced_includes = ['company_user'];
$company = (new CreateCompany($request->all(), auth()->user()->company()->account))->handle();
(new CreateCompanyPaymentTerms($company, auth()->user()))->handle();
(new CreateCompanyTaskStatuses($company, auth()->user()))->handle();
/** @var \App\Models\User $user */
$user = auth()->user();
$company = (new CreateCompany($request->all(), $user->company()->account))->handle();
(new CreateCompanyPaymentTerms($company, $user))->handle();
(new CreateCompanyTaskStatuses($company, $user))->handle();
$company = $this->company_repo->save($request->all(), $company);
$this->uploadLogo($request->file('company_logo'), $company, $company);
auth()->user()->companies()->attach($company->id, [
$user->companies()->attach($company->id, [
'account_id' => $company->account->id,
'is_owner' => 1,
'is_admin' => 1,
@ -231,7 +241,7 @@ class CompanyController extends BaseController
/*
* Required dependencies
*/
auth()->user()->setCompany($company);
$user->setCompany($company);
/*
* Create token
@ -412,9 +422,6 @@ class CompanyController extends BaseController
$company = $this->company_repo->save($request->all(), $company);
/** We save the settings in the repository - this is duplicated */
// $company->saveSettings($request->input('settings'), $company);
if ($request->has('documents')) {
$this->saveDocuments($request->input('documents'), $company, false);
}

View File

@ -61,7 +61,6 @@ class SelfUpdateController extends BaseController
nlog('copying release file');
// if (copy($this->getDownloadUrl(), storage_path('app/invoiceninja.zip'))) {
if (copy($this->getDownloadUrl(), storage_path("app/{$this->filename}"))) {
nlog('Copied file from URL');
} else {
@ -70,7 +69,6 @@ class SelfUpdateController extends BaseController
nlog('Finished copying');
// if($this->use_zip) {
$file = Storage::disk('local')->path($this->filename);
nlog('Extracting tar');
@ -81,10 +79,6 @@ class SelfUpdateController extends BaseController
nlog('Finished extracting files');
unlink($file);
// }
// else {
// $this->extractUsingZip();
// }
nlog('Deleted release zip file');
@ -110,31 +104,13 @@ class SelfUpdateController extends BaseController
return response()->json(['message' => 'Update completed'], 200);
}
// private function extractUsingZip()
// {
// $file = Storage::disk('local')->path($this->filename);
// nlog('Extracting zip');
// $zipFile = new \PhpZip\ZipFile();
// $zipFile->openFile($file);
// $zipFile->deleteFromName(".htaccess");
// $zipFile->rewrite();
// $zipFile->extractTo(base_path());
// $zipFile->close();
// $zipFile = null;
// unlink($file);
// }
private function clearCacheDir()
{
$directoryIterator = new \RecursiveDirectoryIterator(base_path('bootstrap/cache'), \RecursiveDirectoryIterator::SKIP_DOTS);
foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) {
unlink(base_path('bootstrap/cache/').$file->getFileName());
$file = null;
}
$directoryIterator = null;
@ -155,6 +131,8 @@ class SelfUpdateController extends BaseController
throw new FilePermissionsFailure("Cannot update system because {$file->getFileName()} is not writable");
}
$file = null;
}
$directoryIterator = null;
@ -169,10 +147,8 @@ class SelfUpdateController extends BaseController
private function getDownloadUrl()
{
$version = $this->checkVersion();
// if(request()->has('zip'))
// return "https://github.com/invoiceninja/invoiceninja/releases/download/v{$version}/invoiceninja.zip";
$version = $this->checkVersion();
return "https://github.com/invoiceninja/invoiceninja/releases/download/v{$version}/invoiceninja.tar";

View File

@ -82,7 +82,7 @@ class UpdateCompanyRequest extends Request
$input['settings'] = (array)$this->filterSaveableSettings($input['settings']);
}
if(array_key_exists('subdomain', $input) && $this->subdomain == $input['subdomain']) {
if(array_key_exists('subdomain', $input) && $this->company->subdomain == $input['subdomain']) {
unset($input['subdomain']);
}

View File

@ -72,7 +72,7 @@ class ImportCompleted extends Mailable
'client_gateway_token_count' => $this->company->client_gateway_tokens()->count(),
'tax_rate_count' => $this->company->tax_rates()->count(),
'document_count' => $this->company->documents()->count(),
'url' => Ninja::isHosted() ? config('ninja.react_url') : config('ninja.app_url'),
]);
return $this

View File

@ -12,6 +12,7 @@
namespace App\Repositories;
use App\Models\Company;
use App\Utils\Ninja;
/**
* CompanyRepository.
@ -31,12 +32,18 @@ class CompanyRepository extends BaseRepository
*/
public function save(array $data, Company $company) : ?Company
{
if (isset($data['custom_fields']) && is_array($data['custom_fields'])) {
$data['custom_fields'] = $this->parseCustomFields($data['custom_fields']);
}
$company->fill($data);
/** Only required to handle v4 migration workloads */
if(Ninja::isHosted() && $company->isDirty('is_disabled') && !$company->is_disabled) {
Ninja::triggerForwarding($company->company_key, $company->owner()->email);
}
if (array_key_exists('settings', $data)) {
$company->saveSettings($data['settings'], $company);
}
@ -46,6 +53,12 @@ class CompanyRepository extends BaseRepository
return $company;
}
/**
* parseCustomFields
*
* @param array $fields
* @return array
*/
private function parseCustomFields($fields) :array
{
foreach ($fields as &$value) {

View File

@ -276,9 +276,8 @@ class Design extends BaseDesign
$header = [];
$header[] = ['element' => 'p', 'content' => ctrans('texts.shipping_address'), 'properties' => ['data-ref' => 'shipping_address-label', 'style' => 'font-weight: bold; text-transform: uppercase']];
return array_merge($header, $elements);
// return $elements;
return array_merge($header, $elements);
}

View File

@ -12,6 +12,7 @@
namespace App\Utils;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
/**
* Class Ninja.
@ -152,6 +153,21 @@ class Ninja
return $translations;
}
public static function triggerForwarding(string $company_key, string $email)
{
try {
Http::withHeaders([
'X-API-HOSTED-SECRET' => config('ninja.ninja_hosted_secret'),
])->post(config('ninja.license_url').'/api/v1/enable_forwarding', [
'account_key' => $company_key,
'email' => $email,
]);
}
catch (\Exception $e) {
nlog("attempt forwarding for{$email} - {$company_key}");
}
}
public function createLicense($request)
{
// $affiliate = Affiliate::where('affiliate_key', '=', SELF_HOST_AFFILIATE_KEY)->first();

View File

@ -15,8 +15,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => '5.6.1',
'app_tag' => '5.6.1',
'app_version' => '5.6.2',
'app_tag' => '5.6.2',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''),

View File

@ -0,0 +1,35 @@
<?php
use App\Models\Language;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Language::unguard();
if (!Language::find(39)) {
$hungarian = ['id' => 39, 'name' => 'Hungarian', 'locale' => 'hu'];
Language::create($hungarian);
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
};

View File

@ -63,6 +63,7 @@ class LanguageSeeder extends Seeder
['id' => 36, 'name' => 'Bulgarian', 'locale' => 'bg'],
['id' => 37, 'name' => 'Hebrew', 'locale' => 'he'],
['id' => 38, 'name' => 'Khmer', 'locale' => 'km_KH'],
['id' => 39, 'name' => 'Hungarian', 'locale' => 'hu'],
];
foreach ($languages as $language) {

View File

@ -5105,6 +5105,8 @@ $LANG = array(
'gallery' => 'Gallery',
'project_location' => 'Project Location',
'add_gateway_help_message' => 'Add a payment gateway (ie. Stripe, WePay or PayPal) to accept online payments',
'lang_Hungarian' => 'Hungarian',
'use_mobile_to_manage_plan' => 'Use your phone subscription settings to manage your plan',
);

View File

@ -5087,6 +5087,16 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'upload_certificate' => 'Téléverser le certificat',
'certificate_passphrase' => 'Passphrase du certificat',
'valid_vat_number' => 'Numéro valide de taxe',
'react_notification_link' => 'Lien de notifications React',
'react_notification_link_help' => 'Les courriels provenant de l\'administration contiennent des liens vers l\'application React',
'show_task_billable' => 'Afficher la facturation de tâche',
'credit_item' => 'Credit Item',
'drop_file_here' => 'Déposer le fichier ici',
'files' => 'Fichiers',
'camera' => 'Caméra',
'gallery' => 'Galerie',
'project_location' => 'Emplacement du projet',
'add_gateway_help_message' => 'Ajouter un passerelle de paiement (Stripe, WePay, ou PayPal) pour accepter les paiements en ligne',
);

19
lang/hu/auth.php Normal file
View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'Ovi podaci ne odgovaraju našima.',
'throttle' => 'Previše pokušaja prijave. Molim Vas pokušajte ponovno za :seconds sekundi.',
];

19
lang/hu/pagination.php Normal file
View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Prethodna',
'next' => 'Sljedeća &raquo;',
];

22
lang/hu/passwords.php Normal file
View File

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reminder Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Lozinke moraju biti duge barem 6 znakova i moraju odgovarati potvrdi.',
'reset' => 'Lozinka je postavljena!',
'sent' => 'Poveznica za ponovono postavljanje lozinke je poslana!',
'token' => 'Oznaka za ponovno postavljanje lozinke više nije važeća.',
'user' => 'Korisnik nije pronađen.',
];

5088
lang/hu/texts.php Normal file

File diff suppressed because it is too large Load Diff

116
lang/hu/validation.php Normal file
View File

@ -0,0 +1,116 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| such as the size rules. Feel free to tweak each of these messages.
|
*/
'accepted' => 'Polje :attribute mora biti prihvaćeno.',
'active_url' => 'Polje :attribute nije ispravan URL.',
'after' => 'Polje :attribute mora biti datum nakon :date.',
'alpha' => 'Polje :attribute smije sadržavati samo slova.',
'alpha_dash' => 'Polje :attribute smije sadržavati samo slova, brojeve i crtice.',
'alpha_num' => 'Polje :attribute smije sadržavati samo slova i brojeve.',
'array' => 'Polje :attribute mora biti niz.',
'before' => 'Polje :attribute mora biti datum prije :date.',
'between' => [
'numeric' => 'Polje :attribute mora biti između :min - :max.',
'file' => 'Polje :attribute mora biti između :min - :max kilobajta.',
'string' => 'Polje :attribute mora biti između :min - :max znakova.',
'array' => 'Polje :attribute mora imati između :min - :max stavki.',
],
'boolean' => 'Polje :attribute mora biti false ili true.',
'confirmed' => 'Potvrda polja :attribute se ne podudara.',
'date' => 'Polje :attribute nije ispravan datum.',
'date_format' => 'Polje :attribute ne podudara s formatom :format.',
'different' => 'Polja :attribute i :other moraju biti različita.',
'digits' => 'Polje :attribute mora sadržavati :digits znamenki.',
'digits_between' => 'Polje :attribute mora imati između :min i :max znamenki.',
'dimensions' => 'The :attribute has invalid image dimensions.',
'distinct' => 'The :attribute field has a duplicate value.',
'email' => 'Polje :attribute mora biti ispravna e-mail adresa.',
'exists' => 'Odabrano polje :attribute nije ispravno.',
'filled' => 'The :attribute field is required.',
'image' => 'Polje :attribute mora biti slika.',
'in' => 'Odabrano polje :attribute nije ispravno.',
'in_array' => 'The :attribute field does not exist in :other.',
'integer' => 'Polje :attribute mora biti broj.',
'ip' => 'Polje :attribute mora biti ispravna IP adresa.',
'json' => 'The :attribute must be a valid JSON string.',
'max' => [
'numeric' => 'Polje :attribute mora biti manje od :max.',
'file' => 'Polje :attribute mora biti manje od :max kilobajta.',
'string' => 'Polje :attribute mora sadržavati manje od :max znakova.',
'array' => 'Polje :attribute ne smije imati više od :max stavki.',
],
'mimes' => 'Polje :attribute mora biti datoteka tipa: :values.',
'min' => [
'numeric' => 'Polje :attribute mora biti najmanje :min.',
'file' => 'Polje :attribute mora biti najmanje :min kilobajta.',
'string' => 'Polje :attribute mora sadržavati najmanje :min znakova.',
'array' => 'Polje :attribute mora sadržavati najmanje :min stavki.',
],
'not_in' => 'Odabrano polje :attribute nije ispravno.',
'numeric' => 'Polje :attribute mora biti broj.',
'present' => 'The :attribute field must be present.',
'regex' => 'Polje :attribute se ne podudara s formatom.',
'required' => 'Polje :attribute je obavezno.',
'required_if' => 'Polje :attribute je obavezno kada polje :other sadrži :value.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'Polje :attribute je obavezno kada postoji polje :values.',
'required_with_all' => 'Polje :attribute je obavezno kada postje polja :values.',
'required_without' => 'Polje :attribute je obavezno kada ne postoji polje :values.',
'required_without_all' => 'Polje :attribute je obavezno kada nijedno od polja :values ne postoji.',
'same' => 'Polja :attribute i :other se moraju podudarati.',
'size' => [
'numeric' => 'Polje :attribute mora biti :size.',
'file' => 'Polje :attribute mora biti :size kilobajta.',
'string' => 'Polje :attribute mora biti :size znakova.',
'array' => 'Polje :attribute mora sadržavati :size stavki.',
],
'string' => 'The :attribute must be a string.',
'timezone' => 'Polje :attribute mora biti ispravna vremenska zona.',
'unique' => 'Polje :attribute već postoji.',
'url' => 'Polje :attribute nije ispravnog formata.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [
//
],
];

View File

@ -40,7 +40,7 @@ Route::get('tmp_pdf/{hash}', [App\Http\Controllers\ClientPortal\TempRouteControl
Route::get('client/key_login/{contact_key}', [App\Http\Controllers\ClientPortal\ContactHashLoginController::class, 'login'])->name('client.contact_login')->middleware(['domain_db','contact_key_login']);
Route::get('client/magic_link/{magic_link}', [App\Http\Controllers\ClientPortal\ContactHashLoginController::class, 'magicLink'])->name('client.contact_magic_link')->middleware(['domain_db','contact_key_login']);
Route::get('documents/{document_hash}', [App\Http\Controllers\ClientPortal\DocumentController::class, 'publicDownload'])->name('documents.public_download')->middleware(['domain_db']);
Route::get('documents/{document_hash}', [App\Http\Controllers\ClientPortal\DocumentController::class, 'publicDownload'])->name('documents.public_download')->middleware(['domain_db','token_auth']);
Route::get('error', [App\Http\Controllers\ClientPortal\ContactHashLoginController::class, 'errorPage'])->name('client.error');
Route::get('client/payment/{contact_key}/{payment_id}', [App\Http\Controllers\ClientPortal\InvitationController::class, 'paymentRouter'])->middleware(['domain_db','contact_key_login']);
Route::get('client/ninja/{contact_key}/{company_key}', [App\Http\Controllers\ClientPortal\NinjaPlanController::class, 'index'])->name('client.ninja_contact_login')->middleware(['domain_db']);