Browse Source

Evolution #164: Proposition de tag sur un élément

bastien 13 years ago
parent
commit
99dff9e2bd

+ 5 - 0
app/Resources/translations/elements.fr.yml View File

55
       label:            M'avertir en cas de nouveaux commentaires
55
       label:            M'avertir en cas de nouveaux commentaires
56
   vote:
56
   vote:
57
     good:               Ce partage mérite un point supplémentaire (cliquez a nouveau pour enlever)
57
     good:               Ce partage mérite un point supplémentaire (cliquez a nouveau pour enlever)
58
+  tag_proposition:
59
+    form:
60
+      submit:           Proposer ces tags
61
+      cancel:           Annuler
62
+      description:      Proposez ci-dessous les tags que vous trouvez les plus appropriés pour ce partage
58
   
63
   
59
 comment:
64
 comment:
60
   edit:
65
   edit:

+ 3 - 1
app/Resources/translations/userui.fr.yml View File

119
     confirm: 
119
     confirm: 
120
       sentence:          Signaler ce contenu comme inapproprié ?
120
       sentence:          Signaler ce contenu comme inapproprié ?
121
       yes:               Oui
121
       yes:               Oui
122
-      no:                Non
122
+      no:                Non
123
+  proposition_tags:
124
+    link_title:        Proposer des tags

+ 118 - 0
src/Muzich/CoreBundle/Controller/ElementController.php View File

5
 use Muzich\CoreBundle\lib\Controller;
5
 use Muzich\CoreBundle\lib\Controller;
6
 use Muzich\CoreBundle\ElementFactory\ElementManager;
6
 use Muzich\CoreBundle\ElementFactory\ElementManager;
7
 use Muzich\CoreBundle\Propagator\EventElement;
7
 use Muzich\CoreBundle\Propagator\EventElement;
8
+use Muzich\CoreBundle\Entity\ElementTagsProposition;
8
 
9
 
9
 class ElementController extends Controller
10
 class ElementController extends Controller
10
 {
11
 {
489
       )
490
       )
490
     ));
491
     ));
491
   }
492
   }
493
+    
494
+  /**
495
+   * Retourne un json avec le form permettant a l'utilisateur de proposer des
496
+   * tags sur un élément.
497
+   * 
498
+   * @param int $element_id
499
+   * @return Response 
500
+   */
501
+  public function proposeTagsOpenAction($element_id)
502
+  {
503
+    if (($response = $this->mustBeConnected(true)))
504
+    {
505
+      return $response;
506
+    }
507
+    
508
+    if (!($element = $this->getDoctrine()->getRepository('MuzichCoreBundle:Element')
509
+      ->findOneById($element_id)))
510
+    {
511
+      return $this->jsonResponse(array(
512
+        'status' => 'error',
513
+        'errors' => array('NotFound')
514
+      ));
515
+    }
516
+    
517
+    $search_tags = array();
518
+    foreach ($element->getTags() as $tag)
519
+    {
520
+      $search_tags[$tag->getId()] = $tag->getName();
521
+    }
522
+    
523
+    $element->setTags($element->getTagsIdsJson());
524
+    $form = $this->getAddForm($element, 'element_tag_proposition_'.$element->getId());
525
+    $response = $this->render('MuzichCoreBundle:Element:tag.proposition.html.twig', array(
526
+      'form'        => $form->createView(),
527
+      'form_name'   => 'element_tag_proposition_'.$element->getId(),
528
+      'element_id'  => $element->getId(),
529
+      'search_tags' => $search_tags
530
+    ));
531
+    
532
+    if ($this->getRequest()->isXmlHttpRequest())
533
+    {
534
+      return $this->jsonResponse(array(
535
+        'status'    => 'success',
536
+        'form_name' => 'element_tag_proposition_'.$element->getId(),
537
+        'tags'      => $search_tags,
538
+        'html'      => $response->getContent()
539
+      ));
540
+    }
541
+  }
542
+  
543
+  public function proposeTagsProceedAction($element_id, $token)
544
+  {
545
+    if (($response = $this->mustBeConnected(true)))
546
+    {
547
+      return $response;
548
+    }
549
+    
550
+    if (!($element = $this->getDoctrine()->getRepository('MuzichCoreBundle:Element')
551
+      ->findOneById($element_id)) || $token != $this->getUser()->getPersonalHash())
552
+    {
553
+      return $this->jsonResponse(array(
554
+        'status' => 'error',
555
+        'errors' => array('NotFound')
556
+      ));
557
+    }
558
+    
559
+    $values   = $this->getRequest()->request->get('element_tag_proposition_'.$element->getId());
560
+    $tags_ids = json_decode($values['tags'], true);
561
+    
562
+    // On récupère les tags en base
563
+    $tags = $this->getDoctrine()->getEntityManager()->getRepository('MuzichCoreBundle:Tag')
564
+      ->getTagsWithIds($tags_ids)
565
+    ;
566
+    
567
+    if (!count($tags))
568
+    {
569
+      return $this->jsonResponse(array(
570
+        'status' => 'error',
571
+        'errors' => array('NotFound')
572
+      ));
573
+    }
574
+    
575
+    $proposition = new ElementTagsProposition();
576
+    $proposition->setElement($element);
577
+    $proposition->setUser($this->getUser());
578
+    
579
+    foreach ($tags as $tag)
580
+    {
581
+      // Si le tag est a modérer, il faut que le propriétaire de l'élément
582
+      // puisse voir ce tag, afin d'accepter en toute connaisance la proposition.
583
+      if ($tag->getTomoderate())
584
+      {
585
+        if (!$tag->hasIdInPrivateIds($element->getOwner()->getId()))
586
+        {
587
+          // Si son id n'y est pas on la rajoute afin que le proprio puisse voir 
588
+          // ces nouveau tags
589
+          $private_ids = json_decode($tag->getPrivateids(), true);
590
+          $private_ids[] = $element->getOwner()->getId();
591
+          $tag->setPrivateids(json_encode($private_ids));
592
+          $this->getDoctrine()->getEntityManager()->persist($tag);
593
+        }
594
+      }
595
+          
596
+      $proposition->addTag($tag);
597
+    }
598
+    
599
+    $element->setHasTagProposition(true);
600
+    
601
+    $this->getDoctrine()->getEntityManager()->persist($element);
602
+    $this->getDoctrine()->getEntityManager()->persist($proposition);
603
+    $this->getDoctrine()->getEntityManager()->flush();
604
+    
605
+    return $this->jsonResponse(array(
606
+      'status' => 'success',
607
+      'dom_id' => 'element_'.$element->getId()
608
+    ));
609
+  }
492
   
610
   
493
 }
611
 }

+ 24 - 0
src/Muzich/CoreBundle/Entity/Element.php View File

82
   protected $tags_propositions;
82
   protected $tags_propositions;
83
   
83
   
84
   /**
84
   /**
85
+   * Permet de savoir sans faire de gros calculs en base si il y a des 
86
+   * propositions de tags en cours sur cet élément.
87
+   * 
88
+   * @ORM\Column(type="boolean", nullable = true)
89
+   * @var type string
90
+   */
91
+  protected $has_tags_proposition = false;
92
+  
93
+  /**
85
    * L'url est l'url du media. 
94
    * L'url est l'url du media. 
86
    * 
95
    * 
87
    * @ORM\Column(type="string", length=1024)
96
    * @ORM\Column(type="string", length=1024)
485
     $this->comments = json_encode($comments);
494
     $this->comments = json_encode($comments);
486
   }
495
   }
487
   
496
   
497
+  public function setHasTagProposition($has_prop)
498
+  {
499
+    $this->has_tags_proposition = $has_prop;
500
+  }
501
+  
502
+  public function hasTagProposition()
503
+  {
504
+    if ($this->has_tags_proposition === null)
505
+    {
506
+      return false;
507
+    }
508
+    
509
+    return $this->has_tags_proposition;
510
+  }
511
+  
488
   /**
512
   /**
489
    * Etablie des relation vers des tags.
513
    * Etablie des relation vers des tags.
490
    * (Supprime les anciens tags, au niveau de l'objet seulement)
514
    * (Supprime les anciens tags, au niveau de l'objet seulement)

+ 55 - 54
src/Muzich/CoreBundle/Entity/ElementTagsProposition.php View File

12
  * ne leurs appartenant pas.
12
  * ne leurs appartenant pas.
13
  * 
13
  * 
14
  * @ORM\Entity
14
  * @ORM\Entity
15
+ * @ORM\Table(name="element_tags_proposition")
15
  * @ORM\Entity(repositoryClass="Muzich\CoreBundle\Repository\ElementTagsProposition")
16
  * @ORM\Entity(repositoryClass="Muzich\CoreBundle\Repository\ElementTagsProposition")
16
  * 
17
  * 
17
  */
18
  */
51
    */
52
    */
52
   protected $tags;
53
   protected $tags;
53
   
54
   
54
-  /**
55
-   * @var datetime $created
56
-   *
57
-   * @Gedmo\Timestampable(on="create")
58
-   * @ORM\Column(type="datetime")
59
-   */
60
-  private $created;
61
-
62
-  /**
63
-   * @var datetime $updated
64
-   *
65
-   * @ORM\Column(type="datetime")
66
-   * @Gedmo\Timestampable(on="update")
67
-   */
68
-  private $updated;
55
+//  /**
56
+//   * @var datetime $created
57
+//   *
58
+//   * @Gedmo\Timestampable(on="create")
59
+//   * @ORM\Column(type="datetime")
60
+//   */
61
+//  private $created;
62
+//
63
+//  /**
64
+//   * @var datetime $updated
65
+//   *
66
+//   * @ORM\Column(type="datetime")
67
+//   * @Gedmo\Timestampable(on="update")
68
+//   */
69
+//  private $updated;
69
   
70
   
70
     
71
     
71
   /**
72
   /**
78
     return $this->id;
79
     return $this->id;
79
   }
80
   }
80
 
81
 
81
-  /**
82
-   * Set created
83
-   *
84
-   * @param datetime $created
85
-   */
86
-  public function setCreated($created)
87
-  {
88
-    $this->created = $created;
89
-  }
90
-
91
-  /**
92
-   * Get created
93
-   *
94
-   * @return datetime 
95
-   */
96
-  public function getCreated()
97
-  {
98
-    return $this->created;
99
-  }
100
-
101
-  /**
102
-   * Set updated
103
-   *
104
-   * @param datetime $updated
105
-   */
106
-  public function setUpdated($updated)
107
-  {
108
-    $this->updated = $updated;
109
-  }
110
-
111
-  /**
112
-   * Get updated
113
-   *
114
-   * @return datetime 
115
-   */
116
-  public function getUpdated()
117
-  {
118
-    return $this->updated;
119
-  }
82
+//  /**
83
+//   * Set created
84
+//   *
85
+//   * @param datetime $created
86
+//   */
87
+//  public function setCreated($created)
88
+//  {
89
+//    $this->created = $created;
90
+//  }
91
+//
92
+//  /**
93
+//   * Get created
94
+//   *
95
+//   * @return datetime 
96
+//   */
97
+//  public function getCreated()
98
+//  {
99
+//    return $this->created;
100
+//  }
101
+//
102
+//  /**
103
+//   * Set updated
104
+//   *
105
+//   * @param datetime $updated
106
+//   */
107
+//  public function setUpdated($updated)
108
+//  {
109
+//    $this->updated = $updated;
110
+//  }
111
+//
112
+//  /**
113
+//   * Get updated
114
+//   *
115
+//   * @return datetime 
116
+//   */
117
+//  public function getUpdated()
118
+//  {
119
+//    return $this->updated;
120
+//  }
120
 
121
 
121
   /**
122
   /**
122
    * Set user
123
    * Set user

+ 12 - 0
src/Muzich/CoreBundle/Entity/Tag.php View File

238
     return $this->privateids;
238
     return $this->privateids;
239
   }
239
   }
240
   
240
   
241
+  public function hasIdInPrivateIds($id)
242
+  {
243
+    foreach (json_decode($this->privateids) as $pid)
244
+    {
245
+      if ($pid == $id)
246
+      {
247
+        return true;
248
+      }
249
+    }
250
+    return false;
251
+  }
252
+  
241
   public function getArguments()
253
   public function getArguments()
242
   {
254
   {
243
     return $this->arguments;
255
     return $this->arguments;

+ 11 - 0
src/Muzich/CoreBundle/Form/Element/ElementAddForm.php View File

7
 
7
 
8
 class ElementAddForm extends AbstractType
8
 class ElementAddForm extends AbstractType
9
 {
9
 {
10
+  private $name = null;
11
+  
10
   public function buildForm(FormBuilder $builder, array $options)
12
   public function buildForm(FormBuilder $builder, array $options)
11
   {    
13
   {    
12
     $builder->add('name', 'text', array(
14
     $builder->add('name', 'text', array(
21
         
23
         
22
     $builder->add('tags', 'hidden');    
24
     $builder->add('tags', 'hidden');    
23
   }
25
   }
26
+  
27
+  public function setName($name)
28
+  {
29
+    $this->name = $name;
30
+  }
24
 
31
 
25
   public function getName()
32
   public function getName()
26
   {
33
   {
34
+    if ($this->name)
35
+    {
36
+      return $this->name;
37
+    }
27
     return 'element_add';
38
     return 'element_add';
28
   }
39
   }
29
   
40
   

+ 5 - 0
src/Muzich/CoreBundle/Repository/TagRepository.php View File

41
     ")->setParameter('tids', $ids);
41
     ")->setParameter('tids', $ids);
42
   }
42
   }
43
   
43
   
44
+  public function getTagsWithIds($ids)
45
+  {
46
+    return $this->findByIds($ids)->getResult();
47
+  }
48
+  
44
   public function getTagsForElementSearch($ids)
49
   public function getTagsForElementSearch($ids)
45
   {
50
   {
46
     $tags = array();
51
     $tags = array();

+ 9 - 1
src/Muzich/CoreBundle/Resources/config/routing.yml View File

112
   
112
   
113
 ajax_report_element:
113
 ajax_report_element:
114
   pattern: /ajax/element/report/{element_id}/{token}
114
   pattern: /ajax/element/report/{element_id}/{token}
115
-  defaults: { _controller: MuzichCoreBundle:Core:reportElement }
115
+  defaults: { _controller: MuzichCoreBundle:Core:reportElement }
116
+  
117
+ajax_element_propose_tags_open:
118
+  pattern: /ajax/element/propose/tags/{element_id}
119
+  defaults: { _controller: MuzichCoreBundle:Element:proposeTagsOpen }
120
+  
121
+ajax_element_propose_tags_proceed:
122
+  pattern: /ajax/element/propose/tags/{element_id}/proceed/{token}
123
+  defaults: { _controller: MuzichCoreBundle:Element:proposeTagsProceed }

+ 20 - 0
src/Muzich/CoreBundle/Resources/views/Element/tag.proposition.html.twig View File

1
+
2
+<div class="tag_proposition">
3
+  <form id="element_tag_proposition_{{ element_id }}" 
4
+    action="{{ path('ajax_element_propose_tags_proceed', {'element_id':element_id , 'token':app.user.getPersonalHash}) }}" name="element_tag_proposition_{{ element_id }}" method="post">
5
+
6
+    <p>
7
+      {{ 'element.tag_proposition.form.description'|trans({}, 'elements') }}
8
+    </p>
9
+
10
+  {% include "MuzichCoreBundle:Tag:tagsPrompt.html.twig" with { 
11
+    'form_name'     : form_name
12
+  } %}
13
+
14
+  {{ form_widget(form.tags, { 'attr': {'class': 'tagBox_tags_ids'} }) }}
15
+
16
+    <input type="submit" value="{{ 'element.tag_proposition.form.submit'|trans({}, 'elements') }}" class="button" />
17
+    <input type="button" value="{{ 'element.tag_proposition.form.cancel'|trans({}, 'elements') }}" class="button cancel" />
18
+
19
+  </form>
20
+</div>

+ 15 - 5
src/Muzich/CoreBundle/Resources/views/SearchElement/element.html.twig View File

51
         <img src="{{ asset('bundles/muzichcore/img/1324917097_link.png') }}" alt="link" />
51
         <img src="{{ asset('bundles/muzichcore/img/1324917097_link.png') }}" alt="link" />
52
       </a>
52
       </a>
53
       
53
       
54
-      <a title="{{ 'element.report.link_title'|trans({}, 'userui') }}" 
55
-        class="element_report" 
56
-        href="{{ path('ajax_report_element', {'element_id':element.id, 'token':app.user.getPersonalHash}) }}">
57
-        <img src="{{ asset('bundles/muzichcore/img/1331832708_comment_alert.png') }}" alt="report" />
58
-      </a>
54
+      {% if app.user.id != element.owner.id %}
55
+      
56
+        <a title="{{ 'element.proposition_tags.link_title'|trans({}, 'userui') }}" 
57
+          class="element_propose_tags" 
58
+          href="{{ path('ajax_element_propose_tags_open', {'element_id' : element.id}) }}">
59
+          <img src="{{ asset('bundles/muzichcore/img/1333484018_rss-tag.png') }}" alt="tags_proposition" />
60
+        </a>
61
+      
62
+        <a title="{{ 'element.report.link_title'|trans({}, 'userui') }}" 
63
+          class="element_report" 
64
+          href="{{ path('ajax_report_element', {'element_id':element.id, 'token':app.user.getPersonalHash}) }}">
65
+          <img src="{{ asset('bundles/muzichcore/img/1331832708_comment_alert.png') }}" alt="report" />
66
+        </a>
67
+      
68
+      {% endif %}
59
       
69
       
60
       {% if app.user.id == element.owner.id %}
70
       {% if app.user.id == element.owner.id %}
61
         <a title="{{ 'element.edit.link'|trans({}, 'elements') }}" class="element_edit_link" 
71
         <a title="{{ 'element.edit.link'|trans({}, 'elements') }}" class="element_edit_link" 

+ 4 - 2
src/Muzich/CoreBundle/lib/Controller.php View File

294
    * @param \Muzich\CoreBundle\Searcher\Searcher $search_object
294
    * @param \Muzich\CoreBundle\Searcher\Searcher $search_object
295
    * @return \Symfony\Component\Form\Form
295
    * @return \Symfony\Component\Form\Form
296
    */
296
    */
297
-  protected function getAddForm($element = array())
297
+  protected function getAddForm($element = array(), $name = null)
298
   {
298
   {
299
+    $form = new ElementAddForm();
300
+    $form->setName($name);
299
     return $this->createForm(
301
     return $this->createForm(
300
-      new ElementAddForm(),
302
+      $form,
301
       $element,
303
       $element,
302
       array()
304
       array()
303
     );
305
     );

BIN
web/bundles/muzichcore/img/1333484018_rss-tag.png View File


+ 79 - 0
web/bundles/muzichcore/js/muzich.js View File

1709
     
1709
     
1710
     return false;
1710
     return false;
1711
   });
1711
   });
1712
+  
1713
+  /*
1714
+   * 
1715
+   * Proposition de tags sur un élément
1716
+   * 
1717
+   */
1718
+  
1719
+ // Ouverture du formulaire de modification
1720
+  $('a.element_propose_tags').live('click', function(){
1721
+    
1722
+    link = $(this);
1723
+    li = link.parent('td').parent('tr').parent().parent().parent('li.element');
1724
+    
1725
+    li.find('img.element_loader').show();
1726
+    
1727
+    $.getJSON($(this).attr('href'), function(response) {
1728
+      
1729
+      if (response.status == 'mustbeconnected')
1730
+      {
1731
+        $(location).attr('href', url_index);
1732
+      }
1733
+      
1734
+      li.find('img.element_loader').hide();
1735
+      
1736
+      if (response.status == 'success')
1737
+      {
1738
+        
1739
+        // On prépare le tagBox
1740
+        table = li.find('table:first');
1741
+        li.find('div.tag_proposition').remove();
1742
+        table.after(response.html);
1743
+
1744
+        // Pour le click sur l'input de saisie de tag
1745
+        li.find('ul.tagbox li.input input[type="text"]').formDefaults();
1746
+
1747
+        var options = new Array();
1748
+        options.form_name  = response.form_name;
1749
+        options.tag_init   = response.tags;
1750
+
1751
+        ajax_query_timestamp = null;
1752
+
1753
+        $("#tags_prompt_list_"+response.form_name).tagBox(options);
1754
+      
1755
+      // On rend ce formulaire ajaxFormable
1756
+      $('form[name="'+response.form_name+'"] input[type="submit"]').live('click', function(){
1757
+        li = $(this).parent('form').parent('div').parent('li');
1758
+        li.find('img.element_loader').show();
1759
+      });
1760
+      $('form[name="'+response.form_name+'"]').ajaxForm(function(response){
1761
+        
1762
+        if (response.status == 'mustbeconnected')
1763
+        {
1764
+          $(location).attr('href', url_index);
1765
+        }
1766
+                
1767
+        if (response.status == 'success')
1768
+        {
1769
+          li = $('li#'+response.dom_id);
1770
+          li.find('img.element_loader').hide();
1771
+          li.find('form')
1772
+          li.find('div.tag_proposition').remove();
1773
+        }
1774
+      });
1775
+      
1776
+      }
1777
+    });
1778
+    return false;
1779
+  });
1780
+  
1781
+  // Annulation d'un formulaire de modification d'élément
1782
+  $('form.edit_element input.cancel_edit').live('click', function(){
1783
+    var li = $(this).parent('form').parent('li');
1784
+    li.html(elements_edited[li.attr('id')]);
1785
+    delete(elements_edited[li.attr('id')]);
1786
+  });
1787
+  
1788
+  /*
1789
+   * Proposition de tag sur un élément FIN
1790
+   */
1712
 
1791
 
1713
 });
1792
 });