Merge pull request #6909 from Simounet/feat/homepage-perfs

Improve performance on homepage
This commit is contained in:
Nicolas Lœuillet 2023-09-01 14:13:31 +02:00 committed by GitHub
commit dbed27f8d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 104 additions and 21 deletions

View File

@ -675,9 +675,6 @@ class EntryController extends AbstractController
} }
} }
$nbEntriesUntagged = $this->entryRepository
->countUntaggedEntriesByUser($this->getUser()->getId());
return $this->render( return $this->render(
'@WallabagCore/Entry/entries.html.twig', [ '@WallabagCore/Entry/entries.html.twig', [
'form' => $form->createView(), 'form' => $form->createView(),
@ -685,7 +682,6 @@ class EntryController extends AbstractController
'currentPage' => $page, 'currentPage' => $page,
'searchTerm' => $searchTerm, 'searchTerm' => $searchTerm,
'isFiltered' => $form->isSubmitted(), 'isFiltered' => $form->isSubmitted(),
'nbEntriesUntagged' => $nbEntriesUntagged,
] ]
); );
} }

View File

@ -37,6 +37,20 @@ class EntryRepository extends ServiceEntityRepository
; ;
} }
/**
* Retrieves all entries count for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getCountBuilderForAllByUser($userId)
{
return $this
->getQueryBuilderByUser($userId)
;
}
/** /**
* Retrieves unread entries for a user. * Retrieves unread entries for a user.
* *
@ -52,6 +66,21 @@ class EntryRepository extends ServiceEntityRepository
; ;
} }
/**
* Retrieves unread entries count for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getCountBuilderForUnreadByUser($userId)
{
return $this
->getQueryBuilderByUser($userId)
->andWhere('e.isArchived = false')
;
}
/** /**
* Retrieves entries with the same domain. * Retrieves entries with the same domain.
* *
@ -94,6 +123,21 @@ class EntryRepository extends ServiceEntityRepository
; ;
} }
/**
* Retrieves read entries count for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getCountBuilderForArchiveByUser($userId)
{
return $this
->getQueryBuilderByUser($userId)
->andWhere('e.isArchived = true')
;
}
/** /**
* Retrieves starred entries for a user. * Retrieves starred entries for a user.
* *
@ -109,6 +153,21 @@ class EntryRepository extends ServiceEntityRepository
; ;
} }
/**
* Retrieves starred entries count for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getCountBuilderForStarredByUser($userId)
{
return $this
->getQueryBuilderByUser($userId)
->andWhere('e.isStarred = true')
;
}
/** /**
* Retrieves entries filtered with a search term for a user. * Retrieves entries filtered with a search term for a user.
* *
@ -167,6 +226,21 @@ class EntryRepository extends ServiceEntityRepository
; ;
} }
/**
* Retrieve entries with annotations count for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getCountBuilderForAnnotationsByUser($userId)
{
return $this
->getQueryBuilderByUser($userId)
->innerJoin('e.annotations', 'a')
;
}
/** /**
* Retrieve untagged entries for a user. * Retrieve untagged entries for a user.
* *
@ -563,6 +637,23 @@ class EntryRepository extends ServiceEntityRepository
return $qb->getQuery()->getArrayResult(); return $qb->getQuery()->getArrayResult();
} }
/**
* @param int $userId
*
* @return array
*/
public function findEmptyEntriesIdByUserId($userId = null)
{
$qb = $this->createQueryBuilder('e')
->select('e.id');
if (null !== $userId) {
$qb->where('e.user = :userid AND e.content IS NULL')->setParameter(':userid', $userId);
}
return $qb->getQuery()->getArrayResult();
}
/** /**
* Find all entries by url and owner. * Find all entries by url and owner.
* *

View File

@ -118,9 +118,9 @@
<h4 class="center">{{ 'entry.filters.title'|trans }}</h4> <h4 class="center">{{ 'entry.filters.title'|trans }}</h4>
<div class="row"> <div class="row">
{% if current_route != 'untagged' and nbEntriesUntagged != 0 %} {% if current_route != 'untagged' %}
<div class="col s12 center-align"> <div class="col s12 center-align">
<a href="{{ path('untagged') }}">{{ 'tag.list.see_untagged_entries'|trans }} ({{ nbEntriesUntagged }})</a> <a href="{{ path('untagged') }}">{{ 'tag.list.see_untagged_entries'|trans }}</a>
</div> </div>
{% endif %} {% endif %}

View File

@ -168,7 +168,7 @@
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col m12 l8"> <div class="col m12 l8">
<p class="footer-text" title="{{ display_stats()|raw|striptags }}"> <p class="footer-text">
{{ display_stats() }} {{ display_stats() }}
</p> </p>
</div> </div>

View File

@ -88,35 +88,32 @@ class WallabagExtension extends AbstractExtension implements GlobalsInterface
switch ($type) { switch ($type) {
case 'starred': case 'starred':
$qb = $this->entryRepository->getBuilderForStarredByUser($user->getId()); $qb = $this->entryRepository->getCountBuilderForStarredByUser($user->getId());
break; break;
case 'archive': case 'archive':
$qb = $this->entryRepository->getBuilderForArchiveByUser($user->getId()); $qb = $this->entryRepository->getCountBuilderForArchiveByUser($user->getId());
break; break;
case 'unread': case 'unread':
$qb = $this->entryRepository->getBuilderForUnreadByUser($user->getId()); $qb = $this->entryRepository->getCountBuilderForUnreadByUser($user->getId());
break; break;
case 'annotated': case 'annotated':
$qb = $this->entryRepository->getBuilderForAnnotationsByUser($user->getId()); $qb = $this->entryRepository->getCountBuilderForAnnotationsByUser($user->getId());
break; break;
case 'all': case 'all':
$qb = $this->entryRepository->getBuilderForAllByUser($user->getId()); $qb = $this->entryRepository->getCountBuilderForAllByUser($user->getId());
break; break;
default: default:
throw new \InvalidArgumentException(sprintf('Type "%s" is not implemented.', $type)); throw new \InvalidArgumentException(sprintf('Type "%s" is not implemented.', $type));
} }
// THANKS to PostgreSQL we CAN'T make a DEAD SIMPLE count(e.id)
// ERROR: column "e0_.id" must appear in the GROUP BY clause or be used in an aggregate function
$query = $qb $query = $qb
->select('e.id') ->select('COUNT(e.id)')
->groupBy('e.id')
->getQuery(); ->getQuery();
$query->useQueryCache(true); $query->useQueryCache(true);
$query->enableResultCache($this->lifeTime); $query->enableResultCache($this->lifeTime);
return \count($query->getArrayResult()); return $query->getSingleScalarResult();
} }
/** /**
@ -148,15 +145,14 @@ class WallabagExtension extends AbstractExtension implements GlobalsInterface
return 0; return 0;
} }
$query = $this->entryRepository->getBuilderForArchiveByUser($user->getId()) $query = $this->entryRepository->getCountBuilderForArchiveByUser($user->getId())
->select('e.id') ->select('COUNT(e.id)')
->groupBy('e.id')
->getQuery(); ->getQuery();
$query->useQueryCache(true); $query->useQueryCache(true);
$query->enableResultCache($this->lifeTime); $query->enableResultCache($this->lifeTime);
$nbArchives = \count($query->getArrayResult()); $nbArchives = $query->getSingleScalarResult();
$interval = $user->getCreatedAt()->diff(new \DateTime('now')); $interval = $user->getCreatedAt()->diff(new \DateTime('now'));
$nbDays = (int) $interval->format('%a') ?: 1; $nbDays = (int) $interval->format('%a') ?: 1;