Commit 26710191 authored by Hermann Mayer's avatar Hermann Mayer

Completely rewritten the Navigation component. Implemented the backend for Feature #5.

parent 5f87f89e
......@@ -78,12 +78,12 @@
<ul class="nav">
{% if page is defined %}
{% set currentSlug = page.slug %}
{% render 'JityHomepageBundle:Default:renderNavigation' with {'resource': page} %}
{% else %}
{% set currentSlug = '' %}
{% endif%}
{% render 'JityHomepageBundle:Default:renderNavigation' %}
{% endif %}
{% render 'JityHomepageBundle:Default:renderNavigation' with {'currentSlug': currentSlug, 'navigation': 'Default'} %}
{% block navigation %}{% endblock %}
</ul>
</div>
......
......@@ -9,3 +9,7 @@ _profiler:
_main:
resource: routing.yml
JityHomepageBundleDev:
resource: "@JityHomepageBundle/Resources/config/routing_dev.yml"
prefix: /
<?php
/*
* This file is part of the Jity package.
*
* (c) Hermann Mayer <hermann.mayer92@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Jity\HomepageBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route,
Symfony\Component\HttpFoundation\Request,
Symfony\Bundle\FrameworkBundle\Controller\Controller,
Symfony\Component\HttpFoundation\Response,
Jity\HomepageBundle\Entity\NavigationContainer,
Jity\HomepageBundle\Entity\Page,
Jity\HomepageBundle\Entity\Article;
/**
* DebugController
*
* Debug Controller to develop and test new features.
*
* @uses Controller
* @author Hermann Mayer <hermann.mayer92@gmail.com>
*/
class DebugController extends Controller
{
/**
* indexAction
*
* @Route("/")
*
* @access public
* @return void
*/
public function indexAction()
{
$em = $this->getDoctrine()->getEntityManager();
$page = $em->getRepository('JityHomepageBundle:Page')
->findOneBySlug('uber-mich');
$navRenderer = $this->get('jity.navigation.renderer');
return $this->render('JityHomepageBundle:Debug:index.html.twig', array(
'nav' => $navRenderer->renderContainer(
$page->getNavigationContainer()
)
));
}
}
......@@ -12,6 +12,8 @@
namespace Jity\HomepageBundle\Controller;
use Jity\HomepageBundle\JityHomepageBundle,
Jity\HomepageBundle\Entity\NavigationContainer,
Jity\HomepageBundle\Entity\AbstractPage,
Symfony\Bundle\FrameworkBundle\Controller\Controller,
Symfony\Component\HttpFoundation\Response;
......@@ -165,34 +167,49 @@ class DefaultController extends Controller
/**
* renderNavigationAction
*
* Render the application navigation outgoing of the current slug (page).
* Render the application navigation outgoing of the given resource.
*
* @param string $currentSlug Slug of the current AbstractPage
* @param string $navigation Name of the Navigation to render
* @param AbstractPage|NavigationContainer $resource Resource to render
*
* @access public
* @return Response
*/
public function renderNavigationAction($currentSlug, $navigation = 'Default')
public function renderNavigationAction($resource = null)
{
// Get Entity Manager
$em = $this->getDoctrine()->getEntityManager();
if ($resource instanceof AbstractPage) {
$container = $resource->getNavigationContainer();
}
if ($resource instanceof NavigationContainer) {
$container = $resource;
$resource = null;
}
// Try to get the requested navigation
$nav = $em->getRepository('JityHomepageBundle:Navigation')
->findOneByName($navigation);
// Fallback case - Use the navigation container from the marked homepage
if (null === $resource || null === $container) {
$pages = array();
$em = $this->getDoctrine()->getEntityManager();
$page = $em
->getRepository('JityHomepageBundle:Service')
->findOneByName('homepage')
->getPages()
->first();
// Only process further on found navigation
if ($nav) {
$pages = array_merge($pages, $nav->getPages()->toArray());
if (!$page) {
return new Response();
}
$container = $page->getNavigationContainer();
}
$navRenderer = $this->get('jity.navigation.renderer');
return $this->render('JityHomepageBundle:Default:navigation.html.twig', array(
'pages' => $pages,
'currentSlug' => $currentSlug
));
'renderedNavigation' => $navRenderer->renderContainer(
$container,
$resource
)));
}
/**
......
......@@ -41,14 +41,6 @@ class Load03MetaData extends AbstractFixture implements OrderedFixtureInterface
*/
public function load(ObjectManager $manager)
{
// Build default Navigation
$navigationPage = new Navigation();
$navigationPage->setName('Default');
// Build default Navigation
$navigationBlog = new Navigation();
$navigationBlog->setName('Blog');
// Build default Sidebar
$sidebarPage = new Sidebar();
$sidebarPage->setName('Default');
......@@ -62,8 +54,6 @@ class Load03MetaData extends AbstractFixture implements OrderedFixtureInterface
$category->setName('Default');
// Save all Metadata
$manager->persist($navigationPage);
$manager->persist($navigationBlog);
$manager->persist($sidebarPage);
$manager->persist($sidebarBlog);
$manager->persist($category);
......@@ -71,8 +61,6 @@ class Load03MetaData extends AbstractFixture implements OrderedFixtureInterface
// Flush to Database
$manager->flush();
$this->addReference('default-navigation', $navigationPage);
$this->addReference('blog-navigation', $navigationBlog);
$this->addReference('default-sidebar', $sidebarPage);
$this->addReference('blog-sidebar', $sidebarBlog);
$this->addReference('default-category', $category);
......
......@@ -43,9 +43,9 @@ class Load20HomePageData extends AbstractFixture implements OrderedFixtureInterf
$home = new Page();
$home
->setTitle('Über mich')
->setContent('<img src="{{ asset("bundles/jityhomepage/img/myself-cc3-300px.png") }}" alt="" class="img-polaroid pull-left" />
Ein paar Worte zu meiner Person
--------------------------------
->setContent('<legend>Ein paar Worte zu meiner Person</legend>
<img src="{{ asset("bundles/jityhomepage/img/myself-cc3-300px.png") }}" alt="" class="img-polaroid pull-left" />
Mein Name ist Hermann Mayer, ich wurde am 02. August im Jahre 1992 in Berlin geboren und bin
in einem kleinen Örtchen Namens Augsdorf, dass im ehemaligen Mansfelder Land liegt, aufgewachsen.
......@@ -79,7 +79,6 @@ zusätzliche Arbeit bedeutet.
')
->setCategory($this->getReference('default-category'))
->setSidebar($this->getReference('default-sidebar'))
->setNavigation($this->getReference('default-navigation'))
->setAuthor($this->getReference('admin-user'))
->setService($this->getReference('homepage-service'))
->setIcon('icon-user');
......
......@@ -44,12 +44,9 @@ class Load30PageData extends AbstractFixture implements OrderedFixtureInterface
$blogDashboard = new Page();
$blogDashboard
->setTitle('Blog')
->setContent('Neue Artikel
--------
')
->setContent('<legend>Letzte Artikel</legend>')
->setCategory($this->getReference('default-category'))
->setSidebar($this->getReference('blog-sidebar'))
->setNavigation($this->getReference('default-navigation'))
->setAuthor($this->getReference('admin-user'))
->setService($this->getReference('blog-dashboard-service'))
->setIcon('icon-pencil');
......@@ -64,7 +61,6 @@ class Load30PageData extends AbstractFixture implements OrderedFixtureInterface
->setTitle('Archiv')
->setCategory($this->getReference('default-category'))
->setSidebar($this->getReference('blog-sidebar'))
->setNavigation($this->getReference('blog-navigation'))
->setAuthor($this->getReference('admin-user'))
->setService($this->getReference('blog-archiv-service'))
->setIcon('icon-pencil');
......@@ -80,7 +76,6 @@ class Load30PageData extends AbstractFixture implements OrderedFixtureInterface
->setContent('')
->setCategory($this->getReference('default-category'))
->setSidebar($this->getReference('default-sidebar'))
->setNavigation($this->getReference('default-navigation'))
->setAuthor($this->getReference('admin-user'))
->setService($this->getReference('impress-service'))
->setIcon('icon-list');
......@@ -96,7 +91,6 @@ class Load30PageData extends AbstractFixture implements OrderedFixtureInterface
->setContent('')
->setCategory($this->getReference('default-category'))
->setSidebar($this->getReference('default-sidebar'))
->setNavigation($this->getReference('default-navigation'))
->setAuthor($this->getReference('admin-user'))
->setService($this->getReference('contact-service'))
->setIcon('icon-comment');
......@@ -123,8 +117,7 @@ class Load30PageData extends AbstractFixture implements OrderedFixtureInterface
$demo = new Page();
$demo
->setTitle('Jity Demo')
->setContent('Jity Demo
----------
->setContent('<legend>Jity Demo</legend>
Das Projekt, welches hinter dieser Website steckt, ist eine Open Source
Applikation. Dies entstand aus dem Wunsch heraus ein Projekt mit
......@@ -148,7 +141,6 @@ Administrator einzuloggen.
')
->setCategory($this->getReference('default-category'))
->setSidebar($this->getReference('default-sidebar'))
->setNavigation($this->getReference('default-navigation'))
->setAuthor($this->getReference('admin-user'))
->setIcon('icon-hand-right');
......
......@@ -376,7 +376,6 @@ erreichen, oder über Google+.
')
->setCategory($this->getReference('default-category'))
->setSidebar($this->getReference('blog-sidebar'))
->setNavigation($this->getReference('blog-navigation'))
->setAuthor($this->getReference('admin-user'))
->setIcon('icon-font')
->setCreatedAt(new \DateTime('15.10.2012'))
......
<?php
/*
* This file is part of the Jity package.
*
* (c) Hermann Mayer <hermann.mayer92@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Jity\HomepageBundle\DataFixtures\ORM;
use Jity\HomepageBundle\Entity\NavigationContainer,
Doctrine\Common\Persistence\ObjectManager,
Doctrine\Common\DataFixtures\AbstractFixture,
Doctrine\Common\DataFixtures\OrderedFixtureInterface;
/**
* Load50NavigationData
*
* Description
*
* @uses AbstractFixture
* @uses OrderedFixtureInterface
* @author Hermann Mayer <hermann.mayer92@gmail.com>
*/
class Load50NavigationData extends AbstractFixture implements OrderedFixtureInterface
{
/**
* load
*
* Load the fixtures.
*
* @param ObjectManager $manager ObjectManager Instance
*
* @access public
* @return void
*/
public function load(ObjectManager $manager)
{
$homepageContainer = new NavigationContainer();
$homepageContainer
->setName('Homepage')
->addResource($this->getReference('home-page'))
->addResource($this->getReference('blog-dashboard-page'))
->addResource($this->getReference('demo-page'))
->addResource($this->getReference('impress-page'))
->addResource($this->getReference('contact-page'));
$pages = array(
$this->getReference('home-page'),
$this->getReference('blog-dashboard-page'),
$this->getReference('blog-archiv-page'),
$this->getReference('demo-page'),
$this->getReference('impress-page'),
$this->getReference('contact-page'),
$this->getReference('search-page')
);
foreach ($pages as &$page) {
$page->setNavigationContainer($homepageContainer);
}
/*
* --------------------------------------------------------------------
*/
// Save all Metadata
$manager->persist($homepageContainer);
// Flush to Database
$manager->flush();
}
/**
* getOrder
*
* Get the position (in order) of the fixture.
*
* @access public
* @return void
*/
public function getOrder()
{
return 50;
}
}
<?php
/*
* This file is part of the Jity package.
*
* (c) Hermann Mayer <hermann.mayer92@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Jity\HomepageBundle\DependencyInjection;
use Jity\HomepageBundle\Entity\NavigationContainer,
Jity\HomepageBundle\Entity\AbstractPage,
JMS\DiExtraBundle\Annotation as DI;
/**
* NavigationRenderer
*
* Abstract Navigation Renderer based on
* a Navigation Container Entity.
*
* @DI\Service("jity.navigation.renderer")
*
* @author Hermann Mayer <hermann.mayer92@gmail.com>
*/
class NavigationRenderer
{
private $router;
/**
* __construct
*
* Initalize a new NavigationRenderer instance.
*
* @param mixed $router DI Injected Router
*
* @DI\InjectParams({
* "router" = @DI\Inject("router")
* })
*
* @access public
* @return void
*/
public function __construct($router)
{
$this->router = $router;
}
/**
* renderContainer
*
* Render a given container entity.
*
* @param NavigationContainer $container Container to process
* @param AbstractPage $currentPage Current page to mark as active
* @param int $level Current container depth-level
*
* @access public
* @return string
*/
public function renderContainer(
NavigationContainer $container,
AbstractPage $currentPage = null,
$level = 0)
{
// Get default options for formatting the node
$options = $this->getOptions($container, true, $level);
$output = '';
$activeRoute = null;
// Find active route for the current page
if (null !== $currentPage) {
$activeRoute = $this->router->generate(
strtolower($currentPage->getType()),
array(
'slug' => $currentPage->getSlug()
)
);
}
// Process all resources for the current container
foreach ($container->getResources() as $resource) {
if ('NavigationContainer' == $resource->getType()) {
// Get default options for formatting the node
$options = $this->getOptions($resource, true, $level);
// Render the current node and all child nodes
$output .= $this->wrap(
$this->add(
$this->wrap(
$resource->getName(),
$options->head->start,
$options->head->end
),
$this->wrap(
$this->renderContainer(
$resource, $currentPage, $level+1
),
$options->childNodes->start,
$options->childNodes->end
)
),
$options->node->start,
$options->node->end
);
continue;
}
$route = $this->router->generate(
strtolower($resource->getType()),
array(
'slug' => $resource->getSlug()
)
);
// Mark the current resource as our active resource
if ($activeRoute == $route) {
$options->page->oldStart = $options->page->start;
$options->page->start = '<li class="active">';
} elseif (isset($options->page->oldStart)) {
// Revert page start if it was replaced
$options->page->start = $options->page->oldStart;
}
$output .= $this->wrap(
'<a href="' . $route . '">'
. '<i class="icon-white '. $resource->getIcon() . '"></i> '
. $resource->getTitle() . '</a>',
$options->page->start,
$options->page->end
);
}
return $output;
}
/**
* getOptions
*
* Get default styling options for the rendering.
*
* @param NavigationContainer $container Container to process
* @param boolean $dynamic Run dynamic options
* @param int $level Current container depth-level
*
* @access private
* @return StdClass
*/
private function getOptions(
NavigationContainer $container = null,
$dynamic = true,
$level = 0)
{
$rootNode = (object) array(
'start' => '',
'end' => ''
);
$node = (object) array(
'start' => '<li class="dropdown">',
'end' => '</li>'
);
$head = (object) array(
'start' => '<a class="dropdown-toggle" '
. 'data-toggle="dropdown" href = "#">',
'end' => '</a>'
);
$page = (object) array(
'start' => '<li>',
'end' => '</li>'
);
$childNodes = (object) array(
'start' => '<ul class="dropdown-menu">',
'end' => '</ul>'
);
if (true === $dynamic) {
$icon = $container->getIcon();
if (false === $container->getSubmenu()) {
if (0 == $level) {
if (!empty($icon)) {
$head->start .= '<i class="icon-white ' . $icon . '"></i> ';
}
}
if ($level > 0) {
$head->start = '<li class="divider"></li>'
. '<li class="nav-header">';
$head->end = '</li>';
$childNodes->start = '';
$childNodes->end = '';
}
} else {
if ($level > 0) {
$node->start = '<li class="dropdown-submenu">';
}
if (!empty($icon)) {
$head->start .= '<i class="icon-white ' . $icon . '"></i> ';
}
}
}
return (object) array(
'rootNode' => $rootNode,
'node' => $node,
'head' => $head,
'page' => $page,
'childNodes' => $childNodes
);
}
/**
* wrap
*
* Wrap content in two strings.
*
* @param string $content Content to wrap with start and end
* @param string $start Start of the string
* @param string $end End of the string
*
* @access private
* @return string
*/
private function wrap($content, $start, $end)
{
return $start . $content . $end;
}
/**
* add
*
* Concat two strings.
*
* @param string $contentFirst First string
* @param string $contentSecond Second string
*
* @access private
* @return string
*/
private function add($contentFirst, $contentSecond)
{
return $contentFirst . $contentSecond;
}
}
......@@ -33,7 +33,7 @@ use Gedmo\Mapping\Annotation as Gedmo,
* @abstract
* @author Hermann Mayer <hermann.mayer92@gmail.com>
*/
abstract class AbstractPage
abstract class AbstractPage extends NavigationResource
{
/**
* @ORM\Id
......@@ -76,10 +76,10 @@ abstract class AbstractPage
protected $sidebar;
/**
* @ORM\ManyToOne(targetEntity="Navigation", inversedBy="pages")
* @ORM\JoinColumn(name="navigation_id", referencedColumnName="id")
* @ORM\ManyToOne(targetEntity="NavigationContainer", inversedBy="pages")
* @ORM\JoinColumn(name="navigation_container_id", referencedColumnName="id")
**/
protected $navigation;
protected $navigationContainer;
/**
* @ORM\OneToMany(
......@@ -299,37 +299,6 @@ abstract class AbstractPage
return $this->sidebar;
}
/**
* setNavigation
*
* Set the navigation of the entity.
*
* @param Jity\HomepageBundle\Entity\Navigation $navigation Navigation to set
*
* @access public
* @return AbstractPage
*/
public function setNavigation(\Jity\HomepageBundle\Entity\Navigation $navigation)
{
$navigation->addPage($this);
$this->navigation = $navigation;
return $this;
}
/**
* getNavigation
*
* Get the navigation of the entity.
*
* @access public
* @return Jity\HomepageBundle\Entity\Navigation
*/
public function getNavigation()
{
return $this->navigation;
}
/**
* setAuthor
*
......@@ -635,5 +604,33 @@ abstract class AbstractPage
return trim(substr($entity->getContent(), 0, 400));
}
}
}
/**
* setNavigationContainer
*
* Set the Navigation Container of the entity.
*