Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tags #2

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Controller/DefaultController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
Soloist\Bundle\CoreBundle\Entity\Node;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;


class DefaultController extends Controller
{
public function indexAction()
Expand Down Expand Up @@ -53,4 +54,5 @@ public function pageShortcutAction($page, $path_image, $description)
'description' => $description,
);
}

}
33 changes: 32 additions & 1 deletion Controller/NavigationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
namespace Soloist\Bundle\CoreBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Soloist\Bundle\CoreBundle\Entity\Node;
use Soloist\Bundle\CoreBundle\Entity\Node,
DoctrineExtensions\Taggable\Taggable;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class NavigationController extends Controller
Expand Down Expand Up @@ -41,4 +42,34 @@ public function showPartAction($node, $depth = null)
'current' => $node
);
}

/**
* Show similars elements
*
* @param Taggable $node
* @return Respons
*/
public function showSimilarAction(Taggable $node)
{
if (!$node instanceof Taggable) {
throw new InvalidArgumentException('Sorry ! I need tags to search similar content. Therefore your element must implements "DoctrineExtensions\Taggable\Taggable".');
}
$type = $node->getType();

if ($type != 'page') {
throw new InvalidArgumentException('Sorry ! This node is currently not supported.');
}

$tagManager = $this->get('fpn_tag.tag_manager');
$tagManager->loadTagging($node);

$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('SoloistCoreBundle:Node');

$similarElements = $repo->getSimilarResults($node);

return $this->render('SoloistCoreBundle:Navigation:Similar/'. $type . '.html.twig', array(
'nodes' => $similarElements
));
}
}
16 changes: 16 additions & 0 deletions Entity/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,4 +224,20 @@ public function getUpdatedAt()
public function postLoad()
{
}

public function getGlobalId()
{
return 'core-' . $this->getType() . '-' . $this->getId();
}

/**
* Get tag type
* This method is a part of the Taggable interface
*
* @return string
*/
public function getTaggableType()
{
return 'soloist_node';
}
}
36 changes: 35 additions & 1 deletion Entity/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
namespace Soloist\Bundle\CoreBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use DoctrineExtensions\Taggable\Taggable;

class Page extends Node
class Page extends Node implements Taggable
{

/**
Expand All @@ -27,9 +28,22 @@ class Page extends Node
*/
protected $blocks;

/**
* Tags managed by FPNTagBundle
* @var \Doctrine\Common\Collections\Collection
*/
protected $tags;

/**
* Tas as text
* @var string
*/
public $tagsAsText;

public function __construct()
{
$this->blocks = new ArrayCollection;
$this->tags = new ArrayCollection;
}

/**
Expand Down Expand Up @@ -113,4 +127,24 @@ public function postLoad()
$this->blocks = $blocks;
}

/**
* Get tags
* @return ArrayCollection
*/
public function getTags()
{
$this->tags = $this->tags ?: new ArrayCollection();

return $this->tags;
}

/**
* Get id of the current entity
* @return integer
*/
public function getTaggableId()
{
return $this->getId();
}

}
62 changes: 62 additions & 0 deletions Entity/Repository/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use Doctrine\ORM\Query\Expr;
use Gedmo\Tree\Entity\Repository\NestedTreeRepository;
use DoctrineExtensions\Taggable\Taggable;

use Doctrine\ORM\Query\ResultSetMappingBuilder;

class Node extends NestedTreeRepository
{
Expand All @@ -27,4 +30,63 @@ public function findRoot()
->getSingleResult()
;
}

/**
* Get similar results
* NEED a taggable node
* Sql draft available here: https://gist.github.com/3105206/70ab5aaa6654890433d8e5d9671f320a695d3627
* Notice that the only node who will work is tha page
*
* @param Taggable $resource
* @param integer $limit
* @return array
*/
public function getSimilarResults(Taggable $resource, $limit = 5)
{
$tagsList = '';
$count = $resource->getTags()->count();

if ($count < 1) {
return array();
}

foreach ($resource->getTags() as $tag) {
if (!empty($tagsList)) {
$tagsList .= ', ';
}
$tagsList .= '\'' . $tag->getSlug() . '\'';
}

$part = <<<SQL
SELECT DISTINCT * FROM node n
WHERE n.id IN (
SELECT resourceId FROM tagging tg
INNER JOIN t.name as t ON t.id = tg.tag_id
WHERE t.slug IN({$tagsList})
AND resourceType = 'soloist_node'
GROUP BY resourceId
HAVING COUNT(t.id) = $count
) AND n.discr = 'page'
ORDER BY node.created_at ASC
SQL;
$sql = '';

do {
if (!empty($sql)) {
$sql .= ' UNION ';
}
$sql .= str_replace('$count', $count, $sql);
$count--;
} while ($sql === '' || $count > 0);


$sql .= "\n" . 'LIMIT ' . $limit;

$rsm = new ResultSetMappingBuilder($this->_em);
$rsm->addRootEntityFromClassMetadata('SoloistCoreBundle:Node', 'n');

$query = $this->_em->createNativeQuery($sql, $rsm);

return $query->getResult();
}
}
10 changes: 10 additions & 0 deletions Entity/Tag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Soloist\Bundle\CoreBundle\Entity;

use FPN\TagBundle\Entity\Tag as BaseTag;

class Tag extends BaseTag
{

}
10 changes: 10 additions & 0 deletions Entity/Tagging.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Soloist\Bundle\CoreBundle\Entity;

use \FPN\TagBundle\Entity\Tagging as BaseTagging;

class Tagging extends BaseTagging
{

}
32 changes: 32 additions & 0 deletions EventListener/BlogListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Soloist\Bundle\CoreBundle\EventListener;

use Soloist\Bundle\CoreBundle\Form\Type\BlockSettings\PageShortcutType,
Soloist\Bundle\BlogBundle\EventListener\Event\RequestCategories;

use Doctrine\ORM\EntityManager;

class BlogListener
{
private $em;

public function __construct(EntityManager $em)
{
$this->em = $em;
}
/**
* Listen to the RequestCategories event from blog bundle
*
* @param \Soloist\Bundle\BlogBundle\EventListener\Event\RequestCategories $event
*/
public function onRequestCategories(RequestCategories $event)
{
$repo = $this->em->getRepository('SoloistCoreBundle:Category');
$categories = $repo->findAll();

foreach($categories as $category) {
$event->addCategory($category->getGlobalId(), $category->getTitle());
}
}
}
55 changes: 52 additions & 3 deletions Form/Handler/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

use Symfony\Component\HttpFoundation\Request,
Symfony\Component\Form\FormFactory,
Symfony\Component\Form\Form;
Symfony\Component\Form\Form,
FPN\TagBundle\Entity\TagManager,
DoctrineExtensions\Taggable\Taggable;

use Soloist\Bundle\CoreBundle\Node\Factory as NodeFactory,
Soloist\Bundle\CoreBundle\Entity\Node as NodeEntity,
Expand All @@ -31,20 +33,39 @@ class Node
*/
protected $nodeFactory;

public function __construct(NodeFactory $nodeFactory, EntityManager $em, FormFactory $factory)
/**
* @var FPN\TagBundle\Entity\TagManager
*/
protected $tagManager;

public function __construct(NodeFactory $nodeFactory, EntityManager $em, FormFactory $factory, TagManager $tagManager)
{
$this->em = $em;
$this->factory = $factory;
$this->nodeFactory = $nodeFactory;
$this->tagManager = $tagManager;
}

public function create(Form $form, Request $request)
{
$form->bindRequest($request);

if ($form->isValid()) {
$this->em->persist($form->getData());
$data = $form->getData();

if ($data instanceof Taggable) {

$tags = $this->tagManager->splitTagNames($data->tagsAsText);

$tags = $this->tagManager->loadOrCreateTags($tags);
$this->tagManager->addTags($tags, $data);
}

$this->em->persist($data);
$this->em->flush();

$tagManager->saveTagging($data);

return true;
}

Expand All @@ -53,10 +74,25 @@ public function create(Form $form, Request $request)

public function update(Form $form, Request $request)
{
$data = $form->getData();

$form->bindRequest($request);
if ($form->isValid()) {

// if entity is taggable, we should remove old tags
// and add new
if ($data instanceof Taggable) {

$tags = $this->tagManager->splitTagNames($data->tagsAsText);

$tags = $this->tagManager->loadOrCreateTags($tags);
$this->tagManager->addTags($tags, $data);
}

$this->em->flush();

$tagManager->saveTagging($data);

return true;
}

Expand All @@ -66,6 +102,19 @@ public function update(Form $form, Request $request)
public function getCreateForm($type, $pageType = null)
{
$node = $this->nodeFactory->getNode($type, $pageType);

if ($node instanceof Taggable) {
$this->tagManager->loadTagging($node);
$text = '';
foreach($node->getTags() as $tag) {
if($text !== '') {
$text .= ', ';
}
$text .= $tag->getSlug();
}
$node->tagsAsText = $text;
}

$form = $this->nodeFactory->getFormType($type);

return $this->factory->create($form, $node);
Expand Down
1 change: 1 addition & 0 deletions Form/Type/PageType.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
'choice_list' => new SimpleChoiceList($this->factory->getPageTypes())
))
->add('blocks', new BlockCollectionType, array('block_factory' => $this->factory))
->add('tagsAsText', 'text')
;
}

Expand Down
17 changes: 17 additions & 0 deletions Resources/config/doctrine/Tag.orm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

<entity name="Soloist\Bundle\CoreBundle\Entity\Tag" table="soloist_tag">

<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>

<one-to-many field="tagging" target-entity="Soloist\Bundle\CoreBundle\Entity\Tagging" mapped-by="tag" fetch="EAGER" />

</entity>

</doctrine-mapping>
Loading