diff options
author | Thomas Citharel <tcit@tcit.fr> | 2017-05-31 09:31:18 +0200 |
---|---|---|
committer | Thomas Citharel <tcit@tcit.fr> | 2017-06-23 10:08:54 +0200 |
commit | bf6c0346d8d35a719dd1bff1cb4d573d422f99ff (patch) | |
tree | 04fb80e20ad1cffacb72357a632a9afe2ec058cb /src/Wallabag/FederationBundle/Controller | |
parent | d6d3f4ec3698effd1d4b063e295341791bdcf7d7 (diff) | |
download | wallabag-bf6c0346d8d35a719dd1bff1cb4d573d422f99ff.tar.gz wallabag-bf6c0346d8d35a719dd1bff1cb4d573d422f99ff.tar.zst wallabag-bf6c0346d8d35a719dd1bff1cb4d573d422f99ff.zip |
WIPfederation
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
Diffstat (limited to 'src/Wallabag/FederationBundle/Controller')
6 files changed, 613 insertions, 0 deletions
diff --git a/src/Wallabag/FederationBundle/Controller/InboxController.php b/src/Wallabag/FederationBundle/Controller/InboxController.php new file mode 100644 index 00000000..99cfeadf --- /dev/null +++ b/src/Wallabag/FederationBundle/Controller/InboxController.php | |||
@@ -0,0 +1,43 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\FederationBundle\Controller; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | ||
6 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
7 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
8 | use Symfony\Component\HttpFoundation\Request; | ||
9 | use Symfony\Component\HttpFoundation\Response; | ||
10 | use Wallabag\FederationBundle\Entity\Account; | ||
11 | use Wallabag\FederationBundle\Entity\Instance; | ||
12 | use Wallabag\FederationBundle\Federation\CloudId; | ||
13 | |||
14 | class InboxController extends Controller | ||
15 | { | ||
16 | /** | ||
17 | * @Route("/profile/inbox", name="user-inbox") | ||
18 | * | ||
19 | * @param Request $request | ||
20 | * @return Response | ||
21 | */ | ||
22 | public function userInboxAction(Request $request) | ||
23 | { | ||
24 | $em = $this->getDoctrine()->getManager(); | ||
25 | $response = new Response(); | ||
26 | |||
27 | if ($activity = json_decode($request->getContent())) { | ||
28 | if ($activity->type === 'Follow' && isset($activity->actor->id)) { | ||
29 | $cloudId = new CloudId($activity->actor->id); | ||
30 | $account = new Account(); | ||
31 | $account->setServer($cloudId->getRemote()) | ||
32 | ->setUsername($cloudId->getUser()); | ||
33 | $em->persist($account); | ||
34 | $em->flush(); | ||
35 | |||
36 | $response->setStatusCode(201); | ||
37 | } else { | ||
38 | $response->setStatusCode(400); | ||
39 | } | ||
40 | } | ||
41 | return $response; | ||
42 | } | ||
43 | } | ||
diff --git a/src/Wallabag/FederationBundle/Controller/LikedController.php b/src/Wallabag/FederationBundle/Controller/LikedController.php new file mode 100644 index 00000000..3e86d50d --- /dev/null +++ b/src/Wallabag/FederationBundle/Controller/LikedController.php | |||
@@ -0,0 +1,19 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\FederationBundle\Controller; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
7 | use Wallabag\CoreBundle\Entity\Entry; | ||
8 | |||
9 | class LikedController extends Controller | ||
10 | { | ||
11 | /** | ||
12 | * @Route("/like/{entry}", name="like") | ||
13 | * @param Entry $entry | ||
14 | */ | ||
15 | public function likeAction(Entry $entry) | ||
16 | { | ||
17 | |||
18 | } | ||
19 | } | ||
diff --git a/src/Wallabag/FederationBundle/Controller/MetadataController.php b/src/Wallabag/FederationBundle/Controller/MetadataController.php new file mode 100644 index 00000000..90d3eb4d --- /dev/null +++ b/src/Wallabag/FederationBundle/Controller/MetadataController.php | |||
@@ -0,0 +1,69 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\FederationBundle\Controller; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
7 | use Symfony\Component\HttpFoundation\JsonResponse; | ||
8 | use Symfony\Component\HttpFoundation\Request; | ||
9 | use Symfony\Component\HttpFoundation\Response; | ||
10 | use Wallabag\FederationBundle\Federation\CloudId; | ||
11 | |||
12 | class MetadataController extends Controller | ||
13 | { | ||
14 | /** | ||
15 | * @Route("/.well-known/host-meta", name="webfinger-host-meta") | ||
16 | * | ||
17 | * @return Response | ||
18 | */ | ||
19 | public function getHostMeta() | ||
20 | { | ||
21 | $response = new Response(); | ||
22 | $response->setContent('<XRD xmlns=\"http://docs.oasis-open.org/ns/xri/xrd-1.0\"> | ||
23 | <Link rel=\"lrdd\" type=\"application/xrd+xml\" template=\"' . $this->generateUrl('webfinger') . '?resource={uri}\"/> | ||
24 | </XRD>'); | ||
25 | $response->headers->set('Content-Type', 'application/xrd+xml'); | ||
26 | return $response; | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * @Route("/.well-known/webfinger", name="webfinger") | ||
31 | * @param Request $request | ||
32 | * @return JsonResponse | ||
33 | */ | ||
34 | public function getWebfingerData(Request $request) | ||
35 | { | ||
36 | $subject = $request->query->get('resource'); | ||
37 | |||
38 | if (!$subject || strlen($subject) < 12 || 0 !== strpos($subject, 'acct:') || false !== strpos($subject, '@')) { | ||
39 | return new JsonResponse([]); | ||
40 | } | ||
41 | $subjectId = substr($subject, 5); | ||
42 | |||
43 | $cloudId = $this->getCloudId($subjectId); | ||
44 | |||
45 | |||
46 | $data = [ | ||
47 | 'subject' => $subject, | ||
48 | 'aliases' => [$this->generateUrl('profile', $cloudId->getUser())], | ||
49 | 'links' => [ | ||
50 | [ | ||
51 | 'rel' => 'http://webfinger.net/rel/profile-page', | ||
52 | 'type' => 'text/html', | ||
53 | 'href' => $this->generateUrl('profile', $cloudId->getUser()) | ||
54 | ], | ||
55 | ] | ||
56 | ]; | ||
57 | return new JsonResponse($data); | ||
58 | } | ||
59 | |||
60 | private function getCloudId($subjectId) | ||
61 | { | ||
62 | return new CloudId($subjectId); | ||
63 | } | ||
64 | |||
65 | |||
66 | # | ||
67 | # {"subject":"acct:tcit@social.tcit.fr","aliases":["https://social.tcit.fr/@tcit","https://social.tcit.fr/users/tcit"],"links":[{"rel":"http://webfinger.net/rel/profile-page","type":"text/html","href":"https://social.tcit.fr/@tcit"},{"rel":"http://schemas.google.com/g/2010#updates-from","type":"application/atom+xml","href":"https://social.tcit.fr/users/tcit.atom"},{"rel":"self","type":"application/activity+json","href":"https://social.tcit.fr/@tcit"},{"rel":"salmon","href":"https://social.tcit.fr/api/salmon/1"},{"rel":"magic-public-key","href":"data:application/magic-public-key,RSA.pXwYMUdFg3XUd-bGsh8CyiMRGpRGAWuCdM5pDWx5uM4pW2pM3xbHbcI21j9h8BmlAiPg6hbZD73KGly2N8Rt5iIS0I-l6i8kA1JCCdlAaDTRd41RKMggZDoQvjVZQtsyE1VzMeU2kbqqTFN6ew7Hvbd6O0NhixoKoZ5f3jwuBDZoT0p1TAcaMdmG8oqHD97isizkDnRn8cOBA6wtI-xb5xP2zxZMsLpTDZLiKU8XcPKZCw4OfQfmDmKkHtrFb77jCAQj_s_FxjVnvxRwmfhNnWy0D-LUV_g63nHh_b5zXIeV92QZLvDYbgbezmzUzv9UeA1s70GGbaDqCIy85gw9-w==.AQAB"},{"rel":"http://ostatus.org/schema/1.0/subscribe","template":"https://social.tcit.fr/authorize_follow?acct={uri}"}]} | ||
68 | # | ||
69 | } | ||
diff --git a/src/Wallabag/FederationBundle/Controller/OutboxController.php b/src/Wallabag/FederationBundle/Controller/OutboxController.php new file mode 100644 index 00000000..87ebdba1 --- /dev/null +++ b/src/Wallabag/FederationBundle/Controller/OutboxController.php | |||
@@ -0,0 +1,23 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\FederationBundle\Controller; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
7 | use Symfony\Component\HttpFoundation\Request; | ||
8 | use Wallabag\FederationBundle\Entity\Account; | ||
9 | use Wallabag\UserBundle\Entity\User; | ||
10 | |||
11 | class OutboxController extends Controller | ||
12 | { | ||
13 | /** | ||
14 | * @Route("/profile/outbox", name="user-outbox") | ||
15 | * | ||
16 | * @param Request $request | ||
17 | * @param Account $user | ||
18 | */ | ||
19 | public function userOutboxAction(Request $request, Account $user) | ||
20 | { | ||
21 | |||
22 | } | ||
23 | } | ||
diff --git a/src/Wallabag/FederationBundle/Controller/ProfileController.php b/src/Wallabag/FederationBundle/Controller/ProfileController.php new file mode 100644 index 00000000..7e472e11 --- /dev/null +++ b/src/Wallabag/FederationBundle/Controller/ProfileController.php | |||
@@ -0,0 +1,425 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\FederationBundle\Controller; | ||
4 | |||
5 | use Pagerfanta\Adapter\DoctrineORMAdapter; | ||
6 | use Pagerfanta\Pagerfanta; | ||
7 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | ||
8 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
9 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
10 | use Symfony\Component\HttpFoundation\JsonResponse; | ||
11 | use Symfony\Component\HttpFoundation\Request; | ||
12 | use Symfony\Component\HttpFoundation\Response; | ||
13 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | ||
14 | use Wallabag\CoreBundle\Entity\Entry; | ||
15 | use Wallabag\FederationBundle\Entity\Account; | ||
16 | use Wallabag\FederationBundle\Federation\CloudId; | ||
17 | |||
18 | class ProfileController extends Controller | ||
19 | { | ||
20 | /** | ||
21 | * @Route("/profile/@{user}", name="user-profile") | ||
22 | * @ParamConverter("user", class="WallabagFederationBundle:Account", options={ | ||
23 | * "repository_method" = "findOneByUsername"}) | ||
24 | * | ||
25 | * @param Request $request | ||
26 | * @param Account $user | ||
27 | * @return JsonResponse|Response | ||
28 | */ | ||
29 | public function getUserProfile(Request $request, Account $user) | ||
30 | { | ||
31 | if (in_array('application/ld+json; profile="https://www.w3.org/ns/activitystreams', $request->getAcceptableContentTypes(), true)) { | ||
32 | $data = [ | ||
33 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
34 | 'type' => 'Person', | ||
35 | 'id' => CloudId::getCloudIdFromAccount($user, $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL))->getDisplayId(), | ||
36 | 'following' => $this->generateUrl('following', ['user' => $user->getUsername()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
37 | 'followers' => $this->generateUrl('followers', ['user' => $user->getUsername()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
38 | //'liked' => $this->generateUrl('recommended', ['user' => $user], UrlGeneratorInterface::ABSOLUTE_URL), | ||
39 | 'inbox' => $this->generateUrl('user-inbox', ['user' => $user], UrlGeneratorInterface::ABSOLUTE_URL), | ||
40 | 'outbox' => $this->generateUrl('user-outbox', ['user' => $user->getUsername()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
41 | 'preferredUsername' => $user->getUser()->getName(), | ||
42 | 'name' => $user->getUsername(), | ||
43 | //'oauthAuthorizationEndpoint' => $this->generateUrl('fos_oauth_server_authorize', [], UrlGeneratorInterface::ABSOLUTE_URL), | ||
44 | 'oauthTokenEndpoint' => $this->generateUrl('fos_oauth_server_token', [], UrlGeneratorInterface::ABSOLUTE_URL), | ||
45 | //'publicInbox' => $this->generateUrl('public_inbox', [], UrlGeneratorInterface::ABSOLUTE_URL), | ||
46 | ]; | ||
47 | return new JsonResponse($data); | ||
48 | } | ||
49 | return $this->render( | ||
50 | 'WallabagFederationBundle:User:profile.html.twig', [ | ||
51 | 'user' => $user, | ||
52 | 'registration_enabled' => $this->getParameter('wallabag_user.registration_enabled'), | ||
53 | ] | ||
54 | ); | ||
55 | } | ||
56 | |||
57 | /** | ||
58 | * @Route("/profile/@{user}/followings/{page}", name="following", defaults={"page" : 0}) | ||
59 | * @ParamConverter("user", class="WallabagFederationBundle:Account", options={ | ||
60 | * "repository_method" = "findOneByUsername"}) | ||
61 | * | ||
62 | * @param Request $request | ||
63 | * @param Account $user | ||
64 | * @param int $page | ||
65 | * @return JsonResponse|Response | ||
66 | */ | ||
67 | public function getUsersFollowing(Request $request, Account $user, $page = 0) | ||
68 | { | ||
69 | $qb = $this->getDoctrine()->getRepository('WallabagFederationBundle:Account')->getBuilderForFollowingsByAccount($user->getId()); | ||
70 | |||
71 | $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false); | ||
72 | |||
73 | $following = new Pagerfanta($pagerAdapter); | ||
74 | $totalFollowing = $following->getNbResults(); | ||
75 | |||
76 | $activityStream = in_array('application/ld+json; profile="https://www.w3.org/ns/activitystreams', $request->getAcceptableContentTypes(), true); | ||
77 | |||
78 | if ($page === 0 && $activityStream) { | ||
79 | /** Home page */ | ||
80 | $dataPrez = [ | ||
81 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
82 | 'summary' => $user->getUsername() . " followings'", | ||
83 | 'type' => 'Collection', | ||
84 | 'id' => $this->generateUrl('following', ['user' => $user->getUsername()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
85 | 'totalItems' => $totalFollowing, | ||
86 | 'first' => [ | ||
87 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
88 | 'type' => 'Link', | ||
89 | 'href' => $this->generateUrl('following', ['user' => $user->getUsername(), 'page' => 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
90 | 'name' => 'First page of ' . $user->getUsername() . ' followings' | ||
91 | ], | ||
92 | 'last' => [ | ||
93 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
94 | 'type' => 'Link', | ||
95 | 'href' => $this->generateUrl('following', ['user' => $user->getUsername(), 'page' => $following->getNbPages()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
96 | 'name' => 'Last page of ' . $user->getUsername() . ' followings' | ||
97 | ] | ||
98 | ]; | ||
99 | return new JsonResponse($dataPrez); | ||
100 | //} | ||
101 | } | ||
102 | |||
103 | $following->setMaxPerPage(30); | ||
104 | $following->setCurrentPage($page); | ||
105 | |||
106 | if (!$activityStream) { | ||
107 | return $this->render('WallabagFederationBundle:User:followers.html.twig', [ | ||
108 | 'users' => $following, | ||
109 | 'user' => $user, | ||
110 | 'registration_enabled' => $this->getParameter('wallabag_user.registration_enabled'), | ||
111 | ]); | ||
112 | } | ||
113 | |||
114 | $items = []; | ||
115 | |||
116 | foreach ($following->getCurrentPageResults() as $follow) { | ||
117 | /** @var Account $follow */ | ||
118 | /** Items in the page */ | ||
119 | $items[] = [ | ||
120 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
121 | 'type' => 'Person', | ||
122 | 'name' => $follow->getUsername(), | ||
123 | 'id' => CloudId::getCloudIdFromAccount($follow), | ||
124 | ]; | ||
125 | } | ||
126 | |||
127 | $data = [ | ||
128 | 'summary' => 'Page ' . $page . ' of ' . $user->getUsername() . ' followers', | ||
129 | 'partOf' => $this->generateUrl('following', ['user' => $user->getUsername()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
130 | 'type' => 'OrderedCollectionPage', | ||
131 | 'startIndex' => ($page - 1) * 30, | ||
132 | 'orderedItems' => $items, | ||
133 | 'first' => [ | ||
134 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
135 | 'type' => 'Link', | ||
136 | 'href' => $this->generateUrl('following', ['user' => $user->getUsername(), 'page' => 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
137 | 'name' => 'First page of ' . $user->getUsername() . ' followings' | ||
138 | ], | ||
139 | 'last' => [ | ||
140 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
141 | 'type' => 'Link', | ||
142 | 'href' => $this->generateUrl('following', ['user' => $user->getUsername(), 'page' => $following->getNbPages()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
143 | 'name' => 'Last page of ' . $user->getUsername() . ' followings' | ||
144 | ], | ||
145 | ]; | ||
146 | |||
147 | /** Previous page */ | ||
148 | if ($page > 1) { | ||
149 | $data['prev'] = [ | ||
150 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
151 | 'type' => 'Link', | ||
152 | 'href' => $this->generateUrl('following', ['user' => $user->getUsername(), 'page' => $page - 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
153 | 'name' => 'Previous page of ' . $user->getUsername() . ' followings' | ||
154 | ]; | ||
155 | } | ||
156 | |||
157 | /** Next page */ | ||
158 | if ($page < $following->getNbPages()) { | ||
159 | $data['next'] = [ | ||
160 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
161 | 'type' => 'Link', | ||
162 | 'href' => $this->generateUrl('following', ['user' => $user->getUsername(), 'page' => $page + 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
163 | 'name' => 'Next page of ' . $user->getUsername() . ' followings' | ||
164 | ]; | ||
165 | } | ||
166 | |||
167 | return new JsonResponse($data); | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * @Route("/profile/@{user}/followers/{page}", name="followers", defaults={"page" : 0}) | ||
172 | * @ParamConverter("user", class="WallabagFederationBundle:Account", options={ | ||
173 | * "repository_method" = "findOneByUsername"}) | ||
174 | * | ||
175 | * @param Request $request | ||
176 | * @param Account $user | ||
177 | * @return JsonResponse | ||
178 | */ | ||
179 | public function getUsersFollowers(Request $request, Account $user, $page) | ||
180 | { | ||
181 | $qb = $this->getDoctrine()->getRepository('WallabagFederationBundle:Account')->getBuilderForFollowersByAccount($user->getId()); | ||
182 | |||
183 | $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false); | ||
184 | |||
185 | $followers = new Pagerfanta($pagerAdapter); | ||
186 | $totalFollowers = $followers->getNbResults(); | ||
187 | |||
188 | $activityStream = in_array('application/ld+json; profile="https://www.w3.org/ns/activitystreams', $request->getAcceptableContentTypes(), true); | ||
189 | |||
190 | if ($page === 0 && $activityStream) { | ||
191 | /** Home page */ | ||
192 | $dataPrez = [ | ||
193 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
194 | 'summary' => $user->getUsername() . " followers'", | ||
195 | 'type' => 'Collection', | ||
196 | 'id' => $this->generateUrl('followers', ['user' => $user->getUsername()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
197 | 'totalItems' => $totalFollowers, | ||
198 | 'first' => [ | ||
199 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
200 | 'type' => 'Link', | ||
201 | 'href' => $this->generateUrl('followers', ['user' => $user->getUsername(), 'page' => 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
202 | 'name' => 'First page of ' . $user->getUsername() . ' followers' | ||
203 | ], | ||
204 | 'last' => [ | ||
205 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
206 | 'type' => 'Link', | ||
207 | 'href' => $this->generateUrl('followers', ['user' => $user->getUsername(), 'page' => $followers->getNbPages()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
208 | 'name' => 'Last page of ' . $user->getUsername() . ' followers' | ||
209 | ] | ||
210 | ]; | ||
211 | return new JsonResponse($dataPrez); | ||
212 | } | ||
213 | |||
214 | $followers->setMaxPerPage(30); | ||
215 | if (!$activityStream && $page === 0) { | ||
216 | $followers->setCurrentPage(1); | ||
217 | } else { | ||
218 | $followers->setCurrentPage($page); | ||
219 | } | ||
220 | |||
221 | if (!$activityStream) { | ||
222 | return $this->render('WallabagFederationBundle:User:followers.html.twig', [ | ||
223 | 'users' => $followers, | ||
224 | 'user' => $user, | ||
225 | 'registration_enabled' => $this->getParameter('wallabag_user.registration_enabled'), | ||
226 | ]); | ||
227 | } | ||
228 | |||
229 | $items = []; | ||
230 | |||
231 | foreach ($followers->getCurrentPageResults() as $follow) { | ||
232 | /** @var Account $follow */ | ||
233 | /** Items in the page */ | ||
234 | $items[] = [ | ||
235 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
236 | 'type' => 'Person', | ||
237 | 'name' => $follow->getUsername(), | ||
238 | 'id' => CloudId::getCloudIdFromAccount($follow)->getDisplayId(), | ||
239 | ]; | ||
240 | } | ||
241 | $data = [ | ||
242 | 'summary' => 'Page ' . $page . ' of ' . $user->getUsername() . ' followers', | ||
243 | 'partOf' => $this->generateUrl('followers', ['user' => $user->getUsername()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
244 | 'type' => 'OrderedCollectionPage', | ||
245 | 'startIndex' => ($page - 1) * 30, | ||
246 | 'orderedItems' => $items, | ||
247 | 'first' => [ | ||
248 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
249 | 'type' => 'Link', | ||
250 | 'href' => $this->generateUrl('followers', ['user' => $user->getUsername(), 'page' => 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
251 | 'name' => 'First page of ' . $user->getUsername() . ' followers' | ||
252 | ], | ||
253 | 'last' => [ | ||
254 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
255 | 'type' => 'Link', | ||
256 | 'href' => $this->generateUrl('followers', ['user' => $user->getUsername(), 'page' => $followers->getNbPages()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
257 | 'name' => 'Last page of ' . $user->getUsername() . ' followers' | ||
258 | ], | ||
259 | ]; | ||
260 | |||
261 | /** Previous page */ | ||
262 | if ($page > 1) { | ||
263 | $data['prev'] = [ | ||
264 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
265 | 'type' => 'Link', | ||
266 | 'href' => $this->generateUrl('followers', ['user' => $user->getUsername(), 'page' => $page - 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
267 | 'name' => 'Previous page of ' . $user->getUsername() . ' followers' | ||
268 | ]; | ||
269 | } | ||
270 | |||
271 | /** Next page */ | ||
272 | if ($page < $followers->getNbPages()) { | ||
273 | $data['next'] = [ | ||
274 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
275 | 'type' => 'Link', | ||
276 | 'href' => $this->generateUrl('followers', ['user' => $user->getUsername(), 'page' => $page + 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
277 | 'name' => 'Next page of ' . $user->getUsername() . ' followers' | ||
278 | ]; | ||
279 | } | ||
280 | |||
281 | return new JsonResponse($data); | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * @Route("/profile/@{userToFollow}/follow", name="follow-user") | ||
286 | * @ParamConverter("userToFollow", class="WallabagFederationBundle:Account", options={ | ||
287 | * "repository_method" = "findOneByUsername"}) | ||
288 | * @param Account $userToFollow | ||
289 | */ | ||
290 | public function followAccountAction(Account $userToFollow) | ||
291 | { | ||
292 | // if we're on our own instance | ||
293 | if ($this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { | ||
294 | |||
295 | /** @var Account $userAccount */ | ||
296 | $userAccount = $this->getUser()->getAccount(); | ||
297 | |||
298 | if ($userToFollow === $userAccount) { | ||
299 | $this->createAccessDeniedException("You can't follow yourself"); | ||
300 | } | ||
301 | |||
302 | $em = $this->getDoctrine()->getManager(); | ||
303 | |||
304 | $userAccount->addFollowing($userToFollow); | ||
305 | $userToFollow->addFollower($userAccount); | ||
306 | |||
307 | $em->persist($userAccount); | ||
308 | $em->persist($userToFollow); | ||
309 | |||
310 | $em->flush(); | ||
311 | } else { | ||
312 | // ask cloud id and redirect to instance | ||
313 | } | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * @Route("/profile/@{user}/recommendations", name="user-recommendations", defaults={"page" : 0}) | ||
318 | * @ParamConverter("user", class="WallabagFederationBundle:Account", options={ | ||
319 | * "repository_method" = "findOneByUsername"}) | ||
320 | * | ||
321 | * @param Request $request | ||
322 | * @param Account $user | ||
323 | * @param int $page | ||
324 | * @return JsonResponse|Response | ||
325 | */ | ||
326 | public function getUsersRecommendationsAction(Request $request, Account $user, $page = 0) | ||
327 | { | ||
328 | $qb = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry')->getBuilderForRecommendationsByUser($user->getUser()->getId()); | ||
329 | |||
330 | $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false); | ||
331 | |||
332 | $recommendations = new Pagerfanta($pagerAdapter); | ||
333 | $totalRecommendations = $recommendations->getNbResults(); | ||
334 | |||
335 | $activityStream = in_array('application/ld+json; profile="https://www.w3.org/ns/activitystreams', $request->getAcceptableContentTypes(), true); | ||
336 | |||
337 | if ($page === 0 && $activityStream) { | ||
338 | $dataPrez = [ | ||
339 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
340 | 'summary' => $user->getUsername() . " recommendations'", | ||
341 | 'type' => 'Collection', | ||
342 | 'id' => $this->generateUrl('user-recommendations', ['user' => $user->getUsername()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
343 | 'totalItems' => $totalRecommendations, | ||
344 | 'first' => [ | ||
345 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
346 | 'type' => 'Link', | ||
347 | 'href' => $this->generateUrl('user-recommendations', ['user' => $user->getUsername(), 'page' => 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
348 | 'name' => 'First page of ' . $user->getUsername() . ' followers' | ||
349 | ], | ||
350 | 'last' => [ | ||
351 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
352 | 'type' => 'Link', | ||
353 | 'href' => $this->generateUrl('user-recommendations', ['user' => $user->getUsername(), 'page' => $recommendations->getNbPages()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
354 | 'name' => 'Last page of ' . $user->getUsername() . ' followers' | ||
355 | ] | ||
356 | ]; | ||
357 | return new JsonResponse($dataPrez); | ||
358 | } | ||
359 | |||
360 | $recommendations->setMaxPerPage(30); | ||
361 | if (!$activityStream && $page === 0) { | ||
362 | $recommendations->setCurrentPage(1); | ||
363 | } else { | ||
364 | $recommendations->setCurrentPage($page); | ||
365 | } | ||
366 | |||
367 | if (!$activityStream) { | ||
368 | return $this->render('WallabagFederationBundle:User:recommendations.html.twig', [ | ||
369 | 'recommendations' => $recommendations, | ||
370 | 'registration_enabled' => $this->getParameter('wallabag_user.registration_enabled'), | ||
371 | ]); | ||
372 | } | ||
373 | |||
374 | $items = []; | ||
375 | |||
376 | foreach ($recommendations->getCurrentPageResults() as $recommendation) { | ||
377 | $items[] = [ | ||
378 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
379 | 'type' => 'Person', | ||
380 | 'name' => $recommendation->getTitle(), | ||
381 | 'id' => $recommendation->getUrl(), | ||
382 | ]; | ||
383 | } | ||
384 | $data = [ | ||
385 | 'summary' => 'Page ' . $page . ' of ' . $user->getUsername() . ' recommendations', | ||
386 | 'partOf' => $this->generateUrl('user-recommendations', ['user' => $user->getUsername()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
387 | 'type' => 'OrderedCollectionPage', | ||
388 | 'startIndex' => ($page - 1) * 30, | ||
389 | 'orderedItems' => $items, | ||
390 | 'first' => [ | ||
391 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
392 | 'type' => 'Link', | ||
393 | 'href' => $this->generateUrl('user-recommendations', ['user' => $user->getUsername(), 'page' => 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
394 | 'name' => 'First page of ' . $user->getUsername() . ' recommendations' | ||
395 | ], | ||
396 | 'last' => [ | ||
397 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
398 | 'type' => 'Link', | ||
399 | 'href' => $this->generateUrl('user-recommendations', ['user' => $user->getUsername(), 'page' => $recommendations->getNbPages()], UrlGeneratorInterface::ABSOLUTE_URL), | ||
400 | 'name' => 'Last page of ' . $user->getUsername() . ' recommendations' | ||
401 | ], | ||
402 | ]; | ||
403 | |||
404 | if ($page > 1) { | ||
405 | $data['prev'] = [ | ||
406 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
407 | 'type' => 'Link', | ||
408 | 'href' => $this->generateUrl('user-recommendations', ['user' => $user->getUsername(), 'page' => $page - 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
409 | 'name' => 'Previous page of ' . $user->getUsername() . ' recommendations' | ||
410 | ]; | ||
411 | } | ||
412 | |||
413 | if ($page < $recommendations->getNbPages()) { | ||
414 | $data['next'] = [ | ||
415 | '@context' => 'https://www.w3.org/ns/activitystreams', | ||
416 | 'type' => 'Link', | ||
417 | 'href' => $this->generateUrl('user-recommendations', ['user' => $user->getUsername(), 'page' => $page + 1], UrlGeneratorInterface::ABSOLUTE_URL), | ||
418 | 'name' => 'Next page of ' . $user->getUsername() . ' recommendations' | ||
419 | ]; | ||
420 | } | ||
421 | |||
422 | return new JsonResponse($data); | ||
423 | } | ||
424 | |||
425 | } | ||
diff --git a/src/Wallabag/FederationBundle/Controller/RecommandController.php b/src/Wallabag/FederationBundle/Controller/RecommandController.php new file mode 100644 index 00000000..ea5a6660 --- /dev/null +++ b/src/Wallabag/FederationBundle/Controller/RecommandController.php | |||
@@ -0,0 +1,34 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\FederationBundle\Controller; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
7 | use Wallabag\CoreBundle\Entity\Entry; | ||
8 | use Wallabag\CoreBundle\Event\Activity\Actions\Federation\RecommendedEntryEvent; | ||
9 | use Wallabag\FederationBundle\Entity\Account; | ||
10 | |||
11 | class RecommandController extends Controller | ||
12 | { | ||
13 | /** | ||
14 | * @Route("/recommend/{entry}", name="recommend-entry") | ||
15 | * | ||
16 | * @param Entry $entry | ||
17 | */ | ||
18 | public function postRecommendAction(Entry $entry) | ||
19 | { | ||
20 | if ($entry->getUser() !== $this->getUser()) { | ||
21 | $this->createAccessDeniedException("You can't recommend entries which are not your own"); | ||
22 | } | ||
23 | $em = $this->getDoctrine()->getManager(); | ||
24 | |||
25 | $entry->setRecommended(true); | ||
26 | |||
27 | $em->persist($entry); | ||
28 | $em->flush(); | ||
29 | |||
30 | $this->get('event_dispatcher')->dispatch(RecommendedEntryEvent::NAME, new RecommendedEntryEvent($entry)); | ||
31 | |||
32 | $this->redirectToRoute('view', ['id' => $entry->getId()]); | ||
33 | } | ||
34 | } | ||