56
src/Repository/AbstractRepository.php
Normal file
56
src/Repository/AbstractRepository.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Repository\Query\BaseQuery;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Pagerfanta\Adapter\DoctrineORMAdapter;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
|
||||
/**
|
||||
* Class AbstractRepository
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
abstract class AbstractRepository extends EntityRepository
|
||||
{
|
||||
/**
|
||||
* @param QueryBuilder $qb
|
||||
* @param BaseQuery $query
|
||||
* @return QueryBuilder|Pagerfanta
|
||||
*/
|
||||
protected function getBaseQueryResult(QueryBuilder $qb, BaseQuery $query)
|
||||
{
|
||||
if ($query->getResultType() == BaseQuery::RESULT_TYPE_PAGER) {
|
||||
return $this->getPager($qb->getQuery(), $query->getPage(), $query->getPageSize());
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Query $query
|
||||
* @param int $page
|
||||
* @param int $maxPerPage
|
||||
* @return Pagerfanta
|
||||
*/
|
||||
protected function getPager(Query $query, $page = 1, $maxPerPage = 25)
|
||||
{
|
||||
$paginator = new Pagerfanta(new DoctrineORMAdapter($query, false));
|
||||
$paginator->setMaxPerPage($maxPerPage);
|
||||
$paginator->setCurrentPage($page);
|
||||
|
||||
return $paginator;
|
||||
}
|
||||
}
|
||||
184
src/Repository/ActivityRepository.php
Normal file
184
src/Repository/ActivityRepository.php
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\User;
|
||||
use Doctrine\ORM\Query;
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Model\ActivityStatistic;
|
||||
use App\Repository\Query\ActivityQuery;
|
||||
|
||||
/**
|
||||
* Class ActivityRepository
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class ActivityRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return null|Activity
|
||||
*/
|
||||
public function getById($id)
|
||||
{
|
||||
return $this->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User|null $user
|
||||
* @param \DateTime|null $startFrom
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRecentActivities(User $user = null, \DateTime $startFrom = null)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select('t', 'a', 'p', 'c')
|
||||
->from(Timesheet::class, 't')
|
||||
->join('t.activity', 'a')
|
||||
->join('a.project', 'p')
|
||||
->join('p.customer', 'c')
|
||||
->where($qb->expr()->isNotNull('t.end'))
|
||||
->andWhere('a.visible = 1')
|
||||
->andWhere('p.visible = 1')
|
||||
->andWhere('c.visible = 1')
|
||||
->groupBy('a.id')
|
||||
->orderBy('t.end', 'DESC')
|
||||
->setMaxResults(10)
|
||||
;
|
||||
|
||||
if ($user !== null) {
|
||||
$qb->andWhere('t.user = :user')
|
||||
->setParameter('user', $user);
|
||||
}
|
||||
|
||||
if ($startFrom !== null) {
|
||||
$qb->andWhere($qb->expr()->gt('t.begin', ':begin'))
|
||||
->setParameter('begin', $startFrom);
|
||||
}
|
||||
|
||||
$results = $qb->getQuery()->getResult();
|
||||
|
||||
$activities = [];
|
||||
/* @var Timesheet $entry */
|
||||
foreach ($results as $entry) {
|
||||
$activities[] = $entry->getActivity();
|
||||
}
|
||||
|
||||
return $activities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return global statistic data for all user.
|
||||
*
|
||||
* @return ActivityStatistic
|
||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
public function getGlobalStatistics()
|
||||
{
|
||||
$countAll = $this->getEntityManager()
|
||||
->createQuery('SELECT COUNT(a.id) FROM '.Activity::class.' a')
|
||||
->getSingleScalarResult();
|
||||
|
||||
$stats = new ActivityStatistic();
|
||||
$stats->setCount($countAll);
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves statistics for one activity.
|
||||
*
|
||||
* @param Activity $activity
|
||||
* @return ActivityStatistic
|
||||
*/
|
||||
public function getActivityStatistics(Activity $activity)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select('COUNT(t.id) as totalRecords', 'SUM(t.duration) as totalDuration')
|
||||
->from(Timesheet::class, 't')
|
||||
->where('t.activity = :activity')
|
||||
;
|
||||
|
||||
$result = $qb->getQuery()->execute(['activity' => $activity], Query::HYDRATE_ARRAY);
|
||||
|
||||
$stats = new ActivityStatistic();
|
||||
|
||||
if (isset($result[0])) {
|
||||
$dbStats = $result[0];
|
||||
|
||||
$stats->setCount(1);
|
||||
$stats->setRecordAmount($dbStats['totalRecords']);
|
||||
$stats->setRecordDuration($dbStats['totalDuration']);
|
||||
}
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a query builder that is used for ActivityType and your own 'query_builder' option.
|
||||
*
|
||||
* @param Activity|null $entity
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
public function builderForEntityType(Activity $entity = null)
|
||||
{
|
||||
$query = new ActivityQuery();
|
||||
$query->setHiddenEntity($entity);
|
||||
$query->setResultType(ActivityQuery::RESULT_TYPE_QUERYBUILDER);
|
||||
return $this->findByQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ActivityQuery $query
|
||||
* @return \Doctrine\ORM\QueryBuilder|\Pagerfanta\Pagerfanta
|
||||
*/
|
||||
public function findByQuery(ActivityQuery $query)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select('a', 'p', 'c')
|
||||
->from(Activity::class, 'a')
|
||||
->join('a.project', 'p')
|
||||
->join('p.customer', 'c')
|
||||
->orderBy('a.' . $query->getOrderBy(), $query->getOrder());
|
||||
|
||||
if ($query->getVisibility() == ActivityQuery::SHOW_VISIBLE) {
|
||||
if (!$query->isExclusiveVisibility()) {
|
||||
$qb->andWhere('c.visible = 1');
|
||||
$qb->andWhere('p.visible = 1');
|
||||
}
|
||||
$qb->andWhere('a.visible = 1');
|
||||
|
||||
/** @var Activity $entity */
|
||||
$entity = $query->getHiddenEntity();
|
||||
if ($entity !== null) {
|
||||
$qb->orWhere('a.id = :activity')->setParameter('activity', $entity);
|
||||
}
|
||||
} elseif ($query->getVisibility() == ActivityQuery::SHOW_HIDDEN) {
|
||||
$qb->andWhere('a.visible = 0');
|
||||
}
|
||||
|
||||
if ($query->getProject() !== null) {
|
||||
$qb->andWhere('a.project = :project')
|
||||
->setParameter('project', $query->getProject());
|
||||
} elseif ($query->getCustomer() !== null) {
|
||||
$qb->andWhere('p.customer = :customer')
|
||||
->setParameter('customer', $query->getCustomer());
|
||||
}
|
||||
|
||||
return $this->getBaseQueryResult($qb, $query);
|
||||
}
|
||||
}
|
||||
136
src/Repository/CustomerRepository.php
Normal file
136
src/Repository/CustomerRepository.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Timesheet;
|
||||
use Doctrine\ORM\Query;
|
||||
use App\Entity\Customer;
|
||||
use App\Model\CustomerStatistic;
|
||||
use App\Repository\Query\CustomerQuery;
|
||||
|
||||
/**
|
||||
* Class CustomerRepository
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class CustomerRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return null|Customer
|
||||
*/
|
||||
public function getById($id)
|
||||
{
|
||||
return $this->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return statistic data for all customer.
|
||||
*
|
||||
* @return CustomerStatistic
|
||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
public function getGlobalStatistics()
|
||||
{
|
||||
$countAll = $this->getEntityManager()
|
||||
->createQuery('SELECT COUNT(c.id) FROM '.Customer::class.' c')
|
||||
->getSingleScalarResult();
|
||||
|
||||
$stats = new CustomerStatistic();
|
||||
$stats->setCount($countAll);
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves statistics for one customer.
|
||||
*
|
||||
* @param Customer $customer
|
||||
* @return CustomerStatistic
|
||||
*/
|
||||
public function getCustomerStatistics(Customer $customer)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select('COUNT(t.id) as recordAmount', 'SUM(t.duration) as recordDuration, COUNT(DISTINCT(a.id)) as activityAmount, COUNT(DISTINCT(p.id)) as projectAmount')
|
||||
->from(Timesheet::class, 't')
|
||||
->join(Activity::class, 'a')
|
||||
->join(Project::class, 'p')
|
||||
->join(Customer::class, 'c')
|
||||
->andWhere('t.activity = a.id')
|
||||
->andWhere('a.project = p.id')
|
||||
->andWhere('p.customer = c.id')
|
||||
->andWhere('c.id = :customer')
|
||||
;
|
||||
|
||||
// dump($qb->getQuery()->getSQL());exit;
|
||||
|
||||
$result = $qb->getQuery()->execute(['customer' => $customer], Query::HYDRATE_ARRAY);
|
||||
|
||||
$stats = new CustomerStatistic();
|
||||
|
||||
if (isset($result[0])) {
|
||||
$dbStats = $result[0];
|
||||
|
||||
$stats->setCount(1);
|
||||
$stats->setRecordAmount($dbStats['recordAmount']);
|
||||
$stats->setRecordDuration($dbStats['recordDuration']);
|
||||
$stats->setActivityAmount($dbStats['activityAmount']);
|
||||
$stats->setProjectAmount($dbStats['projectAmount']);
|
||||
}
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a query builder that is used for CustomerType and your own 'query_builder' option.
|
||||
*
|
||||
* @param Customer|null $entity
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
public function builderForEntityType(Customer $entity = null)
|
||||
{
|
||||
$query = new CustomerQuery();
|
||||
$query->setHiddenEntity($entity);
|
||||
$query->setResultType(CustomerQuery::RESULT_TYPE_QUERYBUILDER);
|
||||
return $this->findByQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CustomerQuery $query
|
||||
* @return \Doctrine\ORM\QueryBuilder|\Pagerfanta\Pagerfanta
|
||||
*/
|
||||
public function findByQuery(CustomerQuery $query)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select('c')
|
||||
->from(Customer::class, 'c')
|
||||
->orderBy('c.' . $query->getOrderBy(), $query->getOrder());
|
||||
|
||||
if ($query->getVisibility() == CustomerQuery::SHOW_VISIBLE) {
|
||||
$qb->andWhere('c.visible = 1');
|
||||
|
||||
/** @var Customer $entity */
|
||||
$entity = $query->getHiddenEntity();
|
||||
if ($entity!== null) {
|
||||
$qb->orWhere('c.id = :customer')->setParameter('customer', $entity);
|
||||
}
|
||||
} elseif ($query->getVisibility() == CustomerQuery::SHOW_HIDDEN) {
|
||||
$qb->andWhere('c.visible = 0');
|
||||
}
|
||||
|
||||
return $this->getBaseQueryResult($qb, $query);
|
||||
}
|
||||
}
|
||||
142
src/Repository/ProjectRepository.php
Normal file
142
src/Repository/ProjectRepository.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Timesheet;
|
||||
use Doctrine\ORM\Query;
|
||||
use App\Entity\Project;
|
||||
use App\Model\ProjectStatistic;
|
||||
use App\Repository\Query\ProjectQuery;
|
||||
|
||||
/**
|
||||
* Class ProjectRepository
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class ProjectRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return null|Project
|
||||
*/
|
||||
public function getById($id)
|
||||
{
|
||||
return $this->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return statistic data for all user.
|
||||
*
|
||||
* @return ProjectStatistic
|
||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
public function getGlobalStatistics()
|
||||
{
|
||||
$countAll = $this->getEntityManager()
|
||||
->createQuery('SELECT COUNT(p.id) FROM '.Project::class.' p')
|
||||
->getSingleScalarResult();
|
||||
|
||||
$stats = new ProjectStatistic();
|
||||
$stats->setCount($countAll);
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves statistics for one activity.
|
||||
*
|
||||
* @param Project $project
|
||||
* @return ProjectStatistic
|
||||
*/
|
||||
public function getProjectStatistics(Project $project)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select('COUNT(t.id) as recordAmount', 'SUM(t.duration) as recordDuration, COUNT(DISTINCT(a.id)) as activityAmount')
|
||||
->from(Activity::class, 'a')
|
||||
->join(Timesheet::class, 't')
|
||||
->where('a.project = :project')
|
||||
->andWhere('t.activity = a.id')
|
||||
;
|
||||
|
||||
$result = $qb->getQuery()->execute(['project' => $project], Query::HYDRATE_ARRAY);
|
||||
|
||||
$stats = new ProjectStatistic();
|
||||
|
||||
if (isset($result[0])) {
|
||||
$dbStats = $result[0];
|
||||
|
||||
$stats->setCount(1);
|
||||
$stats->setRecordAmount($dbStats['recordAmount']);
|
||||
$stats->setRecordDuration($dbStats['recordDuration']);
|
||||
$stats->setActivityAmount($dbStats['activityAmount']);
|
||||
}
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a query builder that is used for ProjectType and your own 'query_builder' option.
|
||||
*
|
||||
* @param Project|null $entity
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
public function builderForEntityType(Project $entity = null)
|
||||
{
|
||||
$query = new ProjectQuery();
|
||||
$query->setHiddenEntity($entity);
|
||||
$query->setResultType(ProjectQuery::RESULT_TYPE_QUERYBUILDER);
|
||||
return $this->findByQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProjectQuery $query
|
||||
* @return \Doctrine\ORM\QueryBuilder|\Pagerfanta\Pagerfanta
|
||||
*/
|
||||
public function findByQuery(ProjectQuery $query)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
// if we join activities, the maxperpage limit will limit the list
|
||||
// due to the raised amount of rows by projects * activities
|
||||
$qb->select('p', 'c')
|
||||
->from(Project::class, 'p')
|
||||
->join('p.customer', 'c')
|
||||
->orderBy('p.' . $query->getOrderBy(), $query->getOrder());
|
||||
|
||||
if ($query->getVisibility() == ProjectQuery::SHOW_VISIBLE) {
|
||||
if (!$query->isExclusiveVisibility()) {
|
||||
$qb->andWhere('c.visible = 1');
|
||||
}
|
||||
$qb->andWhere('p.visible = 1');
|
||||
|
||||
/** @var Project $entity */
|
||||
$entity = $query->getHiddenEntity();
|
||||
if ($entity !== null) {
|
||||
$qb->orWhere('p.id = :project')->setParameter('project', $entity);
|
||||
}
|
||||
|
||||
// TODO check for visibility of customer
|
||||
} elseif ($query->getVisibility() == ProjectQuery::SHOW_HIDDEN) {
|
||||
$qb->andWhere('p.visible = 0');
|
||||
// TODO check for visibility of customer
|
||||
}
|
||||
|
||||
if ($query->getCustomer() !== null) {
|
||||
$qb->andWhere('p.customer = :customer')
|
||||
->setParameter('customer', $query->getCustomer());
|
||||
}
|
||||
|
||||
return $this->getBaseQueryResult($qb, $query);
|
||||
}
|
||||
}
|
||||
71
src/Repository/Query/ActivityQuery.php
Normal file
71
src/Repository/Query/ActivityQuery.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository\Query;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
|
||||
/**
|
||||
* Can be used for advanced queries with the: ActivityRepository
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class ActivityQuery extends VisibilityQuery
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Project
|
||||
*/
|
||||
protected $project;
|
||||
|
||||
/**
|
||||
* @var Customer
|
||||
*/
|
||||
protected $customer;
|
||||
|
||||
/**
|
||||
* @return Customer
|
||||
*/
|
||||
public function getCustomer()
|
||||
{
|
||||
return $this->customer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Customer $customer
|
||||
* @return $this
|
||||
*/
|
||||
public function setCustomer(Customer $customer = null)
|
||||
{
|
||||
$this->customer = $customer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Project
|
||||
*/
|
||||
public function getProject()
|
||||
{
|
||||
return $this->project;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Project $project
|
||||
* @return $this
|
||||
*/
|
||||
public function setProject(Project $project = null)
|
||||
{
|
||||
$this->project = $project;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
172
src/Repository/Query/BaseQuery.php
Normal file
172
src/Repository/Query/BaseQuery.php
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository\Query;
|
||||
|
||||
/**
|
||||
* Base class for advanced Repository queries.
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class BaseQuery
|
||||
{
|
||||
|
||||
const ORDER_ASC = 'ASC';
|
||||
const ORDER_DESC = 'DESC';
|
||||
|
||||
const DEFAULT_PAGESIZE = 25;
|
||||
const DEFAULT_PAGE = 1;
|
||||
|
||||
const RESULT_TYPE_PAGER = 'PagerFanta';
|
||||
const RESULT_TYPE_QUERYBUILDER = 'QueryBuilder';
|
||||
|
||||
/**
|
||||
* @var \stdClass
|
||||
*/
|
||||
protected $hiddenEntity;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $page = self::DEFAULT_PAGE;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $pageSize = self::DEFAULT_PAGESIZE;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $orderBy = 'id';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $order = 'ASC';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $resultType = self::RESULT_TYPE_PAGER;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPage()
|
||||
{
|
||||
return $this->page;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $page
|
||||
* @return $this
|
||||
*/
|
||||
public function setPage($page)
|
||||
{
|
||||
$this->page = (int)$page;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPageSize()
|
||||
{
|
||||
return $this->pageSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pageSize
|
||||
* @return $this
|
||||
*/
|
||||
public function setPageSize($pageSize)
|
||||
{
|
||||
if (!empty($pageSize) && (int)$pageSize > 0) {
|
||||
$this->pageSize = (int)$pageSize;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOrderBy()
|
||||
{
|
||||
return $this->orderBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* You need to validate carefully if this value is used from a user-input.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @return $this
|
||||
*/
|
||||
public function setOrderBy($orderBy)
|
||||
{
|
||||
$this->orderBy = $orderBy;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOrder()
|
||||
{
|
||||
return $this->order;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $order
|
||||
* @return $this
|
||||
*/
|
||||
public function setOrder($order)
|
||||
{
|
||||
if (in_array($order, [self::ORDER_ASC, self::ORDER_DESC])) {
|
||||
$this->order = $order;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getResultType()
|
||||
{
|
||||
return $this->resultType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $resultType
|
||||
* @return $this
|
||||
*/
|
||||
public function setResultType($resultType)
|
||||
{
|
||||
if (in_array($resultType, [self::RESULT_TYPE_PAGER, self::RESULT_TYPE_QUERYBUILDER])) {
|
||||
$this->resultType = $resultType;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getHiddenEntity()
|
||||
{
|
||||
return $this->hiddenEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \stdClass $hiddenEntity
|
||||
* @return BaseQuery
|
||||
*/
|
||||
public function setHiddenEntity($hiddenEntity)
|
||||
{
|
||||
$this->hiddenEntity = $hiddenEntity;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
21
src/Repository/Query/CustomerQuery.php
Normal file
21
src/Repository/Query/CustomerQuery.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository\Query;
|
||||
|
||||
/**
|
||||
* Can be used for advanced queries with the: CustomerRepository
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class CustomerQuery extends VisibilityQuery
|
||||
{
|
||||
}
|
||||
46
src/Repository/Query/ProjectQuery.php
Normal file
46
src/Repository/Query/ProjectQuery.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository\Query;
|
||||
|
||||
use App\Entity\Customer;
|
||||
|
||||
/**
|
||||
* Can be used for advanced queries with the: ProjectRepository
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class ProjectQuery extends VisibilityQuery
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Customer
|
||||
*/
|
||||
protected $customer;
|
||||
|
||||
/**
|
||||
* @return Customer
|
||||
*/
|
||||
public function getCustomer()
|
||||
{
|
||||
return $this->customer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Customer $customer
|
||||
* @return $this
|
||||
*/
|
||||
public function setCustomer(Customer $customer = null)
|
||||
{
|
||||
$this->customer = $customer;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
161
src/Repository/Query/TimesheetQuery.php
Normal file
161
src/Repository/Query/TimesheetQuery.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository\Query;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Repository\Query\BaseQuery;
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
|
||||
/**
|
||||
* Can be used for advanced timesheet repository queries.
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class TimesheetQuery extends BaseQuery
|
||||
{
|
||||
|
||||
const STATE_ALL = 0;
|
||||
const STATE_RUNNING = 1;
|
||||
const STATE_STOPPED = 2;
|
||||
/**
|
||||
* Overwritten for different default order
|
||||
* @var string
|
||||
*/
|
||||
protected $order = self::ORDER_DESC;
|
||||
/**
|
||||
* Overwritten for different default order
|
||||
* @var string
|
||||
*/
|
||||
protected $orderBy = 'begin';
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
protected $user;
|
||||
/**
|
||||
* @var Activity
|
||||
*/
|
||||
protected $activity;
|
||||
/**
|
||||
* @var Project
|
||||
*/
|
||||
protected $project;
|
||||
/**
|
||||
* @var Customer
|
||||
*/
|
||||
protected $customer;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $state = self::STATE_ALL;
|
||||
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @return TimesheetQuery
|
||||
*/
|
||||
public function setUser(User $user = null)
|
||||
{
|
||||
$this->user = $user;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activity overwrites: setProject() and setCustomer()
|
||||
*
|
||||
* @return Activity
|
||||
*/
|
||||
public function getActivity()
|
||||
{
|
||||
return $this->activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Activity $activity
|
||||
* @return TimesheetQuery
|
||||
*/
|
||||
public function setActivity(Activity $activity = null)
|
||||
{
|
||||
$this->activity = $activity;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Project
|
||||
*/
|
||||
public function getProject()
|
||||
{
|
||||
return $this->project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Project overwrites: setCustomer()
|
||||
* Is overwritten by: setActivity()
|
||||
*
|
||||
* @param Project $project
|
||||
* @return TimesheetQuery
|
||||
*/
|
||||
public function setProject(Project $project = null)
|
||||
{
|
||||
$this->project = $project;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Customer
|
||||
*/
|
||||
public function getCustomer()
|
||||
{
|
||||
return $this->customer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Project overwrites: none
|
||||
* Is overwritten by: setActivity() and setProject()
|
||||
*
|
||||
* @param Customer $customer
|
||||
* @return TimesheetQuery
|
||||
*/
|
||||
public function setCustomer(Customer $customer = null)
|
||||
{
|
||||
$this->customer = $customer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getState()
|
||||
{
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $state
|
||||
* @return TimesheetQuery
|
||||
*/
|
||||
public function setState($state)
|
||||
{
|
||||
if (in_array($state, [self::STATE_ALL, self::STATE_RUNNING, self::STATE_STOPPED], true)) {
|
||||
$this->state = $state;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
46
src/Repository/Query/UserQuery.php
Normal file
46
src/Repository/Query/UserQuery.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository\Query;
|
||||
|
||||
/**
|
||||
* Can be used for advanced queries with the: UserRepository
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class UserQuery extends VisibilityQuery
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $role;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRole()
|
||||
{
|
||||
return $this->role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $role
|
||||
* @return UserQuery
|
||||
*/
|
||||
public function setRole($role)
|
||||
{
|
||||
if (strpos($role, 'ROLE_') !== false || $role === null) {
|
||||
$this->role = $role;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
80
src/Repository/Query/VisibilityQuery.php
Normal file
80
src/Repository/Query/VisibilityQuery.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository\Query;
|
||||
|
||||
/**
|
||||
* Query class for Repositories with a visibility field.
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class VisibilityQuery extends BaseQuery
|
||||
{
|
||||
|
||||
const SHOW_VISIBLE = 1;
|
||||
const SHOW_HIDDEN = 2;
|
||||
const SHOW_BOTH = 3;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
protected $visibility = self::SHOW_VISIBLE;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $exclusiveVisibility = false;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getVisibility()
|
||||
{
|
||||
return $this->visibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $visibility
|
||||
* @return $this
|
||||
*/
|
||||
public function setVisibility($visibility)
|
||||
{
|
||||
if (!is_int($visibility) && $visibility != (int) $visibility) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$visibility = (int) $visibility;
|
||||
if (in_array($visibility, [self::SHOW_BOTH, self::SHOW_VISIBLE, self::SHOW_HIDDEN], true)) {
|
||||
$this->visibility = $visibility;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isExclusiveVisibility()
|
||||
{
|
||||
return $this->exclusiveVisibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to true, this will ONLY filter the visibility on the main queried object.
|
||||
*
|
||||
* @param bool $exclusiveVisibility
|
||||
* @return $this
|
||||
*/
|
||||
public function setExclusiveVisibility($exclusiveVisibility)
|
||||
{
|
||||
$this->exclusiveVisibility = (bool) $exclusiveVisibility;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
307
src/Repository/TimesheetRepository.php
Normal file
307
src/Repository/TimesheetRepository.php
Normal file
@@ -0,0 +1,307 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Timesheet;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
use App\Model\Statistic\Month;
|
||||
use App\Model\Statistic\Year;
|
||||
use App\Model\TimesheetGlobalStatistic;
|
||||
use App\Model\TimesheetStatistic;
|
||||
use DateTime;
|
||||
use App\Repository\Query\TimesheetQuery;
|
||||
|
||||
/**
|
||||
* Class TimesheetRepository
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class TimesheetRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Timesheet $entry
|
||||
* @return bool
|
||||
* @throws \Doctrine\ORM\ORMException
|
||||
* @throws \Doctrine\ORM\OptimisticLockException
|
||||
*/
|
||||
public function stopRecording(Timesheet $entry)
|
||||
{
|
||||
$entry->setEnd(new DateTime());
|
||||
|
||||
$entityManager = $this->getEntityManager();
|
||||
$entityManager->persist($entry);
|
||||
$entityManager->flush();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param Activity $activity
|
||||
* @return bool
|
||||
* @throws \Doctrine\ORM\ORMException
|
||||
* @throws \Doctrine\ORM\OptimisticLockException
|
||||
*/
|
||||
public function startRecording(User $user, Activity $activity)
|
||||
{
|
||||
$entry = new Timesheet();
|
||||
$entry
|
||||
->setBegin(new DateTime())
|
||||
->setUser($user)
|
||||
->setActivity($activity);
|
||||
|
||||
$entityManager = $this->getEntityManager();
|
||||
$entityManager->persist($entry);
|
||||
$entityManager->flush();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $select
|
||||
* @param User|null $user
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
protected function queryThisMonth($select, User $user = null)
|
||||
{
|
||||
$end = new DateTime('last day of this month');
|
||||
$end->setTime(23, 59, 59);
|
||||
$begin = new DateTime('first day of this month');
|
||||
$begin->setTime(0, 0, 0);
|
||||
|
||||
return $this->queryTimeRange($select, $begin, $end, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $select
|
||||
* @param DateTime $begin
|
||||
* @param DateTime $end
|
||||
* @param User|null $user
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
protected function queryTimeRange($select, DateTime $begin, DateTime $end, User $user = null)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select($select)
|
||||
->from(Timesheet::class, 't')
|
||||
->where($qb->expr()->gt('t.begin', ':from'))
|
||||
->andWhere($qb->expr()->lt('t.end', ':to'))
|
||||
->setParameter('from', $begin, Type::DATETIME)
|
||||
->setParameter('to', $end, Type::DATETIME);
|
||||
|
||||
if (null !== $user) {
|
||||
$qb->andWhere('t.user = :user')
|
||||
->setParameter('user', $user);
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch statistic data for one user.
|
||||
*
|
||||
* @param User $user
|
||||
* @return TimesheetStatistic
|
||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
public function getUserStatistics(User $user)
|
||||
{
|
||||
$durationTotal = $this->getEntityManager()
|
||||
->createQuery('SELECT SUM(t.duration) FROM '.Timesheet::class.' t WHERE t.user = :user')
|
||||
->setParameter('user', $user)
|
||||
->getSingleScalarResult();
|
||||
$rateTotal = $this->getEntityManager()
|
||||
->createQuery('SELECT SUM(t.rate) FROM '.Timesheet::class.' t WHERE t.user = :user')
|
||||
->setParameter('user', $user)
|
||||
->getSingleScalarResult();
|
||||
$amountMonth = $this->queryThisMonth('SUM(t.rate)', $user)
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
$durationMonth = $this->queryThisMonth('SUM(t.duration)', $user)
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
$firstEntry = $this->getEntityManager()
|
||||
->createQuery('SELECT MIN(t.begin) FROM '.Timesheet::class.' t WHERE t.user = :user')
|
||||
->setParameter('user', $user)
|
||||
->getSingleScalarResult();
|
||||
|
||||
$stats = new TimesheetStatistic();
|
||||
$stats->setAmountTotal($rateTotal);
|
||||
$stats->setDurationTotal($durationTotal);
|
||||
$stats->setAmountThisMonth($amountMonth);
|
||||
$stats->setDurationThisMonth($durationMonth);
|
||||
$stats->setFirstEntry(new DateTime($firstEntry));
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of Year statistics.
|
||||
*
|
||||
* @param User|null $user
|
||||
* @return Year[]
|
||||
*/
|
||||
public function getMonthlyStats(User $user = null)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select('SUM(t.rate) as rate, SUM(t.duration) as duration, MONTH(t.begin) as month, YEAR(t.begin) as year')
|
||||
->from(Timesheet::class, 't')
|
||||
->where($qb->expr()->gt('t.begin', '0'))
|
||||
->andWhere($qb->expr()->isNotNull('t.end'))
|
||||
->orderBy('year', 'DESC')
|
||||
->addOrderBy('month', 'ASC')
|
||||
->groupBy('year')
|
||||
->addGroupBy('month');
|
||||
|
||||
if (null !== $user) {
|
||||
$qb->where('t.user = :user')
|
||||
->setParameter('user', $user);
|
||||
}
|
||||
|
||||
$years = [];
|
||||
foreach ($qb->getQuery()->execute() as $statRow) {
|
||||
$curYear = $statRow['year'];
|
||||
|
||||
if (!isset($years[$curYear])) {
|
||||
$year = new Year($curYear);
|
||||
for ($i = 1; $i < 13; $i++) {
|
||||
$month = $i < 10 ? '0' . $i : (string)$i;
|
||||
$year->setMonth(new Month($month));
|
||||
}
|
||||
$years[$curYear] = $year;
|
||||
}
|
||||
|
||||
$month = new Month($statRow['month']);
|
||||
$month->setTotalDuration($statRow['duration'])
|
||||
->setTotalRate($statRow['rate']);
|
||||
$years[$curYear]->setMonth($month);
|
||||
}
|
||||
|
||||
return $years;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch statistic data for all user.
|
||||
*
|
||||
* @return TimesheetGlobalStatistic
|
||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
public function getGlobalStatistics()
|
||||
{
|
||||
$durationTotal = $this->getEntityManager()
|
||||
->createQuery('SELECT SUM(t.duration) FROM '.Timesheet::class.' t')
|
||||
->getSingleScalarResult();
|
||||
$rateTotal = $this->getEntityManager()
|
||||
->createQuery('SELECT SUM(t.rate) FROM '.Timesheet::class.' t')
|
||||
->getSingleScalarResult();
|
||||
$userTotal = $this->getEntityManager()
|
||||
->createQuery('SELECT COUNT(DISTINCT(t.user)) FROM '.Timesheet::class.' t')
|
||||
->getSingleScalarResult();
|
||||
$activeNow = $this->getActiveEntries();
|
||||
$amountMonth = $this->queryThisMonth('SUM(t.rate)')
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
$durationMonth = $this->queryThisMonth('SUM(t.duration)')
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
$activeMonth = $this->queryThisMonth('COUNT(DISTINCT(t.user))')
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
|
||||
$stats = new TimesheetGlobalStatistic();
|
||||
$stats->setAmountTotal($rateTotal);
|
||||
$stats->setDurationTotal($durationTotal);
|
||||
$stats->setActiveTotal($userTotal);
|
||||
$stats->setActiveCurrently(count($activeNow));
|
||||
$stats->setActiveThisMonth($activeMonth);
|
||||
$stats->setAmountThisMonth($amountMonth);
|
||||
$stats->setDurationThisMonth($durationMonth);
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO replace me by a findByQuery() call
|
||||
*
|
||||
* @param User $user
|
||||
* @return Timesheet[]|null
|
||||
*/
|
||||
public function getActiveEntries(User $user = null)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select('t', 'a', 'p', 'c')
|
||||
->from(Timesheet::class, 't')
|
||||
->join('t.activity', 'a')
|
||||
->join('a.project', 'p')
|
||||
->join('p.customer', 'c')
|
||||
->where($qb->expr()->gt('t.begin', '0'))
|
||||
->andWhere($qb->expr()->isNull('t.end'))
|
||||
->orderBy('t.begin', 'DESC');
|
||||
|
||||
$params = [];
|
||||
|
||||
if (null !== $user) {
|
||||
$qb->andWhere('t.user = :user');
|
||||
$params['user'] = $user;
|
||||
}
|
||||
|
||||
return $qb->getQuery()->execute($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TimesheetQuery $query
|
||||
* @return Pagerfanta
|
||||
*/
|
||||
public function findByQuery(TimesheetQuery $query)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select('t', 'a', 'p', 'c', 'u')
|
||||
->from(Timesheet::class, 't')
|
||||
->join('t.activity', 'a')
|
||||
->join('t.user', 'u')
|
||||
->join('a.project', 'p')
|
||||
->join('p.customer', 'c')
|
||||
->orderBy('t.' . $query->getOrderBy(), $query->getOrder());
|
||||
|
||||
if ($query->getUser() !== null) {
|
||||
$qb->andWhere('t.user = :user')
|
||||
->setParameter('user', $query->getUser());
|
||||
}
|
||||
|
||||
if ($query->getState() == TimesheetQuery::STATE_RUNNING) {
|
||||
$qb->andWhere($qb->expr()->isNull('t.end'));
|
||||
} elseif ($query->getState() == TimesheetQuery::STATE_STOPPED) {
|
||||
$qb->andWhere($qb->expr()->isNotNull('t.end'));
|
||||
}
|
||||
|
||||
if ($query->getActivity() !== null) {
|
||||
$qb->andWhere('t.activity = :activity')
|
||||
->setParameter('activity', $query->getActivity());
|
||||
} elseif ($query->getProject() !== null) {
|
||||
$qb->andWhere('a.project = :project')
|
||||
->setParameter('project', $query->getProject());
|
||||
} elseif ($query->getCustomer() !== null) {
|
||||
$qb->andWhere('p.customer = :customer')
|
||||
->setParameter('customer', $query->getCustomer());
|
||||
}
|
||||
|
||||
return $this->getBaseQueryResult($qb, $query);
|
||||
}
|
||||
}
|
||||
79
src/Repository/UserRepository.php
Normal file
79
src/Repository/UserRepository.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai package.
|
||||
*
|
||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Model\UserStatistic;
|
||||
use App\Repository\Query\UserQuery;
|
||||
|
||||
/**
|
||||
* Class UserRepository
|
||||
*
|
||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||
*/
|
||||
class UserRepository extends AbstractRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* Return statistic data for all user.
|
||||
*
|
||||
* @return UserStatistic
|
||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
public function getGlobalStatistics()
|
||||
{
|
||||
$countAll = $this->getEntityManager()
|
||||
->createQuery('SELECT COUNT(u.id) FROM '.User::class.' u')
|
||||
->getSingleScalarResult();
|
||||
|
||||
$stats = new UserStatistic();
|
||||
$stats->setTotalAmount($countAll);
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a user by his username.
|
||||
*
|
||||
* @param $username
|
||||
* @return null|User
|
||||
*/
|
||||
public function findByUsername($username)
|
||||
{
|
||||
return $this->findOneBy(['username' => $username]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserQuery $query
|
||||
* @return \Pagerfanta\Pagerfanta
|
||||
*/
|
||||
public function findByQuery(UserQuery $query)
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
// if we join activities, the maxperpage limit will limit the list to the amount or projects + activties
|
||||
$qb->select('u')
|
||||
->from(User::class, 'u')
|
||||
->orderBy('u.' . $query->getOrderBy(), $query->getOrder());
|
||||
|
||||
if ($query->getVisibility() == UserQuery::SHOW_VISIBLE) {
|
||||
$qb->andWhere('u.active = 1');
|
||||
} elseif ($query->getVisibility() == UserQuery::SHOW_HIDDEN) {
|
||||
$qb->andWhere('u.active = 0');
|
||||
}
|
||||
|
||||
if ($query->getRole() !== null) {
|
||||
$qb->andWhere('u.roles LIKE :role')->setParameter('role', '%' . $query->getRole() . '%');
|
||||
}
|
||||
|
||||
return $this->getPager($qb->getQuery(), $query->getPage(), $query->getPageSize());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user