mirror of
https://github.com/wallabag/wallabag.git
synced 2024-11-30 04:51:01 +00:00
Comment work with annotator v2
- add missing annotator.js file and fix typo - edit & delete routes, started tests - basic tests
This commit is contained in:
parent
d3f1a9dc1a
commit
f38e03dc02
20 changed files with 828 additions and 9 deletions
|
@ -35,6 +35,7 @@ class AppKernel extends Kernel
|
||||||
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
|
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
|
||||||
new Craue\ConfigBundle\CraueConfigBundle(),
|
new Craue\ConfigBundle\CraueConfigBundle(),
|
||||||
new Lexik\Bundle\MaintenanceBundle\LexikMaintenanceBundle(),
|
new Lexik\Bundle\MaintenanceBundle\LexikMaintenanceBundle(),
|
||||||
|
new Wallabag\CommentBundle\WallabagCommentBundle(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
|
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
wallabag_comment:
|
||||||
|
type : rest
|
||||||
|
resource: "@WallabagCommentBundle/Resources/config/routing_comments.yml"
|
||||||
|
|
||||||
wallabag_import:
|
wallabag_import:
|
||||||
resource: "@WallabagImportBundle/Controller/"
|
resource: "@WallabagImportBundle/Controller/"
|
||||||
type: annotation
|
type: annotation
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
Rest_Wallabag:
|
Rest_Wallabag:
|
||||||
type : rest
|
type : rest
|
||||||
resource: "@WallabagApiBundle/Resources/config/routing_rest.yml"
|
resource: "@WallabagApiBundle/Resources/config/routing_rest.yml"
|
||||||
|
|
||||||
|
|
|
@ -58,4 +58,5 @@ security:
|
||||||
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
|
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||||
- { path: /(unread|starred|archive).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
- { path: /(unread|starred|archive).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||||
- { path: ^/settings, roles: ROLE_SUPER_ADMIN }
|
- { path: ^/settings, roles: ROLE_SUPER_ADMIN }
|
||||||
|
- { path: ^/annotations, roles: ROLE_USER }
|
||||||
- { path: ^/, roles: ROLE_USER }
|
- { path: ^/, roles: ROLE_USER }
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CommentBundle\Controller;
|
||||||
|
|
||||||
|
use FOS\RestBundle\Controller\FOSRestController;
|
||||||
|
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||||
|
use Wallabag\CommentBundle\Entity\Comment;
|
||||||
|
use Wallabag\CoreBundle\Entity\Entry;
|
||||||
|
|
||||||
|
class WallabagCommentController extends FOSRestController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Retrieve comments for an entry.
|
||||||
|
*
|
||||||
|
* @ApiDoc(
|
||||||
|
* requirements={
|
||||||
|
* {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function getAnnotationsAction(Entry $entry)
|
||||||
|
{
|
||||||
|
$commentRows = $this
|
||||||
|
->getDoctrine()
|
||||||
|
->getRepository('WallabagCommentBundle:Comment')
|
||||||
|
->findCommentsByPageId($entry->getId(), $this->getUser()->getId());
|
||||||
|
$total = count($commentRows);
|
||||||
|
$comments = array('total' => $total, 'rows' => $commentRows);
|
||||||
|
|
||||||
|
$json = $this->get('serializer')->serialize($comments, 'json');
|
||||||
|
|
||||||
|
return $this->renderJsonResponse($json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new comment.
|
||||||
|
*
|
||||||
|
* @param Entry $entry
|
||||||
|
*
|
||||||
|
* @ApiDoc(
|
||||||
|
* requirements={
|
||||||
|
* {"name"="ranges", "dataType"="array", "requirement"="\w+", "description"="The range array for the annotation"},
|
||||||
|
* {"name"="quote", "dataType"="string", "required"=false, "description"="Optional, quote for the comment"},
|
||||||
|
* {"name"="text", "dataType"="string", "required"=true, "description"=""},
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function postAnnotationAction(Request $request, Entry $entry)
|
||||||
|
{
|
||||||
|
$data = json_decode($request->getContent(), true);
|
||||||
|
|
||||||
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
|
||||||
|
$comment = new Comment($this->getUser());
|
||||||
|
|
||||||
|
$comment->setText($data['text']);
|
||||||
|
if (array_key_exists('quote', $data)) {
|
||||||
|
$comment->setQuote($data['quote']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('ranges', $data)) {
|
||||||
|
$comment->setRanges($data['ranges']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$comment->setEntry($entry);
|
||||||
|
|
||||||
|
$em->persist($comment);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
$json = $this->get('serializer')->serialize($comment, 'json');
|
||||||
|
|
||||||
|
return $this->renderJsonResponse($json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a comment.
|
||||||
|
*
|
||||||
|
* @ApiDoc(
|
||||||
|
* requirements={
|
||||||
|
* {"name"="comment", "dataType"="string", "requirement"="\w+", "description"="The comment ID"}
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* @ParamConverter("comment", class="WallabagCommentBundle:Comment")
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function putAnnotationAction(Comment $comment, Request $request)
|
||||||
|
{
|
||||||
|
$data = json_decode($request->getContent(), true);
|
||||||
|
|
||||||
|
if (!is_null($data['text'])) {
|
||||||
|
$comment->setText($data['text']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
$json = $this->get('serializer')->serialize($comment, 'json');
|
||||||
|
|
||||||
|
return $this->renderJsonResponse($json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a comment.
|
||||||
|
*
|
||||||
|
* @ApiDoc(
|
||||||
|
* requirements={
|
||||||
|
* {"name"="comment", "dataType"="string", "requirement"="\w+", "description"="The comment ID"}
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* @ParamConverter("comment", class="WallabagCommentBundle:Comment")
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function deleteAnnotationAction(Comment $comment)
|
||||||
|
{
|
||||||
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
$em->remove($comment);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
$json = $this->get('serializer')->serialize($comment, 'json');
|
||||||
|
|
||||||
|
return $this->renderJsonResponse($json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a JSON Response.
|
||||||
|
* We don't use the Symfony JsonRespone, because it takes an array as parameter instead of a JSON string.
|
||||||
|
*
|
||||||
|
* @param string $json
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
private function renderJsonResponse($json, $code = 200)
|
||||||
|
{
|
||||||
|
return new Response($json, $code, array('application/json'));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CoreBundle\DataFixtures\ORM;
|
||||||
|
|
||||||
|
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||||
|
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||||
|
use Doctrine\Common\Persistence\ObjectManager;
|
||||||
|
use Wallabag\CommentBundle\Entity\Comment;
|
||||||
|
|
||||||
|
class LoadCommentData extends AbstractFixture implements OrderedFixtureInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function load(ObjectManager $manager)
|
||||||
|
{
|
||||||
|
$comment1 = new Comment($this->getReference('admin-user'));
|
||||||
|
$comment1->setEntry($this->getReference('entry1'));
|
||||||
|
$comment1->setText('This is my comment /o/');
|
||||||
|
$comment1->setQuote('content');
|
||||||
|
|
||||||
|
$manager->persist($comment1);
|
||||||
|
|
||||||
|
$this->addReference('comment1', $comment1);
|
||||||
|
|
||||||
|
$comment2 = new Comment($this->getReference('admin-user'));
|
||||||
|
$comment2->setEntry($this->getReference('entry2'));
|
||||||
|
$comment2->setText('This is my 2nd comment /o/');
|
||||||
|
$comment2->setQuote('content');
|
||||||
|
|
||||||
|
$manager->persist($comment2);
|
||||||
|
|
||||||
|
$this->addReference('comment2', $comment2);
|
||||||
|
|
||||||
|
$manager->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getOrder()
|
||||||
|
{
|
||||||
|
return 35;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CommentBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||||
|
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||||
|
|
||||||
|
class Configuration implements ConfigurationInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getConfigTreeBuilder()
|
||||||
|
{
|
||||||
|
$treeBuilder = new TreeBuilder();
|
||||||
|
$rootNode = $treeBuilder->root('wallabag_comment');
|
||||||
|
|
||||||
|
return $treeBuilder;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CommentBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\Config\FileLocator;
|
||||||
|
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||||
|
use Symfony\Component\DependencyInjection\Loader;
|
||||||
|
|
||||||
|
class WallabagCommentExtension extends Extension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function load(array $configs, ContainerBuilder $container)
|
||||||
|
{
|
||||||
|
$configuration = new Configuration();
|
||||||
|
$config = $this->processConfiguration($configuration, $configs);
|
||||||
|
|
||||||
|
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||||
|
$loader->load('services.yml');
|
||||||
|
}
|
||||||
|
}
|
270
src/Wallabag/CommentBundle/Entity/Comment.php
Normal file
270
src/Wallabag/CommentBundle/Entity/Comment.php
Normal file
|
@ -0,0 +1,270 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CommentBundle\Entity;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use JMS\Serializer\Annotation\ExclusionPolicy;
|
||||||
|
use JMS\Serializer\Annotation\Exclude;
|
||||||
|
use JMS\Serializer\Annotation\VirtualProperty;
|
||||||
|
use JMS\Serializer\Annotation\SerializedName;
|
||||||
|
use Wallabag\UserBundle\Entity\User;
|
||||||
|
use Wallabag\CoreBundle\Entity\Entry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment.
|
||||||
|
*
|
||||||
|
* @ORM\Table(name="comment")
|
||||||
|
* @ORM\Entity(repositoryClass="Wallabag\CommentBundle\Repository\CommentRepository")
|
||||||
|
* @ORM\HasLifecycleCallbacks()
|
||||||
|
* @ExclusionPolicy("none")
|
||||||
|
*/
|
||||||
|
class Comment
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="id", type="integer")
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\GeneratedValue(strategy="AUTO")
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="text", type="text")
|
||||||
|
*/
|
||||||
|
private $text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \DateTime
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="created_at", type="datetime")
|
||||||
|
*/
|
||||||
|
private $createdAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \DateTime
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="updated_at", type="datetime")
|
||||||
|
*/
|
||||||
|
private $updatedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="quote", type="string")
|
||||||
|
*/
|
||||||
|
private $quote;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="ranges", type="array")
|
||||||
|
*/
|
||||||
|
private $ranges;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Exclude
|
||||||
|
*
|
||||||
|
* @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User")
|
||||||
|
*/
|
||||||
|
private $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Exclude
|
||||||
|
*
|
||||||
|
* @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\Entry", inversedBy="comments")
|
||||||
|
* @ORM\JoinColumn(name="entry_id", referencedColumnName="id")
|
||||||
|
*/
|
||||||
|
private $entry;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param User $user
|
||||||
|
*/
|
||||||
|
public function __construct(\Wallabag\UserBundle\Entity\User $user)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get id.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set text.
|
||||||
|
*
|
||||||
|
* @param string $text
|
||||||
|
*
|
||||||
|
* @return Comment
|
||||||
|
*/
|
||||||
|
public function setText($text)
|
||||||
|
{
|
||||||
|
$this->text = $text;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get text.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getText()
|
||||||
|
{
|
||||||
|
return $this->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\PrePersist
|
||||||
|
* @ORM\PreUpdate
|
||||||
|
*/
|
||||||
|
public function timestamps()
|
||||||
|
{
|
||||||
|
if (is_null($this->createdAt)) {
|
||||||
|
$this->createdAt = new \DateTime();
|
||||||
|
}
|
||||||
|
$this->updatedAt = new \DateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get created.
|
||||||
|
*
|
||||||
|
* @return \DateTime
|
||||||
|
*/
|
||||||
|
public function getCreatedAt()
|
||||||
|
{
|
||||||
|
return $this->createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get updated.
|
||||||
|
*
|
||||||
|
* @return \DateTime
|
||||||
|
*/
|
||||||
|
public function getUpdatedAt()
|
||||||
|
{
|
||||||
|
return $this->updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get quote.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getQuote()
|
||||||
|
{
|
||||||
|
return $this->quote;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set quote.
|
||||||
|
*
|
||||||
|
* @param string $quote
|
||||||
|
*
|
||||||
|
* @return Comment
|
||||||
|
*/
|
||||||
|
public function setQuote($quote)
|
||||||
|
{
|
||||||
|
$this->quote = $quote;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get ranges.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getRanges()
|
||||||
|
{
|
||||||
|
return $this->ranges;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set ranges.
|
||||||
|
*
|
||||||
|
* @param array $ranges
|
||||||
|
*
|
||||||
|
* @return Comment
|
||||||
|
*/
|
||||||
|
public function setRanges($ranges)
|
||||||
|
{
|
||||||
|
$this->ranges = $ranges;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set user.
|
||||||
|
*
|
||||||
|
* @param string $user
|
||||||
|
*
|
||||||
|
* @return Comment
|
||||||
|
*/
|
||||||
|
public function setUser($user)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get user.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUser()
|
||||||
|
{
|
||||||
|
return $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @VirtualProperty
|
||||||
|
* @SerializedName("user")
|
||||||
|
*/
|
||||||
|
public function getUserName()
|
||||||
|
{
|
||||||
|
return $this->user->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set entry.
|
||||||
|
*
|
||||||
|
* @param Entry $entry
|
||||||
|
*
|
||||||
|
* @return Comment
|
||||||
|
*/
|
||||||
|
public function setEntry($entry)
|
||||||
|
{
|
||||||
|
$this->entry = $entry;
|
||||||
|
$entry->setComment($this);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get entry.
|
||||||
|
*
|
||||||
|
* @return Entry
|
||||||
|
*/
|
||||||
|
public function getEntry()
|
||||||
|
{
|
||||||
|
return $this->entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @VirtualProperty
|
||||||
|
* @SerializedName("annotator_schema_version")
|
||||||
|
*/
|
||||||
|
public function getVersion()
|
||||||
|
{
|
||||||
|
return 'v1.0';
|
||||||
|
}
|
||||||
|
}
|
94
src/Wallabag/CommentBundle/Repository/CommentRepository.php
Normal file
94
src/Wallabag/CommentBundle/Repository/CommentRepository.php
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CommentBundle\Repository;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CommentRepository.
|
||||||
|
*
|
||||||
|
* This class was generated by the Doctrine ORM. Add your own custom
|
||||||
|
* repository methods below.
|
||||||
|
*/
|
||||||
|
class CommentRepository extends EntityRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Return a query builder to used by other getBuilderFor* method.
|
||||||
|
*
|
||||||
|
* @param int $userId
|
||||||
|
*
|
||||||
|
* @return QueryBuilder
|
||||||
|
*/
|
||||||
|
private function getBuilderByUser($userId)
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('c')
|
||||||
|
->leftJoin('c.user', 'u')
|
||||||
|
->andWhere('u.id = :userId')->setParameter('userId', $userId)
|
||||||
|
->orderBy('c.id', 'desc')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all comments for a user.
|
||||||
|
*
|
||||||
|
* @param int $userId
|
||||||
|
*
|
||||||
|
* @return QueryBuilder
|
||||||
|
*/
|
||||||
|
public function getBuilderForAllByUser($userId)
|
||||||
|
{
|
||||||
|
return $this
|
||||||
|
->getBuilderByUser($userId)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get comment for this id.
|
||||||
|
*
|
||||||
|
* @param int $commentId
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function findCommentById($commentId)
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('c')
|
||||||
|
->andWhere('c.id = :commentId')->setParameter('commentId', $commentId)
|
||||||
|
->getQuery()->getSingleResult()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find comments for entry id.
|
||||||
|
*
|
||||||
|
* @param int $entryId
|
||||||
|
* @param int $userId
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function findCommentsByPageId($entryId, $userId)
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('c')
|
||||||
|
->where('c.entry = :entryId')->setParameter('entryId', $entryId)
|
||||||
|
->andwhere('c.user = :userId')->setParameter('userId', $userId)
|
||||||
|
->getQuery()->getResult()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find last comment for a given entry id. Used only for tests.
|
||||||
|
*
|
||||||
|
* @param int $entryId
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function findLastCommentByPageId($entryId, $userId)
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('c')
|
||||||
|
->where('c.entry = :entryId')->setParameter('entryId', $entryId)
|
||||||
|
->andwhere('c.user = :userId')->setParameter('userId', $userId)
|
||||||
|
->orderBy('c.id', 'DESC')
|
||||||
|
->setMaxResults(1)
|
||||||
|
->getQuery()
|
||||||
|
->getOneOrNullResult();
|
||||||
|
}
|
||||||
|
}
|
0
src/Wallabag/CommentBundle/Resources/config/routing.yml
Normal file
0
src/Wallabag/CommentBundle/Resources/config/routing.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
annotations:
|
||||||
|
type: rest
|
||||||
|
resource: "WallabagCommentBundle:WallabagComment"
|
||||||
|
name_prefix: annotations_
|
4
src/Wallabag/CommentBundle/Resources/config/services.yml
Normal file
4
src/Wallabag/CommentBundle/Resources/config/services.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
services:
|
||||||
|
# wallabag_comment.example:
|
||||||
|
# class: Wallabag\CommentBundle\Example
|
||||||
|
# arguments: ["@service_id", "plain_value", %parameter%]
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CommentBundle\Tests\Controller;
|
||||||
|
|
||||||
|
use Wallabag\CommentBundle\Tests\WallabagCommentTestCase;
|
||||||
|
|
||||||
|
class CommentControllerTest extends WallabagCommentTestCase
|
||||||
|
{
|
||||||
|
public function testGetComments()
|
||||||
|
{
|
||||||
|
$comment = $this->client->getContainer()
|
||||||
|
->get('doctrine.orm.entity_manager')
|
||||||
|
->getRepository('WallabagCommentBundle:Comment')
|
||||||
|
->findOneBy(array('user' => 1));
|
||||||
|
|
||||||
|
if (!$comment) {
|
||||||
|
$this->markTestSkipped('No content found in db.');
|
||||||
|
}
|
||||||
|
$this->logInAs('admin');
|
||||||
|
$crawler = $this->client->request('GET', 'annotations/'.$comment->getEntry()->getId().'.json');
|
||||||
|
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||||
|
|
||||||
|
$content = json_decode($this->client->getResponse()->getContent(), true);
|
||||||
|
$this->assertEquals(1, $content['total']);
|
||||||
|
$this->assertEquals($comment->getText(), $content['rows'][0]['text']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetcomment()
|
||||||
|
{
|
||||||
|
$this->logInAs('admin');
|
||||||
|
|
||||||
|
$entry = $this->client->getContainer()
|
||||||
|
->get('doctrine.orm.entity_manager')
|
||||||
|
->getRepository('WallabagCoreBundle:Entry')
|
||||||
|
->findOneBy(array('user' => 1));
|
||||||
|
|
||||||
|
$headers = array('CONTENT_TYPE' => 'application/json');
|
||||||
|
$content = json_encode(array(
|
||||||
|
'text' => 'my comment',
|
||||||
|
'quote' => 'my quote',
|
||||||
|
'range' => '[{"start":"","startOffset":24,"end":"","endOffset":31}]',
|
||||||
|
));
|
||||||
|
$crawler = $this->client->request('POST', 'annotations/'.$entry->getId().'.json', array(), array(), $headers, $content);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||||
|
|
||||||
|
$comment = $this->client->getContainer()
|
||||||
|
->get('doctrine.orm.entity_manager')
|
||||||
|
->getRepository('WallabagCommentBundle:Comment')
|
||||||
|
->findLastCommentByPageId($entry->getId(), 1);
|
||||||
|
|
||||||
|
$this->assertEquals('my comment', $comment->getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEditcomment()
|
||||||
|
{
|
||||||
|
$comment = $this->client->getContainer()
|
||||||
|
->get('doctrine.orm.entity_manager')
|
||||||
|
->getRepository('WallabagCommentBundle:Comment')
|
||||||
|
->findOneBy(array('user' => 1));
|
||||||
|
|
||||||
|
$this->logInAs('admin');
|
||||||
|
|
||||||
|
$headers = array('CONTENT_TYPE' => 'application/json');
|
||||||
|
$content = json_encode(array(
|
||||||
|
'text' => 'a modified comment',
|
||||||
|
));
|
||||||
|
$crawler = $this->client->request('PUT', 'annotations/'.$comment->getId().'.json', array(), array(), $headers, $content);
|
||||||
|
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||||
|
|
||||||
|
$content = json_decode($this->client->getResponse()->getContent(), true);
|
||||||
|
|
||||||
|
$this->assertEquals('a modified comment', $content['text']);
|
||||||
|
|
||||||
|
$commentUpdated = $this->client->getContainer()
|
||||||
|
->get('doctrine.orm.entity_manager')
|
||||||
|
->getRepository('WallabagCommentBundle:Comment')
|
||||||
|
->findCommentById($comment->getId());
|
||||||
|
$this->assertEquals('a modified comment', $commentUpdated->getText());
|
||||||
|
}
|
||||||
|
}
|
63
src/Wallabag/CommentBundle/Tests/WallabagCommentTestCase.php
Normal file
63
src/Wallabag/CommentBundle/Tests/WallabagCommentTestCase.php
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CommentBundle\Tests;
|
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||||
|
use Symfony\Component\BrowserKit\Cookie;
|
||||||
|
|
||||||
|
abstract class WallabagCommentTestCase extends WebTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Client
|
||||||
|
*/
|
||||||
|
protected $client = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \FOS\UserBundle\Model\UserInterface
|
||||||
|
*/
|
||||||
|
protected $user;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->client = $this->createAuthorizedClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logInAs($username)
|
||||||
|
{
|
||||||
|
$crawler = $this->client->request('GET', '/login');
|
||||||
|
$form = $crawler->filter('button[type=submit]')->form();
|
||||||
|
$data = array(
|
||||||
|
'_username' => $username,
|
||||||
|
'_password' => 'mypassword',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->client->submit($form, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Client
|
||||||
|
*/
|
||||||
|
protected function createAuthorizedClient()
|
||||||
|
{
|
||||||
|
$client = static::createClient();
|
||||||
|
$container = $client->getContainer();
|
||||||
|
|
||||||
|
/** @var $userManager \FOS\UserBundle\Doctrine\UserManager */
|
||||||
|
$userManager = $container->get('fos_user.user_manager');
|
||||||
|
/** @var $loginManager \FOS\UserBundle\Security\LoginManager */
|
||||||
|
$loginManager = $container->get('fos_user.security.login_manager');
|
||||||
|
$firewallName = $container->getParameter('fos_user.firewall_name');
|
||||||
|
|
||||||
|
$this->user = $userManager->findUserBy(array('username' => 'admin'));
|
||||||
|
$loginManager->loginUser($firewallName, $this->user);
|
||||||
|
|
||||||
|
// save the login token into the session and put it in a cookie
|
||||||
|
$container->get('session')->set('_security_'.$firewallName, serialize($container->get('security.token_storage')->getToken()));
|
||||||
|
$container->get('session')->save();
|
||||||
|
|
||||||
|
$session = $container->get('session');
|
||||||
|
$client->getCookieJar()->set(new Cookie($session->getName(), $session->getId()));
|
||||||
|
|
||||||
|
return $client;
|
||||||
|
}
|
||||||
|
}
|
9
src/Wallabag/CommentBundle/WallabagCommentBundle.php
Normal file
9
src/Wallabag/CommentBundle/WallabagCommentBundle.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CommentBundle;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||||
|
|
||||||
|
class WallabagCommentBundle extends Bundle
|
||||||
|
{
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ use JMS\Serializer\Annotation\Groups;
|
||||||
use JMS\Serializer\Annotation\XmlRoot;
|
use JMS\Serializer\Annotation\XmlRoot;
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
use Wallabag\UserBundle\Entity\User;
|
use Wallabag\UserBundle\Entity\User;
|
||||||
|
use Wallabag\CommentBundle\Entity\Comment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry.
|
* Entry.
|
||||||
|
@ -98,11 +99,10 @@ class Entry
|
||||||
private $updatedAt;
|
private $updatedAt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @ORM\OneToMany(targetEntity="Wallabag\CommentBundle\Entity\Comment", mappedBy="entry", cascade={"persist", "remove"})
|
||||||
|
* @ORM\JoinTable
|
||||||
*
|
*
|
||||||
* @ORM\Column(name="comments", type="text", nullable=true)
|
* @Groups({"entries_for_user", "export_all"})
|
||||||
*
|
|
||||||
* @Groups({"export_all"})
|
|
||||||
*/
|
*/
|
||||||
private $comments;
|
private $comments;
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ class Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return ArrayCollection<Comment>
|
||||||
*/
|
*/
|
||||||
public function getComments()
|
public function getComments()
|
||||||
{
|
{
|
||||||
|
@ -374,11 +374,11 @@ class Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $comments
|
* @param Comment $comment
|
||||||
*/
|
*/
|
||||||
public function setComments($comments)
|
public function setComment(Comment $comment)
|
||||||
{
|
{
|
||||||
$this->comments = $comments;
|
$this->comments[] = $comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
25
src/Wallabag/CoreBundle/Resources/public/themes/_global/js/annotator.min.js
vendored
Normal file
25
src/Wallabag/CoreBundle/Resources/public/themes/_global/js/annotator.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -38,11 +38,13 @@
|
||||||
|
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="{{ asset('bundles/wallabagcore/themes/_global/img/appicon/favicon.ico') }}">
|
<link rel="shortcut icon" type="image/x-icon" href="{{ asset('bundles/wallabagcore/themes/_global/img/appicon/favicon.ico') }}">
|
||||||
|
|
||||||
{% block css %}{% endblock %}
|
{% block css %}
|
||||||
|
{% endblock %}
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script src="{{ asset('bundles/wallabagcore/themes/_global/js/jquery-2.0.3.min.js') }}"></script>
|
<script src="{{ asset('bundles/wallabagcore/themes/_global/js/jquery-2.0.3.min.js') }}"></script>
|
||||||
<script src="{{ asset('bundles/wallabagcore/themes/_global/js/jquery.cookie.js') }}"></script>
|
<script src="{{ asset('bundles/wallabagcore/themes/_global/js/jquery.cookie.js') }}"></script>
|
||||||
<script src="{{ asset('bundles/wallabagcore/themes/_global/js/bookmarklet.js') }}"></script>
|
<script src="{{ asset('bundles/wallabagcore/themes/_global/js/bookmarklet.js') }}"></script>
|
||||||
|
<script src="{{ asset('bundles/wallabagcore/themes/_global/js/annotator.min.js') }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
<title>{% block title %}{% endblock %}</title>
|
<title>{% block title %}{% endblock %}</title>
|
||||||
|
|
|
@ -177,6 +177,32 @@ main {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var app = new annotator.App();
|
||||||
|
app.include(annotator.ui.main, {
|
||||||
|
element: document.querySelector('article')
|
||||||
|
});
|
||||||
|
app.include(annotator.storage.http, {
|
||||||
|
prefix: '',
|
||||||
|
urls: {
|
||||||
|
create: '{{ path('annotations_post_annotation', { 'entry': entry.id }) }}',
|
||||||
|
update: '{{ path('annotations_put_annotation', { 'comment': 'idComment' }) }}',
|
||||||
|
destroy: '{{ path('annotations_delete_annotation', { 'comment': 'idComment' }) }}',
|
||||||
|
search: '{{ path('annotations_get_annotations', { 'entry': entry.id }) }}'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app
|
||||||
|
.start()
|
||||||
|
.then(function () {
|
||||||
|
app.annotations.load({entry: {{ entry.id }}});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
Loading…
Reference in a new issue