2017 © Pedro Peláez
 

symfony-bundle tree-bundle

A Symfony2 bundle to handle tree structures

image

cypresslab/tree-bundle

A Symfony2 bundle to handle tree structures

  • Wednesday, August 1, 2012
  • by matteosister
  • Repository
  • 0 Watchers
  • 0 Stars
  • 235 Installations
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 2 Versions
  • 0 % Grown

The README.md

CypressTreeBundle

WORK IN PROGRESS!!! No tests, no hopes., (*1)

A Symfony2 bundle to manage those f***ing tree structures!, (*2)

Depends on

FOSJsRoutingBundle, (*3)

Install

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;
    }
}

Configuration

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)

  • Add the TreeInterface to the class
<?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)

Usage

Now you are ready to display your trees on your twig templates., (*18)

  • add the FOSJsRouting js call for sorting the tree. Remember to add it on every page that display a tree.

```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)

CypressTreeBundle screenshot, (*23)

Contribution

If you want to contribute to this bundle (you are my hero) please send the PRs to develop branch!, (*24)

About recursion

Remember that if you want to learn recursion, you must first learn recursion, (*25)

The R in RMS stands for RMS, (*26)

The Versions

01/08 2012

dev-develop

dev-develop

A Symfony2 bundle to handle tree structures

  Sources   Download

GPL3

The Requires

 

01/08 2012

dev-master

9999999-dev

A Symfony2 bundle to handle tree structures

  Sources   Download

GPL3

The Requires