dev-develop
dev-developA Symfony2 bundle to handle tree structures
GPL3
The Requires
dev-master
9999999-devA Symfony2 bundle to handle tree structures
GPL3
The Requires
Wallogit.com
2017 © Pedro Peláez
A Symfony2 bundle to handle tree structures
WORK IN PROGRESS!!! No tests, no hopes., (*1)
A Symfony2 bundle to manage those f***ing tree structures!, (*2)
FOSJsRoutingBundle, (*3)
add this to the require section of your composer.json file, (*4)
{
"require": {
"cypresslab/tree-bundle": "dev-master"
}
}
Activate both the CypressTreeBundle and the FOSJsRoutingBundle in you AppKernel class, (*5)
app/AppKernel.php, (*6)
<?php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel
{
public function registerBundles()
{
// other bundles...
$bundles[] = new Cypress\TreeBundle\CypressTreeBundle();
$bundles[] = new FOS\JsRoutingBundle\FOSJsRoutingBundle();
return $bundles;
}
}
You have a php class (an entity, a document, or anything else) and you want it to be a part of a tree structure. For this example let's consider a Doctrine ORM entity with the Tree extension enabled from the awesome gedmo repository. Here is a full configuration tutorial, (*7)
<?php
namespace Cypress\MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Cypress\TreeBundle\Interfaces\TreeInterface;
/**
* MenuItem Document
*
* @ORM\Entity(repositoryClass="Vivacom\CmsBundle\Repositories\ORM\MenuItemRepository")
* @Gedmo\Tree(type="nested")
*/
class MenuItem implements TreeInterface {
/**
* @var MenuItem
*
* @ORM\ManyToOne(targetEntity="MenuItem", inversedBy="children")
* @ORM\JoinColumn(onDelete="CASCADE")
* @Gedmo\TreeParent
*/
private $parent;
/**
* var ArrayCollection
*
* @ORM\OneToMany(targetEntity="MenuItem", mappedBy="parent", cascade={"all"})
* @ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
/**
* Constructor
*/
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* add a MenuItem as children
*
* @param MenuItem $menuItem the children page
*/
public function addChildren(MenuItem $menuItem)
{
$menuItem->setParent($this);
$this->children[] = $menuItem;
}
/**
* Children setter
*
* @param \Doctrine\Common\Collections\ArrayCollection $children la variabile children
*/
public function setChildren($children)
{
$this->children = $children;
}
/**
* Children getter
*
* @return \Doctrine\Common\Collections\ArrayCollection
*/
public function getChildren()
{
return $this->children;
}
/**
* Parent setter
*
* @param \Vivacom\CmsBundle\Document\MenuItem $parent the parent property
*/
public function setParent($parent)
{
$this->parent = $parent;
}
/**
* Parent getter
*
* @return \Vivacom\CmsBundle\Document\MenuItem
*/
public function getParent()
{
return $this->parent;
}
}
TreeInterface define one method that you MUST implement: getChildren(), (*8)
<?php
namespace Cypress\TreeBundle\Interfaces;
/**
* Interface for trees
*/
interface TreeInterface
{
/**
* returns a in iteratable object of children
*
* @abstract
* @return mixed
*/
function getChildren();
}
We already have it in the class as a getter for the children property. You could use any class, as far as you implement TreeInterface, and define the getChildren method., (*9)
Now define your trees in the config.yml file. Here is a complete reference:, (*10)
app/config/config.yml, (*11)
cypress_tree:
trees:
my_tree:
label_template: "MyAwesomeBundle:Menu:item_label.html.twig"
controller: "MyAwesomeBundle:Menu"
editable_root: false
theme: default # or default-rl, classic, apple
root_icon: 'bundles/cypresstree/images/database.png'
node_icon: 'bundles/cypresstree/images/folder.png'
Under the trees section you define every tree that you need for your application. Pick a name that means something to you. For every tree you define: - label_template: A twig template that gets a node variable with the object of the current tree, (*12)
src/MyAwesomeBundle/Resources/views/Menu/item_label.html.twig ```HTML+Django {{ node }}, (*13)
- **controller**: Use the short notation to define a Controller to handle the tree sorting actions. The controller should implements the *TreeControllerSortableInterface* which requires you to define the *function sortNodeAction($node, $ref, $move);* method Here is an example with Doctrine orm entities ```php <?php namespace Cypress\MyAwesomeBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; use Cypress\TreeBundle\Interfaces\TreeControllerSortableInterface; class AdminController extends Controller implements TreeControllerSortableInterface public function sortNodeAction($node, $ref, $move) { try { $repo = $this->get('doctrine.orm.entity_manager')->getRepository('Cypress\MyAwesomeBundle\Entity\MenuItem'); $moved = $repo->findOneBy(array('id' => $node)); $reference = $repo->findOneBy(array('id' => $ref)); $moveAfter = $move == 1; if (!$moveAfter) { $repo->persistAsPrevSiblingOf($moved, $reference); } else { $repo->persistAsNextSiblingOf($moved, $reference); } $this->getEM()->flush(); return new Response('ok'); } catch (\Exception $e) { return new Response('ko'); } } // other actions... }
As you can see the controller receive 3 parameters. The id of the moved node ($node), the id of the reference ($ref), and $move: 0 to move before and 1 to move after the reference The controller should returns a Reponse object with 'ok' if everything worked well, or 'ko' for an error., (*14)
editable_root (boolean) define if the root node of the tree should be editable or not, (*15)
theme the tree theme, (*16)
root_icon and node_icon are the icons to use to represente the root, and the branches of the tree, (*17)
Now you are ready to display your trees on your twig templates., (*18)
```HTML+Django , (*19)
- in the javascript section of your template call the function *cypress_tree_javascripts* with the name of the tree that you have defined in you config.yml file ```HTML+Django {{ cypress_tree_javascripts('my_tree') }}
and in the body of your page call the cypress_tree() function, with the tree name as first argument, and the root node of your tree as the second., (*20)
HTML+Django
{{ cypress_tree('my_tree', root) }}, (*21)
And you should see it!, (*22)
, (*23)
If you want to contribute to this bundle (you are my hero) please send the PRs to develop branch!, (*24)
Remember that if you want to learn recursion, you must first learn recursion, (*25)
The R in RMS stands for RMS, (*26)
A Symfony2 bundle to handle tree structures
GPL3
A Symfony2 bundle to handle tree structures
GPL3