aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag
diff options
context:
space:
mode:
Diffstat (limited to 'src/Wallabag')
-rw-r--r--src/Wallabag/ApiBundle/Controller/EntryRestController.php52
-rw-r--r--src/Wallabag/ApiBundle/Controller/UserRestController.php139
-rw-r--r--src/Wallabag/ApiBundle/Resources/config/routing_rest.yml5
-rw-r--r--src/Wallabag/CoreBundle/Controller/TagController.php2
-rw-r--r--src/Wallabag/CoreBundle/Entity/Entry.php6
-rw-r--r--src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php9
-rw-r--r--src/Wallabag/CoreBundle/Helper/ContentProxy.php34
-rw-r--r--src/Wallabag/CoreBundle/Helper/Redirect.php10
-rw-r--r--src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php1
-rw-r--r--src/Wallabag/ImportBundle/Import/InstapaperImport.php17
-rw-r--r--src/Wallabag/ImportBundle/Import/WallabagV2Import.php4
-rw-r--r--src/Wallabag/UserBundle/Controller/ManageController.php4
-rw-r--r--src/Wallabag/UserBundle/Entity/User.php30
13 files changed, 264 insertions, 49 deletions
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
index 31bb67fd..c3ba1858 100644
--- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
@@ -273,6 +273,9 @@ class EntryRestController extends WallabagRestController
273 /** 273 /**
274 * Create an entry. 274 * Create an entry.
275 * 275 *
276 * 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**.
277 * Otherwise, content will be fetched as normal from the url and values will be overwritten.
278 *
276 * @ApiDoc( 279 * @ApiDoc(
277 * parameters={ 280 * parameters={
278 * {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."}, 281 * {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."},
@@ -280,6 +283,11 @@ class EntryRestController extends WallabagRestController
280 * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."}, 283 * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
281 * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already starred"}, 284 * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already starred"},
282 * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already archived"}, 285 * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already archived"},
286 * {"name"="content", "dataType"="string", "required"=false, "description"="Content of the entry"},
287 * {"name"="language", "dataType"="string", "required"=false, "description"="Language of the entry"},
288 * {"name"="preview_picture", "dataType"="string", "required"=false, "description"="Preview picture of the entry"},
289 * {"name"="published_at", "dataType"="datetime|integer", "format"="YYYY-MM-DDTHH:II:SS+TZ or a timestamp", "required"=false, "description"="Published date of the entry"},
290 * {"name"="authors", "dataType"="string", "format"="Name Firstname,author2,author3", "required"=false, "description"="Authors of the entry"},
283 * } 291 * }
284 * ) 292 * )
285 * 293 *
@@ -291,32 +299,46 @@ class EntryRestController extends WallabagRestController
291 299
292 $url = $request->request->get('url'); 300 $url = $request->request->get('url');
293 $title = $request->request->get('title'); 301 $title = $request->request->get('title');
302 $tags = $request->request->get('tags', []);
294 $isArchived = $request->request->get('archive'); 303 $isArchived = $request->request->get('archive');
295 $isStarred = $request->request->get('starred'); 304 $isStarred = $request->request->get('starred');
305 $content = $request->request->get('content');
306 $language = $request->request->get('language');
307 $picture = $request->request->get('preview_picture');
308 $publishedAt = $request->request->get('published_at');
309 $authors = $request->request->get('authors', '');
296 310
297 $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId()); 311 $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId());
298 312
299 if (false === $entry) { 313 if (false === $entry) {
300 $entry = new Entry($this->getUser()); 314 $entry = new Entry($this->getUser());
301 try {
302 $entry = $this->get('wallabag_core.content_proxy')->updateEntry(
303 $entry,
304 $url
305 );
306 } catch (\Exception $e) {
307 $this->get('logger')->error('Error while saving an entry', [
308 'exception' => $e,
309 'entry' => $entry,
310 ]);
311 $entry->setUrl($url);
312 }
313 } 315 }
314 316
315 if (!is_null($title)) { 317 try {
316 $entry->setTitle($title); 318 $entry = $this->get('wallabag_core.content_proxy')->updateEntry(
319 $entry,
320 $url,
321 [
322 'title' => $title,
323 'html' => $content,
324 'url' => $url,
325 'language' => $language,
326 'date' => $publishedAt,
327 // faking the preview picture
328 'open_graph' => [
329 'og_image' => $picture,
330 ],
331 'authors' => explode(',', $authors),
332 ]
333 );
334 } catch (\Exception $e) {
335 $this->get('logger')->error('Error while saving an entry', [
336 'exception' => $e,
337 'entry' => $entry,
338 ]);
339 $entry->setUrl($url);
317 } 340 }
318 341
319 $tags = $request->request->get('tags', '');
320 if (!empty($tags)) { 342 if (!empty($tags)) {
321 $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); 343 $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags);
322 } 344 }
diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php
new file mode 100644
index 00000000..a1b78e3f
--- /dev/null
+++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php
@@ -0,0 +1,139 @@
1<?php
2
3namespace Wallabag\ApiBundle\Controller;
4
5use FOS\UserBundle\Event\UserEvent;
6use FOS\UserBundle\FOSUserEvents;
7use JMS\Serializer\SerializationContext;
8use Nelmio\ApiDocBundle\Annotation\ApiDoc;
9use Symfony\Component\HttpFoundation\Request;
10use Symfony\Component\HttpFoundation\JsonResponse;
11use Wallabag\UserBundle\Entity\User;
12
13class UserRestController extends WallabagRestController
14{
15 /**
16 * Retrieve current logged in user informations.
17 *
18 * @ApiDoc()
19 *
20 * @return JsonResponse
21 */
22 public function getUserAction()
23 {
24 $this->validateAuthentication();
25
26 return $this->sendUser($this->getUser());
27 }
28
29 /**
30 * Register an user.
31 *
32 * @ApiDoc(
33 * requirements={
34 * {"name"="username", "dataType"="string", "required"=true, "description"="The user's username"},
35 * {"name"="password", "dataType"="string", "required"=true, "description"="The user's password"},
36 * {"name"="email", "dataType"="string", "required"=true, "description"="The user's email"}
37 * }
38 * )
39 *
40 * @todo Make this method (or the whole API) accessible only through https
41 *
42 * @return JsonResponse
43 */
44 public function putUserAction(Request $request)
45 {
46 if (!$this->container->getParameter('fosuser_registration')) {
47 $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json');
48
49 return (new JsonResponse())->setJson($json)->setStatusCode(403);
50 }
51
52 $userManager = $this->get('fos_user.user_manager');
53 $user = $userManager->createUser();
54 // enable created user by default
55 $user->setEnabled(true);
56
57 $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [
58 'csrf_protection' => false,
59 ]);
60
61 // simulate form submission
62 $form->submit([
63 'username' => $request->request->get('username'),
64 'plainPassword' => [
65 'first' => $request->request->get('password'),
66 'second' => $request->request->get('password'),
67 ],
68 'email' => $request->request->get('email'),
69 ]);
70
71 if ($form->isSubmitted() && false === $form->isValid()) {
72 $view = $this->view($form, 400);
73 $view->setFormat('json');
74
75 // handle errors in a more beautiful way than the default view
76 $data = json_decode($this->handleView($view)->getContent(), true)['children'];
77 $errors = [];
78
79 if (isset($data['username']['errors'])) {
80 $errors['username'] = $this->translateErrors($data['username']['errors']);
81 }
82
83 if (isset($data['email']['errors'])) {
84 $errors['email'] = $this->translateErrors($data['email']['errors']);
85 }
86
87 if (isset($data['plainPassword']['children']['first']['errors'])) {
88 $errors['password'] = $this->translateErrors($data['plainPassword']['children']['first']['errors']);
89 }
90
91 $json = $this->get('serializer')->serialize(['error' => $errors], 'json');
92
93 return (new JsonResponse())->setJson($json)->setStatusCode(400);
94 }
95
96 $userManager->updateUser($user);
97
98 // dispatch a created event so the associated config will be created
99 $event = new UserEvent($user, $request);
100 $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event);
101
102 return $this->sendUser($user);
103 }
104
105 /**
106 * Send user response.
107 *
108 * @param User $user
109 *
110 * @return JsonResponse
111 */
112 private function sendUser(User $user)
113 {
114 $json = $this->get('serializer')->serialize(
115 $user,
116 'json',
117 SerializationContext::create()->setGroups(['user_api'])
118 );
119
120 return (new JsonResponse())->setJson($json);
121 }
122
123 /**
124 * Translate errors message.
125 *
126 * @param array $errors
127 *
128 * @return array
129 */
130 private function translateErrors($errors)
131 {
132 $translatedErrors = [];
133 foreach ($errors as $error) {
134 $translatedErrors[] = $this->get('translator')->trans($error);
135 }
136
137 return $translatedErrors;
138 }
139}
diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
index 57d37f4b..c0283e71 100644
--- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
+++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
@@ -17,3 +17,8 @@ misc:
17 type: rest 17 type: rest
18 resource: "WallabagApiBundle:WallabagRest" 18 resource: "WallabagApiBundle:WallabagRest"
19 name_prefix: api_ 19 name_prefix: api_
20
21user:
22 type: rest
23 resource: "WallabagApiBundle:UserRest"
24 name_prefix: api_
diff --git a/src/Wallabag/CoreBundle/Controller/TagController.php b/src/Wallabag/CoreBundle/Controller/TagController.php
index fb6a720b..736eb1dc 100644
--- a/src/Wallabag/CoreBundle/Controller/TagController.php
+++ b/src/Wallabag/CoreBundle/Controller/TagController.php
@@ -70,7 +70,7 @@ class TagController extends Controller
70 $em->flush(); 70 $em->flush();
71 } 71 }
72 72
73 $redirectUrl = $this->get('wallabag_core.helper.redirect')->to($request->headers->get('referer')); 73 $redirectUrl = $this->get('wallabag_core.helper.redirect')->to($request->headers->get('referer'), '', true);
74 74
75 return $this->redirect($redirectUrl); 75 return $this->redirect($redirectUrl);
76 } 76 }
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php
index 08a67c34..9a7dd4e7 100644
--- a/src/Wallabag/CoreBundle/Entity/Entry.php
+++ b/src/Wallabag/CoreBundle/Entity/Entry.php
@@ -550,7 +550,7 @@ class Entry
550 } 550 }
551 551
552 /** 552 /**
553 * @return ArrayCollection<Tag> 553 * @return ArrayCollection
554 */ 554 */
555 public function getTags() 555 public function getTags()
556 { 556 {
@@ -685,7 +685,7 @@ class Entry
685 } 685 }
686 686
687 /** 687 /**
688 * @return int 688 * @return string
689 */ 689 */
690 public function getHttpStatus() 690 public function getHttpStatus()
691 { 691 {
@@ -693,7 +693,7 @@ class Entry
693 } 693 }
694 694
695 /** 695 /**
696 * @param int $httpStatus 696 * @param string $httpStatus
697 * 697 *
698 * @return Entry 698 * @return Entry
699 */ 699 */
diff --git a/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php b/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php
index c712bb26..1c56fa9f 100644
--- a/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php
+++ b/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php
@@ -5,7 +5,6 @@ namespace Wallabag\CoreBundle\GuzzleSiteAuthenticator;
5use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfig; 5use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfig;
6use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfigBuilder; 6use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfigBuilder;
7use Graby\SiteConfig\ConfigBuilder; 7use Graby\SiteConfig\ConfigBuilder;
8use OutOfRangeException;
9use Psr\Log\LoggerInterface; 8use Psr\Log\LoggerInterface;
10 9
11class GrabySiteConfigBuilder implements SiteConfigBuilder 10class GrabySiteConfigBuilder implements SiteConfigBuilder
@@ -38,13 +37,7 @@ class GrabySiteConfigBuilder implements SiteConfigBuilder
38 } 37 }
39 38
40 /** 39 /**
41 * Builds the SiteConfig for a host. 40 * {@inheritdoc}
42 *
43 * @param string $host The "www." prefix is ignored
44 *
45 * @return SiteConfig
46 *
47 * @throws OutOfRangeException If there is no config for $host
48 */ 41 */
49 public function buildForHost($host) 42 public function buildForHost($host)
50 { 43 {
diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
index 4b3e6fbb..8ba77ca9 100644
--- a/src/Wallabag/CoreBundle/Helper/ContentProxy.php
+++ b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
@@ -31,7 +31,7 @@ class ContentProxy
31 } 31 }
32 32
33 /** 33 /**
34 * Fetch content using graby and hydrate given entry with results information. 34 * Fetch content using graby and hydrate given $entry with results information.
35 * In case we couldn't find content, we'll try to use Open Graph data. 35 * In case we couldn't find content, we'll try to use Open Graph data.
36 * 36 *
37 * We can also force the content, in case of an import from the v1 for example, so the function won't 37 * We can also force the content, in case of an import from the v1 for example, so the function won't
@@ -39,12 +39,17 @@ class ContentProxy
39 * 39 *
40 * @param Entry $entry Entry to update 40 * @param Entry $entry Entry to update
41 * @param string $url Url to grab content for 41 * @param string $url Url to grab content for
42 * @param array $content An array with AT LEAST keys title, html, url, language & content_type to skip the fetchContent from the url 42 * @param array $content An array with AT LEAST keys title, html, url to skip the fetchContent from the url
43 * 43 *
44 * @return Entry 44 * @return Entry
45 */ 45 */
46 public function updateEntry(Entry $entry, $url, array $content = []) 46 public function updateEntry(Entry $entry, $url, array $content = [])
47 { 47 {
48 // ensure content is a bit cleaned up
49 if (!empty($content['html'])) {
50 $content['html'] = $this->graby->cleanupHtml($content['html'], $url);
51 }
52
48 // do we have to fetch the content or the provided one is ok? 53 // do we have to fetch the content or the provided one is ok?
49 if (empty($content) || false === $this->validateContent($content)) { 54 if (empty($content) || false === $this->validateContent($content)) {
50 $fetchedContent = $this->graby->fetchContent($url); 55 $fetchedContent = $this->graby->fetchContent($url);
@@ -57,7 +62,7 @@ class ContentProxy
57 } 62 }
58 63
59 $title = $content['title']; 64 $title = $content['title'];
60 if (!$title && isset($content['open_graph']['og_title'])) { 65 if (!$title && !empty($content['open_graph']['og_title'])) {
61 $title = $content['open_graph']['og_title']; 66 $title = $content['open_graph']['og_title'];
62 } 67 }
63 68
@@ -65,7 +70,7 @@ class ContentProxy
65 if (false === $html) { 70 if (false === $html) {
66 $html = $this->fetchingErrorMessage; 71 $html = $this->fetchingErrorMessage;
67 72
68 if (isset($content['open_graph']['og_description'])) { 73 if (!empty($content['open_graph']['og_description'])) {
69 $html .= '<p><i>But we found a short description: </i></p>'; 74 $html .= '<p><i>But we found a short description: </i></p>';
70 $html .= $content['open_graph']['og_description']; 75 $html .= $content['open_graph']['og_description'];
71 } 76 }
@@ -76,8 +81,19 @@ class ContentProxy
76 $entry->setContent($html); 81 $entry->setContent($html);
77 $entry->setHttpStatus(isset($content['status']) ? $content['status'] : ''); 82 $entry->setHttpStatus(isset($content['status']) ? $content['status'] : '');
78 83
79 if (isset($content['date']) && null !== $content['date'] && '' !== $content['date']) { 84 if (!empty($content['date'])) {
80 $entry->setPublishedAt(new \DateTime($content['date'])); 85 $date = $content['date'];
86
87 // is it a timestamp?
88 if (filter_var($date, FILTER_VALIDATE_INT) !== false) {
89 $date = '@'.$content['date'];
90 }
91
92 try {
93 $entry->setPublishedAt(new \DateTime($date));
94 } catch (\Exception $e) {
95 $this->logger->warning('Error while defining date', ['e' => $e, 'url' => $url, 'date' => $content['date']]);
96 }
81 } 97 }
82 98
83 if (!empty($content['authors'])) { 99 if (!empty($content['authors'])) {
@@ -97,12 +113,12 @@ class ContentProxy
97 $entry->setDomainName($domainName); 113 $entry->setDomainName($domainName);
98 } 114 }
99 115
100 if (isset($content['open_graph']['og_image']) && $content['open_graph']['og_image']) { 116 if (!empty($content['open_graph']['og_image'])) {
101 $entry->setPreviewPicture($content['open_graph']['og_image']); 117 $entry->setPreviewPicture($content['open_graph']['og_image']);
102 } 118 }
103 119
104 // if content is an image define as a preview too 120 // if content is an image define as a preview too
105 if (isset($content['content_type']) && in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) { 121 if (!empty($content['content_type']) && in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) {
106 $entry->setPreviewPicture($content['url']); 122 $entry->setPreviewPicture($content['url']);
107 } 123 }
108 124
@@ -128,6 +144,6 @@ class ContentProxy
128 */ 144 */
129 private function validateContent(array $content) 145 private function validateContent(array $content)
130 { 146 {
131 return isset($content['title']) && isset($content['html']) && isset($content['url']) && isset($content['language']) && isset($content['content_type']); 147 return !empty($content['title']) && !empty($content['html']) && !empty($content['url']);
132 } 148 }
133} 149}
diff --git a/src/Wallabag/CoreBundle/Helper/Redirect.php b/src/Wallabag/CoreBundle/Helper/Redirect.php
index f78b7fe0..abc84d08 100644
--- a/src/Wallabag/CoreBundle/Helper/Redirect.php
+++ b/src/Wallabag/CoreBundle/Helper/Redirect.php
@@ -21,12 +21,13 @@ class Redirect
21 } 21 }
22 22
23 /** 23 /**
24 * @param string $url URL to redirect 24 * @param string $url URL to redirect
25 * @param string $fallback Fallback URL if $url is null 25 * @param string $fallback Fallback URL if $url is null
26 * @param bool $ignoreActionMarkAsRead Ignore configured action when mark as read
26 * 27 *
27 * @return string 28 * @return string
28 */ 29 */
29 public function to($url, $fallback = '') 30 public function to($url, $fallback = '', $ignoreActionMarkAsRead = false)
30 { 31 {
31 $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null; 32 $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
32 33
@@ -34,7 +35,8 @@ class Redirect
34 return $url; 35 return $url;
35 } 36 }
36 37
37 if (Config::REDIRECT_TO_HOMEPAGE === $user->getConfig()->getActionMarkAsRead()) { 38 if (!$ignoreActionMarkAsRead &&
39 Config::REDIRECT_TO_HOMEPAGE === $user->getConfig()->getActionMarkAsRead()) {
38 return $this->router->generate('homepage'); 40 return $this->router->generate('homepage');
39 } 41 }
40 42
diff --git a/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php b/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php
index add27db2..509d0dec 100644
--- a/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php
+++ b/src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php
@@ -15,6 +15,7 @@ class RuleBasedTagger
15 private $rulerz; 15 private $rulerz;
16 private $tagRepository; 16 private $tagRepository;
17 private $entryRepository; 17 private $entryRepository;
18 private $logger;
18 19
19 public function __construct(RulerZ $rulerz, TagRepository $tagRepository, EntryRepository $entryRepository, LoggerInterface $logger) 20 public function __construct(RulerZ $rulerz, TagRepository $tagRepository, EntryRepository $entryRepository, LoggerInterface $logger)
20 { 21 {
diff --git a/src/Wallabag/ImportBundle/Import/InstapaperImport.php b/src/Wallabag/ImportBundle/Import/InstapaperImport.php
index 70a53f1a..c8e0cd5b 100644
--- a/src/Wallabag/ImportBundle/Import/InstapaperImport.php
+++ b/src/Wallabag/ImportBundle/Import/InstapaperImport.php
@@ -68,6 +68,14 @@ class InstapaperImport extends AbstractImport
68 continue; 68 continue;
69 } 69 }
70 70
71 // last element in the csv is the folder where the content belong
72 // BUT it can also be the status (since status = folder in Instapaper)
73 // and we don't want archive, unread & starred to become a tag
74 $tags = null;
75 if (false === in_array($data[3], ['Archive', 'Unread', 'Starred'])) {
76 $tags = [$data[3]];
77 }
78
71 $entries[] = [ 79 $entries[] = [
72 'url' => $data[0], 80 'url' => $data[0],
73 'title' => $data[1], 81 'title' => $data[1],
@@ -75,6 +83,7 @@ class InstapaperImport extends AbstractImport
75 'is_archived' => $data[3] === 'Archive' || $data[3] === 'Starred', 83 'is_archived' => $data[3] === 'Archive' || $data[3] === 'Starred',
76 'is_starred' => $data[3] === 'Starred', 84 'is_starred' => $data[3] === 'Starred',
77 'html' => false, 85 'html' => false,
86 'tags' => $tags,
78 ]; 87 ];
79 } 88 }
80 fclose($handle); 89 fclose($handle);
@@ -118,6 +127,14 @@ class InstapaperImport extends AbstractImport
118 // update entry with content (in case fetching failed, the given entry will be return) 127 // update entry with content (in case fetching failed, the given entry will be return)
119 $entry = $this->fetchContent($entry, $importedEntry['url'], $importedEntry); 128 $entry = $this->fetchContent($entry, $importedEntry['url'], $importedEntry);
120 129
130 if (!empty($importedEntry['tags'])) {
131 $this->tagsAssigner->assignTagsToEntry(
132 $entry,
133 $importedEntry['tags'],
134 $this->em->getUnitOfWork()->getScheduledEntityInsertions()
135 );
136 }
137
121 $entry->setArchived($importedEntry['is_archived']); 138 $entry->setArchived($importedEntry['is_archived']);
122 $entry->setStarred($importedEntry['is_starred']); 139 $entry->setStarred($importedEntry['is_starred']);
123 140
diff --git a/src/Wallabag/ImportBundle/Import/WallabagV2Import.php b/src/Wallabag/ImportBundle/Import/WallabagV2Import.php
index d2a89d79..3e085ecf 100644
--- a/src/Wallabag/ImportBundle/Import/WallabagV2Import.php
+++ b/src/Wallabag/ImportBundle/Import/WallabagV2Import.php
@@ -36,8 +36,8 @@ class WallabagV2Import extends WallabagImport
36 return [ 36 return [
37 'html' => $entry['content'], 37 'html' => $entry['content'],
38 'content_type' => $entry['mimetype'], 38 'content_type' => $entry['mimetype'],
39 'is_archived' => (int) ($entry['is_archived'] || $this->markAsRead), 39 'is_archived' => (bool) ($entry['is_archived'] || $this->markAsRead),
40 'is_starred' => false, 40 'is_starred' => (bool) $entry['is_starred'],
41 ] + $entry; 41 ] + $entry;
42 } 42 }
43 43
diff --git a/src/Wallabag/UserBundle/Controller/ManageController.php b/src/Wallabag/UserBundle/Controller/ManageController.php
index 1c5c86d4..084f2c67 100644
--- a/src/Wallabag/UserBundle/Controller/ManageController.php
+++ b/src/Wallabag/UserBundle/Controller/ManageController.php
@@ -33,9 +33,7 @@ class ManageController extends Controller
33 // enable created user by default 33 // enable created user by default
34 $user->setEnabled(true); 34 $user->setEnabled(true);
35 35
36 $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [ 36 $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user);
37 'validation_groups' => ['Profile'],
38 ]);
39 $form->handleRequest($request); 37 $form->handleRequest($request);
40 38
41 if ($form->isSubmitted() && $form->isValid()) { 39 if ($form->isSubmitted() && $form->isValid()) {
diff --git a/src/Wallabag/UserBundle/Entity/User.php b/src/Wallabag/UserBundle/Entity/User.php
index 3a167de7..1ff3046a 100644
--- a/src/Wallabag/UserBundle/Entity/User.php
+++ b/src/Wallabag/UserBundle/Entity/User.php
@@ -4,11 +4,11 @@ namespace Wallabag\UserBundle\Entity;
4 4
5use Doctrine\Common\Collections\ArrayCollection; 5use Doctrine\Common\Collections\ArrayCollection;
6use Doctrine\ORM\Mapping as ORM; 6use Doctrine\ORM\Mapping as ORM;
7use JMS\Serializer\Annotation\Groups;
8use JMS\Serializer\Annotation\XmlRoot;
7use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface; 9use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface;
8use Scheb\TwoFactorBundle\Model\TrustedComputerInterface; 10use Scheb\TwoFactorBundle\Model\TrustedComputerInterface;
9use FOS\UserBundle\Model\User as BaseUser; 11use FOS\UserBundle\Model\User as BaseUser;
10use JMS\Serializer\Annotation\ExclusionPolicy;
11use JMS\Serializer\Annotation\Expose;
12use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; 12use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
13use Symfony\Component\Security\Core\User\UserInterface; 13use Symfony\Component\Security\Core\User\UserInterface;
14use Wallabag\ApiBundle\Entity\Client; 14use Wallabag\ApiBundle\Entity\Client;
@@ -18,23 +18,25 @@ use Wallabag\CoreBundle\Entity\Entry;
18/** 18/**
19 * User. 19 * User.
20 * 20 *
21 * @XmlRoot("user")
21 * @ORM\Entity(repositoryClass="Wallabag\UserBundle\Repository\UserRepository") 22 * @ORM\Entity(repositoryClass="Wallabag\UserBundle\Repository\UserRepository")
22 * @ORM\Table(name="`user`") 23 * @ORM\Table(name="`user`")
23 * @ORM\HasLifecycleCallbacks() 24 * @ORM\HasLifecycleCallbacks()
24 * @ExclusionPolicy("all")
25 * 25 *
26 * @UniqueEntity("email") 26 * @UniqueEntity("email")
27 * @UniqueEntity("username") 27 * @UniqueEntity("username")
28 */ 28 */
29class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface 29class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface
30{ 30{
31 /** @Serializer\XmlAttribute */
31 /** 32 /**
32 * @var int 33 * @var int
33 * 34 *
34 * @Expose
35 * @ORM\Column(name="id", type="integer") 35 * @ORM\Column(name="id", type="integer")
36 * @ORM\Id 36 * @ORM\Id
37 * @ORM\GeneratedValue(strategy="AUTO") 37 * @ORM\GeneratedValue(strategy="AUTO")
38 *
39 * @Groups({"user_api"})
38 */ 40 */
39 protected $id; 41 protected $id;
40 42
@@ -42,13 +44,31 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
42 * @var string 44 * @var string
43 * 45 *
44 * @ORM\Column(name="name", type="text", nullable=true) 46 * @ORM\Column(name="name", type="text", nullable=true)
47 *
48 * @Groups({"user_api"})
45 */ 49 */
46 protected $name; 50 protected $name;
47 51
48 /** 52 /**
53 * @var string
54 *
55 * @Groups({"user_api"})
56 */
57 protected $username;
58
59 /**
60 * @var string
61 *
62 * @Groups({"user_api"})
63 */
64 protected $email;
65
66 /**
49 * @var date 67 * @var date
50 * 68 *
51 * @ORM\Column(name="created_at", type="datetime") 69 * @ORM\Column(name="created_at", type="datetime")
70 *
71 * @Groups({"user_api"})
52 */ 72 */
53 protected $createdAt; 73 protected $createdAt;
54 74
@@ -56,6 +76,8 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
56 * @var date 76 * @var date
57 * 77 *
58 * @ORM\Column(name="updated_at", type="datetime") 78 * @ORM\Column(name="updated_at", type="datetime")
79 *
80 * @Groups({"user_api"})
59 */ 81 */
60 protected $updatedAt; 82 protected $updatedAt;
61 83