Display meta-fields in datatables (#1116)

This commit is contained in:
Kevin Papst
2019-09-19 20:28:31 +02:00
committed by GitHub
parent 24cbe3d281
commit 5aa422dde1
71 changed files with 1461 additions and 212 deletions

View File

@@ -9,6 +9,8 @@
namespace App\Repository\Loader;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\Timesheet;
use Doctrine\ORM\EntityManagerInterface;
@@ -19,10 +21,15 @@ final class TimesheetIdLoader implements LoaderInterface
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @var bool
*/
private $fullyHydrated = false;
public function __construct(EntityManagerInterface $entityManager)
public function __construct(EntityManagerInterface $entityManager, bool $hydrateFullTree = false)
{
$this->entityManager = $entityManager;
$this->fullyHydrated = $hydrateFullTree;
}
/**
@@ -37,23 +44,45 @@ final class TimesheetIdLoader implements LoaderInterface
$em = $this->entityManager;
$qb = $em->createQueryBuilder();
$projects = $qb->select('PARTIAL t.{id}', 'project')
$timesheets = $qb->select('PARTIAL t.{id}', 'project')
->from(Timesheet::class, 't')
->leftJoin('t.project', 'project')
->andWhere($qb->expr()->in('t.id', $ids))
->getQuery()
->execute();
if (!empty($projects)) {
$projectIds = array_map(function (Timesheet $timesheet) {
return $timesheet->getProject()->getId();
$projectIds = array_map(function (Timesheet $timesheet) {
return $timesheet->getProject()->getId();
}, $timesheets);
if ($this->fullyHydrated) {
$qb = $em->createQueryBuilder();
$qb->select('PARTIAL p.{id}', 'meta')
->from(Project::class, 'p')
->leftJoin('p.meta', 'meta')
->andWhere($qb->expr()->in('p.id', $projectIds))
->getQuery()
->execute();
}
$qb = $em->createQueryBuilder();
$projects = $qb->select('PARTIAL p.{id}', 'customer')
->from(Project::class, 'p')
->leftJoin('p.customer', 'customer')
->andWhere($qb->expr()->in('p.id', $projectIds))
->getQuery()
->execute();
if ($this->fullyHydrated) {
$customerIds = array_map(function (Project $project) {
return $project->getCustomer()->getId();
}, $projects);
$qb = $em->createQueryBuilder();
$qb->select('PARTIAL p.{id}', 'customer')
->from(Project::class, 'p')
->leftJoin('p.customer', 'customer')
->andWhere($qb->expr()->in('p.id', $projectIds))
$qb->select('PARTIAL c.{id}', 'meta')
->from(Customer::class, 'c')
->leftJoin('c.meta', 'meta')
->andWhere($qb->expr()->in('c.id', $customerIds))
->getQuery()
->execute();
}
@@ -66,6 +95,20 @@ final class TimesheetIdLoader implements LoaderInterface
->getQuery()
->execute();
if ($this->fullyHydrated) {
$activityIds = array_map(function (Timesheet $timesheet) {
return $timesheet->getActivity()->getId();
}, $timesheets);
$qb = $em->createQueryBuilder();
$qb->select('PARTIAL a.{id}', 'meta')
->from(Activity::class, 'a')
->leftJoin('a.meta', 'meta')
->andWhere($qb->expr()->in('a.id', $activityIds))
->getQuery()
->execute();
}
$qb = $em->createQueryBuilder();
$qb->select('PARTIAL t.{id}', 'user')
->from(Timesheet::class, 't')

View File

@@ -19,9 +19,9 @@ final class TimesheetLoader implements LoaderInterface
*/
private $loader;
public function __construct(EntityManagerInterface $entityManager)
public function __construct(EntityManagerInterface $entityManager, bool $hydrateFullTree = false)
{
$this->loader = new TimesheetIdLoader($entityManager);
$this->loader = new TimesheetIdLoader($entityManager, $hydrateFullTree);
}
/**

View File

@@ -42,6 +42,11 @@ class TagRepository extends EntityRepository
$entityManager->flush();
}
public function findTagByName(string $tagName): ?Tag
{
return $this->findOneBy(['name' => $tagName]);
}
/**
* Find ids of the given tagNames separated by comma
* @param string $tagNames

View File

@@ -432,12 +432,7 @@ class TimesheetRepository extends EntityRepository
$qb->setParameter('user', $user);
}
$results = $qb->getQuery()->getResult();
$loader = new TimesheetLoader($qb->getEntityManager());
$loader->loadResults($results);
return $results;
return $this->getHydratedResultsByQuery($qb, false);
}
/**
@@ -530,16 +525,33 @@ class TimesheetRepository extends EntityRepository
}
/**
* When switching $fullyHydrated to true, the call gets even more expensive.
* You normally don't need this, unless you want to access deeply nested attributes for many entries!
*
* @param TimesheetQuery $query
* @param bool $fullyHydrated
* @return Timesheet[]
*/
public function getTimesheetsForQuery(TimesheetQuery $query): iterable
public function getTimesheetsForQuery(TimesheetQuery $query, bool $fullyHydrated = false): iterable
{
// this is using the paginator internally, as it will load all joined entities into the working unit
// do not "optimize" to use the query directly, as it would results in hundreds of additional lazy queries
$paginator = $this->getPaginatorForQuery($query);
$qb = $this->getQueryBuilderForQuery($query);
return $paginator->getAll();
return $this->getHydratedResultsByQuery($qb, $fullyHydrated);
}
/**
* @param QueryBuilder $qb
* @param bool $fullyHydrated
* @return Timesheet[]
*/
protected function getHydratedResultsByQuery(QueryBuilder $qb, bool $fullyHydrated = false): iterable
{
$results = $qb->getQuery()->getResult();
$loader = new TimesheetLoader($qb->getEntityManager(), $fullyHydrated);
$loader->loadResults($results);
return $results;
}
private function getQueryBuilderForQuery(TimesheetQuery $query): QueryBuilder
@@ -738,12 +750,7 @@ class TimesheetRepository extends EntityRepository
->orderBy('t.end', 'DESC')
;
$results = $qb->getQuery()->getResult();
$loader = new TimesheetLoader($qb->getEntityManager());
$loader->loadResults($results);
return $results;
return $this->getHydratedResultsByQuery($qb, false);
}
/**