2016-10-28 12:46:30 +00:00
< ? php
namespace Wallabag\ApiBundle\Controller ;
use Hateoas\Configuration\Route ;
use Hateoas\Representation\Factory\PagerfantaFactory ;
use Nelmio\ApiDocBundle\Annotation\ApiDoc ;
use Symfony\Component\HttpFoundation\Request ;
use Symfony\Component\HttpFoundation\JsonResponse ;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface ;
use Wallabag\CoreBundle\Entity\Entry ;
use Wallabag\CoreBundle\Entity\Tag ;
2016-11-03 15:41:29 +00:00
use Wallabag\CoreBundle\Event\EntrySavedEvent ;
use Wallabag\CoreBundle\Event\EntryDeletedEvent ;
2016-10-28 12:46:30 +00:00
class EntryRestController extends WallabagRestController
{
/**
* Check if an entry exist by url .
*
* @ ApiDoc (
* parameters = {
* { " name " = " url " , " dataType " = " string " , " required " = true , " format " = " An url " , " description " = " Url to check if it exists " },
* { " name " = " urls " , " dataType " = " string " , " required " = false , " format " = " An array of urls (?urls[]=http...&urls[]=http...) " , " description " = " Urls (as an array) to check if it exists " }
* }
* )
*
* @ return JsonResponse
*/
public function getEntriesExistsAction ( Request $request )
{
$this -> validateAuthentication ();
$urls = $request -> query -> get ( 'urls' , []);
// handle multiple urls first
if ( ! empty ( $urls )) {
$results = [];
foreach ( $urls as $url ) {
$res = $this -> getDoctrine ()
-> getRepository ( 'WallabagCoreBundle:Entry' )
-> findByUrlAndUserId ( $url , $this -> getUser () -> getId ());
2017-02-24 10:31:31 +00:00
$results [ $url ] = $res instanceof Entry ? $res -> getId () : false ;
2016-10-28 12:46:30 +00:00
}
$json = $this -> get ( 'serializer' ) -> serialize ( $results , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
// let's see if it is a simple url?
$url = $request -> query -> get ( 'url' , '' );
if ( empty ( $url )) {
throw $this -> createAccessDeniedException ( 'URL is empty?, logged user id: ' . $this -> getUser () -> getId ());
}
$res = $this -> getDoctrine ()
-> getRepository ( 'WallabagCoreBundle:Entry' )
-> findByUrlAndUserId ( $url , $this -> getUser () -> getId ());
2017-02-24 10:31:31 +00:00
$exists = $res instanceof Entry ? $res -> getId () : false ;
2016-10-28 12:46:30 +00:00
$json = $this -> get ( 'serializer' ) -> serialize ([ 'exists' => $exists ], 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
/**
* Retrieve all entries . It could be filtered by many options .
*
* @ ApiDoc (
* parameters = {
* { " name " = " archive " , " dataType " = " integer " , " required " = false , " format " = " 1 or 0, all entries by default " , " description " = " filter by archived status. " },
* { " name " = " starred " , " dataType " = " integer " , " required " = false , " format " = " 1 or 0, all entries by default " , " description " = " filter by starred status. " },
* { " name " = " sort " , " dataType " = " string " , " required " = false , " format " = " 'created' or 'updated', default 'created' " , " description " = " sort entries by date. " },
* { " name " = " order " , " dataType " = " string " , " required " = false , " format " = " 'asc' or 'desc', default 'desc' " , " description " = " order of sort. " },
* { " name " = " page " , " dataType " = " integer " , " required " = false , " format " = " default '1' " , " description " = " what page you want. " },
* { " name " = " perPage " , " dataType " = " integer " , " required " = false , " format " = " default'30' " , " description " = " results per page. " },
* { " name " = " tags " , " dataType " = " string " , " required " = false , " format " = " api,rest " , " description " = " a list of tags url encoded. Will returns entries that matches ALL tags. " },
* { " name " = " since " , " dataType " = " integer " , " required " = false , " format " = " default '0' " , " description " = " The timestamp since when you want entries updated. " },
* }
* )
*
* @ return JsonResponse
*/
public function getEntriesAction ( Request $request )
{
$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' );
$sort = $request -> query -> get ( 'sort' , 'created' );
$order = $request -> query -> get ( 'order' , 'desc' );
$page = ( int ) $request -> query -> get ( 'page' , 1 );
$perPage = ( int ) $request -> query -> get ( 'perPage' , 30 );
$tags = $request -> query -> get ( 'tags' , '' );
$since = $request -> query -> get ( 'since' , 0 );
$pager = $this -> getDoctrine ()
-> getRepository ( 'WallabagCoreBundle:Entry' )
-> findEntries ( $this -> getUser () -> getId (), $isArchived , $isStarred , $sort , $order , $since , $tags );
$pager -> setCurrentPage ( $page );
$pager -> setMaxPerPage ( $perPage );
$pagerfantaFactory = new PagerfantaFactory ( 'page' , 'perPage' );
$paginatedCollection = $pagerfantaFactory -> createRepresentation (
$pager ,
new Route (
'api_get_entries' ,
[
'archive' => $isArchived ,
'starred' => $isStarred ,
'sort' => $sort ,
'order' => $order ,
'page' => $page ,
'perPage' => $perPage ,
'tags' => $tags ,
'since' => $since ,
],
UrlGeneratorInterface :: ABSOLUTE_URL
)
);
$json = $this -> get ( 'serializer' ) -> serialize ( $paginatedCollection , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
/**
* Retrieve a single entry .
*
* @ ApiDoc (
* requirements = {
* { " name " = " entry " , " dataType " = " integer " , " requirement " = " \ w+ " , " description " = " The entry ID " }
* }
* )
*
* @ return JsonResponse
*/
public function getEntryAction ( Entry $entry )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
$json = $this -> get ( 'serializer' ) -> serialize ( $entry , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
2016-11-03 16:29:16 +00:00
/**
* Retrieve a single entry as a predefined format .
*
* @ ApiDoc (
* requirements = {
* { " name " = " entry " , " dataType " = " integer " , " requirement " = " \ w+ " , " description " = " The entry ID " }
* }
* )
*
* @ return Response
*/
public function getEntryExportAction ( Entry $entry , Request $request )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
return $this -> get ( 'wallabag_core.helper.entries_export' )
-> setEntries ( $entry )
-> updateTitle ( 'entry' )
-> 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
*
* @ ApiDoc (
* parameters = {
2017-04-24 09:31:00 +00:00
* { " name " = " urls " , " dataType " = " string " , " required " = true , " format " = " A JSON array of urls [ { 'url': 'http://...'}, { 'url': 'http://...'}] " , " description " = " Urls (as an array) to delete. " }
2017-04-24 08:22:57 +00:00
* }
* )
*
* @ return JsonResponse
*/
2017-04-24 09:31:00 +00:00
public function deleteEntriesListAction ( Request $request )
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-04-24 08:22:57 +00:00
$results = [];
// handle multiple urls
2017-04-24 09:31:00 +00:00
if ( ! empty ( $urls )) {
2017-04-24 08:22:57 +00:00
$results = [];
2017-04-24 09:31:00 +00:00
foreach ( $urls as $key => $url ) {
2017-04-24 08:22:57 +00:00
$entry = $this -> get ( 'wallabag_core.entry_repository' ) -> findByUrlAndUserId (
2017-04-24 09:31:00 +00:00
$url ,
2017-04-24 08:22:57 +00:00
$this -> getUser () -> getId ()
);
2017-04-24 09:31:00 +00:00
$results [ $key ][ 'url' ] = $url ;
if ( false !== $entry ) {
$em = $this -> getDoctrine () -> getManager ();
$em -> remove ( $entry );
$em -> flush ();
// entry deleted, dispatch event about it!
$this -> get ( 'event_dispatcher' ) -> dispatch ( EntryDeletedEvent :: NAME , new EntryDeletedEvent ( $entry ));
}
2017-04-24 08:22:57 +00:00
2017-04-24 09:31:00 +00:00
$results [ $key ][ 'entry' ] = $entry instanceof Entry ? true : false ;
}
}
2017-04-24 08:22:57 +00:00
2017-04-24 09:31:00 +00:00
$json = $this -> get ( 'serializer' ) -> serialize ( $results , 'json' );
2017-04-24 08:22:57 +00:00
2017-04-24 09:31:00 +00:00
return ( new JsonResponse ()) -> setJson ( $json );
}
2017-04-24 08:22:57 +00:00
2017-04-24 09:31:00 +00:00
/**
* Handles an entries list and create URL .
*
* @ ApiDoc (
* parameters = {
* { " name " = " urls " , " dataType " = " string " , " required " = true , " format " = " A JSON array of urls [ { 'url': 'http://...'}, { 'url': 'http://...'}] " , " description " = " Urls (as an array) to create. " }
* }
* )
*
* @ return JsonResponse
*/
public function postEntriesListAction ( Request $request )
{
$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' , []));
$results = [];
2017-04-24 08:22:57 +00:00
2017-04-24 09:31:00 +00:00
// handle multiple urls
if ( ! empty ( $urls )) {
foreach ( $urls as $key => $url ) {
$entry = $this -> get ( 'wallabag_core.entry_repository' ) -> findByUrlAndUserId (
$url ,
$this -> getUser () -> getId ()
);
2017-04-24 08:22:57 +00:00
2017-04-24 09:31:00 +00:00
$results [ $key ][ 'url' ] = $url ;
2017-04-24 08:22:57 +00:00
2017-04-24 09:31:00 +00:00
if ( false === $entry ) {
$entry = $this -> get ( 'wallabag_core.content_proxy' ) -> updateEntry (
new Entry ( $this -> getUser ()),
$url
);
2017-04-24 08:22:57 +00:00
}
2017-04-24 09:31:00 +00:00
$em = $this -> getDoctrine () -> getManager ();
$em -> persist ( $entry );
$em -> flush ();
$results [ $key ][ 'entry' ] = $entry instanceof Entry ? $entry -> getId () : false ;
// entry saved, dispatch event about it!
$this -> get ( 'event_dispatcher' ) -> dispatch ( EntrySavedEvent :: NAME , new EntrySavedEvent ( $entry ));
2017-04-24 08:22:57 +00:00
}
}
$json = $this -> get ( 'serializer' ) -> serialize ( $results , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
2016-10-28 12:46:30 +00:00
/**
* Create an entry .
*
* @ ApiDoc (
* parameters = {
* { " name " = " url " , " dataType " = " string " , " required " = true , " format " = " http://www.test.com/article.html " , " description " = " Url for the entry. " },
* { " name " = " title " , " dataType " = " string " , " required " = false , " description " = " Optional, we'll get the title from the page. " },
* { " name " = " tags " , " dataType " = " string " , " required " = false , " format " = " tag1,tag2,tag3 " , " description " = " a comma-separated list of tags. " },
* { " name " = " starred " , " dataType " = " integer " , " required " = false , " format " = " 1 or 0 " , " description " = " entry already starred " },
* { " name " = " archive " , " dataType " = " integer " , " required " = false , " format " = " 1 or 0 " , " description " = " entry already archived " },
* }
* )
*
* @ return JsonResponse
*/
public function postEntriesAction ( Request $request )
{
$this -> validateAuthentication ();
$url = $request -> request -> get ( 'url' );
$title = $request -> request -> get ( 'title' );
$isArchived = $request -> request -> get ( 'archive' );
$isStarred = $request -> request -> get ( 'starred' );
$entry = $this -> get ( 'wallabag_core.entry_repository' ) -> findByUrlAndUserId ( $url , $this -> getUser () -> getId ());
if ( false === $entry ) {
$entry = $this -> get ( 'wallabag_core.content_proxy' ) -> updateEntry (
new Entry ( $this -> getUser ()),
$url
);
}
if ( ! is_null ( $title )) {
$entry -> setTitle ( $title );
}
$tags = $request -> request -> get ( 'tags' , '' );
if ( ! empty ( $tags )) {
$this -> get ( 'wallabag_core.content_proxy' ) -> assignTagsToEntry ( $entry , $tags );
}
if ( ! is_null ( $isStarred )) {
$entry -> setStarred (( bool ) $isStarred );
}
if ( ! is_null ( $isArchived )) {
$entry -> setArchived (( bool ) $isArchived );
}
$em = $this -> getDoctrine () -> getManager ();
$em -> persist ( $entry );
$em -> flush ();
2016-11-03 15:41:29 +00:00
// entry saved, dispatch event about it!
$this -> get ( 'event_dispatcher' ) -> dispatch ( EntrySavedEvent :: NAME , new EntrySavedEvent ( $entry ));
2016-10-28 12:46:30 +00:00
$json = $this -> get ( 'serializer' ) -> serialize ( $entry , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
/**
* Change several properties of an entry .
*
* @ ApiDoc (
* requirements = {
* { " name " = " entry " , " dataType " = " integer " , " requirement " = " \ w+ " , " description " = " The entry ID " }
* },
* parameters = {
* { " name " = " title " , " dataType " = " string " , " required " = false },
* { " name " = " tags " , " dataType " = " string " , " required " = false , " format " = " tag1,tag2,tag3 " , " description " = " a comma-separated list of tags. " },
* { " name " = " archive " , " dataType " = " integer " , " required " = false , " format " = " 1 or 0 " , " description " = " archived the entry. " },
* { " name " = " starred " , " dataType " = " integer " , " required " = false , " format " = " 1 or 0 " , " description " = " starred the entry. " },
* }
* )
*
* @ return JsonResponse
*/
public function patchEntriesAction ( Entry $entry , Request $request )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
$title = $request -> request -> get ( 'title' );
$isArchived = $request -> request -> get ( 'archive' );
$isStarred = $request -> request -> get ( 'starred' );
if ( ! is_null ( $title )) {
$entry -> setTitle ( $title );
}
if ( ! is_null ( $isArchived )) {
$entry -> setArchived (( bool ) $isArchived );
}
if ( ! is_null ( $isStarred )) {
$entry -> setStarred (( bool ) $isStarred );
}
$tags = $request -> request -> get ( 'tags' , '' );
if ( ! empty ( $tags )) {
$this -> get ( 'wallabag_core.content_proxy' ) -> assignTagsToEntry ( $entry , $tags );
}
$em = $this -> getDoctrine () -> getManager ();
$em -> flush ();
$json = $this -> get ( 'serializer' ) -> serialize ( $entry , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
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
*
* @ ApiDoc (
* requirements = {
* { " name " = " entry " , " dataType " = " integer " , " requirement " = " \ w+ " , " description " = " The entry ID " }
* }
* )
*
* @ return JsonResponse
*/
public function patchEntriesReloadAction ( Entry $entry )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
try {
$entry = $this -> get ( 'wallabag_core.content_proxy' ) -> updateEntry ( $entry , $entry -> getUrl ());
} catch ( \Exception $e ) {
$this -> get ( 'logger' ) -> error ( 'Error while saving an entry' , [
'exception' => $e ,
'entry' => $entry ,
]);
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
if ( $this -> getParameter ( 'wallabag_core.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
}
$em = $this -> getDoctrine () -> getManager ();
$em -> persist ( $entry );
$em -> flush ();
// entry saved, dispatch event about it!
$this -> get ( 'event_dispatcher' ) -> dispatch ( EntrySavedEvent :: NAME , new EntrySavedEvent ( $entry ));
$json = $this -> get ( 'serializer' ) -> serialize ( $entry , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
2016-10-28 12:46:30 +00:00
/**
* Delete ** permanently ** an entry .
*
* @ ApiDoc (
* requirements = {
* { " name " = " entry " , " dataType " = " integer " , " requirement " = " \ w+ " , " description " = " The entry ID " }
* }
* )
*
* @ return JsonResponse
*/
public function deleteEntriesAction ( Entry $entry )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
$em = $this -> getDoctrine () -> getManager ();
$em -> remove ( $entry );
$em -> flush ();
2016-11-03 15:41:29 +00:00
// entry deleted, dispatch event about it!
$this -> get ( 'event_dispatcher' ) -> dispatch ( EntryDeletedEvent :: NAME , new EntryDeletedEvent ( $entry ));
2016-10-28 12:46:30 +00:00
$json = $this -> get ( 'serializer' ) -> serialize ( $entry , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
/**
* Retrieve all tags for an entry .
*
* @ ApiDoc (
* requirements = {
* { " name " = " entry " , " dataType " = " integer " , " requirement " = " \ w+ " , " description " = " The entry ID " }
* }
* )
*
* @ return JsonResponse
*/
public function getEntriesTagsAction ( Entry $entry )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
$json = $this -> get ( 'serializer' ) -> serialize ( $entry -> getTags (), 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
/**
* Add one or more tags to an entry .
*
* @ ApiDoc (
* requirements = {
* { " name " = " entry " , " dataType " = " integer " , " requirement " = " \ w+ " , " description " = " The entry ID " }
* },
* parameters = {
* { " name " = " tags " , " dataType " = " string " , " required " = false , " format " = " tag1,tag2,tag3 " , " description " = " a comma-separated list of tags. " },
* }
* )
*
* @ return JsonResponse
*/
public function postEntriesTagsAction ( Request $request , Entry $entry )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
$tags = $request -> request -> get ( 'tags' , '' );
if ( ! empty ( $tags )) {
$this -> get ( 'wallabag_core.content_proxy' ) -> assignTagsToEntry ( $entry , $tags );
}
$em = $this -> getDoctrine () -> getManager ();
$em -> persist ( $entry );
$em -> flush ();
$json = $this -> get ( 'serializer' ) -> serialize ( $entry , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
/**
* Permanently remove one tag for an entry .
*
* @ ApiDoc (
* requirements = {
* { " name " = " tag " , " dataType " = " integer " , " requirement " = " \ w+ " , " description " = " The tag ID " },
* { " name " = " entry " , " dataType " = " integer " , " requirement " = " \ w+ " , " description " = " The entry ID " }
* }
* )
*
* @ return JsonResponse
*/
public function deleteEntriesTagsAction ( Entry $entry , Tag $tag )
{
$this -> validateAuthentication ();
$this -> validateUserAccess ( $entry -> getUser () -> getId ());
$entry -> removeTag ( $tag );
$em = $this -> getDoctrine () -> getManager ();
$em -> persist ( $entry );
$em -> flush ();
$json = $this -> get ( 'serializer' ) -> serialize ( $entry , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
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
*
* @ ApiDoc (
* parameters = {
2017-04-24 10:24:17 +00:00
* { " name " = " list " , " dataType " = " string " , " required " = true , " format " = " A JSON array of urls [ { 'url': 'http://...','tags': 'tag1, tag2'}, { 'url': 'http://...','tags': 'tag1, tag2'}] " , " description " = " Urls (as an array) to handle. " }
2017-04-24 09:12:41 +00:00
* }
* )
*
* @ return JsonResponse
*/
2017-04-24 10:24:17 +00:00
public function deleteEntriesTagsListAction ( Request $request )
2017-04-24 09:12:41 +00:00
{
$this -> validateAuthentication ();
$list = json_decode ( $request -> query -> get ( 'list' , []));
$results = [];
// handle multiple urls
if ( ! empty ( $list )) {
foreach ( $list as $key => $element ) {
$entry = $this -> get ( 'wallabag_core.entry_repository' ) -> findByUrlAndUserId (
$element -> url ,
$this -> getUser () -> getId ()
);
$results [ $key ][ 'url' ] = $element -> url ;
$results [ $key ][ 'entry' ] = $entry instanceof Entry ? $entry -> getId () : false ;
$tags = $element -> tags ;
if ( false !== $entry && ! ( empty ( $tags ))) {
2017-04-24 10:24:17 +00:00
$tags = explode ( ',' , $tags );
foreach ( $tags as $label ) {
$label = trim ( $label );
$tag = $this -> getDoctrine ()
-> getRepository ( 'WallabagCoreBundle:Tag' )
-> findOneByLabel ( $label );
if ( false !== $tag ) {
$entry -> removeTag ( $tag );
}
2017-04-24 09:12:41 +00:00
}
$em = $this -> getDoctrine () -> getManager ();
$em -> persist ( $entry );
$em -> flush ();
}
}
}
$json = $this -> get ( 'serializer' ) -> serialize ( $results , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
2017-04-24 10:24:17 +00:00
/**
* Handles an entries list and add tags to them .
*
* @ ApiDoc (
* parameters = {
* { " name " = " list " , " dataType " = " string " , " required " = true , " format " = " A JSON array of urls [ { 'url': 'http://...','tags': 'tag1, tag2'}, { 'url': 'http://...','tags': 'tag1, tag2'}] " , " description " = " Urls (as an array) to handle. " }
* }
* )
*
* @ return JsonResponse
*/
public function postEntriesTagsListAction ( Request $request )
{
$this -> validateAuthentication ();
$list = json_decode ( $request -> query -> get ( 'list' , []));
$results = [];
// handle multiple urls
if ( ! empty ( $list )) {
foreach ( $list as $key => $element ) {
$entry = $this -> get ( 'wallabag_core.entry_repository' ) -> findByUrlAndUserId (
$element -> url ,
$this -> getUser () -> getId ()
);
$results [ $key ][ 'url' ] = $element -> url ;
$results [ $key ][ 'entry' ] = $entry instanceof Entry ? $entry -> getId () : false ;
$tags = $element -> tags ;
if ( false !== $entry && ! ( empty ( $tags ))) {
$this -> get ( 'wallabag_core.content_proxy' ) -> assignTagsToEntry ( $entry , $tags );
$em = $this -> getDoctrine () -> getManager ();
$em -> persist ( $entry );
$em -> flush ();
}
}
}
$json = $this -> get ( 'serializer' ) -> serialize ( $results , 'json' );
return ( new JsonResponse ()) -> setJson ( $json );
}
2016-10-28 12:46:30 +00:00
}