diff --git a/.deploy/docker/entrypoint.sh b/.deploy/docker/entrypoint.sh index 17d62270c3..d95e3c4626 100755 --- a/.deploy/docker/entrypoint.sh +++ b/.deploy/docker/entrypoint.sh @@ -1,8 +1,8 @@ #!/bin/bash # make sure we own the volumes: -chown -R www-data:www-data -R $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/logs $FIREFLY_PATH/storage/cache -chmod -R 775 $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/logs $FIREFLY_PATH/storage/cache +chown -R www-data:www-data -R $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/logs $FIREFLY_PATH/storage/framework/cache +chmod -R 775 $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/logs $FIREFLY_PATH/storage/framework/cache # remove any lingering files that may break upgrades: rm -f $FIREFLY_PATH/storage/logs/laravel.log diff --git a/app/Http/Controllers/DebugController.php b/app/Http/Controllers/DebugController.php index 3b0a444d23..a5e7b81036 100644 --- a/app/Http/Controllers/DebugController.php +++ b/app/Http/Controllers/DebugController.php @@ -23,13 +23,18 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use Artisan; use Carbon\Carbon; use DB; use Exception; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Middleware\IsDemoUser; use Illuminate\Http\Request; +use Illuminate\Routing\Route; use Log; use Monolog\Handler\RotatingFileHandler; +use Preferences; +use Route as RouteFacade; /** * Class DebugController @@ -45,6 +50,52 @@ class DebugController extends Controller $this->middleware(IsDemoUser::class); } + /** + * @throws FireflyException + */ + public function displayError() + { + Log::debug('This is a test message at the DEBUG level.'); + Log::info('This is a test message at the INFO level.'); + Log::notice('This is a test message at the NOTICE level.'); + Log::warning('This is a test message at the WARNING level.'); + Log::error('This is a test message at the ERROR level.'); + Log::critical('This is a test message at the CRITICAL level.'); + Log::alert('This is a test message at the ALERT level.'); + Log::emergency('This is a test message at the EMERGENCY level.'); + throw new FireflyException('A very simple test error.'); + } + + /** + * @param Request $request + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + public function flush(Request $request) + { + Preferences::mark(); + $request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range']); + Log::debug('Call cache:clear...'); + Artisan::call('cache:clear'); + Log::debug('Call config:clear...'); + Artisan::call('config:clear'); + Log::debug('Call route:clear...'); + Artisan::call('route:clear'); + Log::debug('Call twig:clean...'); + try { + Artisan::call('twig:clean'); + // @codeCoverageIgnoreStart + } catch (Exception $e) { + // don't care + Log::debug('Called twig:clean.'); + } + // @codeCoverageIgnoreEnd + Log::debug('Call view:clear...'); + Artisan::call('view:clear'); + Log::debug('Done! Redirecting...'); + + return redirect(route('index')); + } /** * @param Request $request @@ -120,6 +171,61 @@ class DebugController extends Controller ); } + /** + * @return string + */ + public function routes(): string + { + $set = RouteFacade::getRoutes(); + $ignore = ['chart.', 'javascript.', 'json.', 'report-data.', 'popup.', 'debugbar.', 'attachments.download', 'attachments.preview', + 'bills.rescan', 'budgets.income', 'currencies.def', 'error', 'flush', 'help.show', 'import.file', + 'login', 'logout', 'password.reset', 'profile.confirm-email-change', 'profile.undo-email-change', + 'register', 'report.options', 'routes', 'rule-groups.down', 'rule-groups.up', 'rules.up', 'rules.down', + 'rules.select', 'search.search', 'test-flash', 'transactions.link.delete', 'transactions.link.switch', + 'two-factor.lost', 'reports.options', 'debug', 'import.create-job', 'import.download', 'import.start', 'import.status.json', + 'preferences.delete-code', 'rules.test-triggers', 'piggy-banks.remove-money', 'piggy-banks.add-money', + 'accounts.reconcile.transactions', 'accounts.reconcile.overview', 'export.download', + 'transactions.clone', 'two-factor.index', 'api.v1', 'installer.','attachments.view','import.create', + 'import.job.download','import.job.start','import.job.status.json','import.job.store','recurring.events', + 'recurring.suggest' + ]; + $return = ' '; + /** @var Route $route */ + foreach ($set as $route) { + $name = $route->getName(); + if (null !== $name && \strlen($name) > 0 && \in_array('GET', $route->methods(), true)) { + + $found = false; + foreach ($ignore as $string) { + if (!(false === stripos($name, $string))) { + $found = true; + break; + } + } + if ($found === false) { + $return .= 'touch ' . $route->getName() . '.md;'; + } + } + } + + return $return; + } + + /** + * @param Request $request + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + public function testFlash(Request $request) + { + $request->session()->flash('success', 'This is a success message.'); + $request->session()->flash('info', 'This is an info message.'); + $request->session()->flash('warning', 'This is a warning.'); + $request->session()->flash('error', 'This is an error!'); + + return redirect(route('home')); + } + /** * Some common combinations. * @@ -151,7 +257,7 @@ class DebugController extends Controller private function collectPackages(): array { $packages = []; - $file = realpath(__DIR__ . '/../../../vendor/composer/installed.json'); + $file = \dirname(__DIR__, 3) . '/vendor/composer/installed.json'; if (!($file === false) && file_exists($file)) { // file exists! $content = file_get_contents($file); diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 993d3273e5..dcca1c2d3f 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -99,52 +99,7 @@ class HomeController extends Controller } - /** - * @throws FireflyException - */ - public function displayError() - { - Log::debug('This is a test message at the DEBUG level.'); - Log::info('This is a test message at the INFO level.'); - Log::notice('This is a test message at the NOTICE level.'); - Log::warning('This is a test message at the WARNING level.'); - Log::error('This is a test message at the ERROR level.'); - Log::critical('This is a test message at the CRITICAL level.'); - Log::alert('This is a test message at the ALERT level.'); - Log::emergency('This is a test message at the EMERGENCY level.'); - throw new FireflyException('A very simple test error.'); - } - /** - * @param Request $request - * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector - */ - public function flush(Request $request) - { - Preferences::mark(); - $request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range']); - Log::debug('Call cache:clear...'); - Artisan::call('cache:clear'); - Log::debug('Call config:clear...'); - Artisan::call('config:clear'); - Log::debug('Call route:clear...'); - Artisan::call('route:clear'); - Log::debug('Call twig:clean...'); - try { - Artisan::call('twig:clean'); - // @codeCoverageIgnoreStart - } catch (Exception $e) { - // don't care - Log::debug('Called twig:clean.'); - } - // @codeCoverageIgnoreEnd - Log::debug('Call view:clear...'); - Artisan::call('view:clear'); - Log::debug('Done! Redirecting...'); - - return redirect(route('index')); - } /** * @param AccountRepositoryInterface $repository @@ -193,56 +148,4 @@ class HomeController extends Controller ); } - /** - * @return string - */ - public function routes() - { - $set = RouteFacade::getRoutes(); - $ignore = ['chart.', 'javascript.', 'json.', 'report-data.', 'popup.', 'debugbar.', 'attachments.download', 'attachments.preview', - 'bills.rescan', 'budgets.income', 'currencies.def', 'error', 'flush', 'help.show', 'import.file', - 'login', 'logout', 'password.reset', 'profile.confirm-email-change', 'profile.undo-email-change', - 'register', 'report.options', 'routes', 'rule-groups.down', 'rule-groups.up', 'rules.up', 'rules.down', - 'rules.select', 'search.search', 'test-flash', 'transactions.link.delete', 'transactions.link.switch', - 'two-factor.lost', 'reports.options', 'debug', 'import.create-job', 'import.download', 'import.start', 'import.status.json', - 'preferences.delete-code', 'rules.test-triggers', 'piggy-banks.remove-money', 'piggy-banks.add-money', - 'accounts.reconcile.transactions', 'accounts.reconcile.overview', 'export.download', - 'transactions.clone', 'two-factor.index', - ]; - $return = ' '; - /** @var Route $route */ - foreach ($set as $route) { - $name = $route->getName(); - if (null !== $name && \in_array('GET', $route->methods()) && \strlen($name) > 0) { - - $found = false; - foreach ($ignore as $string) { - if (!(false === stripos($name, $string))) { - $found = true; - break; - } - } - if ($found === false) { - $return .= 'touch ' . $route->getName() . '.md;'; - } - } - } - - return $return; - } - - /** - * @param Request $request - * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector - */ - public function testFlash(Request $request) - { - $request->session()->flash('success', 'This is a success message.'); - $request->session()->flash('info', 'This is an info message.'); - $request->session()->flash('warning', 'This is a warning.'); - $request->session()->flash('error', 'This is an error!'); - - return redirect(route('home')); - } } diff --git a/app/Http/Controllers/Recurring/IndexController.php b/app/Http/Controllers/Recurring/IndexController.php index c11541832b..ed25962773 100644 --- a/app/Http/Controllers/Recurring/IndexController.php +++ b/app/Http/Controllers/Recurring/IndexController.php @@ -25,8 +25,10 @@ namespace FireflyIII\Http\Controllers\Recurring; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Recurrence; +use FireflyIII\Models\RecurrenceRepetition; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Transformers\RecurrenceTransformer; use Illuminate\Http\JsonResponse; @@ -66,13 +68,58 @@ class IndexController extends Controller /** * @param Request $request * - * @return string + * @throws FireflyException + * @return JsonResponse */ - public function calendar(Request $request) + function events(RecurringRepositoryInterface $repository, Request $request): JsonResponse { - return view('recurring.calendar'); + $return = []; + $start = Carbon::createFromFormat('Y-m-d', $request->get('start')); + $end = Carbon::createFromFormat('Y-m-d', $request->get('end')); + $endsAt = (string)$request->get('ends'); + $repetitionType = explode(',', $request->get('type'))[0]; + $repetitionMoment = ''; + + switch ($repetitionType) { + default: + throw new FireflyException(sprintf('Cannot handle repetition type "%s"', $repetitionType)); + case 'daily': + break; + case 'weekly': + case 'monthly': + $repetitionMoment = explode(',', $request->get('type'))[1] ?? '1'; + break; + case 'ndom': + $repetitionMoment = explode(',', $request->get('type'))[1] ?? '1,1'; + break; + case 'yearly': + $repetitionMoment = explode(',', $request->get('type'))[1] ?? '2018-01-01'; + break; + } + + $repetition = new RecurrenceRepetition; + $repetition->repetition_type = $repetitionType; + $repetition->repetition_moment = $repetitionMoment; + $repetition->repetition_skip = (int)$request->get('skip'); + + var_dump($repository->getXOccurrences($repetition, $start, 5)); + exit; + + + // calculate events in range, depending on type: + switch ($endsAt) { + default: + throw new FireflyException(sprintf('Cannot generate events for "%s"', $endsAt)); + case 'forever': + break; + + } + + + return Response::json($return); } + /** * @param Request $request * diff --git a/app/Repositories/Recurring/RecurringRepository.php b/app/Repositories/Recurring/RecurringRepository.php index 79905c1019..2bf58c2066 100644 --- a/app/Repositories/Recurring/RecurringRepository.php +++ b/app/Repositories/Recurring/RecurringRepository.php @@ -82,7 +82,7 @@ class RecurringRepository implements RecurringRepositoryInterface * @return array * @throws FireflyException */ - public function getOccurrences(RecurrenceRepetition $repetition, Carbon $date, int $count = 5): array + public function getXOccurrences(RecurrenceRepetition $repetition, Carbon $date, int $count = 5): array { $return = []; $mutator = clone $date; diff --git a/app/Repositories/Recurring/RecurringRepositoryInterface.php b/app/Repositories/Recurring/RecurringRepositoryInterface.php index d72738b785..f0e7646827 100644 --- a/app/Repositories/Recurring/RecurringRepositoryInterface.php +++ b/app/Repositories/Recurring/RecurringRepositoryInterface.php @@ -63,7 +63,7 @@ interface RecurringRepositoryInterface * * @return array */ - public function getOccurrences(RecurrenceRepetition $repetition, Carbon $date, int $count = 5): array; + public function getXOccurrences(RecurrenceRepetition $repetition, Carbon $date, int $count = 5): array; /** * Parse the repetition in a string that is user readable. diff --git a/app/Transformers/RecurrenceTransformer.php b/app/Transformers/RecurrenceTransformer.php index db984a4c85..713928ac3b 100644 --- a/app/Transformers/RecurrenceTransformer.php +++ b/app/Transformers/RecurrenceTransformer.php @@ -141,7 +141,7 @@ class RecurrenceTransformer extends TransformerAbstract ]; // get the (future) occurrences for this specific type of repetition: - $occurrences = $this->repository->getOccurrences($repetition, $fromDate, 5); + $occurrences = $this->repository->getXOccurrences($repetition, $fromDate, 5); /** @var Carbon $carbon */ foreach ($occurrences as $carbon) { $repetitionArray['occurrences'][] = $carbon->format('Y-m-d'); diff --git a/public/js/ff/recurring/create.js b/public/js/ff/recurring/create.js index 5f2317fe68..083f42f9aa 100644 --- a/public/js/ff/recurring/create.js +++ b/public/js/ff/recurring/create.js @@ -44,6 +44,15 @@ $(document).ready(function () { * */ function showRepCalendar() { + + // pre-append URL with repetition info: + var newEventsUri = eventsUri + '?type=' + $('#ffInput_repetition_type').val(); + newEventsUri += '&skip=' + $('#ffInput_skip').val(); + newEventsUri += '&ends=' + $('#ffInput_repetition_end').val(); + newEventsUri += '&endDate=' + $('#ffInput_repeat_until').val(); + newEventsUri += '&reps=' + $('#ffInput_repetitions').val(); + + $('#recurring_calendar').fullCalendar( { defaultDate: '2018-06-13', @@ -53,12 +62,7 @@ function showRepCalendar() { contentHeight: 300, aspectRatio: 1.25, eventLimit: true, // allow "more" link when too many events - events: [ - { - title: '', - start: '2018-06-14' - } - ] + events: newEventsUri }); $('#calendarModal').modal('show'); return false; diff --git a/resources/views/recurring/calendar.twig b/resources/views/recurring/calendar.twig deleted file mode 100644 index 2b3446b3fb..0000000000 --- a/resources/views/recurring/calendar.twig +++ /dev/null @@ -1,16 +0,0 @@ -