2016-10-28 12:46:30 +00:00
< ? php
2024-02-19 00:30:12 +00:00
namespace Wallabag\Controller\Api ;
2016-10-28 12:46:30 +00:00
2022-11-23 11:44:55 +00:00
use Hateoas\Configuration\Route as HateoasRoute ;
2016-10-28 12:46:30 +00:00
use Hateoas\Representation\Factory\PagerfantaFactory ;
2022-11-06 12:00:41 +00:00
use Nelmio\ApiDocBundle\Annotation\Operation ;
2022-12-23 13:40:42 +00:00
use OpenApi\Annotations as OA ;
2022-08-28 14:59:43 +00:00
use Pagerfanta\Pagerfanta ;
2022-12-19 09:37:22 +00:00
use Psr\Log\LoggerInterface ;
2022-08-28 00:01:46 +00:00
use Symfony\Component\EventDispatcher\EventDispatcherInterface ;
2016-10-28 12:46:30 +00:00
use Symfony\Component\HttpFoundation\JsonResponse ;
2017-07-01 07:52:38 +00:00
use Symfony\Component\HttpFoundation\Request ;
2017-07-29 20:51:50 +00:00
use Symfony\Component\HttpFoundation\Response ;
2019-01-14 16:01:21 +00:00
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException ;
2017-07-01 07:52:38 +00:00
use Symfony\Component\HttpKernel\Exception\HttpException ;
2022-11-23 11:44:55 +00:00
use Symfony\Component\Routing\Annotation\Route ;
2024-02-19 00:30:12 +00:00
use Wallabag\Entity\Entry ;
use Wallabag\Entity\Tag ;
use Wallabag\Event\EntryDeletedEvent ;
use Wallabag\Event\EntrySavedEvent ;
use Wallabag\Helper\ContentProxy ;
use Wallabag\Helper\EntriesExport ;
use Wallabag\Helper\TagsAssigner ;
use Wallabag\Helper\UrlHasher ;
use Wallabag\Repository\EntryRepository ;
use Wallabag\Repository\TagRepository ;
2016-10-28 12:46:30 +00:00
class EntryRestController extends WallabagRestController
{
/**
* Check if an entry exist by url .
2017-06-23 06:30:23 +00:00
* Return ID if entry ( ies ) exist ( and if you give the return_id parameter ) .
* Otherwise it returns false .
2016-10-28 12:46:30 +00:00
*
2017-06-28 06:15:06 +00:00
* @ todo Remove that `return_id` in the next major release
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Check if an entry exist by url. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " return_id " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Set 1 if you want to retrieve ID in case entry(ies) exists, 0 by default " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " url " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " DEPRECATED, use hashed_url instead. An url " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " urls " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " DEPRECATED, use hashed_urls instead. An array of urls (?urls[]=http...&urls[]=http...) " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " hashed_url " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Hashed url using SHA1 to check if it exists. A hashed url " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " hashed_urls " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " An array of hashed urls using SHA1 to check if they exist. An array of hashed urls (?hashed_urls[]=xxx...&hashed_urls[]=xxx...) " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-10-28 12:46:30 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/exists. { _format} " , methods = { " GET " }, name = " api_get_entries_exists " , defaults = { " _format " : " json " })
*
2016-10-28 12:46:30 +00:00
* @ return JsonResponse
*/
2022-12-19 09:37:22 +00:00
public function getEntriesExistsAction ( Request $request , EntryRepository $entryRepository )
2016-10-28 12:46:30 +00:00
{
$this -> validateAuthentication ();
2017-06-28 07:18:22 +00:00
$returnId = ( null === $request -> query -> get ( 'return_id' )) ? false : ( bool ) $request -> query -> get ( 'return_id' );
2016-10-28 12:46:30 +00:00
2024-01-01 18:51:22 +00:00
$hashedUrls = $request -> query -> all ( 'hashed_urls' );
2019-05-02 11:19:20 +00:00
$hashedUrl = $request -> query -> get ( 'hashed_url' , '' );
if ( ! empty ( $hashedUrl )) {
$hashedUrls [] = $hashedUrl ;
}
2017-05-28 12:53:04 +00:00
2024-01-01 18:51:22 +00:00
$urls = $request -> query -> all ( 'urls' );
2019-05-02 11:19:20 +00:00
$url = $request -> query -> get ( 'url' , '' );
if ( ! empty ( $url )) {
$urls [] = $url ;
}
2016-10-28 12:46:30 +00:00
2019-05-02 11:19:20 +00:00
$urlHashMap = [];
2019-05-10 12:07:55 +00:00
foreach ( $urls as $urlToHash ) {
$urlHash = UrlHasher :: hashUrl ( $urlToHash );
2019-05-02 11:19:20 +00:00
$hashedUrls [] = $urlHash ;
$urlHashMap [ $urlHash ] = $urlToHash ;
2016-10-28 12:46:30 +00:00
}
2019-05-02 11:19:20 +00:00
if ( empty ( $hashedUrls )) {
throw $this -> createAccessDeniedException ( 'URL is empty?, logged user id: ' . $this -> getUser () -> getId ());
}
2019-04-01 09:50:33 +00:00
2021-04-28 22:19:37 +00:00
$results = array_fill_keys ( $hashedUrls , null );
2022-12-19 09:37:22 +00:00
$res = $entryRepository -> findByUserIdAndBatchHashedUrls ( $this -> getUser () -> getId (), $hashedUrls );
2021-04-28 22:19:37 +00:00
foreach ( $res as $e ) {
$_hashedUrl = array_keys ( $hashedUrls , 'blah' , true );
if ([] !== array_keys ( $hashedUrls , $e [ 'hashedUrl' ], true )) {
$_hashedUrl = $e [ 'hashedUrl' ];
} elseif ([] !== array_keys ( $hashedUrls , $e [ 'hashedGivenUrl' ], true )) {
$_hashedUrl = $e [ 'hashedGivenUrl' ];
} else {
continue ;
}
$results [ $_hashedUrl ] = $e [ 'id' ];
}
2019-04-01 09:50:33 +00:00
2021-04-28 22:19:37 +00:00
if ( false === $returnId ) {
$results = array_map ( function ( $v ) {
return null !== $v ;
}, $results );
2019-04-01 09:50:33 +00:00
}
2019-05-02 11:19:20 +00:00
$results = $this -> replaceUrlHashes ( $results , $urlHashMap );
2017-05-28 12:53:04 +00:00
2019-05-02 11:19:20 +00:00
if ( ! empty ( $url ) || ! empty ( $hashedUrl )) {
$hu = array_keys ( $results )[ 0 ];
2016-10-28 12:46:30 +00:00
2019-05-02 11:19:20 +00:00
return $this -> sendResponse ([ 'exists' => $results [ $hu ]]);
2016-10-28 12:46:30 +00:00
}
2019-05-10 12:07:55 +00:00
return $this -> sendResponse ( $results );
2016-10-28 12:46:30 +00:00
}
/**
* Retrieve all entries . It could be filtered by many options .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Retrieve all entries. It could be filtered by many options. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " archive " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " filter by archived status. all entries by default. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " starred " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " filter by starred status. all entries by default " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2023-07-28 12:58:43 +00:00
* name = " notParsed " ,
* in = " query " ,
* description = " filter by notParsed status. all entries by default " ,
* required = false ,
* @ OA\Schema (
* type = " integer " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " sort " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " sort entries by date. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* enum = { " created " , " updated " , " archived " },
* default = " created "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " order " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " order of sort. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* enum = { " asc " , " desc " },
* default = " desc "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " page " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " what page you want. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* default = 1
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " perPage " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " results per page. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* default = 30
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " tags " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
* description = " a comma-seperated list of tags url encoded. Will returns entries that matches ALL tags. " ,
2022-11-06 12:00:41 +00:00
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* example = " api,rest "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " since " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " The timestamp since when you want entries updated. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* default = 0
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " public " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " filter by entries with a public link. all entries by default " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " detail " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " include content field if 'full'. 'full' by default for backward compatibility. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* enum = { " metadata " , " full " },
* default = " full "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " domain_name " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " filter entries with the given domain name " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* example = " example.com " ,
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-10-28 12:46:30 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries. { _format} " , methods = { " GET " }, name = " api_get_entries " , defaults = { " _format " : " json " })
*
2016-10-28 12:46:30 +00:00
* @ return JsonResponse
*/
2022-12-19 09:37:22 +00:00
public function getEntriesAction ( Request $request , EntryRepository $entryRepository )
2016-10-28 12:46:30 +00:00
{
$this -> validateAuthentication ();
$isArchived = ( null === $request -> query -> get ( 'archive' )) ? null : ( bool ) $request -> query -> get ( 'archive' );
$isStarred = ( null === $request -> query -> get ( 'starred' )) ? null : ( bool ) $request -> query -> get ( 'starred' );
2017-06-10 13:31:57 +00:00
$isPublic = ( null === $request -> query -> get ( 'public' )) ? null : ( bool ) $request -> query -> get ( 'public' );
2023-07-28 12:58:43 +00:00
$isNotParsed = ( null === $request -> query -> get ( 'notParsed' )) ? null : ( bool ) $request -> query -> get ( 'notParsed' );
2019-01-14 16:01:21 +00:00
$sort = strtolower ( $request -> query -> get ( 'sort' , 'created' ));
$order = strtolower ( $request -> query -> get ( 'order' , 'desc' ));
2016-10-28 12:46:30 +00:00
$page = ( int ) $request -> query -> get ( 'page' , 1 );
$perPage = ( int ) $request -> query -> get ( 'perPage' , 30 );
2018-09-05 12:25:32 +00:00
$tags = \is_array ( $request -> query -> get ( 'tags' )) ? '' : ( string ) $request -> query -> get ( 'tags' , '' );
2016-10-28 12:46:30 +00:00
$since = $request -> query -> get ( 'since' , 0 );
2019-05-11 22:00:00 +00:00
$detail = strtolower ( $request -> query -> get ( 'detail' , 'full' ));
2022-10-16 15:35:23 +00:00
$domainName = ( null === $request -> query -> get ( 'domain_name' )) ? '' : ( string ) $request -> query -> get ( 'domain_name' );
2016-10-28 12:46:30 +00:00
2019-01-14 16:01:21 +00:00
try {
2022-08-28 14:59:43 +00:00
/** @var Pagerfanta $pager */
2022-12-19 09:37:22 +00:00
$pager = $entryRepository -> findEntries (
2019-01-14 16:01:21 +00:00
$this -> getUser () -> getId (),
$isArchived ,
$isStarred ,
$isPublic ,
$sort ,
$order ,
$since ,
2019-05-11 22:00:00 +00:00
$tags ,
2022-10-16 15:35:23 +00:00
$detail ,
2023-07-28 12:58:43 +00:00
$domainName ,
$isNotParsed
2019-01-14 16:01:21 +00:00
);
} catch ( \Exception $e ) {
throw new BadRequestHttpException ( $e -> getMessage ());
}
2016-10-28 12:46:30 +00:00
$pager -> setMaxPerPage ( $perPage );
2017-05-08 14:27:16 +00:00
$pager -> setCurrentPage ( $page );
2016-10-28 12:46:30 +00:00
$pagerfantaFactory = new PagerfantaFactory ( 'page' , 'perPage' );
$paginatedCollection = $pagerfantaFactory -> createRepresentation (
$pager ,
2022-11-23 11:44:55 +00:00
new HateoasRoute (
2016-10-28 12:46:30 +00:00
'api_get_entries' ,
[
'archive' => $isArchived ,
'starred' => $isStarred ,
2017-06-10 13:31:57 +00:00
'public' => $isPublic ,
2023-07-28 12:58:43 +00:00
'notParsed' => $isNotParsed ,
2016-10-28 12:46:30 +00:00
'sort' => $sort ,
'order' => $order ,
'page' => $page ,
'perPage' => $perPage ,
'tags' => $tags ,
'since' => $since ,
2019-05-11 22:00:00 +00:00
'detail' => $detail ,
2016-10-28 12:46:30 +00:00
],
2018-10-24 18:29:33 +00:00
true
2016-10-28 12:46:30 +00:00
)
);
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $paginatedCollection );
2016-10-28 12:46:30 +00:00
}
/**
* Retrieve a single entry .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Retrieve a single entry. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " entry " ,
* in = " path " ,
* description = " The entry ID " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
* type = " integer " ,
* pattern = " \ w+ " ,
* )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-10-28 12:46:30 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/ { entry}. { _format} " , methods = { " GET " }, name = " api_get_entry " , defaults = { " _format " : " json " })
*
2016-10-28 12:46:30 +00:00
* @ return JsonResponse
*/
public function getEntryAction ( Entry $entry )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $entry );
2016-10-28 12:46:30 +00:00
}
2016-11-03 16:29:16 +00:00
/**
* Retrieve a single entry as a predefined format .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Retrieve a single entry as a predefined format. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " entry " ,
* in = " path " ,
* description = " The entry ID " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
* type = " integer " ,
* pattern = " \ w+ " ,
* )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " _format " ,
* in = " path " ,
* description = " " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
* type = " string " ,
2023-08-23 06:44:40 +00:00
* enum = { " xml " , " json " , " txt " , " csv " , " pdf " , " epub " },
2022-12-23 13:40:42 +00:00
* )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-11-03 16:29:16 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/ { entry}/export. { _format} " , methods = { " GET " }, name = " api_get_entry_export " , defaults = { " _format " : " json " })
*
2016-11-03 16:29:16 +00:00
* @ return Response
*/
2022-12-19 09:37:22 +00:00
public function getEntryExportAction ( Entry $entry , Request $request , EntriesExport $entriesExport )
2016-11-03 16:29:16 +00:00
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
2022-12-19 09:37:22 +00:00
return $entriesExport
2016-11-03 16:29:16 +00:00
-> setEntries ( $entry )
-> updateTitle ( 'entry' )
2017-07-08 15:55:58 +00:00
-> updateAuthor ( 'entry' )
2016-11-03 16:29:16 +00:00
-> exportAs ( $request -> attributes -> get ( '_format' ));
}
2017-04-24 08:22:57 +00:00
/**
2017-04-24 09:31:00 +00:00
* Handles an entries list and delete URL .
2017-04-24 08:22:57 +00:00
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Handles an entries list and delete URL. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " urls " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Urls (as an array) to delete. A JSON array of urls [ { 'url': 'http://...'}, { 'url': 'http://...'}] " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2017-04-24 08:22:57 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/list. { _format} " , methods = { " DELETE " }, name = " api_delete_entries_list " , defaults = { " _format " : " json " })
*
2017-04-24 08:22:57 +00:00
* @ return JsonResponse
*/
2022-12-19 09:37:22 +00:00
public function deleteEntriesListAction ( Request $request , EntryRepository $entryRepository , EventDispatcherInterface $eventDispatcher )
2017-04-24 08:22:57 +00:00
{
$this -> validateAuthentication ();
2017-04-24 09:31:00 +00:00
$urls = json_decode ( $request -> query -> get ( 'urls' , []));
2017-05-05 10:05:50 +00:00
if ( empty ( $urls )) {
return $this -> sendResponse ([]);
}
2017-04-24 08:22:57 +00:00
$results = [];
// handle multiple urls
2017-05-05 10:05:50 +00:00
foreach ( $urls as $key => $url ) {
2022-12-19 09:37:22 +00:00
$entry = $entryRepository -> findByUrlAndUserId (
2017-05-05 10:05:50 +00:00
$url ,
$this -> getUser () -> getId ()
);
2017-04-24 09:31:00 +00:00
2017-05-05 10:05:50 +00:00
$results [ $key ][ 'url' ] = $url ;
2017-04-24 09:31:00 +00:00
2017-05-05 10:05:50 +00:00
if ( false !== $entry ) {
2020-04-06 14:11:05 +00:00
// entry deleted, dispatch event about it!
2022-12-19 09:37:22 +00:00
$eventDispatcher -> dispatch ( new EntryDeletedEvent ( $entry ), EntryDeletedEvent :: NAME );
2020-04-06 14:11:05 +00:00
2022-12-19 09:37:22 +00:00
$this -> entityManager -> remove ( $entry );
$this -> entityManager -> flush ();
2017-04-24 09:31:00 +00:00
}
2017-04-24 08:22:57 +00:00
2017-05-05 10:05:50 +00:00
$results [ $key ][ 'entry' ] = $entry instanceof Entry ? true : false ;
}
2017-04-24 08:22:57 +00:00
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $results );
2017-04-24 09:31:00 +00:00
}
2017-04-24 08:22:57 +00:00
2017-04-24 09:31:00 +00:00
/**
* Handles an entries list and create URL .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Handles an entries list and create URL. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " urls " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Urls (as an array) to create. A JSON array of urls [ { 'url': 'http://...'}, { 'url': 'http://...'}] " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2017-04-24 09:31:00 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/lists. { _format} " , methods = { " POST " }, name = " api_post_entries_list " , defaults = { " _format " : " json " })
*
2017-05-05 10:05:50 +00:00
* @ throws HttpException When limit is reached
2017-07-01 07:52:38 +00:00
*
* @ return JsonResponse
2017-04-24 09:31:00 +00:00
*/
2022-12-19 09:37:22 +00:00
public function postEntriesListAction ( Request $request , EntryRepository $entryRepository , EventDispatcherInterface $eventDispatcher , ContentProxy $contentProxy )
2017-04-24 09:31:00 +00:00
{
$this -> validateAuthentication ();
2017-04-24 08:22:57 +00:00
2017-04-24 09:31:00 +00:00
$urls = json_decode ( $request -> query -> get ( 'urls' , []));
2017-04-24 08:22:57 +00:00
2024-02-19 23:47:53 +00:00
$limit = $this -> getParameter ( 'wallabag.api_limit_mass_actions' );
2017-05-01 07:21:59 +00:00
2018-09-05 12:25:32 +00:00
if ( \count ( $urls ) > $limit ) {
2024-02-24 01:34:46 +00:00
throw new BadRequestHttpException ( 'API limit reached' );
2017-05-01 07:21:59 +00:00
}
2017-05-30 15:48:24 +00:00
$results = [];
if ( empty ( $urls )) {
return $this -> sendResponse ( $results );
}
2017-04-24 09:31:00 +00:00
// handle multiple urls
2017-05-30 15:48:24 +00:00
foreach ( $urls as $key => $url ) {
2022-12-19 09:37:22 +00:00
$entry = $entryRepository -> findByUrlAndUserId (
2017-05-30 15:48:24 +00:00
$url ,
$this -> getUser () -> getId ()
);
2017-04-24 08:22:57 +00:00
2017-05-30 15:48:24 +00:00
$results [ $key ][ 'url' ] = $url ;
2017-04-24 08:22:57 +00:00
2017-05-30 15:48:24 +00:00
if ( false === $entry ) {
$entry = new Entry ( $this -> getUser ());
2017-04-24 09:31:00 +00:00
2022-12-19 09:37:22 +00:00
$contentProxy -> updateEntry ( $entry , $url );
2017-05-30 15:48:24 +00:00
}
2017-04-24 09:31:00 +00:00
2022-12-19 09:37:22 +00:00
$this -> entityManager -> persist ( $entry );
$this -> entityManager -> flush ();
2017-04-24 09:31:00 +00:00
2017-05-30 15:48:24 +00:00
$results [ $key ][ 'entry' ] = $entry instanceof Entry ? $entry -> getId () : false ;
// entry saved, dispatch event about it!
2022-12-19 09:37:22 +00:00
$eventDispatcher -> dispatch ( new EntrySavedEvent ( $entry ), EntrySavedEvent :: NAME );
2017-04-24 08:22:57 +00:00
}
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $results );
2017-04-24 08:22:57 +00:00
}
2016-10-28 12:46:30 +00:00
/**
* Create an entry .
*
2017-05-24 14:02:49 +00:00
* If you want to provide the HTML content ( which means wallabag won ' t fetch it from the url ), you must provide `content` , `title` & `url` fields ** non - empty **.
* Otherwise , content will be fetched as normal from the url and values will be overwritten .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Create an entry. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " url " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Url for the entry. " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* example = " http://www.test.com/article.html "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " title " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Optional, we'll get the title from the page. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " tags " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " a comma-separated list of tags. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* example = " tag1,tag2,tag3 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " archive " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " entry already archived " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " starred " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " entry already starred " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " content " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Content of the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " language " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Language of the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " preview_picture " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Preview picture of the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " published_at " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Published date of the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
*
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
2022-12-23 13:40:42 +00:00
* format = " YYYY-MM-DDTHH:II:SS+TZ or a timestamp (integer) " ,
2022-11-06 12:00:41 +00:00
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " authors " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Authors of the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* example = " Name Firstname,author2,author3 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " public " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " will generate a public link for the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " origin_url " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Origin url for the entry (from where you found it). " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* example = " http://www.test.com/article.html "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-10-28 12:46:30 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries. { _format} " , methods = { " POST " }, name = " api_post_entries " , defaults = { " _format " : " json " })
*
2016-10-28 12:46:30 +00:00
* @ return JsonResponse
*/
2022-12-19 09:37:22 +00:00
public function postEntriesAction ( Request $request , EntryRepository $entryRepository , ContentProxy $contentProxy , LoggerInterface $logger , TagsAssigner $tagsAssigner , EventDispatcherInterface $eventDispatcher )
2016-10-28 12:46:30 +00:00
{
$this -> validateAuthentication ();
$url = $request -> request -> get ( 'url' );
2022-12-19 09:37:22 +00:00
$entry = $entryRepository -> findByUrlAndUserId (
2017-06-07 13:07:55 +00:00
$url ,
$this -> getUser () -> getId ()
);
2016-10-28 12:46:30 +00:00
if ( false === $entry ) {
2017-05-08 10:35:02 +00:00
$entry = new Entry ( $this -> getUser ());
2017-05-11 06:14:29 +00:00
$entry -> setUrl ( $url );
2016-10-28 12:46:30 +00:00
}
2017-06-30 14:54:26 +00:00
$data = $this -> retrieveValueFromRequest ( $request );
try {
2022-12-19 09:37:22 +00:00
$contentProxy -> updateEntry (
2017-06-30 14:54:26 +00:00
$entry ,
$entry -> getUrl (),
[
'title' => ! empty ( $data [ 'title' ]) ? $data [ 'title' ] : $entry -> getTitle (),
'html' => ! empty ( $data [ 'content' ]) ? $data [ 'content' ] : $entry -> getContent (),
'url' => $entry -> getUrl (),
'language' => ! empty ( $data [ 'language' ]) ? $data [ 'language' ] : $entry -> getLanguage (),
'date' => ! empty ( $data [ 'publishedAt' ]) ? $data [ 'publishedAt' ] : $entry -> getPublishedAt (),
// faking the open graph preview picture
2017-11-11 19:04:15 +00:00
'image' => ! empty ( $data [ 'picture' ]) ? $data [ 'picture' ] : $entry -> getPreviewPicture (),
2018-09-05 12:25:32 +00:00
'authors' => \is_string ( $data [ 'authors' ]) ? explode ( ',' , $data [ 'authors' ]) : $entry -> getPublishedBy (),
2017-06-30 14:54:26 +00:00
]
);
} catch ( \Exception $e ) {
2022-12-19 09:37:22 +00:00
$logger -> error ( 'Error while saving an entry' , [
'exception' => $e ,
'entry' => $entry ,
]);
2017-06-30 14:54:26 +00:00
}
2017-07-03 11:56:39 +00:00
if ( null !== $data [ 'isArchived' ]) {
2018-04-11 09:42:52 +00:00
$entry -> updateArchived (( bool ) $data [ 'isArchived' ]);
2017-06-30 14:54:26 +00:00
}
2017-07-03 11:56:39 +00:00
if ( null !== $data [ 'isStarred' ]) {
2017-08-23 21:06:40 +00:00
$entry -> updateStar (( bool ) $data [ 'isStarred' ]);
2017-06-30 14:54:26 +00:00
}
if ( ! empty ( $data [ 'tags' ])) {
2022-12-19 09:37:22 +00:00
$tagsAssigner -> assignTagsToEntry ( $entry , $data [ 'tags' ]);
2017-06-30 14:54:26 +00:00
}
2017-09-04 21:39:08 +00:00
if ( ! empty ( $data [ 'origin_url' ])) {
$entry -> setOriginUrl ( $data [ 'origin_url' ]);
}
2017-07-03 11:56:39 +00:00
if ( null !== $data [ 'isPublic' ]) {
2017-06-30 14:54:26 +00:00
if ( true === ( bool ) $data [ 'isPublic' ] && null === $entry -> getUid ()) {
$entry -> generateUid ();
} elseif ( false === ( bool ) $data [ 'isPublic' ]) {
$entry -> cleanUid ();
}
}
2017-11-26 22:20:23 +00:00
if ( empty ( $entry -> getDomainName ())) {
2022-12-19 09:37:22 +00:00
$contentProxy -> setEntryDomainName ( $entry );
2017-11-26 22:20:23 +00:00
}
if ( empty ( $entry -> getTitle ())) {
2022-12-19 09:37:22 +00:00
$contentProxy -> setDefaultEntryTitle ( $entry );
2017-11-26 22:20:23 +00:00
}
2022-12-19 09:37:22 +00:00
$this -> entityManager -> persist ( $entry );
$this -> entityManager -> flush ();
2017-06-30 14:54:26 +00:00
// entry saved, dispatch event about it!
2022-12-19 09:37:22 +00:00
$eventDispatcher -> dispatch ( new EntrySavedEvent ( $entry ), EntrySavedEvent :: NAME );
2016-11-03 15:41:29 +00:00
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $entry );
2016-10-28 12:46:30 +00:00
}
/**
* Change several properties of an entry .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Change several properties of an entry. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " entry " ,
* in = " path " ,
* description = " The entry ID " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
* type = " integer " ,
* pattern = " \ w+ " ,
* )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " title " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " tags " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " a comma-separated list of tags. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* example = " tag1,tag2,tag3 " ,
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " archive " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " archived the entry. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " starred " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " starred the entry. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " content " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Content of the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " language " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Language of the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " preview_picture " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Preview picture of the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " published_at " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Published date of the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
* type = " datetime|integer " ,
* format = " YYYY-MM-DDTHH:II:SS+TZ or a timestamp " ,
* )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " authors " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Authors of the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* example = " Name Firstname,author2,author3 " ,
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " public " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " will generate a public link for the entry " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " integer " ,
* enum = { " 1 " , " 0 " },
* default = " 0 "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " origin_url " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Origin url for the entry (from where you found it). " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* example = " http://www.test.com/article.html " ,
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-10-28 12:46:30 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/ { entry}. { _format} " , methods = { " PATCH " }, name = " api_patch_entries " , defaults = { " _format " : " json " })
*
2016-10-28 12:46:30 +00:00
* @ return JsonResponse
*/
2022-12-19 09:37:22 +00:00
public function patchEntriesAction ( Entry $entry , Request $request , ContentProxy $contentProxy , LoggerInterface $logger , TagsAssigner $tagsAssigner , EventDispatcherInterface $eventDispatcher )
2016-10-28 12:46:30 +00:00
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
2017-06-30 14:54:26 +00:00
$data = $this -> retrieveValueFromRequest ( $request );
// this is a special case where user want to manually update the entry content
// the ContentProxy will only cleanup the html
// and also we force to not re-fetch the content in case of error
if ( ! empty ( $data [ 'content' ])) {
try {
$contentProxy -> updateEntry (
$entry ,
$entry -> getUrl (),
[
'html' => $data [ 'content' ],
],
true
);
} catch ( \Exception $e ) {
2022-12-19 09:37:22 +00:00
$logger -> error ( 'Error while saving an entry' , [
'exception' => $e ,
'entry' => $entry ,
]);
2017-06-30 14:54:26 +00:00
}
}
if ( ! empty ( $data [ 'title' ])) {
$entry -> setTitle ( $data [ 'title' ]);
}
if ( ! empty ( $data [ 'language' ])) {
$contentProxy -> updateLanguage ( $entry , $data [ 'language' ]);
}
2018-09-05 12:25:32 +00:00
if ( ! empty ( $data [ 'authors' ]) && \is_string ( $data [ 'authors' ])) {
2017-06-30 14:54:26 +00:00
$entry -> setPublishedBy ( explode ( ',' , $data [ 'authors' ]));
}
if ( ! empty ( $data [ 'picture' ])) {
$contentProxy -> updatePreviewPicture ( $entry , $data [ 'picture' ]);
}
if ( ! empty ( $data [ 'publishedAt' ])) {
$contentProxy -> updatePublishedAt ( $entry , $data [ 'publishedAt' ]);
}
2017-07-03 11:56:39 +00:00
if ( null !== $data [ 'isArchived' ]) {
2018-04-11 09:42:52 +00:00
$entry -> updateArchived (( bool ) $data [ 'isArchived' ]);
2017-06-30 14:54:26 +00:00
}
2017-07-03 11:56:39 +00:00
if ( null !== $data [ 'isStarred' ]) {
2017-08-23 21:06:40 +00:00
$entry -> updateStar (( bool ) $data [ 'isStarred' ]);
2017-06-30 14:54:26 +00:00
}
if ( ! empty ( $data [ 'tags' ])) {
$entry -> removeAllTags ();
2022-12-19 09:37:22 +00:00
$tagsAssigner -> assignTagsToEntry ( $entry , $data [ 'tags' ]);
2017-06-30 14:54:26 +00:00
}
2017-07-03 11:56:39 +00:00
if ( null !== $data [ 'isPublic' ]) {
2017-06-30 14:54:26 +00:00
if ( true === ( bool ) $data [ 'isPublic' ] && null === $entry -> getUid ()) {
$entry -> generateUid ();
} elseif ( false === ( bool ) $data [ 'isPublic' ]) {
$entry -> cleanUid ();
}
}
2017-09-04 21:39:08 +00:00
if ( ! empty ( $data [ 'origin_url' ])) {
$entry -> setOriginUrl ( $data [ 'origin_url' ]);
}
2017-11-26 22:20:23 +00:00
if ( empty ( $entry -> getDomainName ())) {
2022-12-19 09:37:22 +00:00
$contentProxy -> setEntryDomainName ( $entry );
2017-11-26 22:20:23 +00:00
}
if ( empty ( $entry -> getTitle ())) {
2022-12-19 09:37:22 +00:00
$contentProxy -> setDefaultEntryTitle ( $entry );
2017-11-26 22:20:23 +00:00
}
2022-12-19 09:37:22 +00:00
$this -> entityManager -> persist ( $entry );
$this -> entityManager -> flush ();
2017-06-30 14:54:26 +00:00
// entry saved, dispatch event about it!
2022-12-19 09:37:22 +00:00
$eventDispatcher -> dispatch ( new EntrySavedEvent ( $entry ), EntrySavedEvent :: NAME );
2016-10-28 12:46:30 +00:00
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $entry );
2016-10-28 12:46:30 +00:00
}
2016-11-20 12:08:41 +00:00
/**
* Reload an entry .
2016-11-22 09:45:17 +00:00
* An empty response with HTTP Status 304 will be send if we weren 't able to update the content (because it hasn' t changed or we got an error ) .
2016-11-20 12:08:41 +00:00
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Reload an entry. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " entry " ,
* in = " path " ,
* description = " The entry ID " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
* type = " integer " ,
* pattern = " \ w+ " ,
* )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-11-20 12:08:41 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/ { entry}/reload. { _format} " , methods = { " PATCH " }, name = " api_patch_entries_reload " , defaults = { " _format " : " json " })
*
2016-11-20 12:08:41 +00:00
* @ return JsonResponse
*/
2022-12-19 09:37:22 +00:00
public function patchEntriesReloadAction ( Entry $entry , ContentProxy $contentProxy , LoggerInterface $logger , EventDispatcherInterface $eventDispatcher )
2016-11-20 12:08:41 +00:00
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
try {
2022-12-19 09:37:22 +00:00
$contentProxy -> updateEntry ( $entry , $entry -> getUrl ());
2016-11-20 12:08:41 +00:00
} catch ( \Exception $e ) {
2022-12-19 09:37:22 +00:00
$logger -> error ( 'Error while saving an entry' , [
'exception' => $e ,
'entry' => $entry ,
]);
2016-11-20 12:08:41 +00:00
2016-11-22 09:45:17 +00:00
return new JsonResponse ([], 304 );
2016-11-20 12:08:41 +00:00
}
// if refreshing entry failed, don't save it
2024-02-19 23:47:53 +00:00
if ( $this -> getParameter ( 'wallabag.fetching_error_message' ) === $entry -> getContent ()) {
2016-11-22 09:45:17 +00:00
return new JsonResponse ([], 304 );
2016-11-20 12:08:41 +00:00
}
2022-12-19 09:37:22 +00:00
$this -> entityManager -> persist ( $entry );
$this -> entityManager -> flush ();
2016-11-20 12:08:41 +00:00
// entry saved, dispatch event about it!
2022-12-19 09:37:22 +00:00
$eventDispatcher -> dispatch ( new EntrySavedEvent ( $entry ), EntrySavedEvent :: NAME );
2016-11-20 12:08:41 +00:00
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $entry );
2016-11-20 12:08:41 +00:00
}
2016-10-28 12:46:30 +00:00
/**
* Delete ** permanently ** an entry .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Delete permanently an entry. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " expect " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Only returns the id instead of the deleted entry's full entity if 'id' is specified. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* enum = { " id " , " entry " },
* default = " entry "
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-10-28 12:46:30 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/ { entry}. { _format} " , methods = { " DELETE " }, name = " api_delete_entries " , defaults = { " _format " : " json " })
*
2016-10-28 12:46:30 +00:00
* @ return JsonResponse
*/
2022-12-19 09:37:22 +00:00
public function deleteEntriesAction ( Entry $entry , Request $request , EventDispatcherInterface $eventDispatcher )
2016-10-28 12:46:30 +00:00
{
2019-02-17 14:30:42 +00:00
$expect = $request -> query -> get ( 'expect' , 'entry' );
if ( ! \in_array ( $expect , [ 'id' , 'entry' ], true )) {
throw new BadRequestHttpException ( sprintf ( " expect: 'id' or 'entry' expected, %s given " , $expect ));
}
2016-10-28 12:46:30 +00:00
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
2019-02-17 14:30:42 +00:00
$response = $this -> sendResponse ([
'id' => $entry -> getId (),
]);
// We clone $entry to keep id in returned object
if ( 'entry' === $expect ) {
$e = clone $entry ;
$response = $this -> sendResponse ( $e );
}
2017-12-17 20:05:25 +00:00
2020-04-06 14:11:05 +00:00
// entry deleted, dispatch event about it!
2022-12-19 09:37:22 +00:00
$eventDispatcher -> dispatch ( new EntryDeletedEvent ( $entry ), EntryDeletedEvent :: NAME );
2020-04-06 14:11:05 +00:00
2022-12-19 09:37:22 +00:00
$this -> entityManager -> remove ( $entry );
$this -> entityManager -> flush ();
2016-10-28 12:46:30 +00:00
2019-02-17 14:30:42 +00:00
return $response ;
2016-10-28 12:46:30 +00:00
}
/**
* Retrieve all tags for an entry .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Retrieve all tags for an entry. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " entry " ,
* in = " path " ,
* description = " The entry ID " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
* type = " integer " ,
* pattern = " \ w+ " ,
* )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-10-28 12:46:30 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/ { entry}/tags. { _format} " , methods = { " GET " }, name = " api_get_entries_tags " , defaults = { " _format " : " json " })
*
2016-10-28 12:46:30 +00:00
* @ return JsonResponse
*/
public function getEntriesTagsAction ( Entry $entry )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $entry -> getTags ());
2016-10-28 12:46:30 +00:00
}
/**
* Add one or more tags to an entry .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Add one or more tags to an entry. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " entry " ,
* in = " path " ,
* description = " The entry ID " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
* type = " integer " ,
* pattern = " \ w+ " ,
* )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " tags " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " a comma-separated list of tags. " ,
* required = false ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
2022-11-06 12:00:41 +00:00
* type = " string " ,
* example = " tag1,tag2,tag3 " ,
* )
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-10-28 12:46:30 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/ { entry}/tags. { _format} " , methods = { " POST " }, name = " api_post_entries_tags " , defaults = { " _format " : " json " })
*
2016-10-28 12:46:30 +00:00
* @ return JsonResponse
*/
2022-12-19 09:37:22 +00:00
public function postEntriesTagsAction ( Request $request , Entry $entry , TagsAssigner $tagsAssigner )
2016-10-28 12:46:30 +00:00
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
$tags = $request -> request -> get ( 'tags' , '' );
if ( ! empty ( $tags )) {
2022-12-19 09:37:22 +00:00
$tagsAssigner -> assignTagsToEntry ( $entry , $tags );
2016-10-28 12:46:30 +00:00
}
2022-12-19 09:37:22 +00:00
$this -> entityManager -> persist ( $entry );
$this -> entityManager -> flush ();
2016-10-28 12:46:30 +00:00
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $entry );
2016-10-28 12:46:30 +00:00
}
/**
* Permanently remove one tag for an entry .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Permanently remove one tag for an entry. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " entry " ,
* in = " path " ,
* description = " The entry ID " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
* type = " integer " ,
* pattern = " \ w+ " ,
* )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " tag " ,
* in = " path " ,
* description = " The tag ID " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema (
* type = " integer " ,
* pattern = " \ w+ " ,
* )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2016-10-28 12:46:30 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/ { entry}/tags/ { tag}. { _format} " , methods = { " DELETE " }, name = " api_delete_entries_tags " , defaults = { " _format " : " json " })
*
2016-10-28 12:46:30 +00:00
* @ return JsonResponse
*/
public function deleteEntriesTagsAction ( Entry $entry , Tag $tag )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
$entry -> removeTag ( $tag );
2022-12-19 09:37:22 +00:00
$this -> entityManager -> persist ( $entry );
$this -> entityManager -> flush ();
2016-10-28 12:46:30 +00:00
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $entry );
2016-10-28 12:46:30 +00:00
}
2017-04-24 09:12:41 +00:00
/**
2017-04-24 10:24:17 +00:00
* Handles an entries list delete tags from them .
2017-04-24 09:12:41 +00:00
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Handles an entries list delete tags from them. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " list " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Urls (as an array) to handle. A JSON array of urls [ { 'url': 'http://...','tags': 'tag1, tag2'}, { 'url': 'http://...','tags': 'tag1, tag2'}] " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2017-04-24 09:12:41 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/tags/list. { _format} " , methods = { " DELETE " }, name = " api_delete_entries_tags_list " , defaults = { " _format " : " json " })
*
2017-04-24 09:12:41 +00:00
* @ return JsonResponse
*/
2022-12-19 09:37:22 +00:00
public function deleteEntriesTagsListAction ( Request $request , TagRepository $tagRepository , EntryRepository $entryRepository )
2017-04-24 09:12:41 +00:00
{
$this -> validateAuthentication ();
$list = json_decode ( $request -> query -> get ( 'list' , []));
2017-05-05 10:05:50 +00:00
if ( empty ( $list )) {
return $this -> sendResponse ([]);
}
2017-04-24 09:12:41 +00:00
// handle multiple urls
2017-05-05 10:05:50 +00:00
$results = [];
2017-04-24 09:12:41 +00:00
2017-05-05 10:05:50 +00:00
foreach ( $list as $key => $element ) {
2022-12-19 09:37:22 +00:00
$entry = $entryRepository -> findByUrlAndUserId (
2017-05-05 10:05:50 +00:00
$element -> url ,
$this -> getUser () -> getId ()
);
2017-04-24 09:12:41 +00:00
2017-05-05 10:05:50 +00:00
$results [ $key ][ 'url' ] = $element -> url ;
$results [ $key ][ 'entry' ] = $entry instanceof Entry ? $entry -> getId () : false ;
2017-04-24 09:12:41 +00:00
2017-05-05 10:05:50 +00:00
$tags = $element -> tags ;
2017-04-24 10:24:17 +00:00
2017-05-05 10:05:50 +00:00
if ( false !== $entry && ! ( empty ( $tags ))) {
$tags = explode ( ',' , $tags );
foreach ( $tags as $label ) {
$label = trim ( $label );
2017-04-24 10:24:17 +00:00
2022-12-19 09:37:22 +00:00
$tag = $tagRepository -> findOneByLabel ( $label );
2017-04-24 09:12:41 +00:00
2017-05-05 10:05:50 +00:00
if ( false !== $tag ) {
$entry -> removeTag ( $tag );
}
2017-04-24 09:12:41 +00:00
}
2017-05-05 10:05:50 +00:00
2022-12-19 09:37:22 +00:00
$this -> entityManager -> persist ( $entry );
$this -> entityManager -> flush ();
2017-04-24 09:12:41 +00:00
}
}
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $results );
2017-04-24 09:12:41 +00:00
}
2017-04-24 10:24:17 +00:00
/**
* Handles an entries list and add tags to them .
*
2022-11-06 12:00:41 +00:00
* @ Operation (
* tags = { " Entries " },
* summary = " Handles an entries list and add tags to them. " ,
2022-12-23 13:40:42 +00:00
* @ OA\Parameter (
2022-11-06 12:00:41 +00:00
* name = " list " ,
2022-12-23 13:40:42 +00:00
* in = " query " ,
2022-11-06 12:00:41 +00:00
* description = " Urls (as an array) to handle. A JSON array of urls [ { 'url': 'http://...','tags': 'tag1, tag2'}, { 'url': 'http://...','tags': 'tag1, tag2'}] " ,
* required = true ,
2022-12-23 13:40:42 +00:00
* @ OA\Schema ( type = " string " )
2022-11-06 12:00:41 +00:00
* ),
2022-12-23 13:40:42 +00:00
* @ OA\Response (
2022-11-06 12:00:41 +00:00
* response = " 200 " ,
* description = " Returned when successful "
* )
2017-04-24 10:24:17 +00:00
* )
*
2022-11-23 11:44:55 +00:00
* @ Route ( " /api/entries/tags/lists. { _format} " , methods = { " POST " }, name = " api_post_entries_tags_list " , defaults = { " _format " : " json " })
*
2017-04-24 10:24:17 +00:00
* @ return JsonResponse
*/
2022-12-19 09:37:22 +00:00
public function postEntriesTagsListAction ( Request $request , EntryRepository $entryRepository , TagsAssigner $tagsAssigner )
2017-04-24 10:24:17 +00:00
{
$this -> validateAuthentication ();
$list = json_decode ( $request -> query -> get ( 'list' , []));
2017-05-05 10:05:50 +00:00
if ( empty ( $list )) {
return $this -> sendResponse ([]);
}
2017-04-24 10:24:17 +00:00
$results = [];
// handle multiple urls
2017-05-05 10:05:50 +00:00
foreach ( $list as $key => $element ) {
2022-12-19 09:37:22 +00:00
$entry = $entryRepository -> findByUrlAndUserId (
2017-05-05 10:05:50 +00:00
$element -> url ,
$this -> getUser () -> getId ()
);
2017-04-24 10:24:17 +00:00
2017-05-05 10:05:50 +00:00
$results [ $key ][ 'url' ] = $element -> url ;
$results [ $key ][ 'entry' ] = $entry instanceof Entry ? $entry -> getId () : false ;
2017-04-24 10:24:17 +00:00
2017-05-05 10:05:50 +00:00
$tags = $element -> tags ;
2017-04-24 10:24:17 +00:00
2017-05-05 10:05:50 +00:00
if ( false !== $entry && ! ( empty ( $tags ))) {
2022-12-19 09:37:22 +00:00
$tagsAssigner -> assignTagsToEntry ( $entry , $tags );
2017-04-24 10:24:17 +00:00
2022-12-19 09:37:22 +00:00
$this -> entityManager -> persist ( $entry );
$this -> entityManager -> flush ();
2017-04-24 10:24:17 +00:00
}
}
2017-05-05 10:05:50 +00:00
return $this -> sendResponse ( $results );
}
2019-05-10 12:07:55 +00:00
/**
* Replace the hashedUrl keys in $results with the unhashed URL from the
* request , as recorded in $urlHashMap .
*/
private function replaceUrlHashes ( array $results , array $urlHashMap )
{
$newResults = [];
foreach ( $results as $hash => $res ) {
if ( isset ( $urlHashMap [ $hash ])) {
$newResults [ $urlHashMap [ $hash ]] = $res ;
} else {
$newResults [ $hash ] = $res ;
}
}
return $newResults ;
}
2017-06-07 13:07:55 +00:00
/**
2017-06-30 14:54:26 +00:00
* Retrieve value from the request .
* Used for POST & PATCH on a an entry .
2017-06-07 13:07:55 +00:00
*
2017-06-30 14:54:26 +00:00
* @ return array
2017-06-07 13:07:55 +00:00
*/
2017-06-30 14:54:26 +00:00
private function retrieveValueFromRequest ( Request $request )
2017-06-07 13:07:55 +00:00
{
2017-06-30 14:54:26 +00:00
return [
'title' => $request -> request -> get ( 'title' ),
'tags' => $request -> request -> get ( 'tags' , []),
'isArchived' => $request -> request -> get ( 'archive' ),
'isStarred' => $request -> request -> get ( 'starred' ),
'isPublic' => $request -> request -> get ( 'public' ),
'content' => $request -> request -> get ( 'content' ),
'language' => $request -> request -> get ( 'language' ),
'picture' => $request -> request -> get ( 'preview_picture' ),
'publishedAt' => $request -> request -> get ( 'published_at' ),
'authors' => $request -> request -> get ( 'authors' , '' ),
2017-09-04 21:39:08 +00:00
'origin_url' => $request -> request -> get ( 'origin_url' , '' ),
2017-06-30 14:54:26 +00:00
];
2017-06-07 13:07:55 +00:00
}
2016-10-28 12:46:30 +00:00
}