diff --git a/.travis.yml b/.travis.yml index 0771080d51..1dba72615d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php php: - - 7.1.18 + - 7.2 cache: directories: diff --git a/app/Console/Commands/UpgradeDatabase.php b/app/Console/Commands/UpgradeDatabase.php index 246222edfa..a5de3d1e7b 100644 --- a/app/Console/Commands/UpgradeDatabase.php +++ b/app/Console/Commands/UpgradeDatabase.php @@ -98,6 +98,7 @@ class UpgradeDatabase extends Command $this->migrateAttachmentData(); $this->migrateBillsToRules(); $this->budgetLimitCurrency(); + $this->removeCCLiabilities(); $this->info('Firefly III database is up to date.'); @@ -535,6 +536,28 @@ class UpgradeDatabase extends Command } } + /** + * + */ + private function removeCCLiabilities(): void + { + $ccType = AccountType::where('type', AccountType::CREDITCARD)->first(); + $debtType =AccountType::where('type', AccountType::DEBT)->first(); + if(null === $ccType || null === $debtType) { + return; + } + /** @var Collection $accounts */ + $accounts = Account::where('account_type_id', $ccType->id)->get(); + foreach($accounts as $account) { + $account->account_type_id = $debtType->id; + $account->save(); + $this->line(sprintf('Converted credit card liability account "%s" (#%d) to generic debt liability.', $account->name, $account->id)); + } + if($accounts->count() > 0) { + $this->info('Credit card liability types are no longer supported and have been converted to generic debts. See: http://bit.ly/FF3-credit-cards'); + } + } + /** * This method makes sure that the transaction journal uses the currency given in the transaction. * diff --git a/app/Factory/TransactionFactory.php b/app/Factory/TransactionFactory.php index a53e314045..ab66656da7 100644 --- a/app/Factory/TransactionFactory.php +++ b/app/Factory/TransactionFactory.php @@ -108,6 +108,7 @@ class TransactionFactory { Log::debug('Start of TransactionFactory::createPair()', $data); // all this data is the same for both transactions: + Log::debug('Searching for currency info.'); $currency = $this->findCurrency($data['currency_id'], $data['currency_code']); $description = $journal->description === $data['description'] ? null : $data['description']; @@ -164,6 +165,7 @@ class TransactionFactory } // set foreign currency + Log::debug('Trying to find foreign currency information.'); $foreign = $this->findCurrency($data['foreign_currency_id'], $data['foreign_currency_code']); $this->setForeignCurrency($source, $foreign); $this->setForeignCurrency($dest, $foreign); diff --git a/app/Factory/TransactionJournalFactory.php b/app/Factory/TransactionJournalFactory.php index f57af20e70..da8a3ffbc1 100644 --- a/app/Factory/TransactionJournalFactory.php +++ b/app/Factory/TransactionJournalFactory.php @@ -36,6 +36,11 @@ use Log; */ class TransactionJournalFactory { + /** @var User The user */ + private $user; + + use JournalServiceTrait, TransactionTypeTrait; + /** * Constructor. */ @@ -46,10 +51,6 @@ class TransactionJournalFactory } } - use JournalServiceTrait, TransactionTypeTrait; - /** @var User The user */ - private $user; - /** * Store a new transaction journal. * @@ -67,13 +68,15 @@ class TransactionJournalFactory $type = $this->findTransactionType($data['type']); $defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user); Log::debug(sprintf('Going to store a %s', $type->type)); - $journal = TransactionJournal::create( + $description = app('steam')->cleanString($data['description']); + $description = str_replace(["\n", "\t", "\r"], "\x20", $description); + $journal = TransactionJournal::create( [ 'user_id' => $data['user'], 'transaction_type_id' => $type->id, 'bill_id' => null, 'transaction_currency_id' => $defaultCurrency->id, - 'description' => $data['description'], + 'description' => $description, 'date' => $data['date']->format('Y-m-d'), 'order' => 0, 'tag_count' => 0, @@ -114,7 +117,7 @@ class TransactionJournalFactory // store date meta fields (if present): $fields = ['sepa-cc', 'sepa-ct-op', 'sepa-ct-id', 'sepa-db', 'sepa-country', 'sepa-ep', 'sepa-ci', 'interest_date', 'book_date', 'process_date', 'due_date', 'recurrence_id', 'payment_date', 'invoice_date', 'internal_reference', 'bunq_payment_id', 'importHash', 'importHashV2', - 'external_id', 'sepa-batch-id','original-source']; + 'external_id', 'sepa-batch-id', 'original-source']; foreach ($fields as $field) { $this->storeMeta($journal, $data, $field); diff --git a/app/Helpers/Attachments/AttachmentHelper.php b/app/Helpers/Attachments/AttachmentHelper.php index 39bb6eb94e..dab8e627ac 100644 --- a/app/Helpers/Attachments/AttachmentHelper.php +++ b/app/Helpers/Attachments/AttachmentHelper.php @@ -182,13 +182,17 @@ class AttachmentHelper implements AttachmentHelperInterface /** * Save attachments that get uploaded with models, through the app. * - * @param Model $model + * @param object $model * @param array|null $files * * @return bool + * @throws \Illuminate\Contracts\Encryption\EncryptException */ - public function saveAttachmentsForModel(Model $model, ?array $files): bool + public function saveAttachmentsForModel(object $model, ?array $files): bool { + if(!($model instanceof Model)) { + return false; + } Log::debug(sprintf('Now in saveAttachmentsForModel for model %s', \get_class($model))); if (\is_array($files)) { Log::debug('$files is an array.'); diff --git a/app/Helpers/Attachments/AttachmentHelperInterface.php b/app/Helpers/Attachments/AttachmentHelperInterface.php index 7305202738..8671e4f677 100644 --- a/app/Helpers/Attachments/AttachmentHelperInterface.php +++ b/app/Helpers/Attachments/AttachmentHelperInterface.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace FireflyIII\Helpers\Attachments; use FireflyIII\Models\Attachment; -use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Collection; use Illuminate\Support\MessageBag; @@ -84,10 +83,10 @@ interface AttachmentHelperInterface /** * Save attachments that got uploaded. * - * @param Model $model + * @param object $model * @param null|array $files * * @return bool */ - public function saveAttachmentsForModel(Model $model, ?array $files): bool; + public function saveAttachmentsForModel(object $model, ?array $files): bool; } diff --git a/app/Http/Controllers/Account/CreateController.php b/app/Http/Controllers/Account/CreateController.php index 6440aae26b..02c32fb94b 100644 --- a/app/Http/Controllers/Account/CreateController.php +++ b/app/Http/Controllers/Account/CreateController.php @@ -83,12 +83,10 @@ class CreateController extends Controller $debt = $this->repository->getAccountTypeByType(AccountType::DEBT); $loan = $this->repository->getAccountTypeByType(AccountType::LOAN); $mortgage = $this->repository->getAccountTypeByType(AccountType::MORTGAGE); - $creditCard = $this->repository->getAccountTypeByType(AccountType::CREDITCARD); $liabilityTypes = [ $debt->id => (string)trans('firefly.account_type_' . AccountType::DEBT), $loan->id => (string)trans('firefly.account_type_' . AccountType::LOAN), $mortgage->id => (string)trans('firefly.account_type_' . AccountType::MORTGAGE), - $creditCard->id => (string)trans('firefly.account_type_' . AccountType::CREDITCARD), ]; asort($liabilityTypes); diff --git a/app/Http/Controllers/Account/EditController.php b/app/Http/Controllers/Account/EditController.php index 2ce4d98aa7..b984efb5cb 100644 --- a/app/Http/Controllers/Account/EditController.php +++ b/app/Http/Controllers/Account/EditController.php @@ -90,12 +90,10 @@ class EditController extends Controller $debt = $this->repository->getAccountTypeByType(AccountType::DEBT); $loan = $this->repository->getAccountTypeByType(AccountType::LOAN); $mortgage = $this->repository->getAccountTypeByType(AccountType::MORTGAGE); - $creditCard = $this->repository->getAccountTypeByType(AccountType::CREDITCARD); $liabilityTypes = [ $debt->id => (string)trans('firefly.account_type_' . AccountType::DEBT), $loan->id => (string)trans('firefly.account_type_' . AccountType::LOAN), $mortgage->id => (string)trans('firefly.account_type_' . AccountType::MORTGAGE), - $creditCard->id => (string)trans('firefly.account_type_' . AccountType::CREDITCARD), ]; asort($liabilityTypes); diff --git a/app/Http/Controllers/Import/JobStatusController.php b/app/Http/Controllers/Import/JobStatusController.php index 949f15d156..d211001939 100644 --- a/app/Http/Controllers/Import/JobStatusController.php +++ b/app/Http/Controllers/Import/JobStatusController.php @@ -47,6 +47,8 @@ class JobStatusController extends Controller public function __construct() { parent::__construct(); + // set time limit to zero to prevent timeouts. + set_time_limit(0); $this->middleware( function ($request, $next) { diff --git a/app/Http/Controllers/Json/AutoCompleteController.php b/app/Http/Controllers/Json/AutoCompleteController.php index 66f1ddb14e..1b43a2f879 100644 --- a/app/Http/Controllers/Json/AutoCompleteController.php +++ b/app/Http/Controllers/Json/AutoCompleteController.php @@ -36,8 +36,10 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Support\CacheProperties; use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; /** + * TODO refactor so each auto-complete thing is a function call because lots of code duplication. * Class AutoCompleteController. * * @SuppressWarnings(PHPMD.TooManyPublicMethods) @@ -49,18 +51,40 @@ class AutoCompleteController extends Controller /** * Returns a JSON list of all accounts. * + * @param Request $request * @param AccountRepositoryInterface $repository * * @return JsonResponse */ - public function allAccounts(AccountRepositoryInterface $repository): JsonResponse + public function allAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse { - $return = array_unique( - $repository->getAccountsByType( - [AccountType::REVENUE, AccountType::EXPENSE, AccountType::BENEFICIARY, AccountType::DEFAULT, AccountType::ASSET] - )->pluck('name')->toArray() + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-all-accounts'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: + $return = array_values( + array_unique( + $repository->getAccountsByType( + [AccountType::REVENUE, AccountType::EXPENSE, AccountType::BENEFICIARY, AccountType::DEFAULT, AccountType::ASSET] + )->pluck('name')->toArray() + ) ); - sort($return); + if ('' !== $search) { + $return = array_values( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ); + } + $cache->store($return); return response()->json($return); } @@ -68,15 +92,86 @@ class AutoCompleteController extends Controller /** * List of all journals. * + * @param Request $request * @param TransactionCollectorInterface $collector * * @return JsonResponse */ - public function allTransactionJournals(TransactionCollectorInterface $collector): JsonResponse + public function allTransactionJournals(Request $request, TransactionCollectorInterface $collector): JsonResponse { + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-all-journals'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: $collector->setLimit(250)->setPage(1); - $return = array_unique($collector->getTransactions()->pluck('description')->toArray()); - sort($return); + $return = array_values(array_unique($collector->getTransactions()->pluck('description')->toArray())); + + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } + $cache->store($return); + + return response()->json($return); + } + + /** + * List of revenue accounts. + * + * @param Request $request + * @param AccountRepositoryInterface $repository + * + * @return JsonResponse + */ + public function assetAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse + { + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-asset-accounts'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: + $set = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); + $filtered = $set->filter( + function (Account $account) { + if (true === $account->active) { + return $account; + } + + return false; // @codeCoverageIgnore + } + ); + $return = array_values(array_unique($filtered->pluck('name')->toArray())); + + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } + $cache->store($return); return response()->json($return); } @@ -84,16 +179,37 @@ class AutoCompleteController extends Controller /** * Returns a JSON list of all bills. * + * @param Request $request * @param BillRepositoryInterface $repository * * @return JsonResponse */ - public function bills(BillRepositoryInterface $repository): JsonResponse + public function bills(Request $request, BillRepositoryInterface $repository): JsonResponse { - $return = array_unique( - $repository->getActiveBills()->pluck('name')->toArray() - ); - sort($return); + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-bills'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: + $return = array_unique($repository->getActiveBills()->pluck('name')->toArray()); + + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } + $cache->store($return); return response()->json($return); } @@ -101,14 +217,37 @@ class AutoCompleteController extends Controller /** * List of budgets. * + * @param Request $request * @param BudgetRepositoryInterface $repository * * @return JsonResponse */ - public function budgets(BudgetRepositoryInterface $repository): JsonResponse + public function budgets(Request $request, BudgetRepositoryInterface $repository): JsonResponse { + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-budgets'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: $return = array_unique($repository->getBudgets()->pluck('name')->toArray()); - sort($return); + + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } + $cache->store($return); return response()->json($return); } @@ -116,14 +255,34 @@ class AutoCompleteController extends Controller /** * Returns a list of categories. * + * @param Request $request * @param CategoryRepositoryInterface $repository * * @return JsonResponse */ - public function categories(CategoryRepositoryInterface $repository): JsonResponse + public function categories(Request $request, CategoryRepositoryInterface $repository): JsonResponse { + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-categories'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: $return = array_unique($repository->getCategories()->pluck('name')->toArray()); - sort($return); + if ('' !== $search) { + $return = array_values( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ); + } + $cache->store($return); return response()->json($return); } @@ -131,27 +290,62 @@ class AutoCompleteController extends Controller /** * List of currency names. * + * @param Request $request * @param CurrencyRepositoryInterface $repository * * @return JsonResponse */ - public function currencyNames(CurrencyRepositoryInterface $repository): JsonResponse + public function currencyNames(Request $request, CurrencyRepositoryInterface $repository): JsonResponse { + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-currency-names'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: $return = $repository->get()->pluck('name')->toArray(); sort($return); + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } + $cache->store($return); + return response()->json($return); } /** * Returns a JSON list of all beneficiaries. * + * @param Request $request * @param AccountRepositoryInterface $repository * * @return JsonResponse */ - public function expenseAccounts(AccountRepositoryInterface $repository): JsonResponse + public function expenseAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse { + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-expense-accounts'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: $set = $repository->getAccountsByType([AccountType::EXPENSE, AccountType::BENEFICIARY]); $filtered = $set->filter( function (Account $account) { @@ -166,27 +360,43 @@ class AutoCompleteController extends Controller sort($return); + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } + $cache->store($return); + return response()->json($return); } - /** * List of journals with their ID. * + * @param Request $request * @param TransactionCollectorInterface $collector - * @param TransactionJournal $except + * @param TransactionJournal $except * * @return JsonResponse */ - public function journalsWithId(TransactionCollectorInterface $collector, TransactionJournal $except): JsonResponse + public function journalsWithId(Request $request, TransactionCollectorInterface $collector, TransactionJournal $except): JsonResponse { - $cache = new CacheProperties; - $cache->addProperty('recent-journals-id'); - + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-expense-accounts'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); if ($cache->has()) { - return response()->json($cache->get()); // @codeCoverageIgnore + return response()->json($cache->get()); } - + // find everything: $collector->setLimit(400)->setPage(1); $set = $collector->getTransactions()->pluck('description', 'journal_id')->toArray(); $return = []; @@ -200,6 +410,19 @@ class AutoCompleteController extends Controller } } + sort($return); + + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } $cache->store($return); return response()->json($return); @@ -208,12 +431,23 @@ class AutoCompleteController extends Controller /** * List of revenue accounts. * + * @param Request $request * @param AccountRepositoryInterface $repository * * @return JsonResponse */ - public function revenueAccounts(AccountRepositoryInterface $repository): JsonResponse + public function revenueAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse { + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-revenue-accounts'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: $set = $repository->getAccountsByType([AccountType::REVENUE]); $filtered = $set->filter( function (Account $account) { @@ -227,30 +461,18 @@ class AutoCompleteController extends Controller $return = array_unique($filtered->pluck('name')->toArray()); sort($return); - return response()->json($return); - } - - /** - * List of revenue accounts. - * - * @param AccountRepositoryInterface $repository - * - * @return JsonResponse - */ - public function assetAccounts(AccountRepositoryInterface $repository): JsonResponse - { - $set = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); - $filtered = $set->filter( - function (Account $account) { - if (true === $account->active) { - return $account; - } - - return false; // @codeCoverageIgnore - } - ); - $return = array_unique($filtered->pluck('name')->toArray()); - sort($return); + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } + $cache->store($return); return response()->json($return); } @@ -258,28 +480,63 @@ class AutoCompleteController extends Controller /** * Returns a JSON list of all beneficiaries. * + * @param Request $request * @param TagRepositoryInterface $tagRepository * * @return JsonResponse */ - public function tags(TagRepositoryInterface $tagRepository): JsonResponse + public function tags(Request $request, TagRepositoryInterface $tagRepository): JsonResponse { + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-revenue-accounts'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: $return = array_unique($tagRepository->get()->pluck('tag')->toArray()); sort($return); + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } + $cache->store($return); + return response()->json($return); } /** * List of journals by type. * + * @param Request $request * @param TransactionCollectorInterface $collector - * @param string $what + * @param string $what * * @return JsonResponse */ - public function transactionJournals(TransactionCollectorInterface $collector, string $what): JsonResponse + public function transactionJournals(Request $request, TransactionCollectorInterface $collector, string $what): JsonResponse { + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-revenue-accounts'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: $type = config('firefly.transactionTypesByWhat.' . $what); $types = [$type]; @@ -287,21 +544,60 @@ class AutoCompleteController extends Controller $return = array_unique($collector->getTransactions()->pluck('description')->toArray()); sort($return); + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } + $cache->store($return); + return response()->json($return); } /** * List if transaction types. * + * @param Request $request * @param JournalRepositoryInterface $repository * * @return JsonResponse */ - public function transactionTypes(JournalRepositoryInterface $repository): JsonResponse + public function transactionTypes(Request $request, JournalRepositoryInterface $repository): JsonResponse { + $search = (string)$request->get('search'); + $cache = new CacheProperties; + $cache->addProperty('ac-revenue-accounts'); + // very unlikely a user will actually search for this string. + $key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search; + $cache->addProperty($key); + if ($cache->has()) { + return response()->json($cache->get()); + } + // find everything: $return = array_unique($repository->getTransactionTypes()->pluck('type')->toArray()); sort($return); + if ('' !== $search) { + $return = array_values( + array_unique( + array_filter( + $return, function (string $value) use ($search) { + return !(false === stripos($value, $search)); + }, ARRAY_FILTER_USE_BOTH + ) + ) + ); + } + $cache->store($return); + return response()->json($return); + + } } diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 51e954ebe5..fbedb02879 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -68,7 +68,7 @@ class Authenticate */ public function handle($request, Closure $next, ...$guards) { - $this->authenticate($guards); + $this->authenticate($request, $guards); return $next($request); } @@ -86,7 +86,7 @@ class Authenticate * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - protected function authenticate(array $guards) + protected function authenticate($request, array $guards) { if (empty($guards)) { diff --git a/app/Http/Middleware/SecureHeaders.php b/app/Http/Middleware/SecureHeaders.php index 6e63f00c9e..016e40c0a9 100644 --- a/app/Http/Middleware/SecureHeaders.php +++ b/app/Http/Middleware/SecureHeaders.php @@ -57,7 +57,7 @@ class SecureHeaders "form-action 'self'", "font-src 'self'", "connect-src 'self'", - "img-src 'self' data:", + "img-src 'self' data: https://api.tiles.mapbox.com", ]; $featurePolicies = [ diff --git a/app/Http/Requests/Request.php b/app/Http/Requests/Request.php index 262be2b3e3..8877f184e1 100644 --- a/app/Http/Requests/Request.php +++ b/app/Http/Requests/Request.php @@ -92,58 +92,7 @@ class Request extends FormRequest */ public function string(string $field): string { - $string = $this->get($field) ?? ''; - $search = [ - "\u{0001}", // start of heading - "\u{0002}", // start of text - "\u{0003}", // end of text - "\u{0004}", // end of transmission - "\u{0005}", // enquiry - "\u{0006}", // ACK - "\u{0007}", // BEL - "\u{0008}", // backspace - "\u{000E}", // shift out - "\u{000F}", // shift in - "\u{0010}", // data link escape - "\u{0011}", // DC1 - "\u{0012}", // DC2 - "\u{0013}", // DC3 - "\u{0014}", // DC4 - "\u{0015}", // NAK - "\u{0016}", // SYN - "\u{0017}", // ETB - "\u{0018}", // CAN - "\u{0019}", // EM - "\u{001A}", // SUB - "\u{001B}", // escape - "\u{001C}", // file separator - "\u{001D}", // group separator - "\u{001E}", // record separator - "\u{001F}", // unit separator - "\u{007F}", // DEL - "\u{00A0}", // non-breaking space - "\u{1680}", // ogham space mark - "\u{180E}", // mongolian vowel separator - "\u{2000}", // en quad - "\u{2001}", // em quad - "\u{2002}", // en space - "\u{2003}", // em space - "\u{2004}", // three-per-em space - "\u{2005}", // four-per-em space - "\u{2006}", // six-per-em space - "\u{2007}", // figure space - "\u{2008}", // punctuation space - "\u{2009}", // thin space - "\u{200A}", // hair space - "\u{200B}", // zero width space - "\u{202F}", // narrow no-break space - "\u{3000}", // ideographic space - "\u{FEFF}", // zero width no -break space - ]; - $replace = "\x20"; // plain old normal space - $string = str_replace($search, $replace, $string); - - return trim($string); + return app('steam')->cleanString($this->get($field) ?? ''); } /** diff --git a/app/Support/Import/JobConfiguration/Bunq/ChooseAccountsHandler.php b/app/Support/Import/JobConfiguration/Bunq/ChooseAccountsHandler.php index 4a357846e0..0846e8ae79 100644 --- a/app/Support/Import/JobConfiguration/Bunq/ChooseAccountsHandler.php +++ b/app/Support/Import/JobConfiguration/Bunq/ChooseAccountsHandler.php @@ -79,7 +79,7 @@ class ChooseAccountsHandler implements BunqJobConfigurationInterface $config = $this->repository->getConfiguration($this->importJob); $accounts = $config['accounts'] ?? []; $mapping = $data['account_mapping'] ?? []; - $applyRules = 1 === (int)$data['apply_rules']; + $applyRules = 1 === (int)($data['apply_rules'] ?? 0); $final = []; /* diff --git a/app/Support/Steam.php b/app/Support/Steam.php index 1e1d135a73..beab2ebab1 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -30,7 +30,6 @@ use FireflyIII\Models\Transaction; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Support\Collection; -use Log; use stdClass; /** @@ -38,6 +37,7 @@ use stdClass; */ class Steam { + /** * @param \FireflyIII\Models\Account $account * @param \Carbon\Carbon $date @@ -315,6 +315,68 @@ class Steam return $result; } + /** + * Remove weird chars from strings. + * + * @param string $string + * + * @return string + */ + public function cleanString(string $string): string + { + $search = [ + "\u{0001}", // start of heading + "\u{0002}", // start of text + "\u{0003}", // end of text + "\u{0004}", // end of transmission + "\u{0005}", // enquiry + "\u{0006}", // ACK + "\u{0007}", // BEL + "\u{0008}", // backspace + "\u{000E}", // shift out + "\u{000F}", // shift in + "\u{0010}", // data link escape + "\u{0011}", // DC1 + "\u{0012}", // DC2 + "\u{0013}", // DC3 + "\u{0014}", // DC4 + "\u{0015}", // NAK + "\u{0016}", // SYN + "\u{0017}", // ETB + "\u{0018}", // CAN + "\u{0019}", // EM + "\u{001A}", // SUB + "\u{001B}", // escape + "\u{001C}", // file separator + "\u{001D}", // group separator + "\u{001E}", // record separator + "\u{001F}", // unit separator + "\u{007F}", // DEL + "\u{00A0}", // non-breaking space + "\u{1680}", // ogham space mark + "\u{180E}", // mongolian vowel separator + "\u{2000}", // en quad + "\u{2001}", // em quad + "\u{2002}", // en space + "\u{2003}", // em space + "\u{2004}", // three-per-em space + "\u{2005}", // four-per-em space + "\u{2006}", // six-per-em space + "\u{2007}", // figure space + "\u{2008}", // punctuation space + "\u{2009}", // thin space + "\u{200A}", // hair space + "\u{200B}", // zero width space + "\u{202F}", // narrow no-break space + "\u{3000}", // ideographic space + "\u{FEFF}", // zero width no -break space + ]; + $replace = "\x20"; // plain old normal space + $string = str_replace($search, $replace, $string); + + return trim($string); + } + /** * @param int $isEncrypted * @param $value diff --git a/composer.json b/composer.json index 66b1ca985a..b1fb050916 100644 --- a/composer.json +++ b/composer.json @@ -46,21 +46,21 @@ } ], "require": { - "php": ">=7.1.0", + "php": ">=7.2.0", "ext-bcmath": "*", "ext-curl": "*", "ext-gd": "*", "ext-intl": "*", "ext-xml": "*", "ext-zip": "*", - "bacon/bacon-qr-code": "1.*", + "bacon/bacon-qr-code": "2.*", "bunq/sdk_php": "dev-master#8c1faefc111d9b970168a1837ca165d854954941", "davejamesmiller/laravel-breadcrumbs": "5.*", "doctrine/dbal": "2.*", "fideloper/proxy": "4.*", - "laravel/framework": "5.6.*", - "laravel/passport": "^5.0", - "laravelcollective/html": "5.6.*", + "laravel/framework": "5.7.*", + "laravel/passport": "^7.0", + "laravelcollective/html": "5.7.*", "league/commonmark": "0.*", "league/csv": "9.*", "league/fractal": "^0.17.0", @@ -74,9 +74,9 @@ "filp/whoops": "2.*", "fzaninotto/faker": "1.*", "johnkary/phpunit-speedtrap": "^3.0", - "mockery/mockery": "^1.0", + "mockery/mockery": "1.*", "php-coveralls/php-coveralls": "^2.0", - "phpunit/phpunit": "~7.0", + "phpunit/phpunit": "7.*", "roave/security-advisories": "dev-master" }, "autoload": { @@ -112,13 +112,13 @@ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump" ], "post-update-cmd": [ - "php artisan firefly:upgrade-database", - "php artisan firefly:verify", - "php artisan firefly:instructions update", - "php artisan passport:install" + "@php artisan firefly:upgrade-database", + "@php artisan firefly:verify", + "@php artisan firefly:instructions update", + "@php artisan passport:install" ], "post-install-cmd": [ - "php artisan firefly:instructions install" + "@php artisan firefly:instructions install" ] }, "config": { diff --git a/composer.lock b/composer.lock index d254281729..b9f4762001 100644 --- a/composer.lock +++ b/composer.lock @@ -4,36 +4,39 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dcaf20ad3436c4fc4cbebeee09c9de1f", + "content-hash": "364135d1fab7e47564deae52ea0c12c2", "packages": [ { "name": "bacon/bacon-qr-code", - "version": "1.0.3", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/Bacon/BaconQrCode.git", - "reference": "5a91b62b9d37cee635bbf8d553f4546057250bee" + "reference": "eaac909da3ccc32b748a65b127acd8918f58d9b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/5a91b62b9d37cee635bbf8d553f4546057250bee", - "reference": "5a91b62b9d37cee635bbf8d553f4546057250bee", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/eaac909da3ccc32b748a65b127acd8918f58d9b0", + "reference": "eaac909da3ccc32b748a65b127acd8918f58d9b0", "shasum": "" }, "require": { + "dasprid/enum": "^1.0", "ext-iconv": "*", - "php": "^5.4|^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^4.8" + "phly/keep-a-changelog": "^1.4", + "phpunit/phpunit": "^6.4", + "squizlabs/php_codesniffer": "^3.1" }, "suggest": { - "ext-gd": "to generate QR code images" + "ext-imagick": "to generate QR code images" }, "type": "library", "autoload": { - "psr-0": { - "BaconQrCode": "src/" + "psr-4": { + "BaconQrCode\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -50,7 +53,7 @@ ], "description": "BaconQrCode is a QR code generator for PHP.", "homepage": "https://github.com/Bacon/BaconQrCode", - "time": "2017-10-17T09:59:25+00:00" + "time": "2018-04-25T17:53:56+00:00" }, { "name": "bunq/sdk_php", @@ -117,27 +120,69 @@ "time": "2018-09-01T12:54:04+00:00" }, { - "name": "davejamesmiller/laravel-breadcrumbs", - "version": "5.1.0", + "name": "dasprid/enum", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/davejamesmiller/laravel-breadcrumbs.git", - "reference": "2a02abfeca13acba6d528f4fcd385570452308f7" + "url": "https://github.com/DASPRiD/Enum.git", + "reference": "631ef6e638e9494b0310837fa531bedd908fc22b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/davejamesmiller/laravel-breadcrumbs/zipball/2a02abfeca13acba6d528f4fcd385570452308f7", - "reference": "2a02abfeca13acba6d528f4fcd385570452308f7", + "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/631ef6e638e9494b0310837fa531bedd908fc22b", + "reference": "631ef6e638e9494b0310837fa531bedd908fc22b", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "^6.4", + "squizlabs/php_codesniffer": "^3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DASPRiD\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/" + } + ], + "description": "PHP 7.1 enum implementation", + "keywords": [ + "enum", + "map" + ], + "time": "2017-10-25T22:45:27+00:00" + }, + { + "name": "davejamesmiller/laravel-breadcrumbs", + "version": "5.1.2", + "source": { + "type": "git", + "url": "https://github.com/davejamesmiller/laravel-breadcrumbs.git", + "reference": "f24853b97d9f973a9b936d2692f93b11924415e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/davejamesmiller/laravel-breadcrumbs/zipball/f24853b97d9f973a9b936d2692f93b11924415e2", + "reference": "f24853b97d9f973a9b936d2692f93b11924415e2", "shasum": "" }, "require": { - "illuminate/support": "5.6.*", - "illuminate/view": "5.6.*", + "illuminate/support": "5.6.*|5.7.*", + "illuminate/view": "5.6.*|5.7.*", "php": ">=7.1.3" }, "require-dev": { - "laravel/framework": "5.6.*", - "orchestra/testbench": "3.6.*", + "laravel/framework": "5.6.*|5.7.*", + "orchestra/testbench": "3.6.*|3.7.*", "php-coveralls/php-coveralls": "^1.0", "phpunit/phpunit": "7.*" }, @@ -173,7 +218,7 @@ "keywords": [ "laravel" ], - "time": "2018-05-05T19:30:03+00:00" + "time": "2018-09-14T06:29:58+00:00" }, { "name": "defuse/php-encryption", @@ -1022,42 +1067,42 @@ }, { "name": "laravel/framework", - "version": "v5.6.38", + "version": "v5.7.4", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "38d838bab9434af79e8ab274ae63f52f7ed45d6e" + "reference": "f6e8f6562120e0063313e81716666cfcd362569b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/38d838bab9434af79e8ab274ae63f52f7ed45d6e", - "reference": "38d838bab9434af79e8ab274ae63f52f7ed45d6e", + "url": "https://api.github.com/repos/laravel/framework/zipball/f6e8f6562120e0063313e81716666cfcd362569b", + "reference": "f6e8f6562120e0063313e81716666cfcd362569b", "shasum": "" }, "require": { - "doctrine/inflector": "~1.1", - "dragonmantank/cron-expression": "~2.0", - "erusev/parsedown": "~1.7", + "doctrine/inflector": "^1.1", + "dragonmantank/cron-expression": "^2.0", + "erusev/parsedown": "^1.7", "ext-mbstring": "*", "ext-openssl": "*", "league/flysystem": "^1.0.8", - "monolog/monolog": "~1.12", - "nesbot/carbon": "1.25.*", + "monolog/monolog": "^1.12", + "nesbot/carbon": "^1.26.3", "php": "^7.1.3", - "psr/container": "~1.0", + "psr/container": "^1.0", "psr/simple-cache": "^1.0", "ramsey/uuid": "^3.7", - "swiftmailer/swiftmailer": "~6.0", - "symfony/console": "~4.0", - "symfony/debug": "~4.0", - "symfony/finder": "~4.0", - "symfony/http-foundation": "~4.0", - "symfony/http-kernel": "~4.0", - "symfony/process": "~4.0", - "symfony/routing": "~4.0", - "symfony/var-dumper": "~4.0", + "swiftmailer/swiftmailer": "^6.0", + "symfony/console": "^4.1", + "symfony/debug": "^4.1", + "symfony/finder": "^4.1", + "symfony/http-foundation": "^4.1", + "symfony/http-kernel": "^4.1", + "symfony/process": "^4.1", + "symfony/routing": "^4.1", + "symfony/var-dumper": "^4.1", "tijsverkoyen/css-to-inline-styles": "^2.2.1", - "vlucas/phpdotenv": "~2.2" + "vlucas/phpdotenv": "^2.2" }, "conflict": { "tightenco/collect": "<5.5.33" @@ -1093,43 +1138,45 @@ "illuminate/view": "self.version" }, "require-dev": { - "aws/aws-sdk-php": "~3.0", - "doctrine/dbal": "~2.6", + "aws/aws-sdk-php": "^3.0", + "doctrine/dbal": "^2.6", "filp/whoops": "^2.1.4", - "league/flysystem-cached-adapter": "~1.0", - "mockery/mockery": "~1.0", + "league/flysystem-cached-adapter": "^1.0", + "mockery/mockery": "^1.0", "moontoast/math": "^1.1", - "orchestra/testbench-core": "3.6.*", - "pda/pheanstalk": "~3.0", - "phpunit/phpunit": "~7.0", + "orchestra/testbench-core": "3.7.*", + "pda/pheanstalk": "^3.0", + "phpunit/phpunit": "^7.0", "predis/predis": "^1.1.1", - "symfony/css-selector": "~4.0", - "symfony/dom-crawler": "~4.0" + "symfony/css-selector": "^4.1", + "symfony/dom-crawler": "^4.1", + "true/punycode": "^2.1" }, "suggest": { - "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~3.0).", - "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.6).", + "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (^3.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).", "ext-pcntl": "Required to use all features of the queue worker.", "ext-posix": "Required to use all features of the queue worker.", - "fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).", - "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers and the ping methods on schedules (~6.0).", - "laravel/tinker": "Required to use the tinker console command (~1.0).", - "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).", - "league/flysystem-cached-adapter": "Required to use the Flysystem cache (~1.0).", - "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).", - "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (~1.0).", - "nexmo/client": "Required to use the Nexmo transport (~1.0).", - "pda/pheanstalk": "Required to use the beanstalk queue driver (~3.0).", - "predis/predis": "Required to use the redis cache and queue drivers (~1.0).", - "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~3.0).", - "symfony/css-selector": "Required to use some of the crawler integration testing tools (~4.0).", - "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (~4.0).", - "symfony/psr-http-message-bridge": "Required to psr7 bridging features (~1.0)." + "fzaninotto/faker": "Required to use the eloquent factory builder (^1.4).", + "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers and the ping methods on schedules (^6.0).", + "laravel/tinker": "Required to use the tinker console command (^1.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", + "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", + "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (^1.0).", + "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", + "moontoast/math": "Required to use ordered UUIDs (^1.1).", + "nexmo/client": "Required to use the Nexmo transport (^1.0).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^3.0).", + "predis/predis": "Required to use the redis cache and queue drivers (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^3.0).", + "symfony/css-selector": "Required to use some of the crawler integration testing tools (^4.1).", + "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (^4.1).", + "symfony/psr-http-message-bridge": "Required to psr7 bridging features (^1.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.6-dev" + "dev-master": "5.7-dev" } }, "autoload": { @@ -1157,20 +1204,20 @@ "framework", "laravel" ], - "time": "2018-09-04T13:15:09+00:00" + "time": "2018-09-18T13:34:05+00:00" }, { "name": "laravel/passport", - "version": "v5.0.3", + "version": "v7.0.1", "source": { "type": "git", "url": "https://github.com/laravel/passport.git", - "reference": "9dbcc3d6f8f20f1a83cbef73bbb563ce59e43ded" + "reference": "90124969cdd4ff39d4cd5a608c23bbe16e772f7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/9dbcc3d6f8f20f1a83cbef73bbb563ce59e43ded", - "reference": "9dbcc3d6f8f20f1a83cbef73bbb563ce59e43ded", + "url": "https://api.github.com/repos/laravel/passport/zipball/90124969cdd4ff39d4cd5a608c23bbe16e772f7e", + "reference": "90124969cdd4ff39d4cd5a608c23bbe16e772f7e", "shasum": "" }, "require": { @@ -1184,8 +1231,8 @@ "illuminate/encryption": "~5.6", "illuminate/http": "~5.6", "illuminate/support": "~5.6", - "league/oauth2-server": "^6.0", - "php": ">=7.0", + "league/oauth2-server": "^7.0", + "php": ">=7.1", "phpseclib/phpseclib": "^2.0", "symfony/psr-http-message-bridge": "~1.0", "zendframework/zend-diactoros": "~1.0" @@ -1226,39 +1273,39 @@ "oauth", "passport" ], - "time": "2018-03-15T12:39:02+00:00" + "time": "2018-08-13T14:45:04+00:00" }, { "name": "laravelcollective/html", - "version": "v5.6.10", + "version": "v5.7.1", "source": { "type": "git", "url": "https://github.com/LaravelCollective/html.git", - "reference": "974605fcd22a7e4d19f0b2ef635a0d1d7400387d" + "reference": "777b6d390811ba249255ed5750bf17a019cd88a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LaravelCollective/html/zipball/974605fcd22a7e4d19f0b2ef635a0d1d7400387d", - "reference": "974605fcd22a7e4d19f0b2ef635a0d1d7400387d", + "url": "https://api.github.com/repos/LaravelCollective/html/zipball/777b6d390811ba249255ed5750bf17a019cd88a5", + "reference": "777b6d390811ba249255ed5750bf17a019cd88a5", "shasum": "" }, "require": { - "illuminate/http": "5.6.*", - "illuminate/routing": "5.6.*", - "illuminate/session": "5.6.*", - "illuminate/support": "5.6.*", - "illuminate/view": "5.6.*", + "illuminate/http": "5.7.*", + "illuminate/routing": "5.7.*", + "illuminate/session": "5.7.*", + "illuminate/support": "5.7.*", + "illuminate/view": "5.7.*", "php": ">=7.1.3" }, "require-dev": { - "illuminate/database": "5.6.*", + "illuminate/database": "5.7.*", "mockery/mockery": "~1.0", "phpunit/phpunit": "~7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.6-dev" + "dev-master": "5.7-dev" }, "laravel": { "providers": [ @@ -1294,7 +1341,7 @@ ], "description": "HTML and Form Builders for the Laravel Framework", "homepage": "https://laravelcollective.com", - "time": "2018-06-18T15:04:16+00:00" + "time": "2018-09-05T18:32:53+00:00" }, { "name": "lcobucci/jwt", @@ -1356,16 +1403,16 @@ }, { "name": "league/commonmark", - "version": "0.17.5", + "version": "0.18.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "82d7ab62d7f68391cb9d323f3ccce50be24a5369" + "reference": "006af077d4b1b7eb1d9760964f9f984ba188632c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/82d7ab62d7f68391cb9d323f3ccce50be24a5369", - "reference": "82d7ab62d7f68391cb9d323f3ccce50be24a5369", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/006af077d4b1b7eb1d9760964f9f984ba188632c", + "reference": "006af077d4b1b7eb1d9760964f9f984ba188632c", "shasum": "" }, "require": { @@ -1394,7 +1441,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.18-dev" + "dev-master": "0.19-dev" } }, "autoload": { @@ -1421,7 +1468,7 @@ "markdown", "parser" ], - "time": "2018-03-29T14:35:19+00:00" + "time": "2018-09-18T13:13:55+00:00" }, { "name": "league/csv", @@ -1542,26 +1589,26 @@ }, { "name": "league/flysystem", - "version": "1.0.46", + "version": "1.0.47", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "f3e0d925c18b92cf3ce84ea5cc58d62a1762a2b2" + "reference": "a11e4a75f256bdacf99d20780ce42d3b8272975c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/f3e0d925c18b92cf3ce84ea5cc58d62a1762a2b2", - "reference": "f3e0d925c18b92cf3ce84ea5cc58d62a1762a2b2", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a11e4a75f256bdacf99d20780ce42d3b8272975c", + "reference": "a11e4a75f256bdacf99d20780ce42d3b8272975c", "shasum": "" }, "require": { + "ext-fileinfo": "*", "php": ">=5.5.9" }, "conflict": { "league/flysystem-sftp": "<1.0.6" }, "require-dev": { - "ext-fileinfo": "*", "phpspec/phpspec": "^3.4", "phpunit/phpunit": "^5.7.10" }, @@ -1622,7 +1669,7 @@ "sftp", "storage" ], - "time": "2018-08-22T07:45:22+00:00" + "time": "2018-09-14T15:30:29+00:00" }, { "name": "league/fractal", @@ -1690,34 +1737,36 @@ }, { "name": "league/oauth2-server", - "version": "6.1.1", + "version": "7.2.0", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth2-server.git", - "reference": "a0cabb573c7cd5ee01803daec992d6ee3677c4ae" + "reference": "8184f771d43ea7305ddbb893d0daf6f0352ec5fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/a0cabb573c7cd5ee01803daec992d6ee3677c4ae", - "reference": "a0cabb573c7cd5ee01803daec992d6ee3677c4ae", + "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/8184f771d43ea7305ddbb893d0daf6f0352ec5fd", + "reference": "8184f771d43ea7305ddbb893d0daf6f0352ec5fd", "shasum": "" }, "require": { "defuse/php-encryption": "^2.1", "ext-openssl": "*", - "lcobucci/jwt": "^3.1", + "lcobucci/jwt": "^3.2.2", "league/event": "^2.1", - "paragonie/random_compat": "^2.0", - "php": ">=5.6.0", - "psr/http-message": "^1.0" + "php": ">=7.0.0", + "psr/http-message": "^1.0.1" }, "replace": { "league/oauth2server": "*", "lncd/oauth2": "*" }, "require-dev": { - "phpunit/phpunit": "^4.8.38 || ^5.7.21", - "zendframework/zend-diactoros": "^1.0" + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpstan/phpstan-strict-rules": "^0.9.0", + "phpunit/phpunit": "^6.3 || ^7.0", + "zendframework/zend-diactoros": "^1.3.2" }, "type": "library", "autoload": { @@ -1754,7 +1803,7 @@ "secure", "server" ], - "time": "2017-12-23T23:33:42+00:00" + "time": "2018-06-23T16:57:59+00:00" }, { "name": "monolog/monolog", @@ -1836,16 +1885,16 @@ }, { "name": "nesbot/carbon", - "version": "1.25.0", + "version": "1.33.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "cbcf13da0b531767e39eb86e9687f5deba9857b4" + "reference": "55667c1007a99e82030874b1bb14d24d07108413" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/cbcf13da0b531767e39eb86e9687f5deba9857b4", - "reference": "cbcf13da0b531767e39eb86e9687f5deba9857b4", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/55667c1007a99e82030874b1bb14d24d07108413", + "reference": "55667c1007a99e82030874b1bb14d24d07108413", "shasum": "" }, "require": { @@ -1858,13 +1907,15 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.23-dev" + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] } }, "autoload": { "psr-4": { - "Carbon\\": "src/Carbon/" + "": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1885,7 +1936,7 @@ "datetime", "time" ], - "time": "2018-03-19T15:50:49+00:00" + "time": "2018-08-07T08:39:47+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -1951,33 +2002,29 @@ }, { "name": "paragonie/random_compat", - "version": "v2.0.17", + "version": "v9.99.99", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", - "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", "shasum": "" }, "require": { - "php": ">=5.2.0" + "php": "^7" }, "require-dev": { - "phpunit/phpunit": "4.*|5.*" + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" }, "suggest": { "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." }, "type": "library", - "autoload": { - "files": [ - "lib/random.php" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -1996,7 +2043,7 @@ "pseudorandom", "random" ], - "time": "2018-07-04T16:31:37+00:00" + "time": "2018-07-02T15:55:56+00:00" }, { "name": "phpseclib/phpseclib", @@ -2500,22 +2547,22 @@ }, { "name": "rcrowe/twigbridge", - "version": "v0.9.6", + "version": "v0.9.7", "source": { "type": "git", "url": "https://github.com/rcrowe/TwigBridge.git", - "reference": "c3579440a3ca47ca45bfb0ed854bc0ff9b086bf5" + "reference": "d0c998ae6d39f154c4e2d01ef914e49d0b7d5d68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/c3579440a3ca47ca45bfb0ed854bc0ff9b086bf5", - "reference": "c3579440a3ca47ca45bfb0ed854bc0ff9b086bf5", + "url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/d0c998ae6d39f154c4e2d01ef914e49d0b7d5d68", + "reference": "d0c998ae6d39f154c4e2d01ef914e49d0b7d5d68", "shasum": "" }, "require": { - "illuminate/support": "5.0.*|5.1.*|5.2.*|5.3.*|5.4.*|5.5.*|5.6.*", - "illuminate/view": "5.0.*|5.1.*|5.2.*|5.3.*|5.4.*|5.5.*|5.6.*", - "php": ">=5.4.0", + "illuminate/support": "5.5.*|5.6.*|5.7.*", + "illuminate/view": "5.5.*|5.6.*|5.7.*", + "php": ">=7", "twig/twig": "~1.30" }, "require-dev": { @@ -2568,20 +2615,20 @@ "laravel", "twig" ], - "time": "2018-02-08T15:59:23+00:00" + "time": "2018-08-31T13:30:10+00:00" }, { "name": "swiftmailer/swiftmailer", - "version": "v6.1.2", + "version": "v6.1.3", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "7d760881d266d63c5e7a1155cbcf2ac656a31ca8" + "reference": "8ddcb66ac10c392d3beb54829eef8ac1438595f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/7d760881d266d63c5e7a1155cbcf2ac656a31ca8", - "reference": "7d760881d266d63c5e7a1155cbcf2ac656a31ca8", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/8ddcb66ac10c392d3beb54829eef8ac1438595f4", + "reference": "8ddcb66ac10c392d3beb54829eef8ac1438595f4", "shasum": "" }, "require": { @@ -2627,7 +2674,7 @@ "mail", "mailer" ], - "time": "2018-07-13T07:04:35+00:00" + "time": "2018-09-11T07:12:52+00:00" }, { "name": "symfony/console", @@ -3835,16 +3882,16 @@ }, { "name": "zendframework/zend-diactoros", - "version": "1.8.5", + "version": "1.8.6", "source": { "type": "git", "url": "https://github.com/zendframework/zend-diactoros.git", - "reference": "3e4edb822c942f37ade0d09579cfbab11e2fee87" + "reference": "20da13beba0dde8fb648be3cc19765732790f46e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/3e4edb822c942f37ade0d09579cfbab11e2fee87", - "reference": "3e4edb822c942f37ade0d09579cfbab11e2fee87", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/20da13beba0dde8fb648be3cc19765732790f46e", + "reference": "20da13beba0dde8fb648be3cc19765732790f46e", "shasum": "" }, "require": { @@ -3857,6 +3904,7 @@ "require-dev": { "ext-dom": "*", "ext-libxml": "*", + "php-http/psr7-integration-tests": "dev-master", "phpunit/phpunit": "^5.7.16 || ^6.0.8 || ^7.2.7", "zendframework/zend-coding-standard": "~1.0" }, @@ -3894,22 +3942,22 @@ "psr", "psr-7" ], - "time": "2018-08-10T14:16:32+00:00" + "time": "2018-09-05T19:29:37+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-ide-helper", - "version": "v2.5.0", + "version": "v2.5.1", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "09db8c9a76711e98c61af0795934fb15955223fb" + "reference": "7db1843473e1562d8e0490b51db847d3a1415140" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/09db8c9a76711e98c61af0795934fb15955223fb", - "reference": "09db8c9a76711e98c61af0795934fb15955223fb", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/7db1843473e1562d8e0490b51db847d3a1415140", + "reference": "7db1843473e1562d8e0490b51db847d3a1415140", "shasum": "" }, "require": { @@ -3970,7 +4018,7 @@ "phpstorm", "sublime" ], - "time": "2018-08-31T13:28:09+00:00" + "time": "2018-09-06T18:41:09+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -4380,16 +4428,16 @@ }, { "name": "filp/whoops", - "version": "2.2.0", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "181c4502d8f34db7aed7bfe88d4f87875b8e947a" + "reference": "e79cd403fb77fc8963a99ecc30e80ddd885b3311" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/181c4502d8f34db7aed7bfe88d4f87875b8e947a", - "reference": "181c4502d8f34db7aed7bfe88d4f87875b8e947a", + "url": "https://api.github.com/repos/filp/whoops/zipball/e79cd403fb77fc8963a99ecc30e80ddd885b3311", + "reference": "e79cd403fb77fc8963a99ecc30e80ddd885b3311", "shasum": "" }, "require": { @@ -4408,7 +4456,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.2-dev" } }, "autoload": { @@ -4437,7 +4485,7 @@ "throwable", "whoops" ], - "time": "2018-03-03T17:56:25+00:00" + "time": "2018-06-30T13:14:06+00:00" }, { "name": "fzaninotto/faker", @@ -5230,21 +5278,24 @@ }, { "name": "phpunit/php-file-iterator", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c" + "reference": "050bedf145a257b1ff02746c31894800e5122946" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cecbc684605bb0cc288828eb5d65d93d5c676d3c", - "reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", + "reference": "050bedf145a257b1ff02746c31894800e5122946", "shasum": "" }, "require": { "php": "^7.1" }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, "type": "library", "extra": { "branch-alias": { @@ -5273,7 +5324,7 @@ "filesystem", "iterator" ], - "time": "2018-06-11T11:44:00+00:00" + "time": "2018-09-13T20:33:42+00:00" }, { "name": "phpunit/php-text-template", @@ -5416,16 +5467,16 @@ }, { "name": "phpunit/phpunit", - "version": "7.3.3", + "version": "7.3.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1bd5629cccfb2c0a9ef5474b4ff772349e1ec898" + "reference": "7b331efabbb628c518c408fdfcaf571156775de2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1bd5629cccfb2c0a9ef5474b4ff772349e1ec898", - "reference": "1bd5629cccfb2c0a9ef5474b4ff772349e1ec898", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7b331efabbb628c518c408fdfcaf571156775de2", + "reference": "7b331efabbb628c518c408fdfcaf571156775de2", "shasum": "" }, "require": { @@ -5496,7 +5547,7 @@ "testing", "xunit" ], - "time": "2018-09-01T15:49:55+00:00" + "time": "2018-09-08T15:14:29+00:00" }, { "name": "roave/security-advisories", @@ -5508,6 +5559,7 @@ "amphp/http": "<1.0.1", "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", "aws/aws-sdk-php": ">=3,<3.2.1", + "brightlocal/phpwhois": "<=4.2.5", "bugsnag/bugsnag-laravel": ">=2,<2.0.2", "cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.0.15|>=3.1,<3.1.4|>=3.4,<3.4.14|>=3.5,<3.5.17|>=3.6,<3.6.4", "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", @@ -5519,6 +5571,7 @@ "contao/core-bundle": ">=4,<4.4.18|>=4.5,<4.5.8", "contao/listing-bundle": ">=4,<4.4.8", "contao/newsletter-bundle": ">=4,<4.1", + "david-garcia/phpwhois": "<=4.3.1", "doctrine/annotations": ">=1,<1.2.7", "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", @@ -5533,6 +5586,7 @@ "drupal/drupal": ">=7,<7.59|>=8,<8.4.8|>=8.5,<8.5.3", "erusev/parsedown": "<1.7", "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.3|>=5.4,<5.4.11.3|>=2017.8,<2017.8.1.1|>=2017.12,<2017.12.2.1", + "ezyang/htmlpurifier": "<4.1.1", "firebase/php-jwt": "<2", "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", @@ -5544,7 +5598,11 @@ "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.42|>=5.6,<5.6.30", "illuminate/database": ">=4,<4.0.99|>=4.1,<4.1.29", "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "ivankristianto/phpwhois": "<=4.3", + "james-heinrich/getid3": "<1.9.9", "joomla/session": "<1.3.1", + "jsmitty12/phpwhois": "<5.1", + "kazist/phpwhois": "<=4.2.6", "kreait/firebase-php": ">=3.2,<3.8.1", "laravel/framework": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.42|>=5.6,<5.6.30", "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", @@ -5554,6 +5612,7 @@ "monolog/monolog": ">=1.8,<1.12", "namshi/jose": "<2.2", "onelogin/php-saml": "<2.10.4", + "openid/php-openid": "<2.3", "oro/crm": ">=1.7,<1.7.4", "oro/platform": ">=1.7,<1.7.4", "padraic/humbug_get_contents": "<1.1.2", @@ -5562,21 +5621,25 @@ "paypal/merchant-sdk-php": "<3.12", "phpmailer/phpmailer": ">=5,<5.2.24", "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", + "phpwhois/phpwhois": "<=4.2.5", "phpxmlrpc/extras": "<0.6.1", "propel/propel": ">=2.0.0-alpha1,<=2.0.0-alpha7", "propel/propel1": ">=1,<=1.7.1", "pusher/pusher-php-server": "<2.2.1", "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", "sensiolabs/connect": "<4.2.3", + "serluck/phpwhois": "<=4.2.6", "shopware/shopware": "<5.3.7", "silverstripe/cms": ">=3,<=3.0.11|>=3.1,<3.1.11", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", "silverstripe/framework": ">=3,<3.3", "silverstripe/userforms": "<3", + "simple-updates/phpwhois": "<=1", "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", "simplesamlphp/simplesamlphp": "<1.15.2", "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", "slim/slim": "<2.6", + "smarty/smarty": "<3.1.33", "socalnick/scn-social-auth": "<1.15.2", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", "stormpath/sdk": ">=0,<9.9.99", @@ -5603,8 +5666,10 @@ "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", "thelia/backoffice-default-template": ">=2.1,<2.1.2", - "thelia/thelia": ">=2.1,<2.1.2|>=2.1.0-beta1,<2.1.3", + "thelia/thelia": ">=2.1.0-beta1,<2.1.3|>=2.1,<2.1.2", + "theonedemon/phpwhois": "<=4.2.5", "titon/framework": ">=0,<9.9.99", + "truckersmp/phpwhois": "<=4.3.1", "twig/twig": "<1.20", "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.30|>=8,<8.7.17|>=9,<9.3.2", "typo3/cms-core": ">=8,<8.7.17|>=9,<9.3.2", @@ -5657,7 +5722,7 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2018-08-14T15:39:17+00:00" + "time": "2018-09-17T20:20:31+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -6636,7 +6701,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.1.0", + "php": ">=7.2.0", "ext-bcmath": "*", "ext-curl": "*", "ext-gd": "*", diff --git a/config/upgrade.php b/config/upgrade.php index d24e17c798..ea56f43e47 100644 --- a/config/upgrade.php +++ b/config/upgrade.php @@ -31,6 +31,7 @@ return [ '4.7.3' => 'This version of Firefly III handles bills differently. See http://bit.ly/FF3-new-bills for more information.', '4.7.4' => 'This version of Firefly III has a new import routine. See http://bit.ly/FF3-new-import for more information.', '4.7.6' => 'This will be the last version to require PHP7.1. Future versions will require PHP7.2 minimum.', + '4.7.7' => 'This version of Firefly III requires PHP7.2.', ], 'install' => [ @@ -40,6 +41,7 @@ return [ '4.7.3' => 'This version of Firefly III handles bills differently. See http://bit.ly/FF3-new-bills for more information.', '4.7.4' => 'This version of Firefly III has a new import routine. See http://bit.ly/FF3-new-import for more information.', '4.7.6' => 'This will be the last version to require PHP7.1. Future versions will require PHP7.2 minimum.', + '4.7.7' => 'This version of Firefly III requires PHP7.2.', ], ], ]; diff --git a/database/seeds/AccountTypeSeeder.php b/database/seeds/AccountTypeSeeder.php index f695c310d8..c3bb0287e9 100644 --- a/database/seeds/AccountTypeSeeder.php +++ b/database/seeds/AccountTypeSeeder.php @@ -28,7 +28,7 @@ use Illuminate\Database\Seeder; */ class AccountTypeSeeder extends Seeder { - public function run() + public function run(): void { $types = [ AccountType::DEFAULT, @@ -42,8 +42,7 @@ class AccountTypeSeeder extends Seeder AccountType::LOAN, AccountType::RECONCILIATION, AccountType::DEBT, - AccountType::MORTGAGE, - AccountType::CREDITCARD, + AccountType::MORTGAGE ]; foreach ($types as $type) { try { diff --git a/database/seeds/TransactionCurrencySeeder.php b/database/seeds/TransactionCurrencySeeder.php index 764dd26469..0ca9c03bdc 100644 --- a/database/seeds/TransactionCurrencySeeder.php +++ b/database/seeds/TransactionCurrencySeeder.php @@ -65,6 +65,9 @@ class TransactionCurrencySeeder extends Seeder $currencies[] = ['code' => 'BCH', 'name' => 'Bitcoin cash', 'symbol' => '₿C', 'decimal_places' => 8]; $currencies[] = ['code' => 'ETH', 'name' => 'Ethereum', 'symbol' => 'Ξ', 'decimal_places' => 12]; + // PLEASE ADD NEW CURRENCIES BELOW THIS LINE + $currencies[] = ['code' => 'ILS', 'name' => 'Israeli new shekel', 'symbol' => '₪', 'decimal_places' => 2]; + foreach ($currencies as $currency) { try { TransactionCurrency::create($currency); diff --git a/public/css/bootstrap-tagsinput.css b/public/css/bootstrap-tagsinput.css index e8f37d2d64..d561602737 100755 --- a/public/css/bootstrap-tagsinput.css +++ b/public/css/bootstrap-tagsinput.css @@ -1,6 +1,6 @@ /* - * bootstrap-tagsinput v0.8.0 - * + * bootstrap-tagsinput v0.9.1 + * */ .bootstrap-tagsinput { @@ -16,7 +16,6 @@ line-height: 22px; cursor: text; } - .bootstrap-tagsinput input { border: none; box-shadow: none; @@ -27,44 +26,35 @@ width: auto; max-width: inherit; } - .bootstrap-tagsinput.form-control input::-moz-placeholder { color: #777; opacity: 1; } - .bootstrap-tagsinput.form-control input:-ms-input-placeholder { color: #777; } - .bootstrap-tagsinput.form-control input::-webkit-input-placeholder { color: #777; } - .bootstrap-tagsinput input:focus { border: none; box-shadow: none; } - .bootstrap-tagsinput .tag { margin-right: 2px; color: white; } - .bootstrap-tagsinput .tag [data-role="remove"] { margin-left: 8px; cursor: pointer; } - .bootstrap-tagsinput .tag [data-role="remove"]:after { content: "x"; padding: 0px 2px; } - .bootstrap-tagsinput .tag [data-role="remove"]:hover { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); } - .bootstrap-tagsinput .tag [data-role="remove"]:hover:active { box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } diff --git a/public/css/firefly.css b/public/css/firefly.css index dacc76681a..8e64155a3c 100644 --- a/public/css/firefly.css +++ b/public/css/firefly.css @@ -170,3 +170,77 @@ span.info-box-text a:hover, span.info-box-number a:hover { overflow-y: auto; overflow-x: hidden; } + +.bootstrap-tagsinput { + width: 100%; +} + +.accordion { + margin-bottom:-3px; +} + +.accordion-group { + border: none; +} + +.twitter-typeahead { + width:100%; +} +span.twitter-typeahead { + display: inline !important;width:100%; + +} +.tt-input { + background-color:#fff !important; +} + + +.twitter-typeahead .tt-query, +.twitter-typeahead .tt-hint { + margin-bottom: 0; +} + +.twitter-typeahead .tt-hint +{ + display: none; +} + +.tt-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; + cursor: pointer; +} + +.tt-suggestion { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.428571429; + color: #333333; + white-space: nowrap; +} + +.tt-suggestion:hover, +.tt-suggestion:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #428bca; +} \ No newline at end of file diff --git a/public/js/ff/accounts/edit-reconciliation.js b/public/js/ff/accounts/edit-reconciliation.js index 2ee2c8ae37..af72947062 100644 --- a/public/js/ff/accounts/edit-reconciliation.js +++ b/public/js/ff/accounts/edit-reconciliation.js @@ -18,8 +18,6 @@ * along with Firefly III. If not, see . */ -/** global: what, Modernizr, selectsForeignCurrency, convertForeignToNative, validateCurrencyForTransfer, convertSourceToDestination, journalData, journal, accountInfo, exchangeRateInstructions, currencyInfo */ - $(document).ready(function () { "use strict"; setAutocompletes(); @@ -30,24 +28,7 @@ $(document).ready(function () { * Set the auto-complete JSON things. */ function setAutocompletes() { - - $.getJSON('json/categories').done(function (data) { - $('input[name="category"]').typeahead({source: data, autoSelect: false}); - }); - - $.getJSON('json/tags').done(function (data) { - var opt = { - typeahead: { - source: data, - afterSelect: function () { - this.$element.val(""); - }, - autoSelect: false, - } - }; - $('input[name="tags"]').tagsinput( - opt - ); - }); + initCategoryAC(); + initTagsAC(); } diff --git a/public/js/ff/common/autocomplete.js b/public/js/ff/common/autocomplete.js new file mode 100644 index 0000000000..ccba2d5028 --- /dev/null +++ b/public/js/ff/common/autocomplete.js @@ -0,0 +1,165 @@ +/* + * autocomplete.js + * Copyright (c) 2018 thegrumpydictator@gmail.com + * + * This file is part of Firefly III. + * + * Firefly III is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Firefly III is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Firefly III. If not, see . + */ + +/** + * Do tags auto complete. + */ +function initTagsAC() { + console.log('initTagsAC()'); + var tagTags = new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + prefetch: { + url: 'json/tags', + filter: function (list) { + return $.map(list, function (tagTag) { + return {name: tagTag}; + }); + } + }, + remote: { + url: 'json/tags?search=%QUERY', + wildcard: '%QUERY', + filter: function (list) { + return $.map(list, function (name) { + return {name: name}; + }); + } + } + }); + tagTags.initialize(); + $('input[name="tags"]').tagsinput({ + typeaheadjs: { + hint: true, + highlight: true, + name: 'tags', + displayKey: 'name', + valueKey: 'name', + source: tagTags.ttAdapter() + } + }); +} + +/** + * Do destination name (expense accounts) auto complete. + */ +function initExpenseAC() { + initExpenseACField('destination_name'); +} + +/** + * Do destination name (expense accounts) auto complete. + */ +function initExpenseACField(fieldName) { + console.log('initExpenseACField("' + fieldName + '")'); + if ($('input[name="' + fieldName + '"]').length > 0) { + var destNames = new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + prefetch: { + url: 'json/expense-accounts', + filter: function (list) { + return $.map(list, function (name) { + return {name: name}; + }); + } + }, + remote: { + url: 'json/expense-accounts?search=%QUERY', + wildcard: '%QUERY', + filter: function (list) { + return $.map(list, function (name) { + return {name: name}; + }); + } + } + }); + destNames.initialize(); + $('input[name="' + fieldName + '"]').typeahead({hint: true, highlight: true,}, {source: destNames, displayKey: 'name', autoSelect: false}); + } +} + +/** + * Do source name (revenue accounts) auto complete. + */ +function initRevenueAC() { + initRevenueACField('source_name'); +} + +/** + * Do source name (revenue accounts) auto complete. + */ +function initRevenueACField(fieldName) { + console.log('initRevenueACField("' + fieldName + '")'); + if ($('input[name="' + fieldName + '"]').length > 0) { + var sourceNames = new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + prefetch: { + url: 'json/revenue-accounts', + filter: function (list) { + return $.map(list, function (name) { + return {name: name}; + }); + } + }, + remote: { + url: 'json/revenue-accounts?search=%QUERY', + wildcard: '%QUERY', + filter: function (list) { + return $.map(list, function (name) { + return {name: name}; + }); + } + } + }); + sourceNames.initialize(); + $('input[name="' + fieldName + '"]').typeahead({hint: true, highlight: true,}, {source: sourceNames, displayKey: 'name', autoSelect: false}); + } +} + +/** + * Do categories auto complete. + */ +function initCategoryAC() { + var categories = new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + prefetch: { + url: 'json/categories', + filter: function (list) { + return $.map(list, function (name) { + return {name: name}; + }); + } + }, + remote: { + url: 'json/categories?search=%QUERY', + wildcard: '%QUERY', + filter: function (list) { + return $.map(list, function (name) { + return {name: name}; + }); + } + } + }); + categories.initialize(); + $('input[name="category"]').typeahead({hint: true, highlight: true,}, {source: categories, displayKey: 'name', autoSelect: false}); +} \ No newline at end of file diff --git a/public/js/ff/recurring/create.js b/public/js/ff/recurring/create.js index 4d47190f70..8665021ce7 100644 --- a/public/js/ff/recurring/create.js +++ b/public/js/ff/recurring/create.js @@ -137,39 +137,10 @@ function parseRepetitionSuggestions(data) { } function initializeAutoComplete() { - // auto complete things: - $.getJSON('json/tags').done(function (data) { - var opt = { - typeahead: { - source: data, - afterSelect: function () { - this.$element.val(""); - }, - autoSelect: false, - }, - autoSelect: false, - }; - - $('input[name="tags"]').tagsinput( - opt - ); - }); - - if ($('input[name="destination_name"]').length > 0) { - $.getJSON('json/expense-accounts').done(function (data) { - $('input[name="destination_name"]').typeahead({source: data, autoSelect: false}); - }); - } - - if ($('input[name="source_name"]').length > 0) { - $.getJSON('json/revenue-accounts').done(function (data) { - $('input[name="source_name"]').typeahead({source: data, autoSelect: false}); - }); - } - - $.getJSON('json/categories').done(function (data) { - $('input[name="category"]').typeahead({source: data, autoSelect: false}); - }); + initTagsAC(); + initExpenseAC(); + initRevenueAC(); + initCategoryAC(); } /** diff --git a/public/js/ff/recurring/edit.js b/public/js/ff/recurring/edit.js index 2d01c524f3..26a85e59da 100644 --- a/public/js/ff/recurring/edit.js +++ b/public/js/ff/recurring/edit.js @@ -109,11 +109,11 @@ function respondToFirstDateChange() { // preselected value: var preSelected = currentRepType; - if(preSelected === '') { + if (preSelected === '') { preSelected = select.val(); } - $.getJSON(suggestUri, {date: date,pre_select: preSelected,past:true}).fail(function () { + $.getJSON(suggestUri, {date: date, pre_select: preSelected, past: true}).fail(function () { console.error('Could not load repetition suggestions'); alert('Could not load repetition suggestions'); }).done(parseRepetitionSuggestions); @@ -128,8 +128,8 @@ function parseRepetitionSuggestions(data) { if (data.hasOwnProperty(k)) { console.log('label: ' + data[k].label + ', selected: ' + data[k].selected); opt = $('