mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-12 15:35:15 +00:00
Optimize queries for statistics.
This commit is contained in:
@@ -46,19 +46,17 @@ trait AppendsLocationData
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function validLongitude(string $longitude): bool
|
||||
{
|
||||
$number = (float) $longitude;
|
||||
|
||||
return $number >= -180 && $number <= 180;
|
||||
}
|
||||
|
||||
private function validLatitude(string $latitude): bool
|
||||
{
|
||||
$number = (float) $latitude;
|
||||
|
||||
return $number >= -90 && $number <= 90;
|
||||
}
|
||||
/**
|
||||
* Abstract method stolen from "InteractsWithInput".
|
||||
*
|
||||
* @param null $key
|
||||
* @param bool $default
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @SuppressWarnings("PHPMD.BooleanArgumentFlag")
|
||||
*/
|
||||
abstract public function boolean($key = null, $default = false);
|
||||
|
||||
/**
|
||||
* Abstract method.
|
||||
@@ -69,6 +67,22 @@ trait AppendsLocationData
|
||||
*/
|
||||
abstract public function has($key);
|
||||
|
||||
/**
|
||||
* Abstract method.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function method();
|
||||
|
||||
/**
|
||||
* Abstract method.
|
||||
*
|
||||
* @param mixed ...$patterns
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function routeIs(...$patterns);
|
||||
|
||||
/**
|
||||
* Read the submitted Request data and add new or updated Location data to the array.
|
||||
*/
|
||||
@@ -82,12 +96,12 @@ trait AppendsLocationData
|
||||
$data['latitude'] = null;
|
||||
$data['zoom_level'] = null;
|
||||
|
||||
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
||||
$latitudeKey = $this->getLocationKey($prefix, 'latitude');
|
||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||
$isValidPOST = $this->isValidPost($prefix);
|
||||
$isValidPUT = $this->isValidPUT($prefix);
|
||||
$isValidEmptyPUT = $this->isValidEmptyPUT($prefix);
|
||||
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
||||
$latitudeKey = $this->getLocationKey($prefix, 'latitude');
|
||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||
$isValidPOST = $this->isValidPost($prefix);
|
||||
$isValidPUT = $this->isValidPUT($prefix);
|
||||
$isValidEmptyPUT = $this->isValidEmptyPUT($prefix);
|
||||
|
||||
// for a POST (store), all fields must be present and not NULL.
|
||||
if ($isValidPOST) {
|
||||
@@ -132,72 +146,22 @@ trait AppendsLocationData
|
||||
return sprintf('%s_%s', $prefix, $key);
|
||||
}
|
||||
|
||||
private function isValidPost(?string $prefix): bool
|
||||
private function isValidEmptyPUT(?string $prefix): bool
|
||||
{
|
||||
app('log')->debug('Now in isValidPost()');
|
||||
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
||||
$latitudeKey = $this->getLocationKey($prefix, 'latitude');
|
||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||
$hasLocationKey = $this->getLocationKey($prefix, 'has_location');
|
||||
// fields must not be null:
|
||||
if (null !== $this->get($longitudeKey) && null !== $this->get($latitudeKey) && null !== $this->get($zoomLevelKey)) {
|
||||
app('log')->debug('All fields present');
|
||||
// if is POST and route contains API, this is enough:
|
||||
if ('POST' === $this->method() && $this->routeIs('api.v1.*')) {
|
||||
app('log')->debug('Is API location');
|
||||
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
||||
$latitudeKey = $this->getLocationKey($prefix, 'latitude');
|
||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||
|
||||
return true;
|
||||
}
|
||||
// if is POST and route does not contain API, must also have "has_location" = true
|
||||
if ('POST' === $this->method() && $this->routeIs('*.store') && !$this->routeIs('api.v1.*') && '' !== $hasLocationKey) {
|
||||
app('log')->debug('Is POST + store route.');
|
||||
$hasLocation = $this->boolean($hasLocationKey);
|
||||
if (true === $hasLocation) {
|
||||
app('log')->debug('Has form form location');
|
||||
|
||||
return true;
|
||||
}
|
||||
app('log')->debug('Does not have form location');
|
||||
|
||||
return false;
|
||||
}
|
||||
app('log')->debug('Is not POST API or POST form');
|
||||
|
||||
return false;
|
||||
}
|
||||
app('log')->debug('Fields not present');
|
||||
|
||||
return false;
|
||||
return (
|
||||
null === $this->get($longitudeKey)
|
||||
&& null === $this->get($latitudeKey)
|
||||
&& null === $this->get($zoomLevelKey))
|
||||
&& (
|
||||
'PUT' === $this->method()
|
||||
|| ('POST' === $this->method() && $this->routeIs('*.update'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function method();
|
||||
|
||||
/**
|
||||
* Abstract method.
|
||||
*
|
||||
* @param mixed ...$patterns
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function routeIs(...$patterns);
|
||||
|
||||
/**
|
||||
* Abstract method stolen from "InteractsWithInput".
|
||||
*
|
||||
* @param null $key
|
||||
* @param bool $default
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @SuppressWarnings("PHPMD.BooleanArgumentFlag")
|
||||
*/
|
||||
abstract public function boolean($key = null, $default = false);
|
||||
|
||||
private function isValidPUT(?string $prefix): bool
|
||||
{
|
||||
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
||||
@@ -238,19 +202,55 @@ trait AppendsLocationData
|
||||
return false;
|
||||
}
|
||||
|
||||
private function isValidEmptyPUT(?string $prefix): bool
|
||||
private function isValidPost(?string $prefix): bool
|
||||
{
|
||||
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
||||
$latitudeKey = $this->getLocationKey($prefix, 'latitude');
|
||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||
app('log')->debug('Now in isValidPost()');
|
||||
$longitudeKey = $this->getLocationKey($prefix, 'longitude');
|
||||
$latitudeKey = $this->getLocationKey($prefix, 'latitude');
|
||||
$zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level');
|
||||
$hasLocationKey = $this->getLocationKey($prefix, 'has_location');
|
||||
// fields must not be null:
|
||||
if (null !== $this->get($longitudeKey) && null !== $this->get($latitudeKey) && null !== $this->get($zoomLevelKey)) {
|
||||
app('log')->debug('All fields present');
|
||||
// if is POST and route contains API, this is enough:
|
||||
if ('POST' === $this->method() && $this->routeIs('api.v1.*')) {
|
||||
app('log')->debug('Is API location');
|
||||
|
||||
return (
|
||||
null === $this->get($longitudeKey)
|
||||
&& null === $this->get($latitudeKey)
|
||||
&& null === $this->get($zoomLevelKey))
|
||||
&& (
|
||||
'PUT' === $this->method()
|
||||
|| ('POST' === $this->method() && $this->routeIs('*.update'))
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// if is POST and route does not contain API, must also have "has_location" = true
|
||||
if ('POST' === $this->method() && $this->routeIs('*.store') && !$this->routeIs('api.v1.*') && '' !== $hasLocationKey) {
|
||||
app('log')->debug('Is POST + store route.');
|
||||
$hasLocation = $this->boolean($hasLocationKey);
|
||||
if (true === $hasLocation) {
|
||||
app('log')->debug('Has form form location');
|
||||
|
||||
return true;
|
||||
}
|
||||
app('log')->debug('Does not have form location');
|
||||
|
||||
return false;
|
||||
}
|
||||
app('log')->debug('Is not POST API or POST form');
|
||||
|
||||
return false;
|
||||
}
|
||||
app('log')->debug('Fields not present');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function validLatitude(string $latitude): bool
|
||||
{
|
||||
$number = (float)$latitude;
|
||||
|
||||
return $number >= -90 && $number <= 90;
|
||||
}
|
||||
|
||||
private function validLongitude(string $longitude): bool
|
||||
{
|
||||
$number = (float)$longitude;
|
||||
|
||||
return $number >= -180 && $number <= 180;
|
||||
}
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ trait ChecksLogin
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
// Only allow logged-in users
|
||||
$check = auth()->check();
|
||||
$check = auth()->check();
|
||||
if (!$check) {
|
||||
return false;
|
||||
}
|
||||
@@ -79,19 +79,19 @@ trait ChecksLogin
|
||||
public function getUserGroup(): ?UserGroup
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$user = auth()->user();
|
||||
app('log')->debug('Now in getUserGroup()');
|
||||
|
||||
/** @var null|UserGroup $userGroup */
|
||||
$userGroup = $this->route()?->parameter('userGroup');
|
||||
if (null === $userGroup) {
|
||||
app('log')->debug('Request class has no userGroup parameter, but perhaps there is a parameter.');
|
||||
$userGroupId = (int) $this->get('user_group_id');
|
||||
$userGroupId = (int)$this->get('user_group_id');
|
||||
if (0 === $userGroupId) {
|
||||
app('log')->debug(sprintf('Request class has no user_group_id parameter, grab default from user (group #%d).', $user->user_group_id));
|
||||
$userGroupId = (int) $user->user_group_id;
|
||||
$userGroupId = (int)$user->user_group_id;
|
||||
}
|
||||
$userGroup = UserGroup::find($userGroupId);
|
||||
$userGroup = UserGroup::find($userGroupId);
|
||||
if (null === $userGroup) {
|
||||
app('log')->error(sprintf('Request class has user_group_id (#%d), but group does not exist.', $userGroupId));
|
||||
|
||||
|
@@ -31,7 +31,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use function Safe\preg_replace;
|
||||
|
||||
/**
|
||||
@@ -99,28 +98,6 @@ trait ConvertsDataTypes
|
||||
return Steam::filterSpaces($string);
|
||||
}
|
||||
|
||||
public function convertSortParameters(string $field, string $class): array
|
||||
{
|
||||
// assume this all works, because the validator would have caught any errors.
|
||||
$parameter = (string)request()->query->get($field);
|
||||
if ('' === $parameter) {
|
||||
return [];
|
||||
}
|
||||
$parts = explode(',', $parameter);
|
||||
$sortParameters = [];
|
||||
foreach ($parts as $part) {
|
||||
$part = trim($part);
|
||||
$direction = 'asc';
|
||||
if ('-' === $part[0]) {
|
||||
$part = substr($part, 1);
|
||||
$direction = 'desc';
|
||||
}
|
||||
$sortParameters[] = [$part, $direction];
|
||||
}
|
||||
|
||||
return $sortParameters;
|
||||
}
|
||||
|
||||
public function clearString(?string $string): ?string
|
||||
{
|
||||
$string = $this->clearStringKeepNewlines($string);
|
||||
@@ -159,6 +136,36 @@ trait ConvertsDataTypes
|
||||
return Steam::filterSpaces($this->convertString($field));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return integer value.
|
||||
*/
|
||||
public function convertInteger(string $field): int
|
||||
{
|
||||
return (int)$this->get($field);
|
||||
}
|
||||
|
||||
public function convertSortParameters(string $field, string $class): array
|
||||
{
|
||||
// assume this all works, because the validator would have caught any errors.
|
||||
$parameter = (string)request()->query->get($field);
|
||||
if ('' === $parameter) {
|
||||
return [];
|
||||
}
|
||||
$parts = explode(',', $parameter);
|
||||
$sortParameters = [];
|
||||
foreach ($parts as $part) {
|
||||
$part = trim($part);
|
||||
$direction = 'asc';
|
||||
if ('-' === $part[0]) {
|
||||
$part = substr($part, 1);
|
||||
$direction = 'desc';
|
||||
}
|
||||
$sortParameters[] = [$part, $direction];
|
||||
}
|
||||
|
||||
return $sortParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string value.
|
||||
*/
|
||||
@@ -178,14 +185,6 @@ trait ConvertsDataTypes
|
||||
*/
|
||||
abstract public function get(string $key, mixed $default = null): mixed;
|
||||
|
||||
/**
|
||||
* Return integer value.
|
||||
*/
|
||||
public function convertInteger(string $field): int
|
||||
{
|
||||
return (int)$this->get($field);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO duplicate, see SelectTransactionsRequest
|
||||
*
|
||||
@@ -218,6 +217,16 @@ trait ConvertsDataTypes
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method that always exists in the Request classes that use this
|
||||
* trait, OR a stub needs to be added by any other class that uses this train.
|
||||
*
|
||||
* @param mixed $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function has($key);
|
||||
|
||||
/**
|
||||
* Return string value with newlines.
|
||||
*/
|
||||
@@ -386,16 +395,6 @@ trait ConvertsDataTypes
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method that always exists in the Request classes that use this
|
||||
* trait, OR a stub needs to be added by any other class that uses this train.
|
||||
*
|
||||
* @param mixed $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function has($key);
|
||||
|
||||
/**
|
||||
* Return date or NULL.
|
||||
*/
|
||||
@@ -418,6 +417,21 @@ trait ConvertsDataTypes
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse to integer
|
||||
*/
|
||||
protected function integerFromValue(?string $string): ?int
|
||||
{
|
||||
if (null === $string) {
|
||||
return null;
|
||||
}
|
||||
if ('' === $string) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (int)$string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return integer value, or NULL when it's not set.
|
||||
*/
|
||||
@@ -445,7 +459,7 @@ trait ConvertsDataTypes
|
||||
if (!is_array($entry)) {
|
||||
continue;
|
||||
}
|
||||
$amount = null;
|
||||
$amount = null;
|
||||
if (array_key_exists('current_amount', $entry)) {
|
||||
$amount = $this->clearString((string)($entry['current_amount'] ?? '0'));
|
||||
if (null === $entry['current_amount']) {
|
||||
@@ -463,19 +477,4 @@ trait ConvertsDataTypes
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse to integer
|
||||
*/
|
||||
protected function integerFromValue(?string $string): ?int
|
||||
{
|
||||
if (null === $string) {
|
||||
return null;
|
||||
}
|
||||
if ('' === $string) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (int)$string;
|
||||
}
|
||||
}
|
||||
|
@@ -38,12 +38,12 @@ trait GetRecurrenceData
|
||||
|
||||
foreach ($stringKeys as $key) {
|
||||
if (array_key_exists($key, $transaction)) {
|
||||
$return[$key] = (string) $transaction[$key];
|
||||
$return[$key] = (string)$transaction[$key];
|
||||
}
|
||||
}
|
||||
foreach ($intKeys as $key) {
|
||||
if (array_key_exists($key, $transaction)) {
|
||||
$return[$key] = (int) $transaction[$key];
|
||||
$return[$key] = (int)$transaction[$key];
|
||||
}
|
||||
}
|
||||
foreach ($keys as $key) {
|
||||
|
@@ -25,10 +25,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\Request;
|
||||
|
||||
use Illuminate\Validation\Validator;
|
||||
use FireflyIII\Enums\WebhookTrigger;
|
||||
use FireflyIII\Models\Webhook;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
trait ValidatesWebhooks
|
||||
{
|
||||
@@ -40,9 +40,9 @@ trait ValidatesWebhooks
|
||||
if (count($validator->failed()) > 0) {
|
||||
return;
|
||||
}
|
||||
$data = $validator->getData();
|
||||
$triggers = $data['triggers'] ?? [];
|
||||
$responses = $data['responses'] ?? [];
|
||||
$data = $validator->getData();
|
||||
$triggers = $data['triggers'] ?? [];
|
||||
$responses = $data['responses'] ?? [];
|
||||
|
||||
if (0 === count($triggers) || 0 === count($responses)) {
|
||||
Log::debug('No trigger or response, return.');
|
||||
|
Reference in New Issue
Block a user