security.authentication.provider.dao.class: Wallabag\CoreBundle\Security\Authentication\Provider\WallabagAuthenticationProvider
security.encoder.digest.class: Wallabag\CoreBundle\Security\Authentication\Encoder\WallabagPasswordEncoder
security.validator.user_password.class: Wallabag\CoreBundle\Security\Validator\WallabagUserPasswordValidator
+ lexik_form_filter.get_filter.doctrine_orm.class: Wallabag\CoreBundle\Event\Subscriber\CustomDoctrineORMSubscriber
services:
# used for tests
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Symfony\Component\HttpFoundation\Request;
+use Wallabag\CoreBundle\Form\Type\NewTagType;
+use Wallabag\CoreBundle\Entity\Tag;
+use Wallabag\CoreBundle\Entity\Entry;
class TagController extends Controller
{
+ /**
+ * @param Request $request
+ *
+ * @Route("/new-tag/{entry}", requirements={"entry" = "\d+"}, name="new_tag")
+ *
+ * @return \Symfony\Component\HttpFoundation\Response
+ */
+ public function addTagFormAction(Request $request, Entry $entry)
+ {
+ $tag = new Tag($this->getUser());
+ $form = $this->createForm(new NewTagType(), $tag);
+ $form->handleRequest($request);
+
+ if ($form->isValid()) {
+ $existingTag = $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Tag')
+ ->findOneByLabelAndUserId($tag->getLabel(), $this->getUser()->getId());
+
+ $em = $this->getDoctrine()->getManager();
+
+ if (is_null($existingTag)) {
+ $entry->addTag($tag);
+ $em->persist($tag);
+ } else {
+ if (!$existingTag->hasEntry($entry)) {
+ $entry->addTag($existingTag);
+ $em->persist($existingTag);
+ }
+ }
+
+ $em->flush();
+
+ $this->get('session')->getFlashBag()->add(
+ 'notice',
+ 'Tag added'
+ );
+
+ return $this->redirect($this->generateUrl('view', array('id' => $entry->getId())));
+ }
+
+ return $this->render('WallabagCoreBundle:Tag:new_form.html.twig', array(
+ 'form' => $form->createView(),
+ 'entry' => $entry,
+ ));
+ }
+
/**
* Shows tags for current user.
*
$this->entries[] = $entry;
}
+ public function hasEntry($entry)
+ {
+ return $this->entries->contains($entry);
+ }
+
/**
* @return User
*/
--- /dev/null
+<?php
+
+namespace Wallabag\CoreBundle\Event\Subscriber;
+
+use Lexik\Bundle\FormFilterBundle\Event\Subscriber\DoctrineORMSubscriber;
+use Lexik\Bundle\FormFilterBundle\Event\GetFilterConditionEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * This custom class override the default behavior of LexikFilterBundle on `filter_date_range`
+ * It converts a date_range to date_time_range to add hour to be able to grab a whole day (from 00:00:00 to 23:59:59).
+ */
+class CustomDoctrineORMSubscriber extends DoctrineORMSubscriber implements EventSubscriberInterface
+{
+ /**
+ * @param GetFilterConditionEvent $event
+ */
+ public function filterDateRange(GetFilterConditionEvent $event)
+ {
+ $expr = $event->getFilterQuery()->getExpressionBuilder();
+ $values = $event->getValues();
+ $value = $values['value'];
+
+ // left date should start at midnight
+ if (isset($value['left_date'][0]) && $value['left_date'][0] instanceof \DateTime) {
+ $value['left_date'][0]->setTime(0, 0, 0);
+ }
+
+ // right adte should end one second before midnight
+ if (isset($value['right_date'][0]) && $value['right_date'][0] instanceof \DateTime) {
+ $value['right_date'][0]->setTime(23, 59, 59);
+ }
+
+ if (isset($value['left_date'][0]) || isset($value['right_date'][0])) {
+ $event->setCondition($expr->dateTimeInRange($event->getField(), $value['left_date'][0], $value['right_date'][0]));
+ }
+ }
+}
),
'format' => 'dd/MM/yyyy',
'widget' => 'single_text',
- ),
- ))
+ ),
+ )
+ )
->add('domainName', 'filter_text', array(
'apply_filter' => function (QueryInterface $filterQuery, $field, $values) {
$value = $values['value'];
--- /dev/null
+<?php
+
+namespace Wallabag\CoreBundle\Form\Type;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+class NewTagType extends AbstractType
+{
+ public function buildForm(FormBuilderInterface $builder, array $options)
+ {
+ $builder
+ ->add('label', 'text', array('required' => true))
+ ->add('save', 'submit')
+ ;
+ }
+
+ public function configureOptions(OptionsResolver $resolver)
+ {
+ $resolver->setDefaults(array(
+ 'data_class' => 'Wallabag\CoreBundle\Entity\Tag',
+ ));
+ }
+
+ public function getName()
+ {
+ return 'tag';
+ }
+}
return new Pagerfanta($pagerAdapter);
}
+
+ /**
+ * Find a tag by its label and its owner.
+ *
+ * @param string $label
+ * @param int $userId
+ *
+ * @return Tag|null
+ */
+ public function findOneByLabelAndUserId($label, $userId)
+ {
+ return $this->createQueryBuilder('t')
+ ->where('t.label = :label')->setParameter('label', $label)
+ ->andWhere('t.user = :user_id')->setParameter('user_id', $userId)
+ ->getQuery()
+ ->getOneOrNullResult();
+ }
}
<h1>{{ entry.title|raw }} <a href="{{ path('edit', { 'id': entry.id }) }}" title="{% trans %}Edit tags{% endtrans %}">✎</a></h1>
</header>
<aside class="tags">
- tags: {% for tag in entry.tags %}<a href="./?view=tag&id={{ tag.id }}">{{ tag.label }}</a> {% endfor %}<a href="./?view=edit-tags&id={{ entry.id }}" title="{% trans %}Edit tags{% endtrans %}">✎</a>
+ {% for tag in entry.tags %}<span class="mdi-action-label-outline">{{ tag.label }}</span>{% endfor %}
+ {{ render(controller( "WallabagCoreBundle:Tag:addTagForm", { 'id': entry.id } )) }}
</aside>
<article>
{{ entry.content | raw }}
--- /dev/null
+<form name="tag" method="post" action="{{ path('new_tag', { 'entry': entry.id })}}">
+
+ {% if form_errors(form) %}
+ <span class="black-text">{{ form_errors(form) }}</span>
+ {% endif %}
+
+ {% if form_errors(form.label) %}
+ <span class="black-text">{{ form_errors(form.label) }}</span>
+ {% endif %}
+
+ {{ form_widget(form.label, { 'attr': {'autocomplete': 'off'} }) }}
+ {{ form_widget(form.save, { 'attr': {'class': 'btn waves-effect waves-light'}, 'label': 'add tag' }) }}
+
+ <div class="hidden">{{ form_rest(form) }}</div>
+</form>
<div class="row">
<div class="input-field col s12">
<label>Rss token</label>
- {% if rss.token %}
- {{ rss.token }}
- {% else %}
- <em>No token</em>
- {% endif %}
- –
- <a href="{{ path('generate_token') }}">Regenerate ?</a>
+ <div>
+ {% if rss.token %}
+ {{ rss.token }}
+ {% else %}
+ <em>No token</em>
+ {% endif %}
+ –
+ <a href="{{ path('generate_token') }}">Regenerate ?</a>
+ </div>
</div>
</div>
<a href="{{ entry.url|e }}" target="_blank" title="{% trans %}original{% endtrans %} : {{ entry.title|e }}" class="tool link"><span>{{ entry.domainName }}</span></a>
</header>
<aside class="tags">
- tags: {% for tag in entry.tags %}<a href="./?view=tag&id={{ tag.id }}">{{ tag.label }}</a> {% endfor %}<a href="./?view=edit-tags&id={{ entry.id }}" title="{% trans %}Edit tags{% endtrans %}">✎</a>
+ {% for tag in entry.tags %}<span class="mdi-action-label-outline">{{ tag.label }}</span>{% endfor %}
+ {{ render(controller( "WallabagCoreBundle:Tag:addTagForm", { 'id': entry.id } )) }}
</aside>
<article>
{{ entry.content | raw }}
--- /dev/null
+<form name="tag" method="post" action="{{ path('new_tag', { 'entry': entry.id })}}">
+
+ {% if form_errors(form) %}
+ <span class="black-text">{{ form_errors(form) }}</span>
+ {% endif %}
+
+ {% if form_errors(form.label) %}
+ <span class="black-text">{{ form_errors(form.label) }}</span>
+ {% endif %}
+
+ {{ form_widget(form.label, { 'attr': {'autocomplete': 'off'} }) }}
+ {{ form_widget(form.save, { 'attr': {'class': 'btn waves-effect waves-light'}, 'label': 'add tag' }) }}
+
+ <div class="hidden">{{ form_rest(form) }}</div>
+</form>
0 = Common
1 = Nav
2 = Side-nav
-
- 2 = Layout
- 3 = Pictos
- 4 = Messages
+ 3 = Filters slider
+ 4 = Cards
5 = Article
-
6 = Media queries
+ 7 = Others
========================================================================== */
}
/* ==========================================================================
- 3 = Cards
+ 4 = Cards
========================================================================== */
main #content {
}
/* ==========================================================================
- 4 = Article
+ 5 = Article
========================================================================== */
#article {
display: none;
}
}
+/* ==========================================================================
+ 7 = Others
+ ========================================================================== */
+
+div.input-field div, div.input-field ul {
+ margin-top: 40px;
+}
$this->assertCount(5, $crawler->filter('div[class=entry]'));
+ $data = array(
+ 'entry_filter[createdAt][left_date]' => date('d/m/Y'),
+ 'entry_filter[createdAt][right_date]' => date('d/m/Y'),
+ );
+
+ $crawler = $client->submit($form, $data);
+
+ $this->assertCount(5, $crawler->filter('div[class=entry]'));
+
$data = array(
'entry_filter[createdAt][left_date]' => '01/01/1970',
'entry_filter[createdAt][right_date]' => '01/01/1970',
$this->assertEquals(200, $client->getResponse()->getStatusCode());
}
+
+ public function testAddTagToEntry()
+ {
+ $this->logInAs('admin');
+ $client = $this->getClient();
+
+ $entry = $client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneByIsArchived(false);
+
+ $crawler = $client->request('GET', '/view/'.$entry->getId());
+
+ $form = $crawler->filter('button[id=tag_save]')->form();
+
+ $data = array(
+ 'tag[label]' => 'opensource',
+ );
+
+ $client->submit($form, $data);
+ $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+ $this->assertEquals(1, count($entry->getTags()));
+
+ # tag already exists and already assigned
+ $client->submit($form, $data);
+ $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+ $newEntry = $client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneById($entry->getId());
+
+ $this->assertEquals(1, count($newEntry->getTags()));
+
+ # tag already exists but still not assigned to this entry
+ $data = array(
+ 'tag[label]' => 'foo',
+ );
+
+ $client->submit($form, $data);
+ $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+ $newEntry = $client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneById($entry->getId());
+
+ $this->assertEquals(2, count($newEntry->getTags()));
+ }
}