diff --git a/.env.example b/.env.example index 11ca442294..c1a0314177 100644 --- a/.env.example +++ b/.env.example @@ -58,13 +58,24 @@ APP_LOG_LEVEL=notice # For other database types, please see the FAQ: https://docs.firefly-iii.org/support/faq # If you use Docker or similar, you can set these variables from a file by appending them with _FILE # Use "mysql" for MySQL and MariaDB. Use "sqlite" for SQLite. -DB_CONNECTION=pgsql +DB_CONNECTION=mysql DB_HOST=fireflyiiidb -DB_PORT=5432 +DB_PORT=3306 DB_DATABASE=firefly DB_USERNAME=firefly DB_PASSWORD=secret_firefly_password +# MySQL supports SSL. You can configure it here. +# If you use Docker or similar, you can set these variables from a file by appending them with _FILE +MYSQL_USE_SSL=false +MYSQL_SSL_VERIFY_SERVER_CERT=true +# You need to set at least of these options +MYSQL_SSL_CAPATH=/etc/ssl/certs/ +MYSQL_SSL_CA= +MYSQL_SSL_CERT= +MYSQL_SSL_KEY= +MYSQL_SSL_CIPHER= + # PostgreSQL supports SSL. You can configure it here. # If you use Docker or similar, you can set these variables from a file by appending them with _FILE PGSQL_SSL_MODE=prefer @@ -170,8 +181,16 @@ ADLDAP_PORT=389 ADLDAP_TIMEOUT=5 ADLDAP_BASEDN="" ADLDAP_FOLLOW_REFFERALS=false + +# SSL/TLS settings ADLDAP_USE_SSL=false ADLDAP_USE_TLS=false +ADLDAP_SSL_CACERTDIR= +ADLDAP_SSL_CACERTFILE= +ADLDAP_SSL_CERTFILE= +ADLDAP_SSL_KEYFILE= +ADLDAP_SSL_CIPHER_SUITE= +ADLDAP_SSL_REQUIRE_CERT= # You can set the following variables from a file by appending them with _FILE: ADLDAP_ADMIN_USERNAME= @@ -219,8 +238,9 @@ TRACKER_SITE_ID= TRACKER_URL= # -# Firefly III could (in the future) collect telemetry on how you use Firefly III. -# In order to allow this, change the following variable to true: +# Firefly III can collect telemetry on how you use Firefly III. This is opt-in. +# In order to allow this, change the following variable to true. +# To read more about this feature, go to this page: https://docs.firefly-iii.org/support/telemetry SEND_TELEMETRY=false # You can fine tune the start-up of a Docker container by editing these environment variables. @@ -268,7 +288,6 @@ DEMO_USERNAME= DEMO_PASSWORD= USE_ENCRYPTION=false IS_SANDSTORM=false -IS_DOCKER=false IS_HEROKU=false BUNQ_USE_SANDBOX=false diff --git a/.github/lock.yml b/.github/lock.yml index 2c57deaab5..8935e94dc8 100644 --- a/.github/lock.yml +++ b/.github/lock.yml @@ -32,4 +32,4 @@ setLockReason: true # daysUntilLock: 30 # Repository to extend settings from -# _extends: repo \ No newline at end of file +# _extends: repo diff --git a/app/Console/Commands/Correction/CorrectDatabase.php b/app/Console/Commands/Correction/CorrectDatabase.php index 0c87804883..d2e88f4725 100644 --- a/app/Console/Commands/Correction/CorrectDatabase.php +++ b/app/Console/Commands/Correction/CorrectDatabase.php @@ -83,8 +83,6 @@ class CorrectDatabase extends Command echo $result; } - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } } diff --git a/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php b/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php index 063e40e230..d4cca5e04e 100644 --- a/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php +++ b/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php @@ -77,8 +77,6 @@ class CorrectOpeningBalanceCurrencies extends Command $this->info('There was nothing to fix in the opening balance transactions.'); } - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } diff --git a/app/Console/Commands/Correction/CreateAccessTokens.php b/app/Console/Commands/Correction/CreateAccessTokens.php index f541e626f3..9dd515c17a 100644 --- a/app/Console/Commands/Correction/CreateAccessTokens.php +++ b/app/Console/Commands/Correction/CreateAccessTokens.php @@ -78,8 +78,6 @@ class CreateAccessTokens extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verify access tokens in %s seconds.', $end)); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } } diff --git a/app/Console/Commands/Correction/CreateLinkTypes.php b/app/Console/Commands/Correction/CreateLinkTypes.php index 7d93025e2a..0bdf1d924d 100644 --- a/app/Console/Commands/Correction/CreateLinkTypes.php +++ b/app/Console/Commands/Correction/CreateLinkTypes.php @@ -79,8 +79,6 @@ class CreateLinkTypes extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified link types in %s seconds', $end)); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } } diff --git a/app/Console/Commands/Correction/DeleteEmptyGroups.php b/app/Console/Commands/Correction/DeleteEmptyGroups.php index 083266a65e..41e05013d3 100644 --- a/app/Console/Commands/Correction/DeleteEmptyGroups.php +++ b/app/Console/Commands/Correction/DeleteEmptyGroups.php @@ -76,8 +76,6 @@ class DeleteEmptyGroups extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified empty groups in %s seconds', $end)); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } } diff --git a/app/Console/Commands/Correction/DeleteEmptyJournals.php b/app/Console/Commands/Correction/DeleteEmptyJournals.php index 07c23d75c2..93d77eb81e 100644 --- a/app/Console/Commands/Correction/DeleteEmptyJournals.php +++ b/app/Console/Commands/Correction/DeleteEmptyJournals.php @@ -58,8 +58,6 @@ class DeleteEmptyJournals extends Command $this->deleteUnevenJournals(); $this->deleteEmptyJournals(); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } diff --git a/app/Console/Commands/Correction/DeleteOrphanedTransactions.php b/app/Console/Commands/Correction/DeleteOrphanedTransactions.php index f35b35590f..c95007b60f 100644 --- a/app/Console/Commands/Correction/DeleteOrphanedTransactions.php +++ b/app/Console/Commands/Correction/DeleteOrphanedTransactions.php @@ -62,7 +62,6 @@ class DeleteOrphanedTransactions extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified orphans in %s seconds', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Correction/DeleteZeroAmount.php b/app/Console/Commands/Correction/DeleteZeroAmount.php index 2e860610b9..f96b426eee 100644 --- a/app/Console/Commands/Correction/DeleteZeroAmount.php +++ b/app/Console/Commands/Correction/DeleteZeroAmount.php @@ -78,8 +78,6 @@ class DeleteZeroAmount extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified zero-amount integrity in %s seconds', $end)); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } } diff --git a/app/Console/Commands/Correction/EnableCurrencies.php b/app/Console/Commands/Correction/EnableCurrencies.php index 4b85bc8cb9..502d1be977 100644 --- a/app/Console/Commands/Correction/EnableCurrencies.php +++ b/app/Console/Commands/Correction/EnableCurrencies.php @@ -101,8 +101,6 @@ class EnableCurrencies extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified currencies in %s seconds.', $end)); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } } diff --git a/app/Console/Commands/Correction/FixAccountTypes.php b/app/Console/Commands/Correction/FixAccountTypes.php index 7f6dc372cf..8b6bd26d8e 100644 --- a/app/Console/Commands/Correction/FixAccountTypes.php +++ b/app/Console/Commands/Correction/FixAccountTypes.php @@ -106,7 +106,6 @@ class FixAccountTypes extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verifying account types took %s seconds', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Correction/FixLongDescriptions.php b/app/Console/Commands/Correction/FixLongDescriptions.php index ccc5fae5e4..ec93912784 100644 --- a/app/Console/Commands/Correction/FixLongDescriptions.php +++ b/app/Console/Commands/Correction/FixLongDescriptions.php @@ -75,7 +75,6 @@ class FixLongDescriptions extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified all transaction group and journal title lengths in %s seconds.', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } } diff --git a/app/Console/Commands/Correction/FixPiggies.php b/app/Console/Commands/Correction/FixPiggies.php index faf61a361a..14243e1aa2 100644 --- a/app/Console/Commands/Correction/FixPiggies.php +++ b/app/Console/Commands/Correction/FixPiggies.php @@ -98,7 +98,6 @@ class FixPiggies extends Command $end = round(microtime(true) - $start, 2); $this->line(sprintf('Verified the content of %d piggy bank events in %s seconds.', $set->count(), $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } } diff --git a/app/Console/Commands/Correction/FixRecurringTransactions.php b/app/Console/Commands/Correction/FixRecurringTransactions.php index 6c83c63e45..318fee0304 100644 --- a/app/Console/Commands/Correction/FixRecurringTransactions.php +++ b/app/Console/Commands/Correction/FixRecurringTransactions.php @@ -67,7 +67,6 @@ class FixRecurringTransactions extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Corrected recurring transactions %s seconds.', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Correction/FixUnevenAmount.php b/app/Console/Commands/Correction/FixUnevenAmount.php index a8e29d540f..d545d2f11e 100644 --- a/app/Console/Commands/Correction/FixUnevenAmount.php +++ b/app/Console/Commands/Correction/FixUnevenAmount.php @@ -75,7 +75,6 @@ class FixUnevenAmount extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified amount integrity in %s seconds', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Correction/RemoveBills.php b/app/Console/Commands/Correction/RemoveBills.php index 862d4bd851..4966c1887a 100644 --- a/app/Console/Commands/Correction/RemoveBills.php +++ b/app/Console/Commands/Correction/RemoveBills.php @@ -71,7 +71,6 @@ class RemoveBills extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified bills / journals in %s seconds', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } } diff --git a/app/Console/Commands/Correction/RenameMetaFields.php b/app/Console/Commands/Correction/RenameMetaFields.php index 7a32c509d0..0b1adad4f5 100644 --- a/app/Console/Commands/Correction/RenameMetaFields.php +++ b/app/Console/Commands/Correction/RenameMetaFields.php @@ -83,7 +83,6 @@ class RenameMetaFields extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Renamed meta fields in %s seconds', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Correction/TransferBudgets.php b/app/Console/Commands/Correction/TransferBudgets.php index 1f622aac9b..38b8a5684e 100644 --- a/app/Console/Commands/Correction/TransferBudgets.php +++ b/app/Console/Commands/Correction/TransferBudgets.php @@ -74,7 +74,6 @@ class TransferBudgets extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified budget/journals in %s seconds.', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } } diff --git a/app/Console/Commands/DecryptDatabase.php b/app/Console/Commands/DecryptDatabase.php index d0f06bdf5e..e1f48cc388 100644 --- a/app/Console/Commands/DecryptDatabase.php +++ b/app/Console/Commands/DecryptDatabase.php @@ -123,7 +123,6 @@ class DecryptDatabase extends Command } $this->info('Done!'); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Export/ExportData.php b/app/Console/Commands/Export/ExportData.php index 7a18f5ca7e..e187b8ef9c 100644 --- a/app/Console/Commands/Export/ExportData.php +++ b/app/Console/Commands/Export/ExportData.php @@ -137,11 +137,11 @@ class ExportData extends Command } catch (FireflyException $e) { $this->error(sprintf('Could not store data: %s', $e->getMessage())); - // app('telemetry')->feature('executed-command-with-error', $this->signature); + app('telemetry')->feature('system.command.errored', $this->signature); return 1; } - // app('telemetry')->feature('executed-command', $this->signature); + app('telemetry')->feature('system.command.executed', $this->signature); return 0; } diff --git a/app/Console/Commands/Import/CreateCSVImport.php b/app/Console/Commands/Import/CreateCSVImport.php index 537d8bdc96..3da93f17d8 100644 --- a/app/Console/Commands/Import/CreateCSVImport.php +++ b/app/Console/Commands/Import/CreateCSVImport.php @@ -63,279 +63,14 @@ class CreateCSVImport extends Command {configuration? : The configuration file to use for the import.} {--user=1 : The user ID that the import should import for.} {--token= : The user\'s access token.}'; - /** @var ImportJob */ - private $importJob; - /** @var ImportJobRepositoryInterface */ - private $importRepository; - /** @var UserRepositoryInterface */ - private $userRepository; - /** * Run the command. */ public function handle(): int { - $this->stupidLaravel(); - // @codeCoverageIgnoreStart - if (!$this->verifyAccessToken()) { - $this->errorLine('Invalid access token.'); - - return 1; - } - - if (!$this->validArguments()) { - $this->errorLine('Invalid arguments.'); - - return 1; - } - // @codeCoverageIgnoreEnd - /** @var User $user */ - $user = $this->userRepository->findNull((int) $this->option('user')); - $file = (string) $this->argument('file'); - $configuration = (string) $this->argument('configuration'); - - $this->importRepository->setUser($user); - - $configurationData = json_decode(file_get_contents($configuration), true, 512, JSON_THROW_ON_ERROR); - $this->importJob = $this->importRepository->create('file'); - - - // inform user (and log it) - $this->infoLine(sprintf('Import file : %s', $file)); - $this->infoLine(sprintf('Configuration file : %s', $configuration)); - $this->infoLine(sprintf('User : #%d (%s)', $user->id, $user->email)); - $this->infoLine(sprintf('Job : %s', $this->importJob->key)); - - try { - $this->storeFile($file); - } catch (FireflyException $e) { - $this->errorLine($e->getMessage()); - - return 1; - } - - // job is ready to go - $this->importRepository->setConfiguration($this->importJob, $configurationData); - $this->importRepository->setStatus($this->importJob, 'ready_to_run'); - - $this->infoLine('The import routine has started. The process is not visible. Please wait.'); - Log::debug('Go for import!'); - - - // keep repeating this call until job lands on "provider_finished" - try { - $this->processFile(); - } catch (FireflyException $e) { - $this->errorLine($e->getMessage()); - - // app('telemetry')->feature('executed-command-with-error', $this->signature); - return 1; - } - - // then store data: - try { - $this->storeData(); - } catch (FireflyException $e) { - $this->errorLine($e->getMessage()); - - // app('telemetry')->feature('executed-command-with-error', $this->signature); - return 1; - } - - // give feedback: - $this->giveFeedback(); - - // clear cache for user: - app('preferences')->setForUser($user, 'lastActivity', microtime()); - - // app('telemetry')->feature('executed-command', $this->signature); - return 0; + $this->error('This command is disabled.'); + return 1; } - /** - * @param string $message - * @param array|null $data - * - * @codeCoverageIgnore - */ - private function errorLine(string $message, array $data = null): void - { - Log::error($message, $data ?? []); - $this->error($message); - } - - /** - * - */ - private function giveFeedback(): void - { - $this->infoLine('Job has finished.'); - - - if (null !== $this->importJob->tag) { - $this->infoLine(sprintf('%d transaction(s) have been imported.', $this->importJob->tag->transactionJournals->count())); - $this->infoLine(sprintf('You can find your transactions under tag "%s"', $this->importJob->tag->tag)); - } - - if (null === $this->importJob->tag) { - $this->errorLine('No transactions have been imported :(.'); - } - if (count($this->importJob->errors) > 0) { - $this->infoLine(sprintf('%d error(s) occurred:', count($this->importJob->errors))); - foreach ($this->importJob->errors as $err) { - $this->errorLine('- ' . $err); - } - } - } - - /** - * @param string $message - * @param array $data - * - * @codeCoverageIgnore - */ - private function infoLine(string $message, array $data = null): void - { - Log::info($message, $data ?? []); - $this->line($message); - } - - /** - * Keep repeating import call until job lands on "provider_finished". - * - * @throws FireflyException - */ - private function processFile(): void - { - $className = config('import.routine.file'); - $valid = ['provider_finished']; - $count = 0; - - while (!in_array($this->importJob->status, $valid, true) && $count < 6) { - Log::debug(sprintf('Now in loop #%d.', $count + 1)); - /** @var RoutineInterface $routine */ - $routine = app($className); - $routine->setImportJob($this->importJob); - try { - $routine->run(); - } catch (FireflyException|Exception $e) { - $message = 'The import routine crashed: ' . $e->getMessage(); - Log::error($message); - Log::error($e->getTraceAsString()); - - // set job errored out: - $this->importRepository->setStatus($this->importJob, 'error'); - throw new FireflyException($message); - } - $count++; - } - $this->importRepository->setStatus($this->importJob, 'provider_finished'); - $this->importJob->status = 'provider_finished'; - } - - /** - * - * @throws FireflyException - */ - private function storeData(): void - { - if ('provider_finished' === $this->importJob->status) { - $this->infoLine('Import has finished. Please wait for storage of data.'); - // set job to be storing data: - $this->importRepository->setStatus($this->importJob, 'storing_data'); - - /** @var ImportArrayStorage $storage */ - $storage = app(ImportArrayStorage::class); - $storage->setImportJob($this->importJob); - - try { - $storage->store(); - } catch (FireflyException|Exception $e) { - $message = 'The import routine crashed: ' . $e->getMessage(); - Log::error($message); - Log::error($e->getTraceAsString()); - - // set job errored out: - $this->importRepository->setStatus($this->importJob, 'error'); - throw new FireflyException($message); - - } - // set storage to be finished: - $this->importRepository->setStatus($this->importJob, 'storage_finished'); - } - } - - /** - * Store the supplied file as an attachment to this job. - * - * @param string $file - * - * @throws FireflyException - */ - private function storeFile(string $file): void - { - // store file as attachment. - if ('' !== $file) { - $messages = $this->importRepository->storeCLIUpload($this->importJob, 'import_file', $file); - if ($messages->count() > 0) { - throw new FireflyException($messages->first()); - } - } - } - - /** - * Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is - * executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should - * be called from the handle method instead of using the constructor to initialize the command. - * - * @codeCoverageIgnore - */ - private function stupidLaravel(): void - { - $this->userRepository = app(UserRepositoryInterface::class); - $this->importRepository = app(ImportJobRepositoryInterface::class); - } - - /** - * Verify user inserts correct arguments. - * - * @noinspection MultipleReturnStatementsInspection - * @return bool - * @codeCoverageIgnore - */ - private function validArguments(): bool - { - $file = (string) $this->argument('file'); - $configuration = (string) $this->argument('configuration'); - $cwd = getcwd(); - $enabled = (bool) config('import.enabled.file'); - - if (false === $enabled) { - $this->errorLine('CSV Provider is not enabled.'); - - return false; - } - - if (!file_exists($file)) { - $this->errorLine(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd)); - - return false; - } - - if (!file_exists($configuration)) { - $this->errorLine(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd)); - - return false; - } - - $configurationData = json_decode(file_get_contents($configuration), true, 512, JSON_THROW_ON_ERROR); - if (null === $configurationData) { - $this->errorLine(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd)); - - return false; - } - - return true; - } } diff --git a/app/Console/Commands/Integrity/ReportEmptyObjects.php b/app/Console/Commands/Integrity/ReportEmptyObjects.php index 2607a5ef8c..4cca37288b 100644 --- a/app/Console/Commands/Integrity/ReportEmptyObjects.php +++ b/app/Console/Commands/Integrity/ReportEmptyObjects.php @@ -64,7 +64,6 @@ class ReportEmptyObjects extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Report on empty objects finished in %s seconds', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Integrity/ReportIntegrity.php b/app/Console/Commands/Integrity/ReportIntegrity.php index 5a5db4356e..62e45ed110 100644 --- a/app/Console/Commands/Integrity/ReportIntegrity.php +++ b/app/Console/Commands/Integrity/ReportIntegrity.php @@ -69,7 +69,6 @@ class ReportIntegrity extends Command echo $result; } - // app('telemetry')->feature('executed-command', $this->signature); return 0; } } diff --git a/app/Console/Commands/Integrity/ReportSum.php b/app/Console/Commands/Integrity/ReportSum.php index 6485bddddd..2f24e1f00a 100644 --- a/app/Console/Commands/Integrity/ReportSum.php +++ b/app/Console/Commands/Integrity/ReportSum.php @@ -54,7 +54,6 @@ class ReportSum extends Command { $this->reportSum(); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Integrity/RestoreOAuthKeys.php b/app/Console/Commands/Integrity/RestoreOAuthKeys.php index ad7fe3fb42..6efce94e4d 100644 --- a/app/Console/Commands/Integrity/RestoreOAuthKeys.php +++ b/app/Console/Commands/Integrity/RestoreOAuthKeys.php @@ -24,6 +24,7 @@ namespace FireflyIII\Console\Commands\Integrity; use FireflyIII\Support\System\OAuthKeys; use Illuminate\Console\Command; +use Log; /** * Class RestoreOAuthKeys @@ -52,7 +53,6 @@ class RestoreOAuthKeys extends Command { $this->restoreOAuthKeys(); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } @@ -93,7 +93,9 @@ class RestoreOAuthKeys extends Command */ private function restoreOAuthKeys(): void { + Log::debug('Going to restoreOAuthKeys()'); if (!$this->keysInDatabase() && !$this->keysOnDrive()) { + Log::debug('Keys are not in DB and keys are not on the drive.'); $this->generateKeys(); $this->storeKeysInDB(); $this->line('Generated and stored new keys.'); @@ -101,12 +103,14 @@ class RestoreOAuthKeys extends Command return; } if ($this->keysInDatabase() && !$this->keysOnDrive()) { + Log::debug('Keys are in DB and keys are not on the drive. Restore.'); $this->restoreKeysFromDB(); $this->line('Restored OAuth keys from database.'); return; } if (!$this->keysInDatabase() && $this->keysOnDrive()) { + Log::debug('Keys are not in DB and keys are on the drive. Save in DB.'); $this->storeKeysInDB(); $this->line('Stored OAuth keys in database.'); diff --git a/app/Console/Commands/ScanAttachments.php b/app/Console/Commands/ScanAttachments.php index 9a2c4a4655..21af60f99d 100644 --- a/app/Console/Commands/ScanAttachments.php +++ b/app/Console/Commands/ScanAttachments.php @@ -86,7 +86,7 @@ class ScanAttachments extends Command $this->line(sprintf('Fixed attachment #%d', $attachment->id)); } - // app('telemetry')->feature('executed-command', $this->signature); + app('telemetry')->feature('system.command.executed', $this->signature); return 0; } } diff --git a/app/Console/Commands/SetLatestVersion.php b/app/Console/Commands/SetLatestVersion.php index 893b911941..0c3c1c9e36 100644 --- a/app/Console/Commands/SetLatestVersion.php +++ b/app/Console/Commands/SetLatestVersion.php @@ -59,7 +59,7 @@ class SetLatestVersion extends Command app('fireflyconfig')->set('ff3_version', config('firefly.version')); $this->line('Updated version.'); - // app('telemetry')->feature('executed-command', $this->signature); + app('telemetry')->feature('system.command.executed', $this->signature); return 0; } diff --git a/app/Console/Commands/Tools/ApplyRules.php b/app/Console/Commands/Tools/ApplyRules.php index 9973a9a8dc..8a9fd90b5b 100644 --- a/app/Console/Commands/Tools/ApplyRules.php +++ b/app/Console/Commands/Tools/ApplyRules.php @@ -112,7 +112,7 @@ class ApplyRules extends Command $result = $this->verifyInput(); if (false === $result) { - // app('telemetry')->feature('executed-command-with-error', $this->signature); + app('telemetry')->feature('system.command.errored', $this->signature); return 1; } @@ -131,7 +131,7 @@ class ApplyRules extends Command $this->warn(' --rule_groups=1,2,...'); $this->warn(' --all_rules'); - // app('telemetry')->feature('executed-command-with-error', $this->signature); + app('telemetry')->feature('system.command.errored', $this->signature); return 1; } @@ -167,7 +167,7 @@ class ApplyRules extends Command $this->line(''); $this->line('Done!'); - // app('telemetry')->feature('executed-command', $this->signature); + app('telemetry')->feature('system.command.executed', $this->signature); return 0; } diff --git a/app/Console/Commands/Tools/Cron.php b/app/Console/Commands/Tools/Cron.php index 328b473b07..e37676718a 100644 --- a/app/Console/Commands/Tools/Cron.php +++ b/app/Console/Commands/Tools/Cron.php @@ -94,10 +94,10 @@ class Cron extends Command } /* - * Fire telemetry cron job (disabled): + * Fire telemetry cron job */ try { - //$this->telemetryCronJob($force, $date); + $this->telemetryCronJob($force, $date); } catch (FireflyException $e) { Log::error($e->getMessage()); Log::error($e->getTraceAsString()); @@ -106,7 +106,7 @@ class Cron extends Command $this->info('More feedback on the cron jobs can be found in the log files.'); - // app('telemetry')->feature('executed-command', $this->signature); + app('telemetry')->feature('system.command.executed', $this->signature); return 0; } diff --git a/app/Console/Commands/Upgrade/AccountCurrencies.php b/app/Console/Commands/Upgrade/AccountCurrencies.php index 018a219ebc..f8bfc1410d 100644 --- a/app/Console/Commands/Upgrade/AccountCurrencies.php +++ b/app/Console/Commands/Upgrade/AccountCurrencies.php @@ -87,7 +87,6 @@ class AccountCurrencies extends Command $this->info(sprintf('Verified and fixed account currencies in %s seconds.', $end)); $this->markAsExecuted(); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Upgrade/BackToJournals.php b/app/Console/Commands/Upgrade/BackToJournals.php index 283f0e0903..bc6a2aead2 100644 --- a/app/Console/Commands/Upgrade/BackToJournals.php +++ b/app/Console/Commands/Upgrade/BackToJournals.php @@ -78,8 +78,6 @@ class BackToJournals extends Command $this->info(sprintf('Updated category and budget info for all transaction journals in %s seconds.', $end)); $this->markAsExecuted(); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } diff --git a/app/Console/Commands/Upgrade/BudgetLimitCurrency.php b/app/Console/Commands/Upgrade/BudgetLimitCurrency.php index 32e5955043..990b02bbf8 100644 --- a/app/Console/Commands/Upgrade/BudgetLimitCurrency.php +++ b/app/Console/Commands/Upgrade/BudgetLimitCurrency.php @@ -92,8 +92,6 @@ class BudgetLimitCurrency extends Command $this->markAsExecuted(); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } diff --git a/app/Console/Commands/Upgrade/CCLiabilities.php b/app/Console/Commands/Upgrade/CCLiabilities.php index 0d411bf360..e5904a7198 100644 --- a/app/Console/Commands/Upgrade/CCLiabilities.php +++ b/app/Console/Commands/Upgrade/CCLiabilities.php @@ -91,8 +91,6 @@ class CCLiabilities extends Command $this->info(sprintf('Verified credit card liabilities in %s seconds', $end)); $this->markAsExecuted(); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } diff --git a/app/Console/Commands/Upgrade/MigrateAttachments.php b/app/Console/Commands/Upgrade/MigrateAttachments.php index 595e78aa55..9e2270d7d2 100644 --- a/app/Console/Commands/Upgrade/MigrateAttachments.php +++ b/app/Console/Commands/Upgrade/MigrateAttachments.php @@ -101,8 +101,6 @@ class MigrateAttachments extends Command $this->info(sprintf('Migrated attachment notes in %s seconds.', $end)); $this->markAsExecuted(); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } diff --git a/app/Console/Commands/Upgrade/MigrateJournalNotes.php b/app/Console/Commands/Upgrade/MigrateJournalNotes.php index 1a19560810..a234c2948f 100644 --- a/app/Console/Commands/Upgrade/MigrateJournalNotes.php +++ b/app/Console/Commands/Upgrade/MigrateJournalNotes.php @@ -100,8 +100,6 @@ class MigrateJournalNotes extends Command $this->info(sprintf('Migrated notes in %s seconds.', $end)); $this->markAsExecuted(); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } diff --git a/app/Console/Commands/Upgrade/MigrateRecurrenceMeta.php b/app/Console/Commands/Upgrade/MigrateRecurrenceMeta.php index 5bccd92bec..bad0d6f1a2 100644 --- a/app/Console/Commands/Upgrade/MigrateRecurrenceMeta.php +++ b/app/Console/Commands/Upgrade/MigrateRecurrenceMeta.php @@ -72,8 +72,6 @@ class MigrateRecurrenceMeta extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Migrated recurrence meta data in %s seconds.', $end)); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } diff --git a/app/Console/Commands/Upgrade/MigrateTagLocations.php b/app/Console/Commands/Upgrade/MigrateTagLocations.php index bbada0a41d..e5009a60a0 100644 --- a/app/Console/Commands/Upgrade/MigrateTagLocations.php +++ b/app/Console/Commands/Upgrade/MigrateTagLocations.php @@ -65,7 +65,6 @@ class MigrateTagLocations extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Migrated tag locations in %s seconds.', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Upgrade/MigrateToGroups.php b/app/Console/Commands/Upgrade/MigrateToGroups.php index 7b85398825..29a922cad3 100644 --- a/app/Console/Commands/Upgrade/MigrateToGroups.php +++ b/app/Console/Commands/Upgrade/MigrateToGroups.php @@ -112,8 +112,6 @@ class MigrateToGroups extends Command $this->markAsMigrated(); - // app('telemetry')->feature('executed-command', $this->signature); - return 0; } diff --git a/app/Console/Commands/Upgrade/MigrateToRules.php b/app/Console/Commands/Upgrade/MigrateToRules.php index a29188433c..d751ffa7cd 100644 --- a/app/Console/Commands/Upgrade/MigrateToRules.php +++ b/app/Console/Commands/Upgrade/MigrateToRules.php @@ -99,7 +99,6 @@ class MigrateToRules extends Command $this->info(sprintf('Verified and fixed bills in %s seconds.', $end)); $this->markAsExecuted(); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Upgrade/OtherCurrenciesCorrections.php b/app/Console/Commands/Upgrade/OtherCurrenciesCorrections.php index 5c1f5d8187..d021e088ff 100644 --- a/app/Console/Commands/Upgrade/OtherCurrenciesCorrections.php +++ b/app/Console/Commands/Upgrade/OtherCurrenciesCorrections.php @@ -90,7 +90,6 @@ class OtherCurrenciesCorrections extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified and fixed transaction currencies in %s seconds.', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Upgrade/RenameAccountMeta.php b/app/Console/Commands/Upgrade/RenameAccountMeta.php index 355e403c41..6a6e369a8d 100644 --- a/app/Console/Commands/Upgrade/RenameAccountMeta.php +++ b/app/Console/Commands/Upgrade/RenameAccountMeta.php @@ -91,7 +91,6 @@ class RenameAccountMeta extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Fixed account meta data in %s seconds.', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Upgrade/TransactionIdentifier.php b/app/Console/Commands/Upgrade/TransactionIdentifier.php index c8f79c4b6c..a60db0b924 100644 --- a/app/Console/Commands/Upgrade/TransactionIdentifier.php +++ b/app/Console/Commands/Upgrade/TransactionIdentifier.php @@ -101,7 +101,6 @@ class TransactionIdentifier extends Command $this->info(sprintf('Verified and fixed transaction identifiers in %s seconds.', $end)); $this->markAsExecuted(); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Upgrade/TransferCurrenciesCorrections.php b/app/Console/Commands/Upgrade/TransferCurrenciesCorrections.php index 64ccbeb9d7..90023cbb92 100644 --- a/app/Console/Commands/Upgrade/TransferCurrenciesCorrections.php +++ b/app/Console/Commands/Upgrade/TransferCurrenciesCorrections.php @@ -111,7 +111,6 @@ class TransferCurrenciesCorrections extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified and fixed currency information for transfers in %s seconds.', $end)); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/Upgrade/UpgradeDatabase.php b/app/Console/Commands/Upgrade/UpgradeDatabase.php index 28dd57256b..9c330c9554 100644 --- a/app/Console/Commands/Upgrade/UpgradeDatabase.php +++ b/app/Console/Commands/Upgrade/UpgradeDatabase.php @@ -117,7 +117,6 @@ class UpgradeDatabase extends Command // index will set FF3 version. app('fireflyconfig')->set('ff3_version', (string) config('firefly.version')); - // app('telemetry')->feature('executed-command', $this->signature); return 0; } diff --git a/app/Console/Commands/UpgradeFireflyInstructions.php b/app/Console/Commands/UpgradeFireflyInstructions.php index a7ded8703e..5a70f5936d 100644 --- a/app/Console/Commands/UpgradeFireflyInstructions.php +++ b/app/Console/Commands/UpgradeFireflyInstructions.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Console\Commands; +use FireflyIII\Support\System\GeneratesInstallationId; use Illuminate\Console\Command; /** @@ -32,6 +33,8 @@ use Illuminate\Console\Command; */ class UpgradeFireflyInstructions extends Command { + use GeneratesInstallationId; + /** * The console command description. * @@ -50,6 +53,7 @@ class UpgradeFireflyInstructions extends Command */ public function handle(): int { + $this->generateInstallationId(); if ('update' === (string) $this->argument('task')) { $this->updateInstructions(); } @@ -57,7 +61,14 @@ class UpgradeFireflyInstructions extends Command $this->installInstructions(); } - // app('telemetry')->feature('executed-command', $this->signature); + // collect system telemetry + $isDocker = true === env('IS_DOCKER', false) ? 'true' : 'false'; + app('telemetry')->feature('system.php.version', PHP_VERSION); + app('telemetry')->feature('system.os.version', PHP_OS); + app('telemetry')->feature('system.database.driver', env('DB_CONNECTION', '(unknown)')); + app('telemetry')->feature('system.os.is_docker', $isDocker); + app('telemetry')->feature('system.command.executed', $this->signature); + return 0; } diff --git a/app/Helpers/Collector/Extensions/AccountCollection.php b/app/Helpers/Collector/Extensions/AccountCollection.php index 28906281bb..819a87c3a8 100644 --- a/app/Helpers/Collector/Extensions/AccountCollection.php +++ b/app/Helpers/Collector/Extensions/AccountCollection.php @@ -230,4 +230,4 @@ trait AccountCollection return $this; } -} \ No newline at end of file +} diff --git a/app/Helpers/Collector/Extensions/AmountCollection.php b/app/Helpers/Collector/Extensions/AmountCollection.php index 9eb4560c5e..719426bfcc 100644 --- a/app/Helpers/Collector/Extensions/AmountCollection.php +++ b/app/Helpers/Collector/Extensions/AmountCollection.php @@ -84,4 +84,4 @@ trait AmountCollection return $this; } -} \ No newline at end of file +} diff --git a/app/Helpers/Collector/Extensions/CollectorProperties.php b/app/Helpers/Collector/Extensions/CollectorProperties.php index cfb23f656e..ae05ce6338 100644 --- a/app/Helpers/Collector/Extensions/CollectorProperties.php +++ b/app/Helpers/Collector/Extensions/CollectorProperties.php @@ -56,4 +56,4 @@ trait CollectorProperties private $total; /** @var User The user object. */ private $user; -} \ No newline at end of file +} diff --git a/app/Helpers/Collector/Extensions/MetaCollection.php b/app/Helpers/Collector/Extensions/MetaCollection.php index ef3df3b6ac..0f92abbbaf 100644 --- a/app/Helpers/Collector/Extensions/MetaCollection.php +++ b/app/Helpers/Collector/Extensions/MetaCollection.php @@ -288,4 +288,4 @@ trait MetaCollection } -} \ No newline at end of file +} diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 74ab8a9b63..6db9e4f5b1 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -131,6 +131,7 @@ class LoginController extends Controller return redirect(route('register')); // @codeCoverageIgnore } + // is allowed to? $singleUserMode = app('fireflyconfig')->get('single_user_mode', config('firefly.configuration.single_user_mode'))->data; $allowRegistration = true; @@ -148,6 +149,9 @@ class LoginController extends Controller $email = $request->old('email'); $remember = $request->old('remember'); + // todo must forget 2FA if user ends up here. + + return view('auth.login', compact('allowRegistration', 'email', 'remember', 'allowReset', 'title')); } diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index f6671ee5a2..a471c65156 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -104,6 +104,9 @@ class RegisterController extends Controller $this->registered($request, $user); + // telemetry + \Telemetry::feature('system.users.count', User::count()); + return redirect($this->redirectPath()); } diff --git a/app/Http/Controllers/BillController.php b/app/Http/Controllers/BillController.php index d8c02e30e9..2c12d48479 100644 --- a/app/Http/Controllers/BillController.php +++ b/app/Http/Controllers/BillController.php @@ -284,7 +284,7 @@ class BillController extends Controller } - $request->session()->flash('success', (string) trans('firefly.rescanned_bill', ['total' => $total])); + $request->session()->flash('success', (string) trans_choice('firefly.rescanned_bill', $total)); app('preferences')->mark(); return redirect(route('bills.show', [$bill->id])); diff --git a/app/Http/Controllers/Budget/AvailableBudgetController.php b/app/Http/Controllers/Budget/AvailableBudgetController.php index 4d1047cc53..080ca541ae 100644 --- a/app/Http/Controllers/Budget/AvailableBudgetController.php +++ b/app/Http/Controllers/Budget/AvailableBudgetController.php @@ -177,12 +177,26 @@ class AvailableBudgetController extends Controller $end = session()->get('end'); Log::info($e->getMessage()); } + + // validate amount + $amount = (string) $request->get('amount'); + if ('' === $amount) { + session()->flash('error', trans('firefly.invalid_amount')); + + return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); + } + if (0 === bccomp('0', $amount)) { + session()->flash('error', trans('firefly.invalid_amount')); + + return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); + } + // find currency $currency = $this->currencyRepos->find((int) $request->get('currency_id')); if (null === $currency) { session()->flash('error', trans('firefly.invalid_currency')); - return redirect(route('budgets.index')); + return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); } // find existing AB @@ -190,7 +204,7 @@ class AvailableBudgetController extends Controller if (null === $existing) { $this->abRepository->store( [ - 'amount' => $request->get('amount'), + 'amount' => $amount, 'currency' => $currency, 'start' => $start, 'end' => $end, @@ -199,7 +213,7 @@ class AvailableBudgetController extends Controller } if (null !== $existing) { // update amount: - $this->abRepository->update($existing, ['amount' => $request->get('amount')]); + $this->abRepository->update($existing, ['amount' => $amount]); } session()->flash('success', trans('firefly.set_ab')); @@ -217,7 +231,21 @@ class AvailableBudgetController extends Controller */ public function update(Request $request, AvailableBudget $availableBudget, Carbon $start, Carbon $end) { - $this->abRepository->update($availableBudget, ['amount' => $request->get('amount')]); + // validate amount + $amount = (string) $request->get('amount'); + if ('' === $amount) { + session()->flash('error', trans('firefly.invalid_amount')); + + return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); + } + if (0 === bccomp('0', $amount)) { + session()->flash('error', trans('firefly.invalid_amount')); + + return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); + } + + + $this->abRepository->update($availableBudget, ['amount' => $amount]); session()->flash('success', trans('firefly.updated_ab')); return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); diff --git a/app/Http/Controllers/Budget/BudgetLimitController.php b/app/Http/Controllers/Budget/BudgetLimitController.php index 2fa75e527f..7e16f4f793 100644 --- a/app/Http/Controllers/Budget/BudgetLimitController.php +++ b/app/Http/Controllers/Budget/BudgetLimitController.php @@ -132,6 +132,7 @@ class BudgetLimitController extends Controller */ public function store(Request $request) { + Log::debug('Going to store new budget-limit.', $request->all()); // first search for existing one and update it if necessary. $currency = $this->currencyRepos->find((int) $request->get('transaction_currency_id')); $budget = $this->repository->findNull((int) $request->get('budget_id')); @@ -143,7 +144,6 @@ class BudgetLimitController extends Controller $start->startOfDay(); $end->endOfDay(); - Log::debug(sprintf('Start: %s, end: %s', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s'))); $limit = $this->blRepository->find($budget, $currency, $start, $end); diff --git a/app/Http/Controllers/DebugController.php b/app/Http/Controllers/DebugController.php index f887a5b833..03eb6b2d83 100644 --- a/app/Http/Controllers/DebugController.php +++ b/app/Http/Controllers/DebugController.php @@ -121,11 +121,11 @@ class DebugController extends Controller $search = ['~', '#']; $replace = ['\~', '# ']; + $now = Carbon::now()->format('Y-m-d H:i:s e'); $installationId = app('fireflyconfig')->get('installation_id', '')->data; $phpVersion = str_replace($search, $replace, PHP_VERSION); $phpOs = str_replace($search, $replace, PHP_OS); $interface = PHP_SAPI; - $now = Carbon::now()->format('Y-m-d H:i:s e'); $drivers = implode(', ', DB::availableDrivers()); $currentDriver = DB::getDriverName(); $userAgent = $request->header('user-agent'); @@ -137,14 +137,23 @@ class DebugController extends Controller $logChannel = config('logging.default'); $appLogLevel = config('logging.level'); $cacheDriver = config('cache.default'); - $loginProvider = config('auth.driver'); + $loginProvider = config('auth.providers.users.driver'); + + // some new vars. + $telemetry = true === config('firefly.send_telemetry') && true === config('firefly.feature_flags.telemetry'); + $defaultLanguage = (string) config('firefly.default_language'); + $defaultLocale = (string) config('firefly.default_locale'); + $userLanguage = app('steam')->getLanguage(); + $userLocale = app('steam')->getLocale(); + $isDocker = env('IS_DOCKER', false); // set languages, see what happens: $original = setlocale(LC_ALL, 0); $localeAttempts = []; $parts = app('steam')->getLocaleArray(app('steam')->getLocale()); foreach ($parts as $code) { - $code = trim($code); + $code = trim($code); + Log::debug(sprintf('Trying to set %s', $code)); $localeAttempts[$code] = var_export(setlocale(LC_ALL, $code), true); } setlocale(LC_ALL, $original); @@ -194,7 +203,14 @@ class DebugController extends Controller 'interface', 'logContent', 'cacheDriver', - 'trustedProxies' + 'trustedProxies', + 'telemetry', + 'userLanguage', + 'userLocale', + 'defaultLanguage', + 'defaultLocale', + 'isDocker' + ) ); } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 270afd955f..7c315ac633 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -117,7 +117,7 @@ class HomeController extends Controller if (0 === $count) { return redirect(route('new-user.index')); } - $subTitle = (string) trans('firefly.welcomeBack'); + $subTitle = (string) trans('firefly.welcome_back'); $transactions = []; $frontPage = app('preferences')->get( 'frontPageAccounts', diff --git a/app/Http/Controllers/Json/BudgetController.php b/app/Http/Controllers/Json/BudgetController.php index bcdf5e9376..48abeb9f79 100644 --- a/app/Http/Controllers/Json/BudgetController.php +++ b/app/Http/Controllers/Json/BudgetController.php @@ -108,4 +108,4 @@ class BudgetController extends Controller ); } -} \ No newline at end of file +} diff --git a/app/Http/Controllers/NewUserController.php b/app/Http/Controllers/NewUserController.php index 579cb1d5ee..2d31ec34e0 100644 --- a/app/Http/Controllers/NewUserController.php +++ b/app/Http/Controllers/NewUserController.php @@ -124,6 +124,11 @@ class NewUserController extends Controller 'invoice_date' => false, 'internal_reference' => false, 'notes' => true, 'attachments' => true,]; app('preferences')->set('transaction_journal_optional_fields', $visibleFields); + // telemetry: user language preference + default language. + app('telemetry')->feature('config.firefly.default_language', config('firefly.default_language', 'en_US')); + app('telemetry')->feature('user.preferences.language', app('steam')->getLanguage()); + app('telemetry')->feature('user.preferences.locale', app('steam')->getLocale()); + session()->flash('success', (string) trans('firefly.stored_new_accounts_new_user')); app('preferences')->mark(); diff --git a/app/Http/Controllers/PiggyBankController.php b/app/Http/Controllers/PiggyBankController.php index 2890991529..d3a6853761 100644 --- a/app/Http/Controllers/PiggyBankController.php +++ b/app/Http/Controllers/PiggyBankController.php @@ -92,9 +92,7 @@ class PiggyBankController extends Controller */ public function add(PiggyBank $piggyBank) { - /** @var Carbon $date */ - $date = session('end', Carbon::now()->endOfMonth()); - $leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $date); + $leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, new Carbon); $savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank); $leftToSave = bcsub($piggyBank->targetamount, $savedSoFar); $maxAmount = min($leftOnAccount, $leftToSave); @@ -113,7 +111,7 @@ class PiggyBankController extends Controller public function addMobile(PiggyBank $piggyBank) { /** @var Carbon $date */ - $date = session('end', Carbon::now()->endOfMonth()); + $date = session('end', new Carbon); $leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $date); $savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank); $leftToSave = bcsub($piggyBank->targetamount, $savedSoFar); diff --git a/app/Http/Controllers/PreferencesController.php b/app/Http/Controllers/PreferencesController.php index 04cecdac1e..39c3d7460d 100644 --- a/app/Http/Controllers/PreferencesController.php +++ b/app/Http/Controllers/PreferencesController.php @@ -210,6 +210,11 @@ class PreferencesController extends Controller session()->flash('success', (string) trans('firefly.saved_preferences')); app('preferences')->mark(); + // telemetry: user language preference + default language. + app('telemetry')->feature('config.firefly.default_language', config('firefly.default_language', 'en_US')); + app('telemetry')->feature('user.preferences.language', app('steam')->getLanguage()); + app('telemetry')->feature('user.preferences.locale', app('steam')->getLocale()); + return redirect(route('preferences.index')); } } diff --git a/app/Http/Controllers/System/CronController.php b/app/Http/Controllers/System/CronController.php index df44ae8a7b..3baa9a8415 100644 --- a/app/Http/Controllers/System/CronController.php +++ b/app/Http/Controllers/System/CronController.php @@ -42,6 +42,7 @@ class CronController $results = []; $results[] = $this->runRecurring(); $results[] = $this->runAutoBudget(); + $results[] = $this->runTelemetry(); return implode("
\n", $results); } diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index 85e9ff526a..0d5cba455c 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -217,7 +217,7 @@ class TagController extends Controller $count++; } } - session()->flash('success', (string) trans('firefly.deleted_x_tags', ['count' => $count])); + session()->flash('success', (string) trans_choice('firefly.deleted_x_tags', $count)); return redirect(route('tags.index')); } diff --git a/app/Http/Controllers/Transaction/BulkController.php b/app/Http/Controllers/Transaction/BulkController.php index bb01495103..bbf72cc08c 100644 --- a/app/Http/Controllers/Transaction/BulkController.php +++ b/app/Http/Controllers/Transaction/BulkController.php @@ -118,7 +118,7 @@ class BulkController extends Controller } } app('preferences')->mark(); - $request->session()->flash('success', (string) trans('firefly.mass_edited_transactions_success', ['amount' => $count])); + $request->session()->flash('success', (string) trans_choice('firefly.mass_edited_transactions_success', $count)); // redirect to previous URL: return redirect($this->getPreviousUri('transactions.bulk-edit.uri')); diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index 1de06095fa..c5581e58a5 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -114,7 +114,7 @@ class MassController extends Controller app('preferences')->mark(); - session()->flash('success', (string) trans('firefly.mass_deleted_transactions_success', ['amount' => $count])); + session()->flash('success', (string) trans_choice('firefly.mass_deleted_transactions_success', $count)); // redirect to previous URL: return redirect($this->getPreviousUri('transactions.mass-delete.uri')); @@ -188,7 +188,7 @@ class MassController extends Controller } app('preferences')->mark(); - session()->flash('success', (string) trans('firefly.mass_edited_transactions_success', ['amount' => $count])); + session()->flash('success', (string) trans_choice('firefly.mass_edited_transactions_success', $count )); // redirect to previous URL: return redirect($this->getPreviousUri('transactions.mass-edit.uri')); diff --git a/app/Http/Controllers/Transaction/ShowController.php b/app/Http/Controllers/Transaction/ShowController.php index 901e523317..7a4ae30d31 100644 --- a/app/Http/Controllers/Transaction/ShowController.php +++ b/app/Http/Controllers/Transaction/ShowController.php @@ -99,8 +99,9 @@ class ShowController extends Controller $transformer->setParameters(new ParameterBag); $groupArray = $transformer->transformObject($transactionGroup); - // do some amount calculations: + // do some calculations: $amounts = $this->getAmounts($groupArray); + $accounts = $this->getAccounts($groupArray); // make sure notes are escaped but not double escaped. foreach ($groupArray['transactions'] as $index => $transaction) { @@ -127,7 +128,8 @@ class ShowController extends Controller 'groupArray', 'events', 'attachments', - 'links' + 'links', + 'accounts', ) ); } @@ -166,4 +168,31 @@ class ShowController extends Controller return $amounts; } + + /** + * @param array $group + * + * @return array + */ + private function getAccounts(array $group): array + { + $accounts = []; + + foreach ($group['transactions'] as $index => $transaction) { + $accounts['source'][] = [ + 'type' => $transaction['source_type'], + 'id' => $transaction['source_id'], + 'name' => $transaction['source_name'], + 'iban' => $transaction['source_iban'] ]; + $accounts['destination'][] = [ + 'type' => $transaction['destination_type'], + 'id' => $transaction['destination_id'], + 'name' => $transaction['destination_name'], + 'iban' => $transaction['destination_iban'] ]; + } + + $accounts['source'] = array_unique($accounts['source'], SORT_REGULAR); + $accounts['destination'] = array_unique($accounts['destination'], SORT_REGULAR); + return $accounts; + } } diff --git a/app/Http/Middleware/InstallationId.php b/app/Http/Middleware/InstallationId.php index 8e326da273..f8c7de54c3 100644 --- a/app/Http/Middleware/InstallationId.php +++ b/app/Http/Middleware/InstallationId.php @@ -26,8 +26,7 @@ namespace FireflyIII\Http\Middleware; use Closure; use FireflyIII\Exceptions\FireflyException; -use Log; -use Ramsey\Uuid\Uuid; +use FireflyIII\Support\System\GeneratesInstallationId; /** * @@ -35,6 +34,7 @@ use Ramsey\Uuid\Uuid; */ class InstallationId { + use GeneratesInstallationId; /** * Handle an incoming request. * @@ -48,13 +48,7 @@ class InstallationId */ public function handle($request, Closure $next) { - $config = app('fireflyconfig')->get('installation_id', null); - if (null === $config) { - $uuid5 = Uuid::uuid5(Uuid::NAMESPACE_URL, 'firefly-iii.org'); - $uniqueId = (string) $uuid5; - Log::info(sprintf('Created Firefly III installation ID %s', $uniqueId)); - app('fireflyconfig')->set('installation_id', $uniqueId); - } + $this->generateInstallationId(); return $next($request); } diff --git a/app/Http/Middleware/Range.php b/app/Http/Middleware/Range.php index b8a0ca8780..1d273c8124 100644 --- a/app/Http/Middleware/Range.php +++ b/app/Http/Middleware/Range.php @@ -28,6 +28,7 @@ use Closure; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Support\Http\Controllers\RequestInformation; use Illuminate\Http\Request; +use Log; /** * Class SessionFilter. @@ -87,6 +88,7 @@ class Range // send error to view if could not set money format if (false === $moneyResult) { + Log::error('Could not set locale. The following array doesnt work: ', $localeArray); app('view')->share('invalidMonetaryLocale', true); // @codeCoverageIgnore } diff --git a/app/Jobs/MailError.php b/app/Jobs/MailError.php index abcc87a586..f76818063a 100644 --- a/app/Jobs/MailError.php +++ b/app/Jobs/MailError.php @@ -84,7 +84,7 @@ class MailError extends Job implements ShouldQueue $args, function (Message $message) use ($email) { if ('mail@example.com' !== $email) { - $message->to($email, $email)->subject('Caught an error in Firefly III'); + $message->to($email, $email)->subject((string) trans('email.error_subject')); } } ); diff --git a/app/Jobs/SubmitTelemetryData.php b/app/Jobs/SubmitTelemetryData.php index f089ce4da6..3071748d8b 100644 --- a/app/Jobs/SubmitTelemetryData.php +++ b/app/Jobs/SubmitTelemetryData.php @@ -24,6 +24,7 @@ namespace FireflyIII\Jobs; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Telemetry; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; @@ -33,7 +34,9 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Collection; +use JsonException; use Log; +use Exception; /** * Class SubmitTelemetryData @@ -61,7 +64,7 @@ class SubmitTelemetryData implements ShouldQueue } /** - * + * @throws FireflyException */ public function handle(): void { @@ -77,9 +80,17 @@ class SubmitTelemetryData implements ShouldQueue } $json = $this->parseJson($telemetry); + try { + $body = json_encode($json, JSON_THROW_ON_ERROR, 512); + } catch (JsonException $e) { + Log::error($e->getMessage()); + Log::error('Could not parse JSON.'); + throw new FireflyException(sprintf('Could not parse telemetry JSON: %s', $e->getMessage())); + } + $client = new Client; $options = [ - 'body' => json_encode($json, JSON_THROW_ON_ERROR, 512), + 'body' => $body, 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', @@ -89,11 +100,11 @@ class SubmitTelemetryData implements ShouldQueue ]; try { $result = $client->post($url, $options); - } catch (GuzzleException $e) { + } catch (GuzzleException|Exception $e) { Log::error($e->getMessage()); Log::error($e->getTraceAsString()); Log::error('Could not submit telemetry.'); - return; + throw new FireflyException(sprintf('Could not submit telemetry: %s', $e->getMessage())); } $body = (string) $result->getBody(); $statusCode = $result->getStatusCode(); @@ -156,6 +167,7 @@ class SubmitTelemetryData implements ShouldQueue foreach ($telemetry as $entry) { $array[] = [ 'installation_id' => $entry->installation_id, + 'collected_at' => $entry->created_at->format('r'), 'type' => $entry->type, 'key' => $entry->key, 'value' => $entry->value, @@ -165,4 +177,4 @@ class SubmitTelemetryData implements ShouldQueue return $array; } -} \ No newline at end of file +} diff --git a/app/Mail/AccessTokenCreatedMail.php b/app/Mail/AccessTokenCreatedMail.php index 584a7b5eee..3837003be1 100644 --- a/app/Mail/AccessTokenCreatedMail.php +++ b/app/Mail/AccessTokenCreatedMail.php @@ -63,6 +63,6 @@ class AccessTokenCreatedMail extends Mailable public function build(): self { return $this->view('emails.access-token-created-html')->text('emails.access-token-created-text') - ->subject('A new access token was created'); + ->subject((string) trans('email.access_token_created_subject')); } } diff --git a/app/Mail/AdminTestMail.php b/app/Mail/AdminTestMail.php index 91d65bcba2..565672cde3 100644 --- a/app/Mail/AdminTestMail.php +++ b/app/Mail/AdminTestMail.php @@ -62,6 +62,6 @@ class AdminTestMail extends Mailable public function build(): self { return $this->view('emails.admin-test-html')->text('emails.admin-test-text') - ->subject('A test message from your Firefly III installation'); + ->subject((string) trans('email.admin_test_subject')); } } diff --git a/app/Mail/ConfirmEmailChangeMail.php b/app/Mail/ConfirmEmailChangeMail.php index 1e7be38f1a..21f60197ca 100644 --- a/app/Mail/ConfirmEmailChangeMail.php +++ b/app/Mail/ConfirmEmailChangeMail.php @@ -70,6 +70,6 @@ class ConfirmEmailChangeMail extends Mailable public function build(): self { return $this->view('emails.confirm-email-change-html')->text('emails.confirm-email-change-text') - ->subject('Your Firefly III email address has changed'); + ->subject((string) trans('email.email_change_subject')); } } diff --git a/app/Mail/OAuthTokenCreatedMail.php b/app/Mail/OAuthTokenCreatedMail.php index ad3dbfb474..1d2d4cced8 100644 --- a/app/Mail/OAuthTokenCreatedMail.php +++ b/app/Mail/OAuthTokenCreatedMail.php @@ -67,6 +67,6 @@ class OAuthTokenCreatedMail extends Mailable public function build(): self { return $this->view('emails.oauth-client-created-html')->text('emails.oauth-client-created-text') - ->subject('A new OAuth client has been created'); + ->subject((string) trans('email.oauth_created_subject')); } } diff --git a/app/Mail/RegisteredUser.php b/app/Mail/RegisteredUser.php index edda7e6885..1abd4d6caa 100644 --- a/app/Mail/RegisteredUser.php +++ b/app/Mail/RegisteredUser.php @@ -61,6 +61,6 @@ class RegisteredUser extends Mailable */ public function build(): self { - return $this->view('emails.registered-html')->text('emails.registered-text')->subject('Welcome to Firefly III!'); + return $this->view('emails.registered-html')->text('emails.registered-text')->subject((string) trans('email.registered_subject')); } } diff --git a/app/Mail/ReportNewJournalsMail.php b/app/Mail/ReportNewJournalsMail.php index 26da94db1d..a72321dd0c 100644 --- a/app/Mail/ReportNewJournalsMail.php +++ b/app/Mail/ReportNewJournalsMail.php @@ -79,7 +79,7 @@ class ReportNewJournalsMail extends Mailable $this->transform(); return $this->view('emails.report-new-journals-html')->text('emails.report-new-journals-text') - ->subject($subject); + ->subject((string) trans_choice('email.new_journals_subject', $this->groups->count())); } private function transform(): void diff --git a/app/Mail/RequestedNewPassword.php b/app/Mail/RequestedNewPassword.php index f1bb6c9b75..a3d2a83a9a 100644 --- a/app/Mail/RequestedNewPassword.php +++ b/app/Mail/RequestedNewPassword.php @@ -60,6 +60,6 @@ class RequestedNewPassword extends Mailable */ public function build(): self { - return $this->view('emails.password-html')->text('emails.password-text')->subject('Your password reset request'); + return $this->view('emails.password-html')->text('emails.password-text')->subject((string) trans('email.reset_pw_subject')); } } diff --git a/app/Mail/UndoEmailChangeMail.php b/app/Mail/UndoEmailChangeMail.php index dd54a573ef..93cc2979c4 100644 --- a/app/Mail/UndoEmailChangeMail.php +++ b/app/Mail/UndoEmailChangeMail.php @@ -68,6 +68,6 @@ class UndoEmailChangeMail extends Mailable public function build(): self { return $this->view('emails.undo-email-change-html')->text('emails.undo-email-change-text') - ->subject('Your Firefly III email address has changed'); + ->subject((string) trans('email.email_change_subject')); } } diff --git a/app/Models/ObjectGroup.php b/app/Models/ObjectGroup.php new file mode 100644 index 0000000000..74a4dc3647 --- /dev/null +++ b/app/Models/ObjectGroup.php @@ -0,0 +1,21 @@ +morphedByMany(PiggyBank::class, 'object_groupable'); + } +} diff --git a/app/Models/PiggyBank.php b/app/Models/PiggyBank.php index 732cb98c98..4b9f3af2f8 100644 --- a/app/Models/PiggyBank.php +++ b/app/Models/PiggyBank.php @@ -126,6 +126,14 @@ class PiggyBank extends Model throw new NotFoundHttpException; } + /** + * Get all of the tags for the post. + */ + public function objectGroups() + { + return $this->morphToMany(ObjectGroup::class, 'object_groupable'); + } + /** * @codeCoverageIgnore * @return MorphMany diff --git a/app/Models/Telemetry.php b/app/Models/Telemetry.php index 521f4e18c1..b45593cd94 100644 --- a/app/Models/Telemetry.php +++ b/app/Models/Telemetry.php @@ -72,4 +72,4 @@ class Telemetry extends Model 'value' => 'array', ]; -} \ No newline at end of file +} diff --git a/app/Repositories/Account/OperationsRepository.php b/app/Repositories/Account/OperationsRepository.php index 7bedce6638..b7458808fa 100644 --- a/app/Repositories/Account/OperationsRepository.php +++ b/app/Repositories/Account/OperationsRepository.php @@ -198,4 +198,4 @@ class OperationsRepository implements OperationsRepositoryInterface { throw new FireflyException(sprintf('%s is not yet implemented', __METHOD__)); } -} \ No newline at end of file +} diff --git a/app/Repositories/Account/OperationsRepositoryInterface.php b/app/Repositories/Account/OperationsRepositoryInterface.php index 001151b4c2..04a5c214f9 100644 --- a/app/Repositories/Account/OperationsRepositoryInterface.php +++ b/app/Repositories/Account/OperationsRepositoryInterface.php @@ -84,4 +84,4 @@ interface OperationsRepositoryInterface * @return array */ public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null): array; -} \ No newline at end of file +} diff --git a/app/Repositories/Budget/AvailableBudgetRepository.php b/app/Repositories/Budget/AvailableBudgetRepository.php index c8602e290d..127df8f18b 100644 --- a/app/Repositories/Budget/AvailableBudgetRepository.php +++ b/app/Repositories/Budget/AvailableBudgetRepository.php @@ -302,4 +302,4 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface ->where('start_date', $start->format('Y-m-d 00:00:00')) ->where('end_date', $end->format('Y-m-d 00:00:00'))->first(); } -} \ No newline at end of file +} diff --git a/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php b/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php index 4d930241a6..d631233669 100644 --- a/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php +++ b/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php @@ -154,4 +154,4 @@ interface AvailableBudgetRepositoryInterface */ public function updateAvailableBudget(AvailableBudget $availableBudget, array $data): AvailableBudget; -} \ No newline at end of file +} diff --git a/app/Repositories/Budget/BudgetLimitRepository.php b/app/Repositories/Budget/BudgetLimitRepository.php index 127f1a6a5f..b725c943b8 100644 --- a/app/Repositories/Budget/BudgetLimitRepository.php +++ b/app/Repositories/Budget/BudgetLimitRepository.php @@ -463,4 +463,4 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface $budget->budgetlimits()->delete(); } } -} \ No newline at end of file +} diff --git a/app/Repositories/Budget/BudgetLimitRepositoryInterface.php b/app/Repositories/Budget/BudgetLimitRepositoryInterface.php index c7c5c2ee33..c9813fe39a 100644 --- a/app/Repositories/Budget/BudgetLimitRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetLimitRepositoryInterface.php @@ -146,4 +146,4 @@ interface BudgetLimitRepositoryInterface */ public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): ?BudgetLimit; -} \ No newline at end of file +} diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index c68acfa141..a5ba5f1de6 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -330,7 +330,7 @@ class BudgetRepository implements BudgetRepositoryInterface // create initial budget limit. $today = new Carbon; $start = app('navigation')->startOfPeriod($today, $autoBudget->period); - $end = app('navigation')->startOfPeriod($start, $autoBudget->period); + $end = app('navigation')->endOfPeriod($start, $autoBudget->period); $limitRepos = app(BudgetLimitRepositoryInterface::class); $limitRepos->setUser($this->user); diff --git a/app/Repositories/Budget/NoBudgetRepository.php b/app/Repositories/Budget/NoBudgetRepository.php index 70e871170b..8e22217ff2 100644 --- a/app/Repositories/Budget/NoBudgetRepository.php +++ b/app/Repositories/Budget/NoBudgetRepository.php @@ -200,4 +200,4 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface return $array; } -} \ No newline at end of file +} diff --git a/app/Repositories/Budget/NoBudgetRepositoryInterface.php b/app/Repositories/Budget/NoBudgetRepositoryInterface.php index c23124caaa..ca58eebfef 100644 --- a/app/Repositories/Budget/NoBudgetRepositoryInterface.php +++ b/app/Repositories/Budget/NoBudgetRepositoryInterface.php @@ -70,4 +70,4 @@ interface NoBudgetRepositoryInterface */ public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array; -} \ No newline at end of file +} diff --git a/app/Repositories/Budget/OperationsRepository.php b/app/Repositories/Budget/OperationsRepository.php index 8e6c65b25f..c41cc732be 100644 --- a/app/Repositories/Budget/OperationsRepository.php +++ b/app/Repositories/Budget/OperationsRepository.php @@ -433,4 +433,4 @@ class OperationsRepository implements OperationsRepositoryInterface return $repos->getActiveBudgets(); } -} \ No newline at end of file +} diff --git a/app/Repositories/Budget/OperationsRepositoryInterface.php b/app/Repositories/Budget/OperationsRepositoryInterface.php index 8786c29f66..458a640d48 100644 --- a/app/Repositories/Budget/OperationsRepositoryInterface.php +++ b/app/Repositories/Budget/OperationsRepositoryInterface.php @@ -123,4 +123,4 @@ interface OperationsRepositoryInterface */ public function listExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null): array; -} \ No newline at end of file +} diff --git a/app/Repositories/Category/NoCategoryRepository.php b/app/Repositories/Category/NoCategoryRepository.php index 9243e01f30..b8581a2df8 100644 --- a/app/Repositories/Category/NoCategoryRepository.php +++ b/app/Repositories/Category/NoCategoryRepository.php @@ -240,4 +240,4 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface return $array; } -} \ No newline at end of file +} diff --git a/app/Repositories/Category/NoCategoryRepositoryInterface.php b/app/Repositories/Category/NoCategoryRepositoryInterface.php index d5cff14f6d..dd82a6aa2c 100644 --- a/app/Repositories/Category/NoCategoryRepositoryInterface.php +++ b/app/Repositories/Category/NoCategoryRepositoryInterface.php @@ -88,4 +88,4 @@ interface NoCategoryRepositoryInterface public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null): array; -} \ No newline at end of file +} diff --git a/app/Repositories/Category/OperationsRepository.php b/app/Repositories/Category/OperationsRepository.php index 8c76d46c18..4bef77b518 100644 --- a/app/Repositories/Category/OperationsRepository.php +++ b/app/Repositories/Category/OperationsRepository.php @@ -317,4 +317,4 @@ class OperationsRepository implements OperationsRepositoryInterface return $set; } -} \ No newline at end of file +} diff --git a/app/Repositories/Category/OperationsRepositoryInterface.php b/app/Repositories/Category/OperationsRepositoryInterface.php index e03697319b..f2fa4b4e5d 100644 --- a/app/Repositories/Category/OperationsRepositoryInterface.php +++ b/app/Repositories/Category/OperationsRepositoryInterface.php @@ -89,4 +89,4 @@ interface OperationsRepositoryInterface * @return array */ public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array; -} \ No newline at end of file +} diff --git a/app/Repositories/Tag/OperationsRepository.php b/app/Repositories/Tag/OperationsRepository.php index d9d26bca89..f0ac3bab99 100644 --- a/app/Repositories/Tag/OperationsRepository.php +++ b/app/Repositories/Tag/OperationsRepository.php @@ -251,4 +251,4 @@ class OperationsRepository implements OperationsRepositoryInterface return $repository->get(); } -} \ No newline at end of file +} diff --git a/app/Repositories/Tag/OperationsRepositoryInterface.php b/app/Repositories/Tag/OperationsRepositoryInterface.php index 496f985453..bb254c841b 100644 --- a/app/Repositories/Tag/OperationsRepositoryInterface.php +++ b/app/Repositories/Tag/OperationsRepositoryInterface.php @@ -90,4 +90,4 @@ interface OperationsRepositoryInterface * @return array */ public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $tags = null): array; -} \ No newline at end of file +} diff --git a/app/Repositories/Telemetry/TelemetryRepository.php b/app/Repositories/Telemetry/TelemetryRepository.php index bae61595d5..fc7f84bece 100644 --- a/app/Repositories/Telemetry/TelemetryRepository.php +++ b/app/Repositories/Telemetry/TelemetryRepository.php @@ -64,4 +64,4 @@ class TelemetryRepository implements TelemetryRepositoryInterface // created_at is never NULL. Telemetry::whereNotNull('submitted')->delete(); } -} \ No newline at end of file +} diff --git a/app/Repositories/Telemetry/TelemetryRepositoryInterface.php b/app/Repositories/Telemetry/TelemetryRepositoryInterface.php index 16f5dc749b..e4dc3d3dfd 100644 --- a/app/Repositories/Telemetry/TelemetryRepositoryInterface.php +++ b/app/Repositories/Telemetry/TelemetryRepositoryInterface.php @@ -56,4 +56,4 @@ interface TelemetryRepositoryInterface */ public function deleteSubmitted(): void; -} \ No newline at end of file +} diff --git a/app/Rules/IsTransferAccount.php b/app/Rules/IsTransferAccount.php index 851d04e234..d6d0620629 100644 --- a/app/Rules/IsTransferAccount.php +++ b/app/Rules/IsTransferAccount.php @@ -71,4 +71,4 @@ class IsTransferAccount implements Rule return !(false === $validAccount); } -} \ No newline at end of file +} diff --git a/app/Services/FireflyIIIOrg/Update/UpdateRequest.php b/app/Services/FireflyIIIOrg/Update/UpdateRequest.php index 2242f9a36a..10a4d44323 100644 --- a/app/Services/FireflyIIIOrg/Update/UpdateRequest.php +++ b/app/Services/FireflyIIIOrg/Update/UpdateRequest.php @@ -172,6 +172,7 @@ class UpdateRequest implements UpdateRequestInterface 'headers' => [ 'User-Agent' => sprintf('FireflyIII/%s/%s', config('firefly.version'), $channel), ], + 'timeout' => 3.1415 ]; $res = $client->request('GET', $uri, $options); } catch (GuzzleException|Exception $e) { @@ -217,4 +218,4 @@ class UpdateRequest implements UpdateRequestInterface return $return; } -} \ No newline at end of file +} diff --git a/app/Services/FireflyIIIOrg/Update/UpdateRequestInterface.php b/app/Services/FireflyIIIOrg/Update/UpdateRequestInterface.php index 6f7f7eb095..410dee0225 100644 --- a/app/Services/FireflyIIIOrg/Update/UpdateRequestInterface.php +++ b/app/Services/FireflyIIIOrg/Update/UpdateRequestInterface.php @@ -36,4 +36,4 @@ interface UpdateRequestInterface */ public function getUpdateInformation(string $channel): array; -} \ No newline at end of file +} diff --git a/app/Services/Internal/Support/LocationServiceTrait.php b/app/Services/Internal/Support/LocationServiceTrait.php index 5d8ffb21be..0cdaa0a21f 100644 --- a/app/Services/Internal/Support/LocationServiceTrait.php +++ b/app/Services/Internal/Support/LocationServiceTrait.php @@ -53,4 +53,4 @@ trait LocationServiceTrait return null; } -} \ No newline at end of file +} diff --git a/app/Support/Binder/AccountList.php b/app/Support/Binder/AccountList.php index dc6ef92b64..8b10330afd 100644 --- a/app/Support/Binder/AccountList.php +++ b/app/Support/Binder/AccountList.php @@ -52,11 +52,10 @@ class AccountList implements BinderInterface /** @var Collection $collection */ $collection = auth()->user()->accounts() ->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') - ->where('account_types.type', AccountType::ASSET) + ->whereIn('account_types.type', [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]) ->orderBy('accounts.name', 'ASC') ->get(['accounts.*']); } - if ('allAssetAccounts' !== $value) { $incoming = array_map('\intval', explode(',', $value)); $list = array_merge(array_unique($incoming), [0]); diff --git a/app/Support/Chart/Category/FrontpageChartGenerator.php b/app/Support/Chart/Category/FrontpageChartGenerator.php index 0e0a25631a..7a20ece942 100644 --- a/app/Support/Chart/Category/FrontpageChartGenerator.php +++ b/app/Support/Chart/Category/FrontpageChartGenerator.php @@ -264,4 +264,4 @@ class FrontpageChartGenerator return $currencyData; } -} \ No newline at end of file +} diff --git a/app/Support/Cronjobs/AutoBudgetCronjob.php b/app/Support/Cronjobs/AutoBudgetCronjob.php index c4c72827b5..60cce35976 100644 --- a/app/Support/Cronjobs/AutoBudgetCronjob.php +++ b/app/Support/Cronjobs/AutoBudgetCronjob.php @@ -86,4 +86,4 @@ class AutoBudgetCronjob extends AbstractCronjob app('fireflyconfig')->set('last_ab_job', (int)$this->date->format('U')); Log::info('Done with auto budget cron job task.'); } -} \ No newline at end of file +} diff --git a/app/Support/Cronjobs/TelemetryCronjob.php b/app/Support/Cronjobs/TelemetryCronjob.php index 8efd8c889f..b4f6cc7127 100644 --- a/app/Support/Cronjobs/TelemetryCronjob.php +++ b/app/Support/Cronjobs/TelemetryCronjob.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Cronjobs; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Jobs\SubmitTelemetryData; use FireflyIII\Models\Configuration; use Log; @@ -35,9 +36,17 @@ class TelemetryCronjob extends AbstractCronjob /** * @inheritDoc + * @throws FireflyException */ public function fire(): bool { + // do not fire if telemetry is disabled. + if (false === config('firefly.send_telemetry') || false === config('firefly.feature_flags.telemetry')) { + Log::warning('Telemetry is disabled. The cron job will do nothing.'); + return false; + } + + /** @var Configuration $config */ $config = app('fireflyconfig')->get('last_tm_job', 0); $lastTime = (int) $config->data; @@ -46,8 +55,8 @@ class TelemetryCronjob extends AbstractCronjob if (0 === $lastTime) { Log::info('Telemetry cron-job has never fired before.'); } - // less than half a day ago: - if ($lastTime > 0 && $diff <= 43200) { + // less than a week ago: + if ($lastTime > 0 && $diff <= 604800) { Log::info(sprintf('It has been %s since the telemetry cron-job has fired.', $diffForHumans)); if (false === $this->force) { Log::info('The cron-job will not fire now.'); @@ -60,8 +69,8 @@ class TelemetryCronjob extends AbstractCronjob Log::info('Execution of the telemetry cron-job has been FORCED.'); } } - - if ($lastTime > 0 && $diff > 43200) { + // more than a week ago. + if ($lastTime > 0 && $diff > 604799) { Log::info(sprintf('It has been %s since the telemetry cron-job has fired. It will fire now!', $diffForHumans)); } @@ -74,7 +83,7 @@ class TelemetryCronjob extends AbstractCronjob /** - * + * @throws FireflyException */ private function fireTelemetry(): void { @@ -84,7 +93,10 @@ class TelemetryCronjob extends AbstractCronjob $job->setDate($this->date); $job->setForce($this->force); $job->handle(); + + // TODO remove old, submitted telemetry data. + app('fireflyconfig')->set('last_tm_job', (int) $this->date->format('U')); Log::info('Done with telemetry cron job task.'); } -} \ No newline at end of file +} diff --git a/app/Support/ExpandedForm.php b/app/Support/ExpandedForm.php index c782df7c27..a92b013279 100644 --- a/app/Support/ExpandedForm.php +++ b/app/Support/ExpandedForm.php @@ -436,4 +436,33 @@ class ExpandedForm return $html; } + + /** + * @param null $value + * @param array|null $options + * + * @return string + */ + public function objectGroup($value = null, array $options = null): string + { + $name = 'object_group'; + $label = $this->label($name, $options); + $options = $this->expandOptionArray($name, $label, $options); + $classes = $this->getHolderClasses($name); + $value = $this->fillFieldValue($name, $value); + $options['rows'] = 4; + + if (null === $value) { + $value = ''; + } + + try { + $html = view('form.object_group', compact('classes', 'name', 'label', 'value', 'options'))->render(); + } catch (Throwable $e) { + Log::debug(sprintf('Could not render objectGroup(): %s', $e->getMessage())); + $html = 'Could not render objectGroup.'; + } + + return $html; + } } diff --git a/app/Support/Http/Controllers/CronRunner.php b/app/Support/Http/Controllers/CronRunner.php index df513b291a..f5fb065f69 100644 --- a/app/Support/Http/Controllers/CronRunner.php +++ b/app/Support/Http/Controllers/CronRunner.php @@ -26,6 +26,7 @@ namespace FireflyIII\Support\Http\Controllers; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Support\Cronjobs\AutoBudgetCronjob; use FireflyIII\Support\Cronjobs\RecurringCronjob; +use FireflyIII\Support\Cronjobs\TelemetryCronjob; /** * Trait CronRunner @@ -51,6 +52,24 @@ trait CronRunner return 'The recurring transaction cron job fired successfully.'; } + /** + * @return string + */ + protected function runTelemetry(): string { + /** @var TelemetryCronjob $telemetry */ + $telemetry = app(TelemetryCronjob::class); + try { + $result = $telemetry->fire(); + } catch (FireflyException $e) { + return $e->getMessage(); + } + if (false === $result) { + return 'The telemetry cron job did not fire.'; + } + + return 'The telemetry cron job fired successfully.'; + } + /** * @return string */ diff --git a/app/Support/Search/AccountSearch.php b/app/Support/Search/AccountSearch.php index 9eb9aeef64..6badb4291c 100644 --- a/app/Support/Search/AccountSearch.php +++ b/app/Support/Search/AccountSearch.php @@ -143,4 +143,4 @@ class AccountSearch implements GenericSearchInterface $this->user = $user; } -} \ No newline at end of file +} diff --git a/app/Support/Search/GenericSearchInterface.php b/app/Support/Search/GenericSearchInterface.php index 1ca809d1ca..016b1f6820 100644 --- a/app/Support/Search/GenericSearchInterface.php +++ b/app/Support/Search/GenericSearchInterface.php @@ -35,4 +35,4 @@ interface GenericSearchInterface */ public function search(): Collection; -} \ No newline at end of file +} diff --git a/app/Support/Search/TransactionSearch.php b/app/Support/Search/TransactionSearch.php index 45080812d5..7f7aedf8c8 100644 --- a/app/Support/Search/TransactionSearch.php +++ b/app/Support/Search/TransactionSearch.php @@ -37,4 +37,4 @@ class TransactionSearch implements GenericSearchInterface { // TODO: Implement search() method. } -} \ No newline at end of file +} diff --git a/app/Support/Search/TransferSearch.php b/app/Support/Search/TransferSearch.php index aff435b65a..722da14ab6 100644 --- a/app/Support/Search/TransferSearch.php +++ b/app/Support/Search/TransferSearch.php @@ -145,4 +145,4 @@ class TransferSearch implements GenericSearchInterface $this->source = $this->accountRepository->findByName($source, $this->types); } } -} \ No newline at end of file +} diff --git a/app/Support/Steam.php b/app/Support/Steam.php index c1fcdeb2f1..c3d033aa97 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -123,7 +123,7 @@ class Steam $transactions = $account->transactions() ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->where('transaction_journals.date', '<=', $date->format('Y-m-d')) + ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transactions.transaction_currency_id', $currencyId) ->get(['transactions.amount'])->toArray(); $nativeBalance = $this->sumTransactions($transactions, 'amount'); @@ -131,7 +131,7 @@ class Steam // get all balances in foreign currency: $transactions = $account->transactions() ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->where('transaction_journals.date', '<=', $date->format('Y-m-d')) + ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transactions.foreign_currency_id', $currencyId) ->where('transactions.transaction_currency_id', '!=', $currencyId) ->get(['transactions.foreign_amount'])->toArray(); diff --git a/app/Support/System/GeneratesInstallationId.php b/app/Support/System/GeneratesInstallationId.php new file mode 100644 index 0000000000..9dac7661eb --- /dev/null +++ b/app/Support/System/GeneratesInstallationId.php @@ -0,0 +1,28 @@ +get('installation_id', null); + if (null === $config) { + $uuid5 = Uuid::uuid5(Uuid::NAMESPACE_URL, 'firefly-iii.org'); + $uniqueId = (string) $uuid5; + Log::info(sprintf('Created Firefly III installation ID %s', $uniqueId)); + app('fireflyconfig')->set('installation_id', $uniqueId); + } + } + +} diff --git a/app/Support/System/OAuthKeys.php b/app/Support/System/OAuthKeys.php index fc6df6b40c..ee46cf8569 100644 --- a/app/Support/System/OAuthKeys.php +++ b/app/Support/System/OAuthKeys.php @@ -109,4 +109,4 @@ class OAuthKeys } } -} \ No newline at end of file +} diff --git a/app/Support/Telemetry.php b/app/Support/Telemetry.php index cc9c3aacb6..7b8a5cba76 100644 --- a/app/Support/Telemetry.php +++ b/app/Support/Telemetry.php @@ -24,6 +24,7 @@ namespace FireflyIII\Support; use Carbon\Carbon; use FireflyIII\Models\Telemetry as TelemetryModel; +use FireflyIII\Support\System\GeneratesInstallationId; use JsonException; use Log; @@ -32,6 +33,7 @@ use Log; */ class Telemetry { + use GeneratesInstallationId; /** * Feature telemetry stores a $value for the given $feature. * Will only store the given $feature / $value combination once. @@ -166,9 +168,12 @@ class Telemetry */ private function storeEntry(string $type, string $name, string $value): void { + $this->generateInstallationId(); + $config = app('fireflyconfig')->get('installation_id', null); + $installationId = null !== $config ? $config->data : 'empty'; TelemetryModel::create( [ - 'installation_id' => \FireflyConfig::get('installation_id', '')->data, + 'installation_id' => $installationId, 'key' => $name, 'type' => $type, 'value' => $value, diff --git a/app/TransactionRules/Triggers/ForeignCurrencyIs.php b/app/TransactionRules/Triggers/ForeignCurrencyIs.php new file mode 100644 index 0000000000..2705beb91b --- /dev/null +++ b/app/TransactionRules/Triggers/ForeignCurrencyIs.php @@ -0,0 +1,99 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Triggers; + +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use Log; + +/** + * Class ForeignCurrencyIs. + */ +final class ForeignCurrencyIs extends AbstractTrigger implements TriggerInterface +{ + /** + * A trigger is said to "match anything", or match any given transaction, + * when the trigger value is very vague or has no restrictions. Easy examples + * are the "AmountMore"-trigger combined with an amount of 0: any given transaction + * has an amount of more than zero! Other examples are all the "Description"-triggers + * which have hard time handling empty trigger values such as "" or "*" (wild cards). + * + * If the user tries to create such a trigger, this method MUST return true so Firefly III + * can stop the storing / updating the trigger. If the trigger is in any way restrictive + * (even if it will still include 99.9% of the users transactions), this method MUST return + * false. + * + * @param mixed $value + * + * @return bool + */ + public static function willMatchEverything($value = null): bool + { + if (null !== $value) { + return false; + } + + Log::error(sprintf('Cannot use %s with a null value.', self::class)); + + return true; + } + + /** + * Returns true when description is X + * + * @param TransactionJournal $journal + * + * @return bool + */ + public function triggered(TransactionJournal $journal): bool + { + /** @var CurrencyRepositoryInterface $repository */ + $repository = app(CurrencyRepositoryInterface::class); + + // if currency name contains " (" + if (0 === strpos($this->triggerValue, ' (')) { + $parts = explode(' (', $this->triggerValue); + $this->triggerValue = $parts[0]; + } + + $currency = $repository->findByNameNull($this->triggerValue); + $hit = true; + if (null !== $currency) { + /** @var Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + if ((int)$transaction->foreign_currency_id !== (int)$currency->id) { + Log::debug( + sprintf( + 'Trigger ForeignCurrencyIs: Transaction #%d in journal #%d uses currency %d instead of sought for #%d. No hit!', + $transaction->id, $journal->id, $transaction->foreign_currency_id, $currency->id + ) + ); + $hit = false; + } + } + } + + return $hit; + } +} diff --git a/app/Validation/Account/AccountValidatorProperties.php b/app/Validation/Account/AccountValidatorProperties.php index 1bb98af1f0..12f10bc209 100644 --- a/app/Validation/Account/AccountValidatorProperties.php +++ b/app/Validation/Account/AccountValidatorProperties.php @@ -49,4 +49,4 @@ trait AccountValidatorProperties private $transactionType; /** @var User */ private $user; -} \ No newline at end of file +} diff --git a/app/Validation/Account/DepositValidation.php b/app/Validation/Account/DepositValidation.php index b7ae9f397b..1894775386 100644 --- a/app/Validation/Account/DepositValidation.php +++ b/app/Validation/Account/DepositValidation.php @@ -139,4 +139,4 @@ trait DepositValidation // don't expect to end up here: return $result; } -} \ No newline at end of file +} diff --git a/app/Validation/Account/OBValidation.php b/app/Validation/Account/OBValidation.php index 0399592c6d..b3fa427e6d 100644 --- a/app/Validation/Account/OBValidation.php +++ b/app/Validation/Account/OBValidation.php @@ -145,4 +145,4 @@ trait OBValidation return $result; } -} \ No newline at end of file +} diff --git a/app/Validation/Account/ReconciliationValidation.php b/app/Validation/Account/ReconciliationValidation.php index 8bbf48e4b2..cd002e2a6d 100644 --- a/app/Validation/Account/ReconciliationValidation.php +++ b/app/Validation/Account/ReconciliationValidation.php @@ -104,4 +104,4 @@ trait ReconciliationValidation return false; } -} \ No newline at end of file +} diff --git a/app/Validation/Account/TransferValidation.php b/app/Validation/Account/TransferValidation.php index 6f7382132a..c0570e65b1 100644 --- a/app/Validation/Account/TransferValidation.php +++ b/app/Validation/Account/TransferValidation.php @@ -120,4 +120,4 @@ trait TransferValidation return true; } -} \ No newline at end of file +} diff --git a/app/Validation/Account/WithdrawalValidation.php b/app/Validation/Account/WithdrawalValidation.php index 74229c7525..07c2e09f5b 100644 --- a/app/Validation/Account/WithdrawalValidation.php +++ b/app/Validation/Account/WithdrawalValidation.php @@ -117,4 +117,4 @@ trait WithdrawalValidation return true; } -} \ No newline at end of file +} diff --git a/app/Validation/CurrencyValidation.php b/app/Validation/CurrencyValidation.php index b4fa475fdf..1cff24e8b9 100644 --- a/app/Validation/CurrencyValidation.php +++ b/app/Validation/CurrencyValidation.php @@ -69,4 +69,4 @@ trait CurrencyValidation } } } -} \ No newline at end of file +} diff --git a/app/Validation/GroupValidation.php b/app/Validation/GroupValidation.php index a5f1a939cc..4361a757e3 100644 --- a/app/Validation/GroupValidation.php +++ b/app/Validation/GroupValidation.php @@ -129,4 +129,4 @@ trait GroupValidation } -} \ No newline at end of file +} diff --git a/changelog.md b/changelog.md index 53275bca73..072de3515b 100644 --- a/changelog.md +++ b/changelog.md @@ -2,10 +2,45 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [5.2.7 (API 1.1.0) - 2020-06-01 + +### Added +- Firefly III **optional + opt-in** telemetry can now be enabled, if you want to. Read more about it [here](https://docs.firefly-iii.org/support/telemetry). +- [Issue 3133](https://github.com/firefly-iii/firefly-iii/issues/3133) You can remove attachments before you create a transaction. +- [Issue 3395](https://github.com/firefly-iii/firefly-iii/issues/3395) Emails sent by Firefly III have been translated. See the note at the bottom. Thanks to @sephrat +- [Issue 3393](https://github.com/firefly-iii/firefly-iii/issues/3393) New SSL options for LDAP and MySQL. Thanks to @sephrat +- [Issue 3413](https://github.com/firefly-iii/firefly-iii/issues/3413) Better string pluralization. Thanks to @sephrat +- [Issue 3297](https://github.com/firefly-iii/firefly-iii/issues/3297) Rule trigger for foreign currency ID + +### Changed +- The default Docker Compose configuration and documentation switched from PostgreSQL to MariaDB. This will NOT affect existing installations unless you + change your docker compose file. +- [Issue 3404](https://github.com/firefly-iii/firefly-iii/issues/3404) The profile page has been translated. See the note at the bottom. Thanks to @sephrat +- [Issue 3405](https://github.com/firefly-iii/firefly-iii/issues/3405) All error pages have been translated. See the note at the bottom. Thanks to @sephrat + +### Deprecated +- Initial release. + +### Removed +- Initial release. + +### Fixed +- [Issue 3309](https://github.com/firefly-iii/firefly-iii/issues/3309) New budgets would create bad budget limits. +- [Issue 3390](https://github.com/firefly-iii/firefly-iii/issues/3390) Typos and minor text inconsistencies fixed by @sephrat +- [Issue 3407](https://github.com/firefly-iii/firefly-iii/issues/3407) [issue 3408](https://github.com/firefly-iii/firefly-iii/issues/3408) The total transaction amount displayed is no longer empty for opening balances by @sephrat +- [Issue 3409](https://github.com/firefly-iii/firefly-iii/issues/3409) [issue 3420](https://github.com/firefly-iii/firefly-iii/issues/3420) Double accounts no longer listed by @sephrat +- [Issue 3427](https://github.com/firefly-iii/firefly-iii/issues/3427) Add a time-out to version update check. More improvements are coming. +- [Issue 3419](https://github.com/firefly-iii/firefly-iii/issues/3419) Error fixed which would prevent you from adding money to a piggy bank, by @sephrat +- [Issue 3425](https://github.com/firefly-iii/firefly-iii/issues/3425) Budget amount had no validation. +- [Issue 3428](https://github.com/firefly-iii/firefly-iii/issues/3428) Reconciliation "select all"-button would miscalculate. +- [Issue 3415](https://github.com/firefly-iii/firefly-iii/issues/3415) New error views + +A note about new translations: text you see in errors and emails may still be in English. This is not a bug. Translated text is sometimes generated outside of + what's called the user's "session". When Firefly III operates outside of your session, it can't access your preferences or your data. It doesn't know what + language to pick. You can set the `DEFAULT_LANGUAGE`-environment variable. But user specific preferences may be ignored. + ## [5.2.6 (API 1.1.0)] - 2020-05-22 - -## [3.4.2] - 2015-05-25 ### Added - [Issue 3049](https://github.com/firefly-iii/firefly-iii/issues/3049) New transaction triggers for dates. - Warning if recurring transactions no longer run. diff --git a/composer.json b/composer.json index f7d59a2599..ad4c983402 100644 --- a/composer.json +++ b/composer.json @@ -94,11 +94,7 @@ "laravelcollective/html": "6.*", "league/commonmark": "1.*", "league/csv": "9.*", - "league/flysystem-replicate-adapter": "1.*", - "league/flysystem-sftp": "1.*", "league/fractal": "0.*", - "litipk/flysystem-fallback-adapter": "0.*", - "mschindler83/fints-hbci-php": "1.*", "pragmarx/google2fa": "^7.0", "pragmarx/recovery": "^0.1.0", "predis/predis": "^1.1", diff --git a/composer.lock b/composer.lock index 1c37f80912..8d882affdb 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": "63d96a26ef4c9c9e29552e9c45abde06", + "content-hash": "5af5d9774ef0e82cd34d08c63020e85d", "packages": [ { "name": "adldap2/adldap2", @@ -67,16 +67,16 @@ }, { "name": "adldap2/adldap2-laravel", - "version": "v6.0.9", + "version": "v6.1.1", "source": { "type": "git", "url": "https://github.com/Adldap2/Adldap2-Laravel.git", - "reference": "0c828772333936f4c26c1ce27bd372008eae7e6e" + "reference": "c72a2e3757919c39d6a03bd345ec4e586284825c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Adldap2/Adldap2-Laravel/zipball/0c828772333936f4c26c1ce27bd372008eae7e6e", - "reference": "0c828772333936f4c26c1ce27bd372008eae7e6e", + "url": "https://api.github.com/repos/Adldap2/Adldap2-Laravel/zipball/c72a2e3757919c39d6a03bd345ec4e586284825c", + "reference": "c72a2e3757919c39d6a03bd345ec4e586284825c", "shasum": "" }, "require": { @@ -117,7 +117,7 @@ "laravel", "ldap" ], - "time": "2020-03-08T23:15:56+00:00" + "time": "2020-06-02T00:45:05+00:00" }, { "name": "bacon/bacon-qr-code", @@ -354,20 +354,20 @@ }, { "name": "doctrine/cache", - "version": "1.10.0", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62" + "reference": "35a4a70cd94e09e2259dfae7488afc6b474ecbd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/382e7f4db9a12dc6c19431743a2b096041bcdd62", - "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62", + "url": "https://api.github.com/repos/doctrine/cache/zipball/35a4a70cd94e09e2259dfae7488afc6b474ecbd3", + "reference": "35a4a70cd94e09e2259dfae7488afc6b474ecbd3", "shasum": "" }, "require": { - "php": "~7.1" + "php": "~7.1 || ^8.0" }, "conflict": { "doctrine/common": ">2.2,<2.4" @@ -432,7 +432,21 @@ "redis", "xcache" ], - "time": "2019-11-29T15:36:20+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", + "type": "tidelift" + } + ], + "time": "2020-05-27T16:24:54+00:00" }, { "name": "doctrine/dbal", @@ -606,20 +620,20 @@ }, { "name": "doctrine/inflector", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7" + "reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7", - "reference": "18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/9cf661f4eb38f7c881cac67c75ea9b00bf97b210", + "reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210", "shasum": "" }, "require": { - "php": "^7.2" + "php": "^7.2 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^7.0", @@ -693,24 +707,24 @@ "type": "tidelift" } ], - "time": "2020-05-11T11:25:59+00:00" + "time": "2020-05-29T15:13:26+00:00" }, { "name": "doctrine/lexer", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" + "reference": "e864bbf5904cb8f5bb334f99209b48018522f042" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", - "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042", + "reference": "e864bbf5904cb8f5bb334f99209b48018522f042", "shasum": "" }, "require": { - "php": "^7.2" + "php": "^7.2 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^6.0", @@ -755,7 +769,21 @@ "parser", "php" ], - "time": "2019-10-30T14:39:59+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2020-05-25T17:44:05+00:00" }, { "name": "dragonmantank/cron-expression", @@ -1019,16 +1047,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.5.3", + "version": "6.5.4", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e" + "reference": "a4a1b6930528a8f7ee03518e6442ec7a44155d9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/aab4ebd862aa7d04f01a4b51849d657db56d882e", - "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a4a1b6930528a8f7ee03518e6442ec7a44155d9d", + "reference": "a4a1b6930528a8f7ee03518e6442ec7a44155d9d", "shasum": "" }, "require": { @@ -1036,7 +1064,7 @@ "guzzlehttp/promises": "^1.0", "guzzlehttp/psr7": "^1.6.1", "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.11" + "symfony/polyfill-intl-idn": "1.17.0" }, "require-dev": { "ext-curl": "*", @@ -1082,7 +1110,7 @@ "rest", "web service" ], - "time": "2020-04-18T10:38:46+00:00" + "time": "2020-05-25T19:35:05+00:00" }, { "name": "guzzlehttp/promises", @@ -1436,16 +1464,16 @@ }, { "name": "laravel/framework", - "version": "v6.18.15", + "version": "v6.18.18", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "a1fa3ddc0bb5285cafa6844b443633f7627d75dc" + "reference": "9e5226ecc28f960cba1bd38b6d1d82a52e072dc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/a1fa3ddc0bb5285cafa6844b443633f7627d75dc", - "reference": "a1fa3ddc0bb5285cafa6844b443633f7627d75dc", + "url": "https://api.github.com/repos/laravel/framework/zipball/9e5226ecc28f960cba1bd38b6d1d82a52e072dc3", + "reference": "9e5226ecc28f960cba1bd38b6d1d82a52e072dc3", "shasum": "" }, "require": { @@ -1456,7 +1484,7 @@ "ext-mbstring": "*", "ext-openssl": "*", "league/commonmark": "^1.3", - "league/flysystem": "^1.0.8", + "league/flysystem": "^1.0.34", "monolog/monolog": "^1.12|^2.0", "nesbot/carbon": "^2.0", "opis/closure": "^3.1", @@ -1579,7 +1607,7 @@ "framework", "laravel" ], - "time": "2020-05-19T17:03:02+00:00" + "time": "2020-06-02T22:32:07+00:00" }, { "name": "laravel/passport", @@ -2098,94 +2126,6 @@ ], "time": "2020-05-18T15:13:39+00:00" }, - { - "name": "league/flysystem-replicate-adapter", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/flysystem-replicate-adapter.git", - "reference": "864e80409c0918b0ed6921c3941247017d9db77c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-replicate-adapter/zipball/864e80409c0918b0ed6921c3941247017d9db77c", - "reference": "864e80409c0918b0ed6921c3941247017d9db77c", - "shasum": "" - }, - "require": { - "league/flysystem": "~1.0", - "php": ">=5.4.0" - }, - "require-dev": { - "mockery/mockery": "0.9.*", - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Flysystem\\Replicate\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Frank de Jonge", - "email": "info@frenky.net" - } - ], - "description": "Flysystem adapter for Replica's", - "time": "2015-08-18T21:07:17+00:00" - }, - { - "name": "league/flysystem-sftp", - "version": "1.0.22", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/flysystem-sftp.git", - "reference": "cab59dd2277e02fe46f5f23195672a02ed49774d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-sftp/zipball/cab59dd2277e02fe46f5f23195672a02ed49774d", - "reference": "cab59dd2277e02fe46f5f23195672a02ed49774d", - "shasum": "" - }, - "require": { - "league/flysystem": "~1.0", - "php": ">=5.6.0", - "phpseclib/phpseclib": "~2.0" - }, - "require-dev": { - "mockery/mockery": "0.9.*", - "phpunit/phpunit": "^5.7.25" - }, - "type": "library", - "autoload": { - "psr-4": { - "League\\Flysystem\\Sftp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Frank de Jonge", - "email": "info@frenky.net" - } - ], - "description": "Flysystem adapter for SFTP", - "time": "2019-10-16T20:05:49+00:00" - }, { "name": "league/fractal", "version": "0.19.2", @@ -2333,47 +2273,6 @@ ], "time": "2020-04-29T22:14:38+00:00" }, - { - "name": "litipk/flysystem-fallback-adapter", - "version": "0.1.3", - "source": { - "type": "git", - "url": "https://github.com/Litipk/flysystem-fallback-adapter.git", - "reference": "1fdeb9352990deb8cba2a2c57cc94e2ff7e1381b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Litipk/flysystem-fallback-adapter/zipball/1fdeb9352990deb8cba2a2c57cc94e2ff7e1381b", - "reference": "1fdeb9352990deb8cba2a2c57cc94e2ff7e1381b", - "shasum": "" - }, - "require": { - "league/flysystem": "~1.0", - "php": ">=5.4.0" - }, - "require-dev": { - "mockery/mockery": "0.9.*", - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Litipk\\Flysystem\\Fallback\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Andrés Correa Casablanca", - "email": "castarco@litipk.com" - } - ], - "description": "Flysystem adapter for fallback filesystems", - "time": "2016-06-23T00:18:01+00:00" - }, { "name": "monolog/monolog", "version": "2.1.0", @@ -2465,53 +2364,18 @@ ], "time": "2020-05-22T08:12:19+00:00" }, - { - "name": "mschindler83/fints-hbci-php", - "version": "1.0.4", - "source": { - "type": "git", - "url": "https://github.com/mschindler83/fints-hbci-php.git", - "reference": "e58cb825c178d4c39a8974a9dd93abbc8094551f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mschindler83/fints-hbci-php/zipball/e58cb825c178d4c39a8974a9dd93abbc8094551f", - "reference": "e58cb825c178d4c39a8974a9dd93abbc8094551f", - "shasum": "" - }, - "require": { - "php": ">=5.3.2", - "psr/log": "~1.0" - }, - "suggest": { - "monolog/monolog": "Allow sending log messages to a variety of different handlers" - }, - "type": "library", - "autoload": { - "psr-0": { - "Fhp": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHP Library for the protocols fints and hbci", - "homepage": "http://fints-hbci-php.markus-schindler.de", - "time": "2017-02-15T13:48:21+00:00" - }, { "name": "nesbot/carbon", - "version": "2.34.2", + "version": "2.35.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "3e87404329b8072295ea11d548b47a1eefe5a162" + "reference": "4b9bd835261ef23d36397a46a76b496a458305e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/3e87404329b8072295ea11d548b47a1eefe5a162", - "reference": "3e87404329b8072295ea11d548b47a1eefe5a162", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4b9bd835261ef23d36397a46a76b496a458305e5", + "reference": "4b9bd835261ef23d36397a46a76b496a458305e5", "shasum": "" }, "require": { @@ -2581,20 +2445,20 @@ "type": "tidelift" } ], - "time": "2020-05-19T22:14:16+00:00" + "time": "2020-05-24T18:27:52+00:00" }, { "name": "nyholm/psr7", - "version": "1.2.1", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/Nyholm/psr7.git", - "reference": "55ff6b76573f5b242554c9775792bd59fb52e11c" + "reference": "c17f4f73985f62054a331cbc4ffdf9868c4ef256" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Nyholm/psr7/zipball/55ff6b76573f5b242554c9775792bd59fb52e11c", - "reference": "55ff6b76573f5b242554c9775792bd59fb52e11c", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/c17f4f73985f62054a331cbc4ffdf9868c4ef256", + "reference": "c17f4f73985f62054a331cbc4ffdf9868c4ef256", "shasum": "" }, "require": { @@ -2609,8 +2473,9 @@ }, "require-dev": { "http-interop/http-factory-tests": "dev-master", - "php-http/psr7-integration-tests": "dev-master", - "phpunit/phpunit": "^7.5" + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5", + "symfony/error-handler": "^4.4" }, "type": "library", "extra": { @@ -2643,20 +2508,30 @@ "psr-17", "psr-7" ], - "time": "2019-09-05T13:24:16+00:00" + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2020-05-23T11:29:07+00:00" }, { "name": "opis/closure", - "version": "3.5.2", + "version": "3.5.3", "source": { "type": "git", "url": "https://github.com/opis/closure.git", - "reference": "2e3299cea6f485ca64d19c540f46d7896c512ace" + "reference": "cac47092144043d5d676e2e7cf8d0d2f83fc89ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opis/closure/zipball/2e3299cea6f485ca64d19c540f46d7896c512ace", - "reference": "2e3299cea6f485ca64d19c540f46d7896c512ace", + "url": "https://api.github.com/repos/opis/closure/zipball/cac47092144043d5d676e2e7cf8d0d2f83fc89ca", + "reference": "cac47092144043d5d676e2e7cf8d0d2f83fc89ca", "shasum": "" }, "require": { @@ -2704,7 +2579,7 @@ "serialization", "serialize" ], - "time": "2020-05-21T20:09:36+00:00" + "time": "2020-05-25T09:32:45+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -3810,22 +3685,23 @@ }, { "name": "symfony/console", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "10bb3ee3c97308869d53b3e3d03f6ac23ff985f7" + "reference": "326b064d804043005526f5a0494cfb49edb59bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/10bb3ee3c97308869d53b3e3d03f6ac23ff985f7", - "reference": "10bb3ee3c97308869d53b3e3d03f6ac23ff985f7", + "url": "https://api.github.com/repos/symfony/console/zipball/326b064d804043005526f5a0494cfb49edb59bb0", + "reference": "326b064d804043005526f5a0494cfb49edb59bb0", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.1.3", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php80": "^1.15", "symfony/service-contracts": "^1.1|^2" }, "conflict": { @@ -3896,29 +3772,29 @@ "type": "tidelift" } ], - "time": "2020-03-30T11:41:10+00:00" + "time": "2020-05-30T20:06:45+00:00" }, { "name": "symfony/css-selector", - "version": "v5.0.8", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "5f8d5271303dad260692ba73dfa21777d38e124e" + "reference": "e544e24472d4c97b2d11ade7caacd446727c6bf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/5f8d5271303dad260692ba73dfa21777d38e124e", - "reference": "5f8d5271303dad260692ba73dfa21777d38e124e", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/e544e24472d4c97b2d11ade7caacd446727c6bf9", + "reference": "e544e24472d4c97b2d11ade7caacd446727c6bf9", "shasum": "" }, "require": { - "php": "^7.2.5" + "php": ">=7.2.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -3963,25 +3839,26 @@ "type": "tidelift" } ], - "time": "2020-03-27T16:56:45+00:00" + "time": "2020-05-20T17:43:50+00:00" }, { "name": "symfony/debug", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "346636d2cae417992ecfd761979b2ab98b339a45" + "reference": "28f92d08bb6d1fddf8158e02c194ad43870007e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/346636d2cae417992ecfd761979b2ab98b339a45", - "reference": "346636d2cae417992ecfd761979b2ab98b339a45", + "url": "https://api.github.com/repos/symfony/debug/zipball/28f92d08bb6d1fddf8158e02c194ad43870007e6", + "reference": "28f92d08bb6d1fddf8158e02c194ad43870007e6", "shasum": "" }, "require": { - "php": "^7.1.3", - "psr/log": "~1.0" + "php": ">=7.1.3", + "psr/log": "~1.0", + "symfony/polyfill-php80": "^1.15" }, "conflict": { "symfony/http-kernel": "<3.4" @@ -4033,26 +3910,27 @@ "type": "tidelift" } ], - "time": "2020-03-27T16:54:36+00:00" + "time": "2020-05-24T08:33:35+00:00" }, { "name": "symfony/error-handler", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "7e9828fc98aa1cf27b422fe478a84f5b0abb7358" + "reference": "0df9a23c0f9eddbb6682479fee6fd58b88add75b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/7e9828fc98aa1cf27b422fe478a84f5b0abb7358", - "reference": "7e9828fc98aa1cf27b422fe478a84f5b0abb7358", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/0df9a23c0f9eddbb6682479fee6fd58b88add75b", + "reference": "0df9a23c0f9eddbb6682479fee6fd58b88add75b", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.1.3", "psr/log": "~1.0", "symfony/debug": "^4.4.5", + "symfony/polyfill-php80": "^1.15", "symfony/var-dumper": "^4.4|^5.0" }, "require-dev": { @@ -4103,24 +3981,24 @@ "type": "tidelift" } ], - "time": "2020-03-30T14:07:33+00:00" + "time": "2020-05-28T10:39:14+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "abc8e3618bfdb55e44c8c6a00abd333f831bbfed" + "reference": "a5370aaa7807c7a439b21386661ffccf3dff2866" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/abc8e3618bfdb55e44c8c6a00abd333f831bbfed", - "reference": "abc8e3618bfdb55e44c8c6a00abd333f831bbfed", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a5370aaa7807c7a439b21386661ffccf3dff2866", + "reference": "a5370aaa7807c7a439b21386661ffccf3dff2866", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.1.3", "symfony/event-dispatcher-contracts": "^1.1" }, "conflict": { @@ -4187,7 +4065,7 @@ "type": "tidelift" } ], - "time": "2020-03-27T16:54:36+00:00" + "time": "2020-05-20T08:37:50+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -4249,7 +4127,7 @@ }, { "name": "symfony/finder", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -4312,20 +4190,20 @@ }, { "name": "symfony/http-foundation", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "ec5bd254c223786f5fa2bb49a1e705c1b8e7cee2" + "reference": "3adfbd7098c850b02d107330b7b9deacf2581578" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ec5bd254c223786f5fa2bb49a1e705c1b8e7cee2", - "reference": "ec5bd254c223786f5fa2bb49a1e705c1b8e7cee2", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3adfbd7098c850b02d107330b7b9deacf2581578", + "reference": "3adfbd7098c850b02d107330b7b9deacf2581578", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.1.3", "symfony/mime": "^4.3|^5.0", "symfony/polyfill-mbstring": "~1.1" }, @@ -4377,30 +4255,31 @@ "type": "tidelift" } ], - "time": "2020-04-18T20:40:08+00:00" + "time": "2020-05-23T09:11:46+00:00" }, { "name": "symfony/http-kernel", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "1799a6c01f0db5851f399151abdb5d6393fec277" + "reference": "54526b598d7fc86a67850488b194a88a79ab8467" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/1799a6c01f0db5851f399151abdb5d6393fec277", - "reference": "1799a6c01f0db5851f399151abdb5d6393fec277", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/54526b598d7fc86a67850488b194a88a79ab8467", + "reference": "54526b598d7fc86a67850488b194a88a79ab8467", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.1.3", "psr/log": "~1.0", "symfony/error-handler": "^4.4", "symfony/event-dispatcher": "^4.4", "symfony/http-foundation": "^4.4|^5.0", "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-php73": "^1.9" + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.15" }, "conflict": { "symfony/browser-kit": "<4.3", @@ -4481,26 +4360,27 @@ "type": "tidelift" } ], - "time": "2020-04-28T18:47:42+00:00" + "time": "2020-05-31T05:25:51+00:00" }, { "name": "symfony/mime", - "version": "v5.0.8", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "5d6c81c39225a750f3f43bee15f03093fb9aaa0b" + "reference": "56261f89385f9d13cf843a5101ac72131190bc91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/5d6c81c39225a750f3f43bee15f03093fb9aaa0b", - "reference": "5d6c81c39225a750f3f43bee15f03093fb9aaa0b", + "url": "https://api.github.com/repos/symfony/mime/zipball/56261f89385f9d13cf843a5101ac72131190bc91", + "reference": "56261f89385f9d13cf843a5101ac72131190bc91", "shasum": "" }, "require": { - "php": "^7.2.5", + "php": ">=7.2.5", "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0" + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.15" }, "conflict": { "symfony/mailer": "<4.4" @@ -4512,7 +4392,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -4557,7 +4437,7 @@ "type": "tidelift" } ], - "time": "2020-04-17T03:29:44+00:00" + "time": "2020-05-25T12:33:44+00:00" }, { "name": "symfony/polyfill-ctype", @@ -5064,6 +4944,82 @@ ], "time": "2020-05-12T16:47:27+00:00" }, + { + "name": "symfony/polyfill-php80", + "version": "v1.17.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "5e30b2799bc1ad68f7feb62b60a73743589438dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/5e30b2799bc1ad68f7feb62b60a73743589438dd", + "reference": "5e30b2799bc1ad68f7feb62b60a73743589438dd", + "shasum": "" + }, + "require": { + "php": ">=7.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.17-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "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": "2020-05-12T16:47:27+00:00" + }, { "name": "symfony/polyfill-util", "version": "v1.17.0", @@ -5132,16 +5088,16 @@ }, { "name": "symfony/process", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "4b6a9a4013baa65d409153cbb5a895bf093dc7f4" + "reference": "c714958428a85c86ab97e3a0c96db4c4f381b7f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/4b6a9a4013baa65d409153cbb5a895bf093dc7f4", - "reference": "4b6a9a4013baa65d409153cbb5a895bf093dc7f4", + "url": "https://api.github.com/repos/symfony/process/zipball/c714958428a85c86ab97e3a0c96db4c4f381b7f5", + "reference": "c714958428a85c86ab97e3a0c96db4c4f381b7f5", "shasum": "" }, "require": { @@ -5191,7 +5147,7 @@ "type": "tidelift" } ], - "time": "2020-04-15T15:56:18+00:00" + "time": "2020-05-30T20:06:45+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -5259,16 +5215,16 @@ }, { "name": "symfony/routing", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "67b4e1f99c050cbc310b8f3d0dbdc4b0212c052c" + "reference": "0f557911dde75c2a9652b8097bd7c9f54507f646" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/67b4e1f99c050cbc310b8f3d0dbdc4b0212c052c", - "reference": "67b4e1f99c050cbc310b8f3d0dbdc4b0212c052c", + "url": "https://api.github.com/repos/symfony/routing/zipball/0f557911dde75c2a9652b8097bd7c9f54507f646", + "reference": "0f557911dde75c2a9652b8097bd7c9f54507f646", "shasum": "" }, "require": { @@ -5345,24 +5301,24 @@ "type": "tidelift" } ], - "time": "2020-04-21T19:59:53+00:00" + "time": "2020-05-30T20:07:26+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.0.1", + "version": "v2.1.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "144c5e51266b281231e947b51223ba14acf1a749" + "reference": "66a8f0957a3ca54e4f724e49028ab19d75a8918b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", - "reference": "144c5e51266b281231e947b51223ba14acf1a749", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/66a8f0957a3ca54e4f724e49028ab19d75a8918b", + "reference": "66a8f0957a3ca54e4f724e49028ab19d75a8918b", "shasum": "" }, "require": { - "php": "^7.2.5", + "php": ">=7.2.5", "psr/container": "^1.0" }, "suggest": { @@ -5371,7 +5327,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" } }, "autoload": { @@ -5403,24 +5359,38 @@ "interoperability", "standards" ], - "time": "2019-11-18T17:27:11+00:00" + "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": "2020-05-20T17:43:50+00:00" }, { "name": "symfony/translation", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "8272bbd2b7e220ef812eba2a2b30068a5c64b191" + "reference": "79d3ef9096a6a6047dbc69218b68c7b7f63193af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/8272bbd2b7e220ef812eba2a2b30068a5c64b191", - "reference": "8272bbd2b7e220ef812eba2a2b30068a5c64b191", + "url": "https://api.github.com/repos/symfony/translation/zipball/79d3ef9096a6a6047dbc69218b68c7b7f63193af", + "reference": "79d3ef9096a6a6047dbc69218b68c7b7f63193af", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.1.3", "symfony/polyfill-mbstring": "~1.0", "symfony/translation-contracts": "^1.1.6|^2" }, @@ -5493,24 +5463,24 @@ "type": "tidelift" } ], - "time": "2020-04-12T16:45:36+00:00" + "time": "2020-05-30T20:06:45+00:00" }, { "name": "symfony/translation-contracts", - "version": "v2.0.1", + "version": "v2.1.2", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed" + "reference": "e5ca07c8f817f865f618aa072c2fe8e0e637340e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/8cc682ac458d75557203b2f2f14b0b92e1c744ed", - "reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/e5ca07c8f817f865f618aa072c2fe8e0e637340e", + "reference": "e5ca07c8f817f865f618aa072c2fe8e0e637340e", "shasum": "" }, "require": { - "php": "^7.2.5" + "php": ">=7.2.5" }, "suggest": { "symfony/translation-implementation": "" @@ -5518,7 +5488,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" } }, "autoload": { @@ -5550,26 +5520,41 @@ "interoperability", "standards" ], - "time": "2019-11-18T17:27:11+00:00" + "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": "2020-05-20T17:43:50+00:00" }, { "name": "symfony/var-dumper", - "version": "v4.4.8", + "version": "v4.4.9", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c587e04ce5d1aa62d534a038f574d9a709e814cf" + "reference": "56b3aa5eab0ac6720dcd559fd1d590ce301594ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c587e04ce5d1aa62d534a038f574d9a709e814cf", - "reference": "c587e04ce5d1aa62d534a038f574d9a709e814cf", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/56b3aa5eab0ac6720dcd559fd1d590ce301594ac", + "reference": "56b3aa5eab0ac6720dcd559fd1d590ce301594ac", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.1.3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php72": "~1.5" + "symfony/polyfill-php72": "~1.5", + "symfony/polyfill-php80": "^1.15" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", @@ -5640,11 +5625,11 @@ "type": "tidelift" } ], - "time": "2020-04-12T16:14:02+00:00" + "time": "2020-05-30T20:06:45+00:00" }, { "name": "tightenco/collect", - "version": "v7.11.0", + "version": "v7.12.0", "source": { "type": "git", "url": "https://github.com/tightenco/collect.git", @@ -5808,16 +5793,16 @@ }, { "name": "vlucas/phpdotenv", - "version": "v3.6.4", + "version": "v3.6.5", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "10d3f853fdf1f3a6b3c7ea0c4620d2f699713db5" + "reference": "8b64814b356b96a90d2bc942b152c80d8888b8d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/10d3f853fdf1f3a6b3c7ea0c4620d2f699713db5", - "reference": "10d3f853fdf1f3a6b3c7ea0c4620d2f699713db5", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/8b64814b356b96a90d2bc942b152c80d8888b8d4", + "reference": "8b64814b356b96a90d2bc942b152c80d8888b8d4", "shasum": "" }, "require": { @@ -5877,7 +5862,7 @@ "type": "tidelift" } ], - "time": "2020-05-02T13:46:13+00:00" + "time": "2020-05-23T09:42:03+00:00" } ], "packages-dev": [ @@ -6218,16 +6203,16 @@ }, { "name": "composer/composer", - "version": "1.10.6", + "version": "1.10.7", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "be81b9c4735362c26876bdbfd3b5bc7e7f711c88" + "reference": "956608ea4f7de9e58c53dfb019d85ae62b193c39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/be81b9c4735362c26876bdbfd3b5bc7e7f711c88", - "reference": "be81b9c4735362c26876bdbfd3b5bc7e7f711c88", + "url": "https://api.github.com/repos/composer/composer/zipball/956608ea4f7de9e58c53dfb019d85ae62b193c39", + "reference": "956608ea4f7de9e58c53dfb019d85ae62b193c39", "shasum": "" }, "require": { @@ -6235,7 +6220,7 @@ "composer/semver": "^1.0", "composer/spdx-licenses": "^1.2", "composer/xdebug-handler": "^1.1", - "justinrainbow/json-schema": "^3.0 || ^4.0 || ^5.0", + "justinrainbow/json-schema": "^5.2.10", "php": "^5.3.2 || ^7.0", "psr/log": "^1.0", "seld/jsonlint": "^1.4", @@ -6300,12 +6285,16 @@ "url": "https://packagist.com", "type": "custom" }, + { + "url": "https://github.com/composer", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/composer/composer", "type": "tidelift" } ], - "time": "2020-05-06T08:28:10+00:00" + "time": "2020-06-03T08:03:56+00:00" }, { "name": "composer/semver", @@ -6430,16 +6419,16 @@ }, { "name": "composer/xdebug-handler", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7" + "reference": "fa2aaf99e2087f013a14f7432c1cd2dd7d8f1f51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/1ab9842d69e64fb3a01be6b656501032d1b78cb7", - "reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/fa2aaf99e2087f013a14f7432c1cd2dd7d8f1f51", + "reference": "fa2aaf99e2087f013a14f7432c1cd2dd7d8f1f51", "shasum": "" }, "require": { @@ -6474,26 +6463,34 @@ { "url": "https://packagist.com", "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" } ], - "time": "2020-03-01T12:26:26+00:00" + "time": "2020-06-04T11:16:35+00:00" }, { "name": "doctrine/instantiator", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + "reference": "f350df0268e904597e3bd9c4685c53e0e333feea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea", + "reference": "f350df0268e904597e3bd9c4685c53e0e333feea", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^6.0", @@ -6532,7 +6529,21 @@ "constructor", "instantiate" ], - "time": "2019-10-21T16:45:58+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-05-29T17:27:14+00:00" }, { "name": "felixfbecker/advanced-json-rpc", @@ -6831,16 +6842,16 @@ }, { "name": "justinrainbow/json-schema", - "version": "5.2.9", + "version": "5.2.10", "source": { "type": "git", "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "44c6787311242a979fa15c704327c20e7221a0e4" + "reference": "2ba9c8c862ecd5510ed16c6340aa9f6eadb4f31b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/44c6787311242a979fa15c704327c20e7221a0e4", - "reference": "44c6787311242a979fa15c704327c20e7221a0e4", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ba9c8c862ecd5510ed16c6340aa9f6eadb4f31b", + "reference": "2ba9c8c862ecd5510ed16c6340aa9f6eadb4f31b", "shasum": "" }, "require": { @@ -6893,7 +6904,7 @@ "json", "schema" ], - "time": "2019-09-25T14:49:45+00:00" + "time": "2020-05-27T16:41:55+00:00" }, { "name": "mockery/mockery", @@ -7059,16 +7070,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.4.0", + "version": "v4.5.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "bd43ec7152eaaab3bd8c6d0aa95ceeb1df8ee120" + "reference": "53c2753d756f5adb586dca79c2ec0e2654dd9463" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bd43ec7152eaaab3bd8c6d0aa95ceeb1df8ee120", - "reference": "bd43ec7152eaaab3bd8c6d0aa95ceeb1df8ee120", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/53c2753d756f5adb586dca79c2ec0e2654dd9463", + "reference": "53c2753d756f5adb586dca79c2ec0e2654dd9463", "shasum": "" }, "require": { @@ -7107,7 +7118,7 @@ "parser", "php" ], - "time": "2020-04-10T16:34:50+00:00" + "time": "2020-06-03T07:24:19+00:00" }, { "name": "ocramius/package-versions", @@ -7921,16 +7932,16 @@ }, { "name": "phpunit/phpunit", - "version": "8.5.4", + "version": "8.5.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "8474e22d7d642f665084ba5ec780626cbd1efd23" + "reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8474e22d7d642f665084ba5ec780626cbd1efd23", - "reference": "8474e22d7d642f665084ba5ec780626cbd1efd23", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/63dda3b212a0025d380a745f91bdb4d8c985adb7", + "reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7", "shasum": "" }, "require": { @@ -8010,7 +8021,7 @@ "type": "github" } ], - "time": "2020-04-23T04:39:42+00:00" + "time": "2020-05-22T13:51:52+00:00" }, { "name": "psalm/plugin-laravel", @@ -8076,12 +8087,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "e38de1df609b39d97144514d28b0804ad4daaddb" + "reference": "de6fda3af9b36c77fdeb62b968157032f7111b09" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/e38de1df609b39d97144514d28b0804ad4daaddb", - "reference": "e38de1df609b39d97144514d28b0804ad4daaddb", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/de6fda3af9b36c77fdeb62b968157032f7111b09", + "reference": "de6fda3af9b36c77fdeb62b968157032f7111b09", "shasum": "" }, "conflict": { @@ -8135,8 +8146,9 @@ "ezsystems/ezplatform": ">=1.7,<1.7.9.1|>=1.13,<1.13.5.1|>=2.5,<2.5.4", "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6", "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2", + "ezsystems/ezplatform-kernel": ">=1,<1.0.2.1", "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": ">=5.3,<5.3.12.1|>=5.4,<5.4.14.1|>=6,<6.7.9.1|>=6.8,<6.13.6.2|>=7,<7.2.4.1|>=7.3,<7.3.2.1|>=7.5,<7.5.6.2", + "ezsystems/ezpublish-kernel": ">=5.3,<5.3.12.1|>=5.4,<5.4.14.2|>=6,<6.7.9.1|>=6.8,<6.13.6.3|>=7,<7.2.4.1|>=7.3,<7.3.2.1|>=7.5,<7.5.7.1", "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.6|>=5.4,<5.4.14.1|>=2011,<2017.12.7.2|>=2018.6,<2018.6.1.4|>=2018.9,<2018.9.1.3|>=2019.3,<2019.3.4.2", "ezsystems/repository-forms": ">=2.3,<2.3.2.1", "ezyang/htmlpurifier": "<4.1.1", @@ -8174,6 +8186,7 @@ "monolog/monolog": ">=1.8,<1.12", "namshi/jose": "<2.2", "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", + "october/october": ">=1.0.319,<1.0.466", "onelogin/php-saml": "<2.10.4", "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", "openid/php-openid": "<2.3", @@ -8185,7 +8198,7 @@ "paypal/merchant-sdk-php": "<3.12", "pear/archive_tar": "<1.4.4", "phpfastcache/phpfastcache": ">=5,<5.0.13", - "phpmailer/phpmailer": ">=5,<5.2.27|>=6,<6.0.6", + "phpmailer/phpmailer": "<6.1.6", "phpmyadmin/phpmyadmin": "<4.9.2", "phpoffice/phpexcel": "<1.8.2", "phpoffice/phpspreadsheet": "<1.8", @@ -8200,6 +8213,7 @@ "propel/propel": ">=2-alpha.1,<=2-alpha.7", "propel/propel1": ">=1,<=1.7.1", "pusher/pusher-php-server": "<2.2.1", + "rainlab/debugbar-plugin": "<3.1", "robrichards/xmlseclibs": "<3.0.4", "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", @@ -8348,7 +8362,7 @@ "type": "tidelift" } ], - "time": "2020-05-22T06:49:22+00:00" + "time": "2020-06-04T00:00:55+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -9070,26 +9084,26 @@ }, { "name": "symfony/filesystem", - "version": "v5.0.8", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "7cd0dafc4353a0f62e307df90b48466379c8cc91" + "reference": "6e4320f06d5f2cce0d96530162491f4465179157" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/7cd0dafc4353a0f62e307df90b48466379c8cc91", - "reference": "7cd0dafc4353a0f62e307df90b48466379c8cc91", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/6e4320f06d5f2cce0d96530162491f4465179157", + "reference": "6e4320f06d5f2cce0d96530162491f4465179157", "shasum": "" }, "require": { - "php": "^7.2.5", + "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -9130,7 +9144,7 @@ "type": "tidelift" } ], - "time": "2020-04-12T14:40:17+00:00" + "time": "2020-05-30T20:35:19+00:00" }, { "name": "theseer/tokenizer", @@ -9174,16 +9188,16 @@ }, { "name": "vimeo/psalm", - "version": "3.11.4", + "version": "3.11.5", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "58e1d8e68e5098bf4fbfdfb420c38d563f882549" + "reference": "3c60609c218d4d4b3b257728b8089094e5c6c6c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/58e1d8e68e5098bf4fbfdfb420c38d563f882549", - "reference": "58e1d8e68e5098bf4fbfdfb420c38d563f882549", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/3c60609c218d4d4b3b257728b8089094e5c6c6c2", + "reference": "3c60609c218d4d4b3b257728b8089094e5c6c6c2", "shasum": "" }, "require": { @@ -9245,8 +9259,7 @@ }, "autoload": { "psr-4": { - "Psalm\\Plugin\\": "src/Psalm/Plugin", - "Psalm\\": "src/Psalm" + "Psalm\\": "src/Psalm/" }, "files": [ "src/functions.php", @@ -9268,7 +9281,7 @@ "inspection", "php" ], - "time": "2020-05-11T13:39:25+00:00" + "time": "2020-05-27T15:12:09+00:00" }, { "name": "webmozart/assert", diff --git a/config/database.php b/config/database.php index 3ec1f3e55b..ea073f01e5 100644 --- a/config/database.php +++ b/config/database.php @@ -39,6 +39,38 @@ if (!(false === $databaseUrl)) { $database = substr($options['path'] ?? '/firefly', 1); } +/* + * Get SSL parameters from .env file. + */ +$mysql_ssl_ca_dir = envNonEmpty('MYSQL_SSL_CAPATH', null); +$mysql_ssl_ca_file = envNonEmpty('MYSQL_SSL_CA', null); +$mysql_ssl_cert = envNonEmpty('MYSQL_SSL_CERT', null); +$mysql_ssl_key = envNonEmpty('MYSQL_SSL_KEY', null); +$mysql_ssl_ciphers = envNonEmpty('MYSQL_SSL_CIPHER', null); +$mysql_ssl_verify = envNonEmpty('MYSQL_SSL_VERIFY_SERVER_CERT', null); + +$mySqlSSLOptions = []; +if (false !== envNonEmpty('MYSQL_USE_SSL', false)) { + if (null !== $mysql_ssl_ca_dir) { + $mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CAPATH] = $mysql_ssl_ca_dir; + } + if (null !== $mysql_ssl_ca_file) { + $mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CA] = $mysql_ssl_ca_file; + } + if (null !== $mysql_ssl_cert) { + $mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CERT] = $mysql_ssl_cert; + } + if (null !== $mysql_ssl_key) { + $mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_KEY] = $mysql_ssl_key; + } + if (null !== $mysql_ssl_ciphers) { + $mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CIPHER] = $mysql_ssl_ciphers; + } + if (null !== $mysql_ssl_verify) { + $mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $mysql_ssl_verify; + } +} + return [ 'default' => envNonEmpty('DB_CONNECTION', 'pgsql'), 'connections' => [ @@ -60,6 +92,7 @@ return [ 'prefix' => '', 'strict' => true, 'engine' => 'InnoDB', + 'options' => $mySqlSSLOptions, ], 'pgsql' => [ 'driver' => 'pgsql', diff --git a/config/firefly.php b/config/firefly.php index 4e240c9341..ae0f91fbb1 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -85,6 +85,7 @@ use FireflyIII\TransactionRules\Triggers\AmountMore; use FireflyIII\TransactionRules\Triggers\BudgetIs; use FireflyIII\TransactionRules\Triggers\CategoryIs; use FireflyIII\TransactionRules\Triggers\CurrencyIs; +use FireflyIII\TransactionRules\Triggers\ForeignCurrencyIs; use FireflyIII\TransactionRules\Triggers\DateIs; use FireflyIII\TransactionRules\Triggers\DateBefore; use FireflyIII\TransactionRules\Triggers\DateAfter; @@ -139,11 +140,11 @@ return [ ], 'feature_flags' => [ 'export' => true, - 'telemetry' => false, + 'telemetry' => true, ], 'encryption' => null === env('USE_ENCRYPTION') || true === env('USE_ENCRYPTION'), - 'version' => '5.2.6', + 'version' => '5.2.7', 'api_version' => '1.1.0', 'db_version' => 13, 'maxUploadSize' => 15242880, @@ -479,6 +480,7 @@ return [ 'budget_is' => BudgetIs::class, 'tag_is' => TagIs::class, 'currency_is' => CurrencyIs::class, + 'foreign_currency_is' => ForeignCurrencyIs::class, 'has_attachments' => HasAttachment::class, 'has_no_category' => HasNoCategory::class, 'has_any_category' => HasAnyCategory::class, diff --git a/config/ldap.php b/config/ldap.php index 13e18bd41b..1c2d1b52be 100644 --- a/config/ldap.php +++ b/config/ldap.php @@ -38,6 +38,36 @@ if ('ActiveDirectory' === envNonEmpty('ADLDAP_CONNECTION_SCHEME', 'OpenLDAP')) { $schema = ActiveDirectory::class; } +/* + * Get SSL parameters from .env file. + */ +$ssl_ca_dir = envNonEmpty('ADLDAP_SSL_CACERTDIR', null); +$ssl_ca_file = envNonEmpty('ADLDAP_SSL_CACERTFILE', null); +$ssl_cert = envNonEmpty('ADLDAP_SSL_CERTFILE', null); +$ssl_key = envNonEmpty('ADLDAP_SSL_KEYFILE', null); +$ssl_ciphers = envNonEmpty('ADLDAP_SSL_CIPHER_SUITE', null); +$ssl_require = envNonEmpty('ADLDAP_SSL_REQUIRE_CERT', null); + +$sslOptions = []; +if (null !== $ssl_ca_dir) { + $sslOptions[LDAP_OPT_X_TLS_CACERTDIR] = $ssl_ca_dir; +} +if (null !== $ssl_ca_file) { + $sslOptions[LDAP_OPT_X_TLS_CACERTFILE] = $ssl_ca_file; +} +if (null !== $ssl_cert) { + $sslOptions[LDAP_OPT_X_TLS_CERTFILE] = $ssl_cert; +} +if (null !== $ssl_key) { + $sslOptions[LDAP_OPT_X_TLS_KEYFILE] = $ssl_key; +} +if (null !== $ssl_ciphers) { + $sslOptions[LDAP_OPT_X_TLS_CIPHER_SUITE] = $ssl_ciphers; +} +if (null !== $ssl_require) { + $sslOptions[LDAP_OPT_X_TLS_REQUIRE_CERT] = $ssl_require; +} + return [ /* |-------------------------------------------------------------------------- @@ -254,6 +284,7 @@ return [ 'use_ssl' => env('ADLDAP_USE_SSL', false), 'use_tls' => env('ADLDAP_USE_TLS', false), + 'custom_options' => $sslOptions, ], ], diff --git a/public/v1/css/firefly.css b/public/v1/css/firefly.css index 57aa710077..df92ae9e08 100644 --- a/public/v1/css/firefly.css +++ b/public/v1/css/firefly.css @@ -108,26 +108,6 @@ body.waiting * { padding: 0; } -.ff-error-page { - width: 1000px; - margin: 20px auto 0 auto; -} - -.ff-error-page > .error-content { - margin-left: 190px; - display: block; -} - -.ff-error-page > .error-content > h3 { - font-weight: 300; - font-size: 25px; -} - -.ff-error-box { - width: 460px; - margin: 7% auto; -} - /* cursors */ .rule-triggers { cursor: move; @@ -152,7 +132,7 @@ body.waiting * { } .loading { - background: url('/images/loading-small.gif') no-repeat center center; + background: url('/v1/images/loading-small.gif') no-repeat center center; min-height: 30px; } @@ -262,4 +242,4 @@ span.twitter-typeahead { text-decoration: none; outline: 0; background-color: #428bca; -} \ No newline at end of file +} diff --git a/public/v1/js/app.js b/public/v1/js/app.js index b7609c982b..e179698448 100644 --- a/public/v1/js/app.js +++ b/public/v1/js/app.js @@ -1,2 +1,2 @@ /*! For license information please see app.js.LICENSE.txt */ -!function(t){var e={};function n(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return t[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(i,o,function(e){return t[e]}.bind(null,o));return i},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="/",n(n.s=73)}({73:function(t,e,n){t.exports=n(74)},74:function(t,e,n){try{window.$=window.jQuery=n(75),n(76)}catch(t){}},75:function(t,e,n){var i;!function(e,n){"use strict";"object"==typeof t.exports?t.exports=e.document?n(e,!0):function(t){if(!t.document)throw new Error("jQuery requires a window with a document");return n(t)}:n(e)}("undefined"!=typeof window?window:this,(function(n,o){"use strict";var r=[],s=Object.getPrototypeOf,a=r.slice,l=r.flat?function(t){return r.flat.call(t)}:function(t){return r.concat.apply([],t)},u=r.push,c=r.indexOf,f={},p=f.toString,d=f.hasOwnProperty,h=d.toString,g=h.call(Object),v={},m=function(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function(t){return null!=t&&t===t.window},b=n.document,x={type:!0,src:!0,nonce:!0,noModule:!0};function w(t,e,n){var i,o,r=(n=n||b).createElement("script");if(r.text=t,e)for(i in x)(o=e[i]||e.getAttribute&&e.getAttribute(i))&&r.setAttribute(i,o);n.head.appendChild(r).parentNode.removeChild(r)}function T(t){return null==t?t+"":"object"==typeof t||"function"==typeof t?f[p.call(t)]||"object":typeof t}var C=function(t,e){return new C.fn.init(t,e)};function E(t){var e=!!t&&"length"in t&&t.length,n=T(t);return!m(t)&&!y(t)&&("array"===n||0===e||"number"==typeof e&&e>0&&e-1 in t)}C.fn=C.prototype={jquery:"3.5.1",constructor:C,length:0,toArray:function(){return a.call(this)},get:function(t){return null==t?a.call(this):t<0?this[t+this.length]:this[t]},pushStack:function(t){var e=C.merge(this.constructor(),t);return e.prevObject=this,e},each:function(t){return C.each(this,t)},map:function(t){return this.pushStack(C.map(this,(function(e,n){return t.call(e,n,e)})))},slice:function(){return this.pushStack(a.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(C.grep(this,(function(t,e){return(e+1)%2})))},odd:function(){return this.pushStack(C.grep(this,(function(t,e){return e%2})))},eq:function(t){var e=this.length,n=+t+(t<0?e:0);return this.pushStack(n>=0&&n+~]|"+P+")"+P+"*"),z=new RegExp(P+"|>"),V=new RegExp(F),Q=new RegExp("^"+H+"$"),X={ID:new RegExp("^#("+H+")"),CLASS:new RegExp("^\\.("+H+")"),TAG:new RegExp("^("+H+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:new RegExp("^(?:"+q+")$","i"),needsContext:new RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},G=/HTML$/i,Y=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,tt=/[+~]/,et=new RegExp("\\\\[\\da-fA-F]{1,6}"+P+"?|\\\\([^\\r\\n\\f])","g"),nt=function(t,e){var n="0x"+t.slice(1)-65536;return e||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},it=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ot=function(t,e){return e?"\0"===t?"�":t.slice(0,-1)+"\\"+t.charCodeAt(t.length-1).toString(16)+" ":"\\"+t},rt=function(){p()},st=xt((function(t){return!0===t.disabled&&"fieldset"===t.nodeName.toLowerCase()}),{dir:"parentNode",next:"legend"});try{I.apply(N=L.call(w.childNodes),w.childNodes),N[w.childNodes.length].nodeType}catch(t){I={apply:N.length?function(t,e){O.apply(t,L.call(e))}:function(t,e){for(var n=t.length,i=0;t[n++]=e[i++];);t.length=n-1}}}function at(t,e,i,o){var r,a,u,c,f,h,m,y=e&&e.ownerDocument,w=e?e.nodeType:9;if(i=i||[],"string"!=typeof t||!t||1!==w&&9!==w&&11!==w)return i;if(!o&&(p(e),e=e||d,g)){if(11!==w&&(f=Z.exec(t)))if(r=f[1]){if(9===w){if(!(u=e.getElementById(r)))return i;if(u.id===r)return i.push(u),i}else if(y&&(u=y.getElementById(r))&&b(e,u)&&u.id===r)return i.push(u),i}else{if(f[2])return I.apply(i,e.getElementsByTagName(t)),i;if((r=f[3])&&n.getElementsByClassName&&e.getElementsByClassName)return I.apply(i,e.getElementsByClassName(r)),i}if(n.qsa&&!$[t+" "]&&(!v||!v.test(t))&&(1!==w||"object"!==e.nodeName.toLowerCase())){if(m=t,y=e,1===w&&(z.test(t)||U.test(t))){for((y=tt.test(t)&&mt(e.parentNode)||e)===e&&n.scope||((c=e.getAttribute("id"))?c=c.replace(it,ot):e.setAttribute("id",c=x)),a=(h=s(t)).length;a--;)h[a]=(c?"#"+c:":scope")+" "+bt(h[a]);m=h.join(",")}try{return I.apply(i,y.querySelectorAll(m)),i}catch(e){$(t,!0)}finally{c===x&&e.removeAttribute("id")}}}return l(t.replace(B,"$1"),e,i,o)}function lt(){var t=[];return function e(n,o){return t.push(n+" ")>i.cacheLength&&delete e[t.shift()],e[n+" "]=o}}function ut(t){return t[x]=!0,t}function ct(t){var e=d.createElement("fieldset");try{return!!t(e)}catch(t){return!1}finally{e.parentNode&&e.parentNode.removeChild(e),e=null}}function ft(t,e){for(var n=t.split("|"),o=n.length;o--;)i.attrHandle[n[o]]=e}function pt(t,e){var n=e&&t,i=n&&1===t.nodeType&&1===e.nodeType&&t.sourceIndex-e.sourceIndex;if(i)return i;if(n)for(;n=n.nextSibling;)if(n===e)return-1;return t?1:-1}function dt(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function ht(t){return function(e){var n=e.nodeName.toLowerCase();return("input"===n||"button"===n)&&e.type===t}}function gt(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&st(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function vt(t){return ut((function(e){return e=+e,ut((function(n,i){for(var o,r=t([],n.length,e),s=r.length;s--;)n[o=r[s]]&&(n[o]=!(i[o]=n[o]))}))}))}function mt(t){return t&&void 0!==t.getElementsByTagName&&t}for(e in n=at.support={},r=at.isXML=function(t){var e=t.namespaceURI,n=(t.ownerDocument||t).documentElement;return!G.test(e||n&&n.nodeName||"HTML")},p=at.setDocument=function(t){var e,o,s=t?t.ownerDocument||t:w;return s!=d&&9===s.nodeType&&s.documentElement?(h=(d=s).documentElement,g=!r(d),w!=d&&(o=d.defaultView)&&o.top!==o&&(o.addEventListener?o.addEventListener("unload",rt,!1):o.attachEvent&&o.attachEvent("onunload",rt)),n.scope=ct((function(t){return h.appendChild(t).appendChild(d.createElement("div")),void 0!==t.querySelectorAll&&!t.querySelectorAll(":scope fieldset div").length})),n.attributes=ct((function(t){return t.className="i",!t.getAttribute("className")})),n.getElementsByTagName=ct((function(t){return t.appendChild(d.createComment("")),!t.getElementsByTagName("*").length})),n.getElementsByClassName=K.test(d.getElementsByClassName),n.getById=ct((function(t){return h.appendChild(t).id=x,!d.getElementsByName||!d.getElementsByName(x).length})),n.getById?(i.filter.ID=function(t){var e=t.replace(et,nt);return function(t){return t.getAttribute("id")===e}},i.find.ID=function(t,e){if(void 0!==e.getElementById&&g){var n=e.getElementById(t);return n?[n]:[]}}):(i.filter.ID=function(t){var e=t.replace(et,nt);return function(t){var n=void 0!==t.getAttributeNode&&t.getAttributeNode("id");return n&&n.value===e}},i.find.ID=function(t,e){if(void 0!==e.getElementById&&g){var n,i,o,r=e.getElementById(t);if(r){if((n=r.getAttributeNode("id"))&&n.value===t)return[r];for(o=e.getElementsByName(t),i=0;r=o[i++];)if((n=r.getAttributeNode("id"))&&n.value===t)return[r]}return[]}}),i.find.TAG=n.getElementsByTagName?function(t,e){return void 0!==e.getElementsByTagName?e.getElementsByTagName(t):n.qsa?e.querySelectorAll(t):void 0}:function(t,e){var n,i=[],o=0,r=e.getElementsByTagName(t);if("*"===t){for(;n=r[o++];)1===n.nodeType&&i.push(n);return i}return r},i.find.CLASS=n.getElementsByClassName&&function(t,e){if(void 0!==e.getElementsByClassName&&g)return e.getElementsByClassName(t)},m=[],v=[],(n.qsa=K.test(d.querySelectorAll))&&(ct((function(t){var e;h.appendChild(t).innerHTML="",t.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+P+"*(?:''|\"\")"),t.querySelectorAll("[selected]").length||v.push("\\["+P+"*(?:value|"+q+")"),t.querySelectorAll("[id~="+x+"-]").length||v.push("~="),(e=d.createElement("input")).setAttribute("name",""),t.appendChild(e),t.querySelectorAll("[name='']").length||v.push("\\["+P+"*name"+P+"*="+P+"*(?:''|\"\")"),t.querySelectorAll(":checked").length||v.push(":checked"),t.querySelectorAll("a#"+x+"+*").length||v.push(".#.+[+~]"),t.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")})),ct((function(t){t.innerHTML="";var e=d.createElement("input");e.setAttribute("type","hidden"),t.appendChild(e).setAttribute("name","D"),t.querySelectorAll("[name=d]").length&&v.push("name"+P+"*[*^$|!~]?="),2!==t.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),h.appendChild(t).disabled=!0,2!==t.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),t.querySelectorAll("*,:x"),v.push(",.*:")}))),(n.matchesSelector=K.test(y=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ct((function(t){n.disconnectedMatch=y.call(t,"*"),y.call(t,"[s!='']:x"),m.push("!=",F)})),v=v.length&&new RegExp(v.join("|")),m=m.length&&new RegExp(m.join("|")),e=K.test(h.compareDocumentPosition),b=e||K.test(h.contains)?function(t,e){var n=9===t.nodeType?t.documentElement:t,i=e&&e.parentNode;return t===i||!(!i||1!==i.nodeType||!(n.contains?n.contains(i):t.compareDocumentPosition&&16&t.compareDocumentPosition(i)))}:function(t,e){if(e)for(;e=e.parentNode;)if(e===t)return!0;return!1},A=e?function(t,e){if(t===e)return f=!0,0;var i=!t.compareDocumentPosition-!e.compareDocumentPosition;return i||(1&(i=(t.ownerDocument||t)==(e.ownerDocument||e)?t.compareDocumentPosition(e):1)||!n.sortDetached&&e.compareDocumentPosition(t)===i?t==d||t.ownerDocument==w&&b(w,t)?-1:e==d||e.ownerDocument==w&&b(w,e)?1:c?R(c,t)-R(c,e):0:4&i?-1:1)}:function(t,e){if(t===e)return f=!0,0;var n,i=0,o=t.parentNode,r=e.parentNode,s=[t],a=[e];if(!o||!r)return t==d?-1:e==d?1:o?-1:r?1:c?R(c,t)-R(c,e):0;if(o===r)return pt(t,e);for(n=t;n=n.parentNode;)s.unshift(n);for(n=e;n=n.parentNode;)a.unshift(n);for(;s[i]===a[i];)i++;return i?pt(s[i],a[i]):s[i]==w?-1:a[i]==w?1:0},d):d},at.matches=function(t,e){return at(t,null,null,e)},at.matchesSelector=function(t,e){if(p(t),n.matchesSelector&&g&&!$[e+" "]&&(!m||!m.test(e))&&(!v||!v.test(e)))try{var i=y.call(t,e);if(i||n.disconnectedMatch||t.document&&11!==t.document.nodeType)return i}catch(t){$(e,!0)}return at(e,d,null,[t]).length>0},at.contains=function(t,e){return(t.ownerDocument||t)!=d&&p(t),b(t,e)},at.attr=function(t,e){(t.ownerDocument||t)!=d&&p(t);var o=i.attrHandle[e.toLowerCase()],r=o&&D.call(i.attrHandle,e.toLowerCase())?o(t,e,!g):void 0;return void 0!==r?r:n.attributes||!g?t.getAttribute(e):(r=t.getAttributeNode(e))&&r.specified?r.value:null},at.escape=function(t){return(t+"").replace(it,ot)},at.error=function(t){throw new Error("Syntax error, unrecognized expression: "+t)},at.uniqueSort=function(t){var e,i=[],o=0,r=0;if(f=!n.detectDuplicates,c=!n.sortStable&&t.slice(0),t.sort(A),f){for(;e=t[r++];)e===t[r]&&(o=i.push(r));for(;o--;)t.splice(i[o],1)}return c=null,t},o=at.getText=function(t){var e,n="",i=0,r=t.nodeType;if(r){if(1===r||9===r||11===r){if("string"==typeof t.textContent)return t.textContent;for(t=t.firstChild;t;t=t.nextSibling)n+=o(t)}else if(3===r||4===r)return t.nodeValue}else for(;e=t[i++];)n+=o(e);return n},(i=at.selectors={cacheLength:50,createPseudo:ut,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(t){return t[1]=t[1].replace(et,nt),t[3]=(t[3]||t[4]||t[5]||"").replace(et,nt),"~="===t[2]&&(t[3]=" "+t[3]+" "),t.slice(0,4)},CHILD:function(t){return t[1]=t[1].toLowerCase(),"nth"===t[1].slice(0,3)?(t[3]||at.error(t[0]),t[4]=+(t[4]?t[5]+(t[6]||1):2*("even"===t[3]||"odd"===t[3])),t[5]=+(t[7]+t[8]||"odd"===t[3])):t[3]&&at.error(t[0]),t},PSEUDO:function(t){var e,n=!t[6]&&t[2];return X.CHILD.test(t[0])?null:(t[3]?t[2]=t[4]||t[5]||"":n&&V.test(n)&&(e=s(n,!0))&&(e=n.indexOf(")",n.length-e)-n.length)&&(t[0]=t[0].slice(0,e),t[2]=n.slice(0,e)),t.slice(0,3))}},filter:{TAG:function(t){var e=t.replace(et,nt).toLowerCase();return"*"===t?function(){return!0}:function(t){return t.nodeName&&t.nodeName.toLowerCase()===e}},CLASS:function(t){var e=E[t+" "];return e||(e=new RegExp("(^|"+P+")"+t+"("+P+"|$)"))&&E(t,(function(t){return e.test("string"==typeof t.className&&t.className||void 0!==t.getAttribute&&t.getAttribute("class")||"")}))},ATTR:function(t,e,n){return function(i){var o=at.attr(i,t);return null==o?"!="===e:!e||(o+="","="===e?o===n:"!="===e?o!==n:"^="===e?n&&0===o.indexOf(n):"*="===e?n&&o.indexOf(n)>-1:"$="===e?n&&o.slice(-n.length)===n:"~="===e?(" "+o.replace(W," ")+" ").indexOf(n)>-1:"|="===e&&(o===n||o.slice(0,n.length+1)===n+"-"))}},CHILD:function(t,e,n,i,o){var r="nth"!==t.slice(0,3),s="last"!==t.slice(-4),a="of-type"===e;return 1===i&&0===o?function(t){return!!t.parentNode}:function(e,n,l){var u,c,f,p,d,h,g=r!==s?"nextSibling":"previousSibling",v=e.parentNode,m=a&&e.nodeName.toLowerCase(),y=!l&&!a,b=!1;if(v){if(r){for(;g;){for(p=e;p=p[g];)if(a?p.nodeName.toLowerCase()===m:1===p.nodeType)return!1;h=g="only"===t&&!h&&"nextSibling"}return!0}if(h=[s?v.firstChild:v.lastChild],s&&y){for(b=(d=(u=(c=(f=(p=v)[x]||(p[x]={}))[p.uniqueID]||(f[p.uniqueID]={}))[t]||[])[0]===T&&u[1])&&u[2],p=d&&v.childNodes[d];p=++d&&p&&p[g]||(b=d=0)||h.pop();)if(1===p.nodeType&&++b&&p===e){c[t]=[T,d,b];break}}else if(y&&(b=d=(u=(c=(f=(p=e)[x]||(p[x]={}))[p.uniqueID]||(f[p.uniqueID]={}))[t]||[])[0]===T&&u[1]),!1===b)for(;(p=++d&&p&&p[g]||(b=d=0)||h.pop())&&((a?p.nodeName.toLowerCase()!==m:1!==p.nodeType)||!++b||(y&&((c=(f=p[x]||(p[x]={}))[p.uniqueID]||(f[p.uniqueID]={}))[t]=[T,b]),p!==e)););return(b-=o)===i||b%i==0&&b/i>=0}}},PSEUDO:function(t,e){var n,o=i.pseudos[t]||i.setFilters[t.toLowerCase()]||at.error("unsupported pseudo: "+t);return o[x]?o(e):o.length>1?(n=[t,t,"",e],i.setFilters.hasOwnProperty(t.toLowerCase())?ut((function(t,n){for(var i,r=o(t,e),s=r.length;s--;)t[i=R(t,r[s])]=!(n[i]=r[s])})):function(t){return o(t,0,n)}):o}},pseudos:{not:ut((function(t){var e=[],n=[],i=a(t.replace(B,"$1"));return i[x]?ut((function(t,e,n,o){for(var r,s=i(t,null,o,[]),a=t.length;a--;)(r=s[a])&&(t[a]=!(e[a]=r))})):function(t,o,r){return e[0]=t,i(e,null,r,n),e[0]=null,!n.pop()}})),has:ut((function(t){return function(e){return at(t,e).length>0}})),contains:ut((function(t){return t=t.replace(et,nt),function(e){return(e.textContent||o(e)).indexOf(t)>-1}})),lang:ut((function(t){return Q.test(t||"")||at.error("unsupported lang: "+t),t=t.replace(et,nt).toLowerCase(),function(e){var n;do{if(n=g?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(n=n.toLowerCase())===t||0===n.indexOf(t+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}})),target:function(e){var n=t.location&&t.location.hash;return n&&n.slice(1)===e.id},root:function(t){return t===h},focus:function(t){return t===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(t.type||t.href||~t.tabIndex)},enabled:gt(!1),disabled:gt(!0),checked:function(t){var e=t.nodeName.toLowerCase();return"input"===e&&!!t.checked||"option"===e&&!!t.selected},selected:function(t){return t.parentNode&&t.parentNode.selectedIndex,!0===t.selected},empty:function(t){for(t=t.firstChild;t;t=t.nextSibling)if(t.nodeType<6)return!1;return!0},parent:function(t){return!i.pseudos.empty(t)},header:function(t){return J.test(t.nodeName)},input:function(t){return Y.test(t.nodeName)},button:function(t){var e=t.nodeName.toLowerCase();return"input"===e&&"button"===t.type||"button"===e},text:function(t){var e;return"input"===t.nodeName.toLowerCase()&&"text"===t.type&&(null==(e=t.getAttribute("type"))||"text"===e.toLowerCase())},first:vt((function(){return[0]})),last:vt((function(t,e){return[e-1]})),eq:vt((function(t,e,n){return[n<0?n+e:n]})),even:vt((function(t,e){for(var n=0;ne?e:n;--i>=0;)t.push(i);return t})),gt:vt((function(t,e,n){for(var i=n<0?n+e:n;++i1?function(e,n,i){for(var o=t.length;o--;)if(!t[o](e,n,i))return!1;return!0}:t[0]}function Tt(t,e,n,i,o){for(var r,s=[],a=0,l=t.length,u=null!=e;a-1&&(r[u]=!(s[u]=f))}}else m=Tt(m===s?m.splice(h,m.length):m),o?o(null,s,m,l):I.apply(s,m)}))}function Et(t){for(var e,n,o,r=t.length,s=i.relative[t[0].type],a=s||i.relative[" "],l=s?1:0,c=xt((function(t){return t===e}),a,!0),f=xt((function(t){return R(e,t)>-1}),a,!0),p=[function(t,n,i){var o=!s&&(i||n!==u)||((e=n).nodeType?c(t,n,i):f(t,n,i));return e=null,o}];l1&&wt(p),l>1&&bt(t.slice(0,l-1).concat({value:" "===t[l-2].type?"*":""})).replace(B,"$1"),n,l0,o=t.length>0,r=function(r,s,a,l,c){var f,h,v,m=0,y="0",b=r&&[],x=[],w=u,C=r||o&&i.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,S=C.length;for(c&&(u=s==d||s||c);y!==S&&null!=(f=C[y]);y++){if(o&&f){for(h=0,s||f.ownerDocument==d||(p(f),a=!g);v=t[h++];)if(v(f,s||d,a)){l.push(f);break}c&&(T=E)}n&&((f=!v&&f)&&m--,r&&b.push(f))}if(m+=y,n&&y!==m){for(h=0;v=e[h++];)v(b,x,s,a);if(r){if(m>0)for(;y--;)b[y]||x[y]||(x[y]=j.call(l));x=Tt(x)}I.apply(l,x),c&&!r&&x.length>0&&m+e.length>1&&at.uniqueSort(l)}return c&&(T=E,u=w),b};return n?ut(r):r}(r,o))).selector=t}return a},l=at.select=function(t,e,n,o){var r,l,u,c,f,p="function"==typeof t&&t,d=!o&&s(t=p.selector||t);if(n=n||[],1===d.length){if((l=d[0]=d[0].slice(0)).length>2&&"ID"===(u=l[0]).type&&9===e.nodeType&&g&&i.relative[l[1].type]){if(!(e=(i.find.ID(u.matches[0].replace(et,nt),e)||[])[0]))return n;p&&(e=e.parentNode),t=t.slice(l.shift().value.length)}for(r=X.needsContext.test(t)?0:l.length;r--&&(u=l[r],!i.relative[c=u.type]);)if((f=i.find[c])&&(o=f(u.matches[0].replace(et,nt),tt.test(l[0].type)&&mt(e.parentNode)||e))){if(l.splice(r,1),!(t=o.length&&bt(l)))return I.apply(n,o),n;break}}return(p||a(t,d))(o,e,!g,n,!e||tt.test(t)&&mt(e.parentNode)||e),n},n.sortStable=x.split("").sort(A).join("")===x,n.detectDuplicates=!!f,p(),n.sortDetached=ct((function(t){return 1&t.compareDocumentPosition(d.createElement("fieldset"))})),ct((function(t){return t.innerHTML="","#"===t.firstChild.getAttribute("href")}))||ft("type|href|height|width",(function(t,e,n){if(!n)return t.getAttribute(e,"type"===e.toLowerCase()?1:2)})),n.attributes&&ct((function(t){return t.innerHTML="",t.firstChild.setAttribute("value",""),""===t.firstChild.getAttribute("value")}))||ft("value",(function(t,e,n){if(!n&&"input"===t.nodeName.toLowerCase())return t.defaultValue})),ct((function(t){return null==t.getAttribute("disabled")}))||ft(q,(function(t,e,n){var i;if(!n)return!0===t[e]?e.toLowerCase():(i=t.getAttributeNode(e))&&i.specified?i.value:null})),at}(n);C.find=S,C.expr=S.selectors,C.expr[":"]=C.expr.pseudos,C.uniqueSort=C.unique=S.uniqueSort,C.text=S.getText,C.isXMLDoc=S.isXML,C.contains=S.contains,C.escapeSelector=S.escape;var k=function(t,e,n){for(var i=[],o=void 0!==n;(t=t[e])&&9!==t.nodeType;)if(1===t.nodeType){if(o&&C(t).is(n))break;i.push(t)}return i},$=function(t,e){for(var n=[];t;t=t.nextSibling)1===t.nodeType&&t!==e&&n.push(t);return n},A=C.expr.match.needsContext;function D(t,e){return t.nodeName&&t.nodeName.toLowerCase()===e.toLowerCase()}var N=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(t,e,n){return m(e)?C.grep(t,(function(t,i){return!!e.call(t,i,t)!==n})):e.nodeType?C.grep(t,(function(t){return t===e!==n})):"string"!=typeof e?C.grep(t,(function(t){return c.call(e,t)>-1!==n})):C.filter(e,t,n)}C.filter=function(t,e,n){var i=e[0];return n&&(t=":not("+t+")"),1===e.length&&1===i.nodeType?C.find.matchesSelector(i,t)?[i]:[]:C.find.matches(t,C.grep(e,(function(t){return 1===t.nodeType})))},C.fn.extend({find:function(t){var e,n,i=this.length,o=this;if("string"!=typeof t)return this.pushStack(C(t).filter((function(){for(e=0;e1?C.uniqueSort(n):n},filter:function(t){return this.pushStack(j(this,t||[],!1))},not:function(t){return this.pushStack(j(this,t||[],!0))},is:function(t){return!!j(this,"string"==typeof t&&A.test(t)?C(t):t||[],!1).length}});var O,I=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(C.fn.init=function(t,e,n){var i,o;if(!t)return this;if(n=n||O,"string"==typeof t){if(!(i="<"===t[0]&&">"===t[t.length-1]&&t.length>=3?[null,t,null]:I.exec(t))||!i[1]&&e)return!e||e.jquery?(e||n).find(t):this.constructor(e).find(t);if(i[1]){if(e=e instanceof C?e[0]:e,C.merge(this,C.parseHTML(i[1],e&&e.nodeType?e.ownerDocument||e:b,!0)),N.test(i[1])&&C.isPlainObject(e))for(i in e)m(this[i])?this[i](e[i]):this.attr(i,e[i]);return this}return(o=b.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return t.nodeType?(this[0]=t,this.length=1,this):m(t)?void 0!==n.ready?n.ready(t):t(C):C.makeArray(t,this)}).prototype=C.fn,O=C(b);var L=/^(?:parents|prev(?:Until|All))/,R={children:!0,contents:!0,next:!0,prev:!0};function q(t,e){for(;(t=t[e])&&1!==t.nodeType;);return t}C.fn.extend({has:function(t){var e=C(t,this),n=e.length;return this.filter((function(){for(var t=0;t-1:1===n.nodeType&&C.find.matchesSelector(n,t))){r.push(n);break}return this.pushStack(r.length>1?C.uniqueSort(r):r)},index:function(t){return t?"string"==typeof t?c.call(C(t),this[0]):c.call(this,t.jquery?t[0]:t):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(t,e){return this.pushStack(C.uniqueSort(C.merge(this.get(),C(t,e))))},addBack:function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}}),C.each({parent:function(t){var e=t.parentNode;return e&&11!==e.nodeType?e:null},parents:function(t){return k(t,"parentNode")},parentsUntil:function(t,e,n){return k(t,"parentNode",n)},next:function(t){return q(t,"nextSibling")},prev:function(t){return q(t,"previousSibling")},nextAll:function(t){return k(t,"nextSibling")},prevAll:function(t){return k(t,"previousSibling")},nextUntil:function(t,e,n){return k(t,"nextSibling",n)},prevUntil:function(t,e,n){return k(t,"previousSibling",n)},siblings:function(t){return $((t.parentNode||{}).firstChild,t)},children:function(t){return $(t.firstChild)},contents:function(t){return null!=t.contentDocument&&s(t.contentDocument)?t.contentDocument:(D(t,"template")&&(t=t.content||t),C.merge([],t.childNodes))}},(function(t,e){C.fn[t]=function(n,i){var o=C.map(this,e,n);return"Until"!==t.slice(-5)&&(i=n),i&&"string"==typeof i&&(o=C.filter(i,o)),this.length>1&&(R[t]||C.uniqueSort(o),L.test(t)&&o.reverse()),this.pushStack(o)}}));var P=/[^\x20\t\r\n\f]+/g;function H(t){return t}function M(t){throw t}function F(t,e,n,i){var o;try{t&&m(o=t.promise)?o.call(t).done(e).fail(n):t&&m(o=t.then)?o.call(t,e,n):e.apply(void 0,[t].slice(i))}catch(t){n.apply(void 0,[t])}}C.Callbacks=function(t){t="string"==typeof t?function(t){var e={};return C.each(t.match(P)||[],(function(t,n){e[n]=!0})),e}(t):C.extend({},t);var e,n,i,o,r=[],s=[],a=-1,l=function(){for(o=o||t.once,i=e=!0;s.length;a=-1)for(n=s.shift();++a-1;)r.splice(n,1),n<=a&&a--})),this},has:function(t){return t?C.inArray(t,r)>-1:r.length>0},empty:function(){return r&&(r=[]),this},disable:function(){return o=s=[],r=n="",this},disabled:function(){return!r},lock:function(){return o=s=[],n||e||(r=n=""),this},locked:function(){return!!o},fireWith:function(t,n){return o||(n=[t,(n=n||[]).slice?n.slice():n],s.push(n),e||l()),this},fire:function(){return u.fireWith(this,arguments),this},fired:function(){return!!i}};return u},C.extend({Deferred:function(t){var e=[["notify","progress",C.Callbacks("memory"),C.Callbacks("memory"),2],["resolve","done",C.Callbacks("once memory"),C.Callbacks("once memory"),0,"resolved"],["reject","fail",C.Callbacks("once memory"),C.Callbacks("once memory"),1,"rejected"]],i="pending",o={state:function(){return i},always:function(){return r.done(arguments).fail(arguments),this},catch:function(t){return o.then(null,t)},pipe:function(){var t=arguments;return C.Deferred((function(n){C.each(e,(function(e,i){var o=m(t[i[4]])&&t[i[4]];r[i[1]]((function(){var t=o&&o.apply(this,arguments);t&&m(t.promise)?t.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[i[0]+"With"](this,o?[t]:arguments)}))})),t=null})).promise()},then:function(t,i,o){var r=0;function s(t,e,i,o){return function(){var a=this,l=arguments,u=function(){var n,u;if(!(t=r&&(i!==M&&(a=void 0,l=[n]),e.rejectWith(a,l))}};t?c():(C.Deferred.getStackHook&&(c.stackTrace=C.Deferred.getStackHook()),n.setTimeout(c))}}return C.Deferred((function(n){e[0][3].add(s(0,n,m(o)?o:H,n.notifyWith)),e[1][3].add(s(0,n,m(t)?t:H)),e[2][3].add(s(0,n,m(i)?i:M))})).promise()},promise:function(t){return null!=t?C.extend(t,o):o}},r={};return C.each(e,(function(t,n){var s=n[2],a=n[5];o[n[1]]=s.add,a&&s.add((function(){i=a}),e[3-t][2].disable,e[3-t][3].disable,e[0][2].lock,e[0][3].lock),s.add(n[3].fire),r[n[0]]=function(){return r[n[0]+"With"](this===r?void 0:this,arguments),this},r[n[0]+"With"]=s.fireWith})),o.promise(r),t&&t.call(r,r),r},when:function(t){var e=arguments.length,n=e,i=Array(n),o=a.call(arguments),r=C.Deferred(),s=function(t){return function(n){i[t]=this,o[t]=arguments.length>1?a.call(arguments):n,--e||r.resolveWith(i,o)}};if(e<=1&&(F(t,r.done(s(n)).resolve,r.reject,!e),"pending"===r.state()||m(o[n]&&o[n].then)))return r.then();for(;n--;)F(o[n],s(n),r.reject);return r.promise()}});var W=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;C.Deferred.exceptionHook=function(t,e){n.console&&n.console.warn&&t&&W.test(t.name)&&n.console.warn("jQuery.Deferred exception: "+t.message,t.stack,e)},C.readyException=function(t){n.setTimeout((function(){throw t}))};var B=C.Deferred();function _(){b.removeEventListener("DOMContentLoaded",_),n.removeEventListener("load",_),C.ready()}C.fn.ready=function(t){return B.then(t).catch((function(t){C.readyException(t)})),this},C.extend({isReady:!1,readyWait:1,ready:function(t){(!0===t?--C.readyWait:C.isReady)||(C.isReady=!0,!0!==t&&--C.readyWait>0||B.resolveWith(b,[C]))}}),C.ready.then=B.then,"complete"===b.readyState||"loading"!==b.readyState&&!b.documentElement.doScroll?n.setTimeout(C.ready):(b.addEventListener("DOMContentLoaded",_),n.addEventListener("load",_));var U=function(t,e,n,i,o,r,s){var a=0,l=t.length,u=null==n;if("object"===T(n))for(a in o=!0,n)U(t,e,a,n[a],!0,r,s);else if(void 0!==i&&(o=!0,m(i)||(s=!0),u&&(s?(e.call(t,i),e=null):(u=e,e=function(t,e,n){return u.call(C(t),n)})),e))for(;a1,null,!0)},removeData:function(t){return this.each((function(){K.remove(this,t)}))}}),C.extend({queue:function(t,e,n){var i;if(t)return e=(e||"fx")+"queue",i=J.get(t,e),n&&(!i||Array.isArray(n)?i=J.access(t,e,C.makeArray(n)):i.push(n)),i||[]},dequeue:function(t,e){e=e||"fx";var n=C.queue(t,e),i=n.length,o=n.shift(),r=C._queueHooks(t,e);"inprogress"===o&&(o=n.shift(),i--),o&&("fx"===e&&n.unshift("inprogress"),delete r.stop,o.call(t,(function(){C.dequeue(t,e)}),r)),!i&&r&&r.empty.fire()},_queueHooks:function(t,e){var n=e+"queueHooks";return J.get(t,n)||J.access(t,n,{empty:C.Callbacks("once memory").add((function(){J.remove(t,[e+"queue",n])}))})}}),C.fn.extend({queue:function(t,e){var n=2;return"string"!=typeof t&&(e=t,t="fx",n--),arguments.length\x20\t\r\n\f]*)/i,mt=/^$|^module$|\/(?:java|ecma)script/i;dt=b.createDocumentFragment().appendChild(b.createElement("div")),(ht=b.createElement("input")).setAttribute("type","radio"),ht.setAttribute("checked","checked"),ht.setAttribute("name","t"),dt.appendChild(ht),v.checkClone=dt.cloneNode(!0).cloneNode(!0).lastChild.checked,dt.innerHTML="",v.noCloneChecked=!!dt.cloneNode(!0).lastChild.defaultValue,dt.innerHTML="",v.option=!!dt.lastChild;var yt={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function bt(t,e){var n;return n=void 0!==t.getElementsByTagName?t.getElementsByTagName(e||"*"):void 0!==t.querySelectorAll?t.querySelectorAll(e||"*"):[],void 0===e||e&&D(t,e)?C.merge([t],n):n}function xt(t,e){for(var n=0,i=t.length;n",""]);var wt=/<|&#?\w+;/;function Tt(t,e,n,i,o){for(var r,s,a,l,u,c,f=e.createDocumentFragment(),p=[],d=0,h=t.length;d-1)o&&o.push(r);else if(u=st(r),s=bt(f.appendChild(r),"script"),u&&xt(s),n)for(c=0;r=s[c++];)mt.test(r.type||"")&&n.push(r);return f}var Ct=/^key/,Et=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,St=/^([^.]*)(?:\.(.+)|)/;function kt(){return!0}function $t(){return!1}function At(t,e){return t===function(){try{return b.activeElement}catch(t){}}()==("focus"===e)}function Dt(t,e,n,i,o,r){var s,a;if("object"==typeof e){for(a in"string"!=typeof n&&(i=i||n,n=void 0),e)Dt(t,a,n,i,e[a],r);return t}if(null==i&&null==o?(o=n,i=n=void 0):null==o&&("string"==typeof n?(o=i,i=void 0):(o=i,i=n,n=void 0)),!1===o)o=$t;else if(!o)return t;return 1===r&&(s=o,(o=function(t){return C().off(t),s.apply(this,arguments)}).guid=s.guid||(s.guid=C.guid++)),t.each((function(){C.event.add(this,e,o,i,n)}))}function Nt(t,e,n){n?(J.set(t,e,!1),C.event.add(t,e,{namespace:!1,handler:function(t){var i,o,r=J.get(this,e);if(1&t.isTrigger&&this[e]){if(r.length)(C.event.special[e]||{}).delegateType&&t.stopPropagation();else if(r=a.call(arguments),J.set(this,e,r),i=n(this,e),this[e](),r!==(o=J.get(this,e))||i?J.set(this,e,!1):o={},r!==o)return t.stopImmediatePropagation(),t.preventDefault(),o.value}else r.length&&(J.set(this,e,{value:C.event.trigger(C.extend(r[0],C.Event.prototype),r.slice(1),this)}),t.stopImmediatePropagation())}})):void 0===J.get(t,e)&&C.event.add(t,e,kt)}C.event={global:{},add:function(t,e,n,i,o){var r,s,a,l,u,c,f,p,d,h,g,v=J.get(t);if(G(t))for(n.handler&&(n=(r=n).handler,o=r.selector),o&&C.find.matchesSelector(rt,o),n.guid||(n.guid=C.guid++),(l=v.events)||(l=v.events=Object.create(null)),(s=v.handle)||(s=v.handle=function(e){return void 0!==C&&C.event.triggered!==e.type?C.event.dispatch.apply(t,arguments):void 0}),u=(e=(e||"").match(P)||[""]).length;u--;)d=g=(a=St.exec(e[u])||[])[1],h=(a[2]||"").split(".").sort(),d&&(f=C.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=C.event.special[d]||{},c=C.extend({type:d,origType:g,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&C.expr.match.needsContext.test(o),namespace:h.join(".")},r),(p=l[d])||((p=l[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,i,h,s)||t.addEventListener&&t.addEventListener(d,s)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),o?p.splice(p.delegateCount++,0,c):p.push(c),C.event.global[d]=!0)},remove:function(t,e,n,i,o){var r,s,a,l,u,c,f,p,d,h,g,v=J.hasData(t)&&J.get(t);if(v&&(l=v.events)){for(u=(e=(e||"").match(P)||[""]).length;u--;)if(d=g=(a=St.exec(e[u])||[])[1],h=(a[2]||"").split(".").sort(),d){for(f=C.event.special[d]||{},p=l[d=(i?f.delegateType:f.bindType)||d]||[],a=a[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=r=p.length;r--;)c=p[r],!o&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||i&&i!==c.selector&&("**"!==i||!c.selector)||(p.splice(r,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(t,c));s&&!p.length&&(f.teardown&&!1!==f.teardown.call(t,h,v.handle)||C.removeEvent(t,d,v.handle),delete l[d])}else for(d in l)C.event.remove(t,d+e[u],n,i,!0);C.isEmptyObject(l)&&J.remove(t,"handle events")}},dispatch:function(t){var e,n,i,o,r,s,a=new Array(arguments.length),l=C.event.fix(t),u=(J.get(this,"events")||Object.create(null))[l.type]||[],c=C.event.special[l.type]||{};for(a[0]=l,e=1;e=1))for(;u!==this;u=u.parentNode||this)if(1===u.nodeType&&("click"!==t.type||!0!==u.disabled)){for(r=[],s={},n=0;n-1:C.find(o,this,null,[u]).length),s[o]&&r.push(i);r.length&&a.push({elem:u,handlers:r})}return u=this,l\s*$/g;function Lt(t,e){return D(t,"table")&&D(11!==e.nodeType?e:e.firstChild,"tr")&&C(t).children("tbody")[0]||t}function Rt(t){return t.type=(null!==t.getAttribute("type"))+"/"+t.type,t}function qt(t){return"true/"===(t.type||"").slice(0,5)?t.type=t.type.slice(5):t.removeAttribute("type"),t}function Pt(t,e){var n,i,o,r,s,a;if(1===e.nodeType){if(J.hasData(t)&&(a=J.get(t).events))for(o in J.remove(e,"handle events"),a)for(n=0,i=a[o].length;n1&&"string"==typeof h&&!v.checkClone&&Ot.test(h))return t.each((function(o){var r=t.eq(o);g&&(e[0]=h.call(this,o,r.html())),Mt(r,e,n,i)}));if(p&&(r=(o=Tt(e,t[0].ownerDocument,!1,t,i)).firstChild,1===o.childNodes.length&&(o=r),r||i)){for(a=(s=C.map(bt(o,"script"),Rt)).length;f0&&xt(s,!l&&bt(t,"script")),a},cleanData:function(t){for(var e,n,i,o=C.event.special,r=0;void 0!==(n=t[r]);r++)if(G(n)){if(e=n[J.expando]){if(e.events)for(i in e.events)o[i]?C.event.remove(n,i):C.removeEvent(n,i,e.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),C.fn.extend({detach:function(t){return Ft(this,t,!0)},remove:function(t){return Ft(this,t)},text:function(t){return U(this,(function(t){return void 0===t?C.text(this):this.empty().each((function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=t)}))}),null,t,arguments.length)},append:function(){return Mt(this,arguments,(function(t){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Lt(this,t).appendChild(t)}))},prepend:function(){return Mt(this,arguments,(function(t){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var e=Lt(this,t);e.insertBefore(t,e.firstChild)}}))},before:function(){return Mt(this,arguments,(function(t){this.parentNode&&this.parentNode.insertBefore(t,this)}))},after:function(){return Mt(this,arguments,(function(t){this.parentNode&&this.parentNode.insertBefore(t,this.nextSibling)}))},empty:function(){for(var t,e=0;null!=(t=this[e]);e++)1===t.nodeType&&(C.cleanData(bt(t,!1)),t.textContent="");return this},clone:function(t,e){return t=null!=t&&t,e=null==e?t:e,this.map((function(){return C.clone(this,t,e)}))},html:function(t){return U(this,(function(t){var e=this[0]||{},n=0,i=this.length;if(void 0===t&&1===e.nodeType)return e.innerHTML;if("string"==typeof t&&!jt.test(t)&&!yt[(vt.exec(t)||["",""])[1].toLowerCase()]){t=C.htmlPrefilter(t);try{for(;n3,rt.removeChild(t)),a}}))}();var Qt=["Webkit","Moz","ms"],Xt=b.createElement("div").style,Gt={};function Yt(t){var e=C.cssProps[t]||Gt[t];return e||(t in Xt?t:Gt[t]=function(t){for(var e=t[0].toUpperCase()+t.slice(1),n=Qt.length;n--;)if((t=Qt[n]+e)in Xt)return t}(t)||t)}var Jt=/^(none|table(?!-c[ea]).+)/,Kt=/^--/,Zt={position:"absolute",visibility:"hidden",display:"block"},te={letterSpacing:"0",fontWeight:"400"};function ee(t,e,n){var i=it.exec(e);return i?Math.max(0,i[2]-(n||0))+(i[3]||"px"):e}function ne(t,e,n,i,o,r){var s="width"===e?1:0,a=0,l=0;if(n===(i?"border":"content"))return 0;for(;s<4;s+=2)"margin"===n&&(l+=C.css(t,n+ot[s],!0,o)),i?("content"===n&&(l-=C.css(t,"padding"+ot[s],!0,o)),"margin"!==n&&(l-=C.css(t,"border"+ot[s]+"Width",!0,o))):(l+=C.css(t,"padding"+ot[s],!0,o),"padding"!==n?l+=C.css(t,"border"+ot[s]+"Width",!0,o):a+=C.css(t,"border"+ot[s]+"Width",!0,o));return!i&&r>=0&&(l+=Math.max(0,Math.ceil(t["offset"+e[0].toUpperCase()+e.slice(1)]-r-l-a-.5))||0),l}function ie(t,e,n){var i=Bt(t),o=(!v.boxSizingReliable()||n)&&"border-box"===C.css(t,"boxSizing",!1,i),r=o,s=zt(t,e,i),a="offset"+e[0].toUpperCase()+e.slice(1);if(Wt.test(s)){if(!n)return s;s="auto"}return(!v.boxSizingReliable()&&o||!v.reliableTrDimensions()&&D(t,"tr")||"auto"===s||!parseFloat(s)&&"inline"===C.css(t,"display",!1,i))&&t.getClientRects().length&&(o="border-box"===C.css(t,"boxSizing",!1,i),(r=a in t)&&(s=t[a])),(s=parseFloat(s)||0)+ne(t,e,n||(o?"border":"content"),r,i,s)+"px"}function oe(t,e,n,i,o){return new oe.prototype.init(t,e,n,i,o)}C.extend({cssHooks:{opacity:{get:function(t,e){if(e){var n=zt(t,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(t,e,n,i){if(t&&3!==t.nodeType&&8!==t.nodeType&&t.style){var o,r,s,a=X(e),l=Kt.test(e),u=t.style;if(l||(e=Yt(a)),s=C.cssHooks[e]||C.cssHooks[a],void 0===n)return s&&"get"in s&&void 0!==(o=s.get(t,!1,i))?o:u[e];"string"===(r=typeof n)&&(o=it.exec(n))&&o[1]&&(n=ut(t,e,o),r="number"),null!=n&&n==n&&("number"!==r||l||(n+=o&&o[3]||(C.cssNumber[a]?"":"px")),v.clearCloneStyle||""!==n||0!==e.indexOf("background")||(u[e]="inherit"),s&&"set"in s&&void 0===(n=s.set(t,n,i))||(l?u.setProperty(e,n):u[e]=n))}},css:function(t,e,n,i){var o,r,s,a=X(e);return Kt.test(e)||(e=Yt(a)),(s=C.cssHooks[e]||C.cssHooks[a])&&"get"in s&&(o=s.get(t,!0,n)),void 0===o&&(o=zt(t,e,i)),"normal"===o&&e in te&&(o=te[e]),""===n||n?(r=parseFloat(o),!0===n||isFinite(r)?r||0:o):o}}),C.each(["height","width"],(function(t,e){C.cssHooks[e]={get:function(t,n,i){if(n)return!Jt.test(C.css(t,"display"))||t.getClientRects().length&&t.getBoundingClientRect().width?ie(t,e,i):_t(t,Zt,(function(){return ie(t,e,i)}))},set:function(t,n,i){var o,r=Bt(t),s=!v.scrollboxSize()&&"absolute"===r.position,a=(s||i)&&"border-box"===C.css(t,"boxSizing",!1,r),l=i?ne(t,e,i,a,r):0;return a&&s&&(l-=Math.ceil(t["offset"+e[0].toUpperCase()+e.slice(1)]-parseFloat(r[e])-ne(t,e,"border",!1,r)-.5)),l&&(o=it.exec(n))&&"px"!==(o[3]||"px")&&(t.style[e]=n,n=C.css(t,e)),ee(0,n,l)}}})),C.cssHooks.marginLeft=Vt(v.reliableMarginLeft,(function(t,e){if(e)return(parseFloat(zt(t,"marginLeft"))||t.getBoundingClientRect().left-_t(t,{marginLeft:0},(function(){return t.getBoundingClientRect().left})))+"px"})),C.each({margin:"",padding:"",border:"Width"},(function(t,e){C.cssHooks[t+e]={expand:function(n){for(var i=0,o={},r="string"==typeof n?n.split(" "):[n];i<4;i++)o[t+ot[i]+e]=r[i]||r[i-2]||r[0];return o}},"margin"!==t&&(C.cssHooks[t+e].set=ee)})),C.fn.extend({css:function(t,e){return U(this,(function(t,e,n){var i,o,r={},s=0;if(Array.isArray(e)){for(i=Bt(t),o=e.length;s1)}}),C.Tween=oe,oe.prototype={constructor:oe,init:function(t,e,n,i,o,r){this.elem=t,this.prop=n,this.easing=o||C.easing._default,this.options=e,this.start=this.now=this.cur(),this.end=i,this.unit=r||(C.cssNumber[n]?"":"px")},cur:function(){var t=oe.propHooks[this.prop];return t&&t.get?t.get(this):oe.propHooks._default.get(this)},run:function(t){var e,n=oe.propHooks[this.prop];return this.options.duration?this.pos=e=C.easing[this.easing](t,this.options.duration*t,0,1,this.options.duration):this.pos=e=t,this.now=(this.end-this.start)*e+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):oe.propHooks._default.set(this),this}},oe.prototype.init.prototype=oe.prototype,oe.propHooks={_default:{get:function(t){var e;return 1!==t.elem.nodeType||null!=t.elem[t.prop]&&null==t.elem.style[t.prop]?t.elem[t.prop]:(e=C.css(t.elem,t.prop,""))&&"auto"!==e?e:0},set:function(t){C.fx.step[t.prop]?C.fx.step[t.prop](t):1!==t.elem.nodeType||!C.cssHooks[t.prop]&&null==t.elem.style[Yt(t.prop)]?t.elem[t.prop]=t.now:C.style(t.elem,t.prop,t.now+t.unit)}}},oe.propHooks.scrollTop=oe.propHooks.scrollLeft={set:function(t){t.elem.nodeType&&t.elem.parentNode&&(t.elem[t.prop]=t.now)}},C.easing={linear:function(t){return t},swing:function(t){return.5-Math.cos(t*Math.PI)/2},_default:"swing"},C.fx=oe.prototype.init,C.fx.step={};var re,se,ae=/^(?:toggle|show|hide)$/,le=/queueHooks$/;function ue(){se&&(!1===b.hidden&&n.requestAnimationFrame?n.requestAnimationFrame(ue):n.setTimeout(ue,C.fx.interval),C.fx.tick())}function ce(){return n.setTimeout((function(){re=void 0})),re=Date.now()}function fe(t,e){var n,i=0,o={height:t};for(e=e?1:0;i<4;i+=2-e)o["margin"+(n=ot[i])]=o["padding"+n]=t;return e&&(o.opacity=o.width=t),o}function pe(t,e,n){for(var i,o=(de.tweeners[e]||[]).concat(de.tweeners["*"]),r=0,s=o.length;r1)},removeAttr:function(t){return this.each((function(){C.removeAttr(this,t)}))}}),C.extend({attr:function(t,e,n){var i,o,r=t.nodeType;if(3!==r&&8!==r&&2!==r)return void 0===t.getAttribute?C.prop(t,e,n):(1===r&&C.isXMLDoc(t)||(o=C.attrHooks[e.toLowerCase()]||(C.expr.match.bool.test(e)?he:void 0)),void 0!==n?null===n?void C.removeAttr(t,e):o&&"set"in o&&void 0!==(i=o.set(t,n,e))?i:(t.setAttribute(e,n+""),n):o&&"get"in o&&null!==(i=o.get(t,e))?i:null==(i=C.find.attr(t,e))?void 0:i)},attrHooks:{type:{set:function(t,e){if(!v.radioValue&&"radio"===e&&D(t,"input")){var n=t.value;return t.setAttribute("type",e),n&&(t.value=n),e}}}},removeAttr:function(t,e){var n,i=0,o=e&&e.match(P);if(o&&1===t.nodeType)for(;n=o[i++];)t.removeAttribute(n)}}),he={set:function(t,e,n){return!1===e?C.removeAttr(t,n):t.setAttribute(n,n),n}},C.each(C.expr.match.bool.source.match(/\w+/g),(function(t,e){var n=ge[e]||C.find.attr;ge[e]=function(t,e,i){var o,r,s=e.toLowerCase();return i||(r=ge[s],ge[s]=o,o=null!=n(t,e,i)?s:null,ge[s]=r),o}}));var ve=/^(?:input|select|textarea|button)$/i,me=/^(?:a|area)$/i;function ye(t){return(t.match(P)||[]).join(" ")}function be(t){return t.getAttribute&&t.getAttribute("class")||""}function xe(t){return Array.isArray(t)?t:"string"==typeof t&&t.match(P)||[]}C.fn.extend({prop:function(t,e){return U(this,C.prop,t,e,arguments.length>1)},removeProp:function(t){return this.each((function(){delete this[C.propFix[t]||t]}))}}),C.extend({prop:function(t,e,n){var i,o,r=t.nodeType;if(3!==r&&8!==r&&2!==r)return 1===r&&C.isXMLDoc(t)||(e=C.propFix[e]||e,o=C.propHooks[e]),void 0!==n?o&&"set"in o&&void 0!==(i=o.set(t,n,e))?i:t[e]=n:o&&"get"in o&&null!==(i=o.get(t,e))?i:t[e]},propHooks:{tabIndex:{get:function(t){var e=C.find.attr(t,"tabindex");return e?parseInt(e,10):ve.test(t.nodeName)||me.test(t.nodeName)&&t.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),v.optSelected||(C.propHooks.selected={get:function(t){var e=t.parentNode;return e&&e.parentNode&&e.parentNode.selectedIndex,null},set:function(t){var e=t.parentNode;e&&(e.selectedIndex,e.parentNode&&e.parentNode.selectedIndex)}}),C.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],(function(){C.propFix[this.toLowerCase()]=this})),C.fn.extend({addClass:function(t){var e,n,i,o,r,s,a,l=0;if(m(t))return this.each((function(e){C(this).addClass(t.call(this,e,be(this)))}));if((e=xe(t)).length)for(;n=this[l++];)if(o=be(n),i=1===n.nodeType&&" "+ye(o)+" "){for(s=0;r=e[s++];)i.indexOf(" "+r+" ")<0&&(i+=r+" ");o!==(a=ye(i))&&n.setAttribute("class",a)}return this},removeClass:function(t){var e,n,i,o,r,s,a,l=0;if(m(t))return this.each((function(e){C(this).removeClass(t.call(this,e,be(this)))}));if(!arguments.length)return this.attr("class","");if((e=xe(t)).length)for(;n=this[l++];)if(o=be(n),i=1===n.nodeType&&" "+ye(o)+" "){for(s=0;r=e[s++];)for(;i.indexOf(" "+r+" ")>-1;)i=i.replace(" "+r+" "," ");o!==(a=ye(i))&&n.setAttribute("class",a)}return this},toggleClass:function(t,e){var n=typeof t,i="string"===n||Array.isArray(t);return"boolean"==typeof e&&i?e?this.addClass(t):this.removeClass(t):m(t)?this.each((function(n){C(this).toggleClass(t.call(this,n,be(this),e),e)})):this.each((function(){var e,o,r,s;if(i)for(o=0,r=C(this),s=xe(t);e=s[o++];)r.hasClass(e)?r.removeClass(e):r.addClass(e);else void 0!==t&&"boolean"!==n||((e=be(this))&&J.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===t?"":J.get(this,"__className__")||""))}))},hasClass:function(t){var e,n,i=0;for(e=" "+t+" ";n=this[i++];)if(1===n.nodeType&&(" "+ye(be(n))+" ").indexOf(e)>-1)return!0;return!1}});var we=/\r/g;C.fn.extend({val:function(t){var e,n,i,o=this[0];return arguments.length?(i=m(t),this.each((function(n){var o;1===this.nodeType&&(null==(o=i?t.call(this,n,C(this).val()):t)?o="":"number"==typeof o?o+="":Array.isArray(o)&&(o=C.map(o,(function(t){return null==t?"":t+""}))),(e=C.valHooks[this.type]||C.valHooks[this.nodeName.toLowerCase()])&&"set"in e&&void 0!==e.set(this,o,"value")||(this.value=o))}))):o?(e=C.valHooks[o.type]||C.valHooks[o.nodeName.toLowerCase()])&&"get"in e&&void 0!==(n=e.get(o,"value"))?n:"string"==typeof(n=o.value)?n.replace(we,""):null==n?"":n:void 0}}),C.extend({valHooks:{option:{get:function(t){var e=C.find.attr(t,"value");return null!=e?e:ye(C.text(t))}},select:{get:function(t){var e,n,i,o=t.options,r=t.selectedIndex,s="select-one"===t.type,a=s?null:[],l=s?r+1:o.length;for(i=r<0?l:s?r:0;i-1)&&(n=!0);return n||(t.selectedIndex=-1),r}}}}),C.each(["radio","checkbox"],(function(){C.valHooks[this]={set:function(t,e){if(Array.isArray(e))return t.checked=C.inArray(C(t).val(),e)>-1}},v.checkOn||(C.valHooks[this].get=function(t){return null===t.getAttribute("value")?"on":t.value})})),v.focusin="onfocusin"in n;var Te=/^(?:focusinfocus|focusoutblur)$/,Ce=function(t){t.stopPropagation()};C.extend(C.event,{trigger:function(t,e,i,o){var r,s,a,l,u,c,f,p,h=[i||b],g=d.call(t,"type")?t.type:t,v=d.call(t,"namespace")?t.namespace.split("."):[];if(s=p=a=i=i||b,3!==i.nodeType&&8!==i.nodeType&&!Te.test(g+C.event.triggered)&&(g.indexOf(".")>-1&&(v=g.split("."),g=v.shift(),v.sort()),u=g.indexOf(":")<0&&"on"+g,(t=t[C.expando]?t:new C.Event(g,"object"==typeof t&&t)).isTrigger=o?2:3,t.namespace=v.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+v.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),e=null==e?[t]:C.makeArray(e,[t]),f=C.event.special[g]||{},o||!f.trigger||!1!==f.trigger.apply(i,e))){if(!o&&!f.noBubble&&!y(i)){for(l=f.delegateType||g,Te.test(l+g)||(s=s.parentNode);s;s=s.parentNode)h.push(s),a=s;a===(i.ownerDocument||b)&&h.push(a.defaultView||a.parentWindow||n)}for(r=0;(s=h[r++])&&!t.isPropagationStopped();)p=s,t.type=r>1?l:f.bindType||g,(c=(J.get(s,"events")||Object.create(null))[t.type]&&J.get(s,"handle"))&&c.apply(s,e),(c=u&&s[u])&&c.apply&&G(s)&&(t.result=c.apply(s,e),!1===t.result&&t.preventDefault());return t.type=g,o||t.isDefaultPrevented()||f._default&&!1!==f._default.apply(h.pop(),e)||!G(i)||u&&m(i[g])&&!y(i)&&((a=i[u])&&(i[u]=null),C.event.triggered=g,t.isPropagationStopped()&&p.addEventListener(g,Ce),i[g](),t.isPropagationStopped()&&p.removeEventListener(g,Ce),C.event.triggered=void 0,a&&(i[u]=a)),t.result}},simulate:function(t,e,n){var i=C.extend(new C.Event,n,{type:t,isSimulated:!0});C.event.trigger(i,null,e)}}),C.fn.extend({trigger:function(t,e){return this.each((function(){C.event.trigger(t,e,this)}))},triggerHandler:function(t,e){var n=this[0];if(n)return C.event.trigger(t,e,n,!0)}}),v.focusin||C.each({focus:"focusin",blur:"focusout"},(function(t,e){var n=function(t){C.event.simulate(e,t.target,C.event.fix(t))};C.event.special[e]={setup:function(){var i=this.ownerDocument||this.document||this,o=J.access(i,e);o||i.addEventListener(t,n,!0),J.access(i,e,(o||0)+1)},teardown:function(){var i=this.ownerDocument||this.document||this,o=J.access(i,e)-1;o?J.access(i,e,o):(i.removeEventListener(t,n,!0),J.remove(i,e))}}}));var Ee=n.location,Se={guid:Date.now()},ke=/\?/;C.parseXML=function(t){var e;if(!t||"string"!=typeof t)return null;try{e=(new n.DOMParser).parseFromString(t,"text/xml")}catch(t){e=void 0}return e&&!e.getElementsByTagName("parsererror").length||C.error("Invalid XML: "+t),e};var $e=/\[\]$/,Ae=/\r?\n/g,De=/^(?:submit|button|image|reset|file)$/i,Ne=/^(?:input|select|textarea|keygen)/i;function je(t,e,n,i){var o;if(Array.isArray(e))C.each(e,(function(e,o){n||$e.test(t)?i(t,o):je(t+"["+("object"==typeof o&&null!=o?e:"")+"]",o,n,i)}));else if(n||"object"!==T(e))i(t,e);else for(o in e)je(t+"["+o+"]",e[o],n,i)}C.param=function(t,e){var n,i=[],o=function(t,e){var n=m(e)?e():e;i[i.length]=encodeURIComponent(t)+"="+encodeURIComponent(null==n?"":n)};if(null==t)return"";if(Array.isArray(t)||t.jquery&&!C.isPlainObject(t))C.each(t,(function(){o(this.name,this.value)}));else for(n in t)je(n,t[n],e,o);return i.join("&")},C.fn.extend({serialize:function(){return C.param(this.serializeArray())},serializeArray:function(){return this.map((function(){var t=C.prop(this,"elements");return t?C.makeArray(t):this})).filter((function(){var t=this.type;return this.name&&!C(this).is(":disabled")&&Ne.test(this.nodeName)&&!De.test(t)&&(this.checked||!gt.test(t))})).map((function(t,e){var n=C(this).val();return null==n?null:Array.isArray(n)?C.map(n,(function(t){return{name:e.name,value:t.replace(Ae,"\r\n")}})):{name:e.name,value:n.replace(Ae,"\r\n")}})).get()}});var Oe=/%20/g,Ie=/#.*$/,Le=/([?&])_=[^&]*/,Re=/^(.*?):[ \t]*([^\r\n]*)$/gm,qe=/^(?:GET|HEAD)$/,Pe=/^\/\//,He={},Me={},Fe="*/".concat("*"),We=b.createElement("a");function Be(t){return function(e,n){"string"!=typeof e&&(n=e,e="*");var i,o=0,r=e.toLowerCase().match(P)||[];if(m(n))for(;i=r[o++];)"+"===i[0]?(i=i.slice(1)||"*",(t[i]=t[i]||[]).unshift(n)):(t[i]=t[i]||[]).push(n)}}function _e(t,e,n,i){var o={},r=t===Me;function s(a){var l;return o[a]=!0,C.each(t[a]||[],(function(t,a){var u=a(e,n,i);return"string"!=typeof u||r||o[u]?r?!(l=u):void 0:(e.dataTypes.unshift(u),s(u),!1)})),l}return s(e.dataTypes[0])||!o["*"]&&s("*")}function Ue(t,e){var n,i,o=C.ajaxSettings.flatOptions||{};for(n in e)void 0!==e[n]&&((o[n]?t:i||(i={}))[n]=e[n]);return i&&C.extend(!0,t,i),t}We.href=Ee.href,C.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ee.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Ee.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Fe,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":C.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(t,e){return e?Ue(Ue(t,C.ajaxSettings),e):Ue(C.ajaxSettings,t)},ajaxPrefilter:Be(He),ajaxTransport:Be(Me),ajax:function(t,e){"object"==typeof t&&(e=t,t=void 0),e=e||{};var i,o,r,s,a,l,u,c,f,p,d=C.ajaxSetup({},e),h=d.context||d,g=d.context&&(h.nodeType||h.jquery)?C(h):C.event,v=C.Deferred(),m=C.Callbacks("once memory"),y=d.statusCode||{},x={},w={},T="canceled",E={readyState:0,getResponseHeader:function(t){var e;if(u){if(!s)for(s={};e=Re.exec(r);)s[e[1].toLowerCase()+" "]=(s[e[1].toLowerCase()+" "]||[]).concat(e[2]);e=s[t.toLowerCase()+" "]}return null==e?null:e.join(", ")},getAllResponseHeaders:function(){return u?r:null},setRequestHeader:function(t,e){return null==u&&(t=w[t.toLowerCase()]=w[t.toLowerCase()]||t,x[t]=e),this},overrideMimeType:function(t){return null==u&&(d.mimeType=t),this},statusCode:function(t){var e;if(t)if(u)E.always(t[E.status]);else for(e in t)y[e]=[y[e],t[e]];return this},abort:function(t){var e=t||T;return i&&i.abort(e),S(0,e),this}};if(v.promise(E),d.url=((t||d.url||Ee.href)+"").replace(Pe,Ee.protocol+"//"),d.type=e.method||e.type||d.method||d.type,d.dataTypes=(d.dataType||"*").toLowerCase().match(P)||[""],null==d.crossDomain){l=b.createElement("a");try{l.href=d.url,l.href=l.href,d.crossDomain=We.protocol+"//"+We.host!=l.protocol+"//"+l.host}catch(t){d.crossDomain=!0}}if(d.data&&d.processData&&"string"!=typeof d.data&&(d.data=C.param(d.data,d.traditional)),_e(He,d,e,E),u)return E;for(f in(c=C.event&&d.global)&&0==C.active++&&C.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!qe.test(d.type),o=d.url.replace(Ie,""),d.hasContent?d.data&&d.processData&&0===(d.contentType||"").indexOf("application/x-www-form-urlencoded")&&(d.data=d.data.replace(Oe,"+")):(p=d.url.slice(o.length),d.data&&(d.processData||"string"==typeof d.data)&&(o+=(ke.test(o)?"&":"?")+d.data,delete d.data),!1===d.cache&&(o=o.replace(Le,"$1"),p=(ke.test(o)?"&":"?")+"_="+Se.guid+++p),d.url=o+p),d.ifModified&&(C.lastModified[o]&&E.setRequestHeader("If-Modified-Since",C.lastModified[o]),C.etag[o]&&E.setRequestHeader("If-None-Match",C.etag[o])),(d.data&&d.hasContent&&!1!==d.contentType||e.contentType)&&E.setRequestHeader("Content-Type",d.contentType),E.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+Fe+"; q=0.01":""):d.accepts["*"]),d.headers)E.setRequestHeader(f,d.headers[f]);if(d.beforeSend&&(!1===d.beforeSend.call(h,E,d)||u))return E.abort();if(T="abort",m.add(d.complete),E.done(d.success),E.fail(d.error),i=_e(Me,d,e,E)){if(E.readyState=1,c&&g.trigger("ajaxSend",[E,d]),u)return E;d.async&&d.timeout>0&&(a=n.setTimeout((function(){E.abort("timeout")}),d.timeout));try{u=!1,i.send(x,S)}catch(t){if(u)throw t;S(-1,t)}}else S(-1,"No Transport");function S(t,e,s,l){var f,p,b,x,w,T=e;u||(u=!0,a&&n.clearTimeout(a),i=void 0,r=l||"",E.readyState=t>0?4:0,f=t>=200&&t<300||304===t,s&&(x=function(t,e,n){for(var i,o,r,s,a=t.contents,l=t.dataTypes;"*"===l[0];)l.shift(),void 0===i&&(i=t.mimeType||e.getResponseHeader("Content-Type"));if(i)for(o in a)if(a[o]&&a[o].test(i)){l.unshift(o);break}if(l[0]in n)r=l[0];else{for(o in n){if(!l[0]||t.converters[o+" "+l[0]]){r=o;break}s||(s=o)}r=r||s}if(r)return r!==l[0]&&l.unshift(r),n[r]}(d,E,s)),!f&&C.inArray("script",d.dataTypes)>-1&&(d.converters["text script"]=function(){}),x=function(t,e,n,i){var o,r,s,a,l,u={},c=t.dataTypes.slice();if(c[1])for(s in t.converters)u[s.toLowerCase()]=t.converters[s];for(r=c.shift();r;)if(t.responseFields[r]&&(n[t.responseFields[r]]=e),!l&&i&&t.dataFilter&&(e=t.dataFilter(e,t.dataType)),l=r,r=c.shift())if("*"===r)r=l;else if("*"!==l&&l!==r){if(!(s=u[l+" "+r]||u["* "+r]))for(o in u)if((a=o.split(" "))[1]===r&&(s=u[l+" "+a[0]]||u["* "+a[0]])){!0===s?s=u[o]:!0!==u[o]&&(r=a[0],c.unshift(a[1]));break}if(!0!==s)if(s&&t.throws)e=s(e);else try{e=s(e)}catch(t){return{state:"parsererror",error:s?t:"No conversion from "+l+" to "+r}}}return{state:"success",data:e}}(d,x,E,f),f?(d.ifModified&&((w=E.getResponseHeader("Last-Modified"))&&(C.lastModified[o]=w),(w=E.getResponseHeader("etag"))&&(C.etag[o]=w)),204===t||"HEAD"===d.type?T="nocontent":304===t?T="notmodified":(T=x.state,p=x.data,f=!(b=x.error))):(b=T,!t&&T||(T="error",t<0&&(t=0))),E.status=t,E.statusText=(e||T)+"",f?v.resolveWith(h,[p,T,E]):v.rejectWith(h,[E,T,b]),E.statusCode(y),y=void 0,c&&g.trigger(f?"ajaxSuccess":"ajaxError",[E,d,f?p:b]),m.fireWith(h,[E,T]),c&&(g.trigger("ajaxComplete",[E,d]),--C.active||C.event.trigger("ajaxStop")))}return E},getJSON:function(t,e,n){return C.get(t,e,n,"json")},getScript:function(t,e){return C.get(t,void 0,e,"script")}}),C.each(["get","post"],(function(t,e){C[e]=function(t,n,i,o){return m(n)&&(o=o||i,i=n,n=void 0),C.ajax(C.extend({url:t,type:e,dataType:o,data:n,success:i},C.isPlainObject(t)&&t))}})),C.ajaxPrefilter((function(t){var e;for(e in t.headers)"content-type"===e.toLowerCase()&&(t.contentType=t.headers[e]||"")})),C._evalUrl=function(t,e,n){return C.ajax({url:t,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(t){C.globalEval(t,e,n)}})},C.fn.extend({wrapAll:function(t){var e;return this[0]&&(m(t)&&(t=t.call(this[0])),e=C(t,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&e.insertBefore(this[0]),e.map((function(){for(var t=this;t.firstElementChild;)t=t.firstElementChild;return t})).append(this)),this},wrapInner:function(t){return m(t)?this.each((function(e){C(this).wrapInner(t.call(this,e))})):this.each((function(){var e=C(this),n=e.contents();n.length?n.wrapAll(t):e.append(t)}))},wrap:function(t){var e=m(t);return this.each((function(n){C(this).wrapAll(e?t.call(this,n):t)}))},unwrap:function(t){return this.parent(t).not("body").each((function(){C(this).replaceWith(this.childNodes)})),this}}),C.expr.pseudos.hidden=function(t){return!C.expr.pseudos.visible(t)},C.expr.pseudos.visible=function(t){return!!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)},C.ajaxSettings.xhr=function(){try{return new n.XMLHttpRequest}catch(t){}};var ze={0:200,1223:204},Ve=C.ajaxSettings.xhr();v.cors=!!Ve&&"withCredentials"in Ve,v.ajax=Ve=!!Ve,C.ajaxTransport((function(t){var e,i;if(v.cors||Ve&&!t.crossDomain)return{send:function(o,r){var s,a=t.xhr();if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(s in t.xhrFields)a[s]=t.xhrFields[s];for(s in t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||o["X-Requested-With"]||(o["X-Requested-With"]="XMLHttpRequest"),o)a.setRequestHeader(s,o[s]);e=function(t){return function(){e&&(e=i=a.onload=a.onerror=a.onabort=a.ontimeout=a.onreadystatechange=null,"abort"===t?a.abort():"error"===t?"number"!=typeof a.status?r(0,"error"):r(a.status,a.statusText):r(ze[a.status]||a.status,a.statusText,"text"!==(a.responseType||"text")||"string"!=typeof a.responseText?{binary:a.response}:{text:a.responseText},a.getAllResponseHeaders()))}},a.onload=e(),i=a.onerror=a.ontimeout=e("error"),void 0!==a.onabort?a.onabort=i:a.onreadystatechange=function(){4===a.readyState&&n.setTimeout((function(){e&&i()}))},e=e("abort");try{a.send(t.hasContent&&t.data||null)}catch(t){if(e)throw t}},abort:function(){e&&e()}}})),C.ajaxPrefilter((function(t){t.crossDomain&&(t.contents.script=!1)})),C.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(t){return C.globalEval(t),t}}}),C.ajaxPrefilter("script",(function(t){void 0===t.cache&&(t.cache=!1),t.crossDomain&&(t.type="GET")})),C.ajaxTransport("script",(function(t){var e,n;if(t.crossDomain||t.scriptAttrs)return{send:function(i,o){e=C(" diff --git a/resources/assets/js/components/passport/AuthorizedClients.vue b/resources/assets/js/components/passport/AuthorizedClients.vue index 272b27fec0..6a8bf3e918 100644 --- a/resources/assets/js/components/passport/AuthorizedClients.vue +++ b/resources/assets/js/components/passport/AuthorizedClients.vue @@ -35,17 +35,17 @@

- Authorized Applications + {{ $t('firefly.profile_authorized_apps') }}

- + - - + + @@ -67,7 +67,7 @@ diff --git a/resources/assets/js/components/passport/Clients.vue b/resources/assets/js/components/passport/Clients.vue index 43824810f0..92ad305320 100644 --- a/resources/assets/js/components/passport/Clients.vue +++ b/resources/assets/js/components/passport/Clients.vue @@ -34,23 +34,23 @@

- OAuth Clients + {{ $t('firefly.profile_oauth_clients') }}

- You have not created any OAuth clients. + {{ $t('firefly.profile_oauth_no_clients') }}

Authorized clients{{ $t('firefly.profile_authorized_clients') }}
NameScopes{{ $t('firefly.name') }}{{ $t('firefly.profile_scopes') }}
- Revoke + {{ $t('firefly.profile_revoke') }}
- + - - - + + + @@ -76,14 +76,14 @@ @@ -92,7 +92,7 @@ @@ -105,14 +105,14 @@
Clients{{ $t('firefly.profile_oauth_clients_header') }}
Client IDNameSecret{{ $t('firefly.profile_oauth_client_id') }}{{ $t('firefly.name') }}{{ $t('firefly.profile_oauth_client_secret') }}
- Edit + {{ $t('firefly.edit') }} - Delete + {{ $t('firefly.delete') }}
- + - + @@ -63,7 +63,7 @@ @@ -72,7 +72,7 @@ @@ -86,14 +86,14 @@ - + @@ -114,7 +114,7 @@ - +
Personal Access Tokens{{ $t('firefly.profile_personal_access_tokens') }}
Name{{ $t('firefly.name') }}
- Delete + {{ $t('firefly.delete') }}
{{ trans('list.budget_count') }}{{ information.budgets }} {{ trans('firefly.budget_or_budgets') }}, - {{ information.budgets_with_limits }} {{ trans('firefly.budgets_with_limits') }}{{ trans_choice('firefly.budget_or_budgets', information.budgets ) }}, + {{ trans_choice('firefly.budgets_with_limits', information.budgets_with_limits ) }}
{{ trans('list.rule_and_groups_count') }}
{{ trans('list.tags_count') }}{{ information.tags }} {{ 'tag_or_tags'|_ }}{{ trans_choice('firefly.tag_or_tags', information.tags ) }}
diff --git a/resources/views/v1/auth/lost-two-factor.twig b/resources/views/v1/auth/lost-two-factor.twig index a5a8391f2c..4a9e293390 100644 --- a/resources/views/v1/auth/lost-two-factor.twig +++ b/resources/views/v1/auth/lost-two-factor.twig @@ -10,38 +10,37 @@ - {# favicons #} {% include('partials.favicons') %} - -
-