2015-01-22 16:18:56 +00:00
< ? php
2015-01-23 15:28:37 +00:00
namespace Wallabag\CoreBundle\Repository ;
2015-01-22 16:18:56 +00:00
use Doctrine\ORM\EntityRepository ;
2017-07-29 20:51:50 +00:00
use Doctrine\ORM\QueryBuilder ;
2015-03-06 10:07:22 +00:00
use Pagerfanta\Adapter\DoctrineORMAdapter ;
use Pagerfanta\Pagerfanta ;
2017-07-29 20:51:50 +00:00
use Wallabag\CoreBundle\Entity\Entry ;
2015-12-29 13:50:52 +00:00
use Wallabag\CoreBundle\Entity\Tag ;
2015-01-22 16:18:56 +00:00
2015-02-06 06:45:32 +00:00
class EntryRepository extends EntityRepository
2015-01-22 16:18:56 +00:00
{
2015-08-21 05:38:18 +00:00
/**
* Retrieves all entries for a user .
*
* @ param int $userId
*
* @ return QueryBuilder
*/
public function getBuilderForAllByUser ( $userId )
{
return $this
-> getBuilderByUser ( $userId )
;
}
2015-08-20 18:10:06 +00:00
/**
* Retrieves unread entries for a user .
*
* @ param int $userId
*
* @ return QueryBuilder
*/
public function getBuilderForUnreadByUser ( $userId )
{
return $this
-> getBuilderByUser ( $userId )
-> andWhere ( 'e.isArchived = false' )
;
2015-01-22 16:18:56 +00:00
}
2015-01-22 20:11:22 +00:00
2015-01-23 13:58:17 +00:00
/**
2015-05-30 11:52:26 +00:00
* Retrieves read entries for a user .
2015-01-23 13:58:17 +00:00
*
2015-02-08 22:05:51 +00:00
* @ param int $userId
*
2015-08-07 20:20:30 +00:00
* @ return QueryBuilder
2015-01-23 13:58:17 +00:00
*/
2015-08-20 18:10:06 +00:00
public function getBuilderForArchiveByUser ( $userId )
2015-01-22 20:11:22 +00:00
{
2015-08-20 18:10:06 +00:00
return $this
-> getBuilderByUser ( $userId )
-> andWhere ( 'e.isArchived = true' )
;
2015-01-22 20:11:22 +00:00
}
2015-01-23 13:58:17 +00:00
/**
2015-05-30 11:52:26 +00:00
* Retrieves starred entries for a user .
2015-01-23 13:58:17 +00:00
*
2015-02-08 22:05:51 +00:00
* @ param int $userId
*
2015-08-07 20:20:30 +00:00
* @ return QueryBuilder
2015-01-23 13:58:17 +00:00
*/
2015-08-20 18:10:06 +00:00
public function getBuilderForStarredByUser ( $userId )
2015-01-22 20:11:22 +00:00
{
2015-08-20 18:10:06 +00:00
return $this
2017-08-23 21:06:40 +00:00
-> getBuilderByUser ( $userId , 'starredAt' , 'desc' )
2015-08-20 18:10:06 +00:00
-> andWhere ( 'e.isStarred = true' )
;
2015-01-22 20:11:22 +00:00
}
2015-01-30 06:50:52 +00:00
2016-11-04 22:24:43 +00:00
/**
* Retrieves entries filtered with a search term for a user .
*
* @ param int $userId
* @ param string $term
2017-07-29 20:51:50 +00:00
* @ param string $currentRoute
2016-11-04 22:24:43 +00:00
*
* @ return QueryBuilder
*/
2016-11-10 14:23:53 +00:00
public function getBuilderForSearchByUser ( $userId , $term , $currentRoute )
2016-11-04 22:24:43 +00:00
{
2016-11-10 14:23:53 +00:00
$qb = $this
-> getBuilderByUser ( $userId );
if ( 'starred' === $currentRoute ) {
$qb -> andWhere ( 'e.isStarred = true' );
} elseif ( 'unread' === $currentRoute ) {
$qb -> andWhere ( 'e.isArchived = false' );
} elseif ( 'archive' === $currentRoute ) {
$qb -> andWhere ( 'e.isArchived = true' );
}
2017-02-02 20:39:28 +00:00
// We lower() all parts here because PostgreSQL 'LIKE' verb is case-sensitive
2016-11-10 14:23:53 +00:00
$qb
2017-07-01 07:52:38 +00:00
-> andWhere ( 'lower(e.content) LIKE lower(:term) OR lower(e.title) LIKE lower(:term) OR lower(e.url) LIKE lower(:term)' ) -> setParameter ( 'term' , '%' . $term . '%' )
2016-11-04 22:24:43 +00:00
-> leftJoin ( 'e.tags' , 't' )
2016-11-18 16:36:19 +00:00
-> groupBy ( 'e.id' );
2016-11-10 14:23:53 +00:00
return $qb ;
2016-11-04 22:24:43 +00:00
}
2016-08-26 14:55:41 +00:00
/**
* Retrieves untagged entries for a user .
*
* @ param int $userId
*
* @ return QueryBuilder
*/
public function getBuilderForUntaggedByUser ( $userId )
{
return $this
-> getBuilderByUser ( $userId )
2016-12-13 19:12:21 +00:00
-> andWhere ( 'size(e.tags) = 0' );
2016-08-26 14:55:41 +00:00
}
2015-02-08 22:05:51 +00:00
/**
2015-05-30 11:52:26 +00:00
* Find Entries .
2015-02-08 22:05:51 +00:00
*
2015-02-09 21:07:39 +00:00
* @ param int $userId
* @ param bool $isArchived
* @ param bool $isStarred
2017-06-10 13:31:57 +00:00
* @ param bool $isPublic
2015-02-09 21:07:39 +00:00
* @ param string $sort
* @ param string $order
2016-07-24 09:47:03 +00:00
* @ param int $since
* @ param string $tags
2015-02-08 22:05:51 +00:00
*
2017-07-29 20:51:50 +00:00
* @ return Pagerfanta
2015-02-08 22:05:51 +00:00
*/
2017-06-10 13:31:57 +00:00
public function findEntries ( $userId , $isArchived = null , $isStarred = null , $isPublic = null , $sort = 'created' , $order = 'ASC' , $since = 0 , $tags = '' )
2015-01-30 06:50:52 +00:00
{
$qb = $this -> createQueryBuilder ( 'e' )
2016-06-25 14:27:38 +00:00
-> leftJoin ( 'e.tags' , 't' )
2017-08-03 10:46:20 +00:00
-> where ( 'e.user = :userId' ) -> setParameter ( 'userId' , $userId );
2015-02-04 17:06:42 +00:00
2015-02-08 22:05:51 +00:00
if ( null !== $isArchived ) {
2017-06-10 13:31:57 +00:00
$qb -> andWhere ( 'e.isArchived = :isArchived' ) -> setParameter ( 'isArchived' , ( bool ) $isArchived );
2015-02-04 17:06:42 +00:00
}
2015-02-08 22:05:51 +00:00
if ( null !== $isStarred ) {
2017-06-10 13:31:57 +00:00
$qb -> andWhere ( 'e.isStarred = :isStarred' ) -> setParameter ( 'isStarred' , ( bool ) $isStarred );
}
if ( null !== $isPublic ) {
2017-07-01 07:52:38 +00:00
$qb -> andWhere ( 'e.uid IS ' . ( true === $isPublic ? 'NOT' : '' ) . ' NULL' );
2015-02-04 17:06:42 +00:00
}
2016-10-02 13:41:08 +00:00
if ( $since > 0 ) {
2016-06-25 19:05:50 +00:00
$qb -> andWhere ( 'e.updatedAt > :since' ) -> setParameter ( 'since' , new \DateTime ( date ( 'Y-m-d H:i:s' , $since )));
2016-06-29 18:52:37 +00:00
}
2018-09-05 12:25:32 +00:00
if ( \is_string ( $tags ) && '' !== $tags ) {
2017-08-03 10:46:20 +00:00
foreach ( explode ( ',' , $tags ) as $i => $tag ) {
$entryAlias = 'e' . $i ;
$tagAlias = 't' . $i ;
2017-08-03 14:20:49 +00:00
// Complexe queries to ensure multiple tags are associated to an entry
2017-08-03 10:46:20 +00:00
// https://stackoverflow.com/a/6638146/569101
$qb -> andWhere ( $qb -> expr () -> in (
'e.id' ,
$this -> createQueryBuilder ( $entryAlias )
-> select ( $entryAlias . '.id' )
-> leftJoin ( $entryAlias . '.tags' , $tagAlias )
-> where ( $tagAlias . '.label = :label' . $i )
-> getDQL ()
));
// bound parameter to the main query builder
$qb -> setParameter ( 'label' . $i , $tag );
2016-06-25 14:27:38 +00:00
}
2016-06-25 19:05:50 +00:00
}
2015-02-05 06:54:04 +00:00
if ( 'created' === $sort ) {
2015-03-28 13:28:24 +00:00
$qb -> orderBy ( 'e.id' , $order );
2015-02-05 06:54:04 +00:00
} elseif ( 'updated' === $sort ) {
$qb -> orderBy ( 'e.updatedAt' , $order );
}
2016-12-14 08:00:14 +00:00
$pagerAdapter = new DoctrineORMAdapter ( $qb , true , false );
2015-03-06 10:07:22 +00:00
return new Pagerfanta ( $pagerAdapter );
2015-01-30 06:50:52 +00:00
}
2015-02-24 06:42:09 +00:00
2015-02-24 21:00:24 +00:00
/**
* Fetch an entry with a tag . Only used for tests .
*
2016-01-09 13:34:49 +00:00
* @ param int $userId
*
2017-07-29 20:51:50 +00:00
* @ return array
2015-02-24 21:00:24 +00:00
*/
2015-02-26 08:41:42 +00:00
public function findOneWithTags ( $userId )
2015-02-24 06:42:09 +00:00
{
$qb = $this -> createQueryBuilder ( 'e' )
-> innerJoin ( 'e.tags' , 't' )
2015-02-26 13:25:40 +00:00
-> innerJoin ( 'e.user' , 'u' )
-> addSelect ( 't' , 'u' )
2017-08-03 10:46:20 +00:00
-> where ( 'e.user = :userId' ) -> setParameter ( 'userId' , $userId )
2015-02-26 13:25:40 +00:00
;
2015-02-26 08:41:42 +00:00
2015-02-26 13:25:40 +00:00
return $qb -> getQuery () -> getResult ();
2015-02-24 06:42:09 +00:00
}
2015-09-23 05:55:55 +00:00
/**
* Find distinct language for a given user .
* Used to build the filter language list .
*
* @ param int $userId User id
*
* @ return array
*/
public function findDistinctLanguageByUser ( $userId )
{
$results = $this -> createQueryBuilder ( 'e' )
-> select ( 'e.language' )
-> where ( 'e.user = :userId' ) -> setParameter ( 'userId' , $userId )
-> andWhere ( 'e.language IS NOT NULL' )
-> groupBy ( 'e.language' )
-> orderBy ( 'e.language' , ' ASC' )
-> getQuery ()
-> getResult ();
2016-04-12 09:36:01 +00:00
$languages = [];
2015-09-23 05:55:55 +00:00
foreach ( $results as $result ) {
$languages [ $result [ 'language' ]] = $result [ 'language' ];
}
return $languages ;
}
2015-09-28 17:35:55 +00:00
/**
2015-10-01 07:26:52 +00:00
* Used only in test case to get the right entry associated to the right user .
2015-09-28 17:35:55 +00:00
*
2015-10-01 07:26:52 +00:00
* @ param string $username
2015-09-28 17:35:55 +00:00
*
* @ return Entry
*/
public function findOneByUsernameAndNotArchived ( $username )
{
return $this -> createQueryBuilder ( 'e' )
-> leftJoin ( 'e.user' , 'u' )
-> where ( 'u.username = :username' ) -> setParameter ( 'username' , $username )
-> andWhere ( 'e.isArchived = false' )
-> setMaxResults ( 1 )
-> getQuery ()
-> getSingleResult ();
}
2015-12-29 13:50:52 +00:00
/**
* Remove a tag from all user entries .
2015-12-29 14:08:33 +00:00
*
* We need to loop on each entry attached to the given tag to remove it , since Doctrine doesn 't know EntryTag entity because it' s a ManyToMany relation .
2015-12-29 20:59:34 +00:00
* It could be faster with one query but I don ' t know how to retrieve the table name `entry_tag` which can have a prefix :
*
* DELETE et FROM entry_tag et WHERE et . entry_id IN ( SELECT e . id FROM entry e WHERE e . user_id = : userId ) AND et . tag_id = : tagId
2015-12-29 13:50:52 +00:00
*
* @ param int $userId
* @ param Tag $tag
*/
public function removeTag ( $userId , Tag $tag )
{
2015-12-29 14:08:33 +00:00
$entries = $this -> getBuilderByUser ( $userId )
-> innerJoin ( 'e.tags' , 't' )
-> andWhere ( 't.id = :tagId' ) -> setParameter ( 'tagId' , $tag -> getId ())
-> getQuery ()
-> getResult ();
foreach ( $entries as $entry ) {
$entry -> removeTag ( $tag );
}
$this -> getEntityManager () -> flush ();
}
2016-06-25 16:37:41 +00:00
/**
2016-06-25 17:25:50 +00:00
* Remove tags from all user entries .
2016-06-25 16:37:41 +00:00
*
2016-06-25 17:25:50 +00:00
* @ param int $userId
2016-06-25 16:37:41 +00:00
* @ param Array < Tag > $tags
*/
2016-06-25 17:25:50 +00:00
public function removeTags ( $userId , $tags )
{
2016-06-25 16:37:41 +00:00
foreach ( $tags as $tag ) {
$this -> removeTag ( $userId , $tag );
}
}
2015-12-29 14:08:33 +00:00
/**
* Find all entries that are attached to a give tag id .
*
* @ param int $userId
* @ param int $tagId
*
* @ return array
*/
public function findAllByTagId ( $userId , $tagId )
{
return $this -> getBuilderByUser ( $userId )
-> innerJoin ( 'e.tags' , 't' )
-> andWhere ( 't.id = :tagId' ) -> setParameter ( 'tagId' , $tagId )
-> getQuery ()
-> getResult ();
2015-12-29 13:50:52 +00:00
}
2015-10-26 14:49:44 +00:00
/**
* Find an entry by its url and its owner .
2015-12-24 14:19:50 +00:00
* If it exists , return the entry otherwise return false .
2015-10-26 14:49:44 +00:00
*
* @ param $url
* @ param $userId
*
2016-04-12 09:36:01 +00:00
* @ return Entry | bool
2015-10-26 14:49:44 +00:00
*/
2016-01-15 14:28:22 +00:00
public function findByUrlAndUserId ( $url , $userId )
2015-10-26 14:49:44 +00:00
{
2015-12-24 14:19:50 +00:00
$res = $this -> createQueryBuilder ( 'e' )
2016-10-01 15:57:38 +00:00
-> where ( 'e.url = :url' ) -> setParameter ( 'url' , urldecode ( $url ))
2015-10-26 14:49:44 +00:00
-> andWhere ( 'e.user = :user_id' ) -> setParameter ( 'user_id' , $userId )
-> getQuery ()
-> getResult ();
2015-12-24 14:19:50 +00:00
2018-09-05 12:25:32 +00:00
if ( \count ( $res )) {
2015-12-30 11:19:15 +00:00
return current ( $res );
2015-12-24 14:19:50 +00:00
}
return false ;
2015-10-26 14:49:44 +00:00
}
2016-01-09 13:34:49 +00:00
/**
* Count all entries for a user .
*
* @ param int $userId
*
2016-01-17 11:52:30 +00:00
* @ return int
2016-01-09 13:34:49 +00:00
*/
2017-03-30 14:07:48 +00:00
public function countAllEntriesByUser ( $userId )
2016-01-09 13:34:49 +00:00
{
$qb = $this -> createQueryBuilder ( 'e' )
-> select ( 'count(e)' )
2017-08-03 10:46:20 +00:00
-> where ( 'e.user = :userId' ) -> setParameter ( 'userId' , $userId )
;
return ( int ) $qb -> getQuery () -> getSingleScalarResult ();
}
2016-10-01 12:01:13 +00:00
/**
* Remove all entries for a user id .
2016-10-08 09:14:09 +00:00
* Used when a user want to reset all informations .
2016-10-01 12:01:13 +00:00
*
2016-10-08 09:14:09 +00:00
* @ param int $userId
2016-10-01 12:01:13 +00:00
*/
public function removeAllByUserId ( $userId )
{
$this -> getEntityManager ()
2016-10-11 19:45:43 +00:00
-> createQuery ( 'DELETE FROM Wallabag\CoreBundle\Entity\Entry e WHERE e.user = :userId' )
-> setParameter ( 'userId' , $userId )
2016-10-01 12:01:13 +00:00
-> execute ();
}
2017-03-30 14:24:59 +00:00
public function removeArchivedByUserId ( $userId )
{
$this -> getEntityManager ()
-> createQuery ( 'DELETE FROM Wallabag\CoreBundle\Entity\Entry e WHERE e.user = :userId AND e.isArchived = TRUE' )
-> setParameter ( 'userId' , $userId )
-> execute ();
}
2017-02-24 10:27:03 +00:00
/**
* Get id and url from all entries
* Used for the clean - duplicates command .
*/
2017-08-22 08:42:54 +00:00
public function findAllEntriesIdAndUrlByUserId ( $userId )
2017-02-24 10:27:03 +00:00
{
$qb = $this -> createQueryBuilder ( 'e' )
-> select ( 'e.id, e.url' )
-> where ( 'e.user = :userid' ) -> setParameter ( ':userid' , $userId );
return $qb -> getQuery () -> getArrayResult ();
}
2017-05-05 12:33:36 +00:00
2017-08-21 08:36:56 +00:00
/**
* @ param int $userId
*
* @ return array
*/
2017-08-21 16:19:42 +00:00
public function findAllEntriesIdByUserId ( $userId = null )
2017-08-21 08:36:56 +00:00
{
$qb = $this -> createQueryBuilder ( 'e' )
-> select ( 'e.id' );
if ( null !== $userId ) {
$qb -> where ( 'e.user = :userid' ) -> setParameter ( ':userid' , $userId );
}
return $qb -> getQuery () -> getArrayResult ();
}
2017-05-05 12:33:36 +00:00
/**
* Find all entries by url and owner .
*
* @ param $url
* @ param $userId
*
* @ return array
*/
public function findAllByUrlAndUserId ( $url , $userId )
{
2017-05-05 12:54:03 +00:00
return $this -> createQueryBuilder ( 'e' )
2017-05-05 12:33:36 +00:00
-> where ( 'e.url = :url' ) -> setParameter ( 'url' , urldecode ( $url ))
-> andWhere ( 'e.user = :user_id' ) -> setParameter ( 'user_id' , $userId )
-> getQuery ()
-> getResult ();
}
2017-07-01 07:52:38 +00:00
/**
* Return a query builder to used by other getBuilderFor * method .
*
2017-08-23 21:06:40 +00:00
* @ param int $userId
* @ param string $sortBy
* @ param string $direction
2017-07-01 07:52:38 +00:00
*
* @ return QueryBuilder
*/
2017-08-23 21:06:40 +00:00
private function getBuilderByUser ( $userId , $sortBy = 'createdAt' , $direction = 'desc' )
2017-07-01 07:52:38 +00:00
{
return $this -> createQueryBuilder ( 'e' )
-> andWhere ( 'e.user = :userId' ) -> setParameter ( 'userId' , $userId )
2017-08-23 21:06:40 +00:00
-> orderBy ( sprintf ( 'e.%s' , $sortBy ), $direction );
2017-07-01 07:52:38 +00:00
}
2015-01-22 16:18:56 +00:00
}