mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Possible fix for https://github.com/firefly-iii/firefly-iii/issues/5405
This commit is contained in:
parent
32d7a0fd1b
commit
a2f09b305c
@ -119,4 +119,61 @@ trait TimeCollection
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function yearIs(string $year): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereYear('transaction_journals.date', '=', $year);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function monthIs(string $month): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereMonth('transaction_journals.date', '=', $month);
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function dayIs(string $day): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereDay('transaction_journals.date', '=', $day);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function yearBefore(string $year): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereYear('transaction_journals.date', '<=', $year);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function monthBefore(string $month): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereMonth('transaction_journals.date', '<=', $month);
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function dayBefore(string $day): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereDay('transaction_journals.date', '<=', $day);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function yearAfter(string $year): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereYear('transaction_journals.date', '>=', $year);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function monthAfter(string $month): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereMonth('transaction_journals.date', '>=', $month);
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function dayAfter(string $day): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereDay('transaction_journals.date', '>=', $day);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +239,9 @@ class GroupCollector implements GroupCollectorInterface
|
||||
{
|
||||
$result = $this->query->get($this->fields);
|
||||
|
||||
Log::debug('Query in full');
|
||||
$this->dumpQueryInLogs();
|
||||
|
||||
// now to parse this into an array.
|
||||
$collection = $this->parseArray($result);
|
||||
$this->total = $collection->count();
|
||||
@ -559,6 +562,15 @@ class GroupCollector implements GroupCollectorInterface
|
||||
echo '</pre>';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function dumpQueryInLogs(): void
|
||||
{
|
||||
Log::debug($this->query->select($this->fields)->toSql()) ;
|
||||
Log::debug('Bindings',$this->query->getBindings());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a selected set of fields to arrays.
|
||||
*
|
||||
|
@ -565,4 +565,15 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function withoutTags(): GroupCollectorInterface;
|
||||
|
||||
|
||||
public function yearIs(string $year): GroupCollectorInterface;
|
||||
public function monthIs(string $month): GroupCollectorInterface;
|
||||
public function dayIs(string $day): GroupCollectorInterface;
|
||||
public function yearBefore(string $year): GroupCollectorInterface;
|
||||
public function monthBefore(string $month): GroupCollectorInterface;
|
||||
public function dayBefore(string $day): GroupCollectorInterface;
|
||||
public function yearAfter(string $year): GroupCollectorInterface;
|
||||
public function monthAfter(string $month): GroupCollectorInterface;
|
||||
public function dayAfter(string $day): GroupCollectorInterface;
|
||||
|
||||
}
|
||||
|
@ -98,17 +98,17 @@ class ParseDateString
|
||||
return $this->parseRelativeDate($date);
|
||||
}
|
||||
if ('xxxx-xx-xx' === strtolower($date)) {
|
||||
throw new FireflyException(sprintf('[a]Not a recognised date format: "%s"', $date));
|
||||
throw new FireflyException(sprintf('[a] Not a recognised date format: "%s"', $date));
|
||||
}
|
||||
// can't do a partial year:
|
||||
$substrCount = substr_count(substr($date, 0, 4), 'x', 0);
|
||||
if (10 === strlen($date) && $substrCount > 0 && $substrCount < 4) {
|
||||
throw new FireflyException(sprintf('[b]Not a recognised date format: "%s"', $date));
|
||||
throw new FireflyException(sprintf('[b] Not a recognised date format: "%s"', $date));
|
||||
}
|
||||
|
||||
// maybe a date range
|
||||
if (10 === strlen($date) && (str_contains($date, 'xx') || str_contains($date, 'xxxx'))) {
|
||||
Log::debug(sprintf('[c]Detected a date range ("%s"), return a fake date.', $date));
|
||||
Log::debug(sprintf('[c] Detected a date range ("%s"), return a fake date.', $date));
|
||||
// very lazy way to parse the date without parsing it, because this specific function
|
||||
// cant handle date ranges.
|
||||
return new Carbon('1984-09-17');
|
||||
@ -211,33 +211,31 @@ class ParseDateString
|
||||
|
||||
/**
|
||||
* @param string $date
|
||||
* @param Carbon $journalDate
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parseRange(string $date, Carbon $journalDate): array
|
||||
public function parseRange(string $date): array
|
||||
{
|
||||
// several types of range can be submitted
|
||||
switch (true) {
|
||||
default:
|
||||
break;
|
||||
case $this->isDayRange($date):
|
||||
return $this->parseDayRange($date, $journalDate);
|
||||
return $this->parseDayRange($date);
|
||||
case $this->isMonthRange($date):
|
||||
return $this->parseMonthRange($date, $journalDate);
|
||||
return $this->parseMonthRange($date);
|
||||
case $this->isYearRange($date):
|
||||
return $this->parseYearRange($date, $journalDate);
|
||||
return $this->parseYearRange($date);
|
||||
case $this->isMonthDayRange($date):
|
||||
return $this->parseMonthDayRange($date, $journalDate);
|
||||
return $this->parseMonthDayRange($date);
|
||||
case $this->isDayYearRange($date):
|
||||
return $this->parseDayYearRange($date, $journalDate);
|
||||
return $this->parseDayYearRange($date);
|
||||
case $this->isMonthYearRange($date):
|
||||
return $this->parseMonthYearRange($date, $journalDate);
|
||||
return $this->parseMonthYearRange($date);
|
||||
}
|
||||
|
||||
return [
|
||||
'start' => new Carbon('1984-09-17'),
|
||||
'end' => new Carbon('1984-09-17'),
|
||||
'exact' => new Carbon('1984-09-17'),
|
||||
];
|
||||
}
|
||||
|
||||
@ -261,23 +259,18 @@ class ParseDateString
|
||||
}
|
||||
|
||||
/**
|
||||
* format of string is xxxx-xx-DD
|
||||
*
|
||||
* @param string $date
|
||||
* @param Carbon $journalDate
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function parseDayRange(string $date, Carbon $journalDate): array
|
||||
protected function parseDayRange(string $date): array
|
||||
{
|
||||
// format of string is xxxx-xx-DD
|
||||
$validDate = str_replace(['xxxx'], [$journalDate->year], $date);
|
||||
$validDate = str_replace(['xx'], [$journalDate->format('m')], $validDate);
|
||||
Log::debug(sprintf('parseDayRange: Parsed "%s" into "%s"', $date, $validDate));
|
||||
$start = Carbon::createFromFormat('Y-m-d', $validDate)->startOfDay();
|
||||
$end = Carbon::createFromFormat('Y-m-d', $validDate)->endOfDay();
|
||||
$parts = explode('-', $date);
|
||||
|
||||
return [
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'day' => $parts[2],
|
||||
];
|
||||
}
|
||||
|
||||
@ -301,29 +294,19 @@ class ParseDateString
|
||||
}
|
||||
|
||||
/**
|
||||
* format of string is xxxx-MM-xx
|
||||
*
|
||||
* @param string $date
|
||||
* @param Carbon $journalDate
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function parseMonthRange(string $date, Carbon $journalDate): array
|
||||
protected function parseMonthRange(string $date): array
|
||||
{
|
||||
// because 31 would turn February into March unexpectedly and the exact day is irrelevant here.
|
||||
$day = $journalDate->format('d');
|
||||
if ((int)$day > 28) {
|
||||
$day = '28';
|
||||
}
|
||||
|
||||
// format of string is xxxx-MM-xx
|
||||
$validDate = str_replace(['xxxx'], [$journalDate->year], $date);
|
||||
$validDate = str_replace(['xx'], [$day], $validDate);
|
||||
Log::debug(sprintf('parseMonthRange: Parsed "%s" into "%s"', $date, $validDate));
|
||||
$start = Carbon::createFromFormat('Y-m-d', $validDate)->startOfMonth();
|
||||
$end = Carbon::createFromFormat('Y-m-d', $validDate)->endOfMonth();
|
||||
Log::debug(sprintf('parseMonthRange: Parsed "%s".', $date));
|
||||
$parts = explode('-', $date);
|
||||
|
||||
return [
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'month' => $parts[1],
|
||||
];
|
||||
}
|
||||
|
||||
@ -347,24 +330,19 @@ class ParseDateString
|
||||
}
|
||||
|
||||
/**
|
||||
* format of string is YYYY-xx-xx
|
||||
*
|
||||
* @param string $date
|
||||
* @param Carbon $journalDate
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function parseYearRange(string $date, Carbon $journalDate): array
|
||||
protected function parseYearRange(string $date): array
|
||||
{
|
||||
// format of string is YYYY-xx-xx
|
||||
// kind of a convulted way of replacing variables but I'm lazy.
|
||||
$validDate = str_replace(['xx-xx'], [sprintf('%s-xx', $journalDate->format('m'))], $date);
|
||||
$validDate = str_replace(['xx'], [$journalDate->format('d')], $validDate);
|
||||
Log::debug(sprintf('parseYearRange: Parsed "%s" into "%s"', $date, $validDate));
|
||||
$start = Carbon::createFromFormat('Y-m-d', $validDate)->startOfYear();
|
||||
$end = Carbon::createFromFormat('Y-m-d', $validDate)->endOfYear();
|
||||
Log::debug(sprintf('parseYearRange: Parsed "%s"', $date));
|
||||
$parts = explode('-', $date);
|
||||
|
||||
return [
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'year' => $parts[0],
|
||||
];
|
||||
}
|
||||
|
||||
@ -388,23 +366,20 @@ class ParseDateString
|
||||
}
|
||||
|
||||
/**
|
||||
* format of string is xxxx-MM-DD
|
||||
*
|
||||
* @param string $date
|
||||
* @param Carbon $journalDate
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function parseMonthDayRange(string $date, Carbon $journalDate): array
|
||||
private function parseMonthDayRange(string $date): array
|
||||
{
|
||||
// Any year.
|
||||
// format of string is xxxx-MM-DD
|
||||
$validDate = str_replace(['xxxx'], [$journalDate->year], $date);
|
||||
Log::debug(sprintf('parseMonthDayRange: Parsed "%s" into "%s"', $date, $validDate));
|
||||
$start = Carbon::createFromFormat('Y-m-d', $validDate)->startOfDay();
|
||||
$end = Carbon::createFromFormat('Y-m-d', $validDate)->endOfDay();
|
||||
Log::debug(sprintf('parseMonthDayRange: Parsed "%s".', $date));
|
||||
$parts = explode('-', $date);
|
||||
|
||||
return [
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'month' => $parts[1],
|
||||
'day' => $parts[2],
|
||||
];
|
||||
}
|
||||
|
||||
@ -428,23 +403,20 @@ class ParseDateString
|
||||
}
|
||||
|
||||
/**
|
||||
* format of string is YYYY-xx-DD
|
||||
*
|
||||
* @param string $date
|
||||
* @param Carbon $journalDate
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function parseDayYearRange(string $date, Carbon $journalDate): array
|
||||
private function parseDayYearRange(string $date): array
|
||||
{
|
||||
// Any year.
|
||||
// format of string is YYYY-xx-DD
|
||||
$validDate = str_replace(['xx'], [$journalDate->format('m')], $date);
|
||||
Log::debug(sprintf('parseDayYearRange: Parsed "%s" into "%s"', $date, $validDate));
|
||||
$start = Carbon::createFromFormat('Y-m-d', $validDate)->startOfDay();
|
||||
$end = Carbon::createFromFormat('Y-m-d', $validDate)->endOfDay();
|
||||
Log::debug(sprintf('parseDayYearRange: Parsed "%s".', $date));
|
||||
$parts = explode('-', $date);
|
||||
|
||||
return [
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'year' => $parts[0],
|
||||
'day' => $parts[2],
|
||||
];
|
||||
}
|
||||
|
||||
@ -468,28 +440,20 @@ class ParseDateString
|
||||
}
|
||||
|
||||
/**
|
||||
* format of string is YYYY-MM-xx
|
||||
*
|
||||
* @param string $date
|
||||
* @param Carbon $journalDate
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function parseMonthYearRange(string $date, Carbon $journalDate): array
|
||||
protected function parseMonthYearRange(string $date): array
|
||||
{
|
||||
// because 31 would turn February into March unexpectedly and the exact day is irrelevant here.
|
||||
$day = $journalDate->format('d');
|
||||
if ((int)$day > 28) {
|
||||
$day = '28';
|
||||
}
|
||||
|
||||
// format of string is YYYY-MM-xx
|
||||
$validDate = str_replace(['xx'], [$day], $date);
|
||||
Log::debug(sprintf('parseMonthYearRange: Parsed "%s" into "%s"', $date, $validDate));
|
||||
$start = Carbon::createFromFormat('Y-m-d', $validDate)->startOfMonth();
|
||||
$end = Carbon::createFromFormat('Y-m-d', $validDate)->endOfMonth();
|
||||
Log::debug(sprintf('parseMonthYearRange: Parsed "%s".', $date));
|
||||
$parts = explode('-', $date);
|
||||
|
||||
return [
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'year' => $parts[0],
|
||||
'month' => $parts[1],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -606,48 +606,15 @@ class OperatorQuerySearch implements SearchInterface
|
||||
//
|
||||
case 'date_is':
|
||||
$range = $this->parseDateRange($value);
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Set "%s" using collector with value "%s" (%s - %s)', $operator, $value, $range['start']->format('Y-m-d'),
|
||||
$range['end']->format('Y-m-d')
|
||||
)
|
||||
);
|
||||
$this->collector->setRange($range['start'], $range['end']);
|
||||
|
||||
// add to operators manually:
|
||||
$this->operators->push(['type' => 'date_before', 'value' => $range['start']->format('Y-m-d'),]);
|
||||
$this->operators->push(['type' => 'date_after', 'value' => $range['end']->format('Y-m-d'),]);
|
||||
|
||||
$this->setExactDateParams($range);
|
||||
return false;
|
||||
case 'date_before':
|
||||
Log::debug(sprintf('Value for date_before is "%s"', $value));
|
||||
$range = $this->parseDateRange($value);
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Set "%s" using collector with value "%s" (%s - %s)', $operator, $value, $range['start']->format('Y-m-d'),
|
||||
$range['end']->format('Y-m-d')
|
||||
)
|
||||
);
|
||||
|
||||
// add to operators manually:
|
||||
$this->operators->push(['type' => 'date_before', 'value' => $range['start']->format('Y-m-d'),]);
|
||||
$this->collector->setBefore($range['start']);
|
||||
|
||||
$this->setDateBeforeParams($range);
|
||||
return false;
|
||||
case 'date_after':
|
||||
Log::debug(sprintf('Value for date_after is "%s"', $value));
|
||||
$range = $this->parseDateRange($value);
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Set "%s" using collector with value "%s" (%s - %s)', $operator, $value, $range['start']->format('Y-m-d'),
|
||||
$range['end']->format('Y-m-d')
|
||||
)
|
||||
);
|
||||
|
||||
// add to operators manually:
|
||||
$this->operators->push(['type' => 'date_after', 'value' => $range['end']->format('Y-m-d'),]);
|
||||
$this->collector->setAfter($range['end']);
|
||||
|
||||
$this->setDateAfterParams($range);
|
||||
return false;
|
||||
case 'created_on':
|
||||
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
|
||||
@ -867,13 +834,12 @@ class OperatorQuerySearch implements SearchInterface
|
||||
{
|
||||
$parser = new ParseDateString;
|
||||
if ($parser->isDateRange($value)) {
|
||||
return $parser->parseRange($value, $this->date);
|
||||
return $parser->parseRange($value);
|
||||
}
|
||||
$parsedDate = $parser->parseDate($value);
|
||||
|
||||
return [
|
||||
'start' => $parsedDate,
|
||||
'end' => $parsedDate,
|
||||
'exact' => $parsedDate,
|
||||
];
|
||||
}
|
||||
|
||||
@ -884,4 +850,119 @@ class OperatorQuerySearch implements SearchInterface
|
||||
{
|
||||
return $this->words;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $range
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function setExactDateParams(array $range): void
|
||||
{
|
||||
/**
|
||||
* @var string $key
|
||||
* @var Carbon|string $value
|
||||
*/
|
||||
foreach ($range as $key => $value) {
|
||||
switch ($key) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Cannot handle key "%s" in setExactParameters()', $key));
|
||||
case 'exact':
|
||||
Log::debug(sprintf('Set date_is_exact value "%s"', $value->format('Y-m-d')));
|
||||
$this->collector->setRange($value, $value);
|
||||
$this->operators->push(['type' => 'date_is', 'value' => $value->format('Y-m-d'),]);
|
||||
break;
|
||||
case 'year':
|
||||
Log::debug(sprintf('Set date_is_exact YEAR value "%s"', $value));
|
||||
$this->collector->yearIs($value);
|
||||
$this->operators->push(['type' => 'date_is_year', 'value' => $value,]);
|
||||
break;
|
||||
case 'month':
|
||||
Log::debug(sprintf('Set date_is_exact MONTH value "%s"', $value));
|
||||
$this->collector->monthIs($value);
|
||||
$this->operators->push(['type' => 'date_is_month', 'value' => $value,]);
|
||||
break;
|
||||
case 'day':
|
||||
Log::debug(sprintf('Set date_is_exact DAY value "%s"', $value));
|
||||
$this->collector->dayIs($value);
|
||||
$this->operators->push(['type' => 'date_is_day', 'value' => $value,]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $range
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function setDateBeforeParams(array $range): void
|
||||
{
|
||||
/**
|
||||
* @var string $key
|
||||
* @var Carbon|string $value
|
||||
*/
|
||||
foreach ($range as $key => $value) {
|
||||
switch ($key) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Cannot handle key "%s" in setDateBeforeParams()', $key));
|
||||
case 'exact':
|
||||
$this->collector->setBefore($value);
|
||||
$this->operators->push(['type' => 'date_before', 'value' => $value->format('Y-m-d'),]);
|
||||
break;
|
||||
case 'year':
|
||||
Log::debug(sprintf('Set date_is_before YEAR value "%s"', $value));
|
||||
$this->collector->yearBefore($value);
|
||||
$this->operators->push(['type' => 'date_before_year', 'value' => $value,]);
|
||||
break;
|
||||
case 'month':
|
||||
Log::debug(sprintf('Set date_is_before MONTH value "%s"', $value));
|
||||
$this->collector->monthBefore($value);
|
||||
$this->operators->push(['type' => 'date_before_month', 'value' => $value,]);
|
||||
break;
|
||||
case 'day':
|
||||
Log::debug(sprintf('Set date_is_before DAY value "%s"', $value));
|
||||
$this->collector->dayBefore($value);
|
||||
$this->operators->push(['type' => 'date_before_day', 'value' => $value,]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $range
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function setDateAfterParams(array $range)
|
||||
{
|
||||
/**
|
||||
* @var string $key
|
||||
* @var Carbon|string $value
|
||||
*/
|
||||
foreach ($range as $key => $value) {
|
||||
switch ($key) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Cannot handle key "%s" in setDateAfterParams()', $key));
|
||||
case 'exact':
|
||||
$this->collector->setAfter($value);
|
||||
$this->operators->push(['type' => 'date_after', 'value' => $value->format('Y-m-d'),]);
|
||||
break;
|
||||
case 'year':
|
||||
Log::debug(sprintf('Set date_is_after YEAR value "%s"', $value));
|
||||
$this->collector->yearAfter($value);
|
||||
$this->operators->push(['type' => 'date_after_year', 'value' => $value,]);
|
||||
break;
|
||||
case 'month':
|
||||
Log::debug(sprintf('Set date_is_after MONTH value "%s"', $value));
|
||||
$this->collector->monthAfter($value);
|
||||
$this->operators->push(['type' => 'date_after_month', 'value' => $value,]);
|
||||
break;
|
||||
case 'day':
|
||||
Log::debug(sprintf('Set date_is_after DAY value "%s"', $value));
|
||||
$this->collector->dayAfter($value);
|
||||
$this->operators->push(['type' => 'date_after_day', 'value' => $value,]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ return [
|
||||
'webhooks' => true,
|
||||
'handle_debts' => true,
|
||||
],
|
||||
'version' => '5.6.6',
|
||||
'version' => '5.6.7',
|
||||
'api_version' => '1.5.5',
|
||||
'db_version' => 18,
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user