Commit f8fc750d authored by Hermann Mayer's avatar Hermann Mayer

Added Sitemap Generator Bundle. Implemented a EventListener for Sitemap…

Added Sitemap Generator Bundle. Implemented a EventListener for Sitemap generation. Enhanced the blog article navigation and added permalink feature to headlines.
parent bf128b69
......@@ -14,4 +14,7 @@
/web/css/*
/web/js/*
/web/sitemap*
/tags
......@@ -28,6 +28,7 @@ class AppKernel extends Kernel
new HWI\Bundle\OAuthBundle\HWIOAuthBundle(),
new SunCat\MobileDetectBundle\MobileDetectBundle(),
new EWZ\Bundle\RecaptchaBundle\EWZRecaptchaBundle(),
new Presta\SitemapBundle\PrestaSitemapBundle(),
);
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
......
......@@ -5,7 +5,7 @@
{% render 'JityHomepageBundle:Default:overallProcess' %}
<meta charset="utf-8">
<title>Hermann Mayer {% block title %}{% endblock %}</title>
<title>{% block title %}{% endblock %}Hermann Mayer</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="Hermann Mayer">
......
......@@ -84,3 +84,7 @@ mobile_detect:
tablet: ~
switch_device_view: ~
# Sitemap Bundle Config
presta_sitemap:
dumper_base_url: http://hermann-mayer.net/
No preview for this file type
......@@ -13,6 +13,12 @@
"autoload": {
"psr-0": { "": "src/" }
},
"repositories": [
{
"type": "vcs",
"url": "http://github.com/kostiklv/PrestaSitemapBundle"
}
],
"require": {
"php": ">=5.3.3",
"symfony/symfony": "2.1.*",
......@@ -36,7 +42,8 @@
"xi/breadcrumbs-bundle": "dev-master",
"hwi/oauth-bundle": "dev-master",
"suncat/mobile-detect-bundle": "dev-master",
"excelwebzone/recaptcha-bundle": "dev-master"
"excelwebzone/recaptcha-bundle": "dev-master",
"presta/sitemap-bundle": "dev-sitemap-dumper"
},
"scripts": {
"post-install-cmd": [
......
{
"hash": "429b6a3d3411cf9ad33039db7b3519b7",
"hash": "1162cca477117e38816d8cc4c830ec1b",
"packages": [
{
"name": "dflydev/markdown",
......@@ -129,18 +129,18 @@
"source": {
"type": "git",
"url": "https://github.com/doctrine/data-fixtures.git",
"reference": "v1.0.0-ALPHA3"
"reference": "181b71e9a19bcdc93a9bf5c19dc0ef9615656173"
},
"dist": {
"type": "zip",
"url": "https://github.com/doctrine/data-fixtures/zipball/v1.0.0-ALPHA3",
"reference": "v1.0.0-ALPHA3",
"url": "https://github.com/doctrine/data-fixtures/zipball/181b71e9a19bcdc93a9bf5c19dc0ef9615656173",
"reference": "181b71e9a19bcdc93a9bf5c19dc0ef9615656173",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"time": "1348136794",
"time": "1350901469",
"type": "library",
"installation-source": "source",
"autoload": {
......@@ -301,12 +301,12 @@
"source": {
"type": "git",
"url": "https://github.com/doctrine/DoctrineFixturesBundle.git",
"reference": "1e2c7af26f9f7ac9110d47cee8133d700fb99ae1"
"reference": "9edc67af16e736a31605e7fa9c9e3edbd9db6427"
},
"dist": {
"type": "zip",
"url": "https://github.com/doctrine/DoctrineFixturesBundle/zipball/1e2c7af26f9f7ac9110d47cee8133d700fb99ae1",
"reference": "1e2c7af26f9f7ac9110d47cee8133d700fb99ae1",
"url": "https://github.com/doctrine/DoctrineFixturesBundle/zipball/9edc67af16e736a31605e7fa9c9e3edbd9db6427",
"reference": "9edc67af16e736a31605e7fa9c9e3edbd9db6427",
"shasum": ""
},
"require": {
......@@ -315,7 +315,7 @@
"doctrine/doctrine-bundle": "1.0.*",
"symfony/doctrine-bridge": ">=2.1.0,<2.3-dev"
},
"time": "1349789605",
"time": "1350914272",
"type": "symfony-bundle",
"installation-source": "source",
"autoload": {
......@@ -1139,6 +1139,57 @@
"logging"
]
},
{
"name": "presta/sitemap-bundle",
"version": "dev-sitemap-dumper",
"target-dir": "Presta/SitemapBundle",
"source": {
"type": "git",
"url": "http://github.com/kostiklv/PrestaSitemapBundle",
"reference": "91355afdb2793915dca4682811c73de1d6f631e5"
},
"dist": {
"type": "zip",
"url": "https://github.com/kostiklv/PrestaSitemapBundle/zipball/91355afdb2793915dca4682811c73de1d6f631e5",
"reference": "91355afdb2793915dca4682811c73de1d6f631e5",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"symfony/symfony": "2.1.*@dev"
},
"suggest": {
"liip/doctrine-cache-bundle": "Allows to store sitemaps in cache"
},
"time": "1351083372",
"type": "symfony-bundle",
"installation-source": "source",
"autoload": {
"psr-0": {
"Presta\\SitemapBundle\\": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "David Epely",
"homepage": "http://www.prestaconcept.net/"
}
],
"description": "A symfony 2 bundle that provides tools to build your application sitemap.",
"keywords": [
"symfony2",
"bundle",
"sitemap",
"xml",
"prestaconcept"
],
"support": {
"source": "https://github.com/kostiklv/PrestaSitemapBundle/tree/sitemap-dumper"
}
},
{
"name": "sensio/distribution-bundle",
"version": "v2.1.1",
......@@ -1442,22 +1493,22 @@
},
{
"name": "swiftmailer/swiftmailer",
"version": "v4.2.1",
"version": "v4.2.2",
"source": {
"type": "git",
"url": "git://github.com/swiftmailer/swiftmailer.git",
"reference": "v4.2.1"
"reference": "v4.2.2"
},
"dist": {
"type": "zip",
"url": "https://github.com/swiftmailer/swiftmailer/zipball/v4.2.1",
"reference": "v4.2.1",
"url": "https://github.com/swiftmailer/swiftmailer/zipball/v4.2.2",
"reference": "v4.2.2",
"shasum": ""
},
"require": {
"php": ">=5.2.4"
},
"time": "2012-07-13 14:46:37",
"time": "2012-10-25 01:30:40",
"type": "library",
"extra": {
"branch-alias": {
......@@ -1922,6 +1973,7 @@
"xi/breadcrumbs-bundle": 20,
"hwi/oauth-bundle": 20,
"suncat/mobile-detect-bundle": 20,
"excelwebzone/recaptcha-bundle": 20
"excelwebzone/recaptcha-bundle": 20,
"presta/sitemap-bundle": 20
}
}
deploy @ c4aaea87
Subproject commit 9b2410c7596d12c7f794dde6446a81db17080844
Subproject commit c4aaea87157ea0a115f1210713618d25719956a1
......@@ -220,3 +220,4 @@ class CategoryController extends Controller
;
}
}
......@@ -5,7 +5,8 @@ namespace Jity\HomepageBundle\Controller;
use Jity\HomepageBundle\JityHomepageBundle,
Symfony\Bundle\FrameworkBundle\Controller\Controller,
Symfony\Component\HttpFoundation\Response,
Symfony\Component\HttpFoundation\Request;
Symfony\Component\HttpFoundation\Request,
Gedmo\Sluggable\Util\Urlizer;
/**
* EditorController
......@@ -39,6 +40,13 @@ class EditorController extends Controller
// Return to valid unescaped html chars
$html = htmlspecialchars_decode($html);
// Add anchors to all headlines
$html = preg_replace_callback('/(<h[1-6]>(.+)<\/h[1-6]>)/', function($matches){
return '<a name="' . Urlizer::urlize($matches[2]) . '"></a>' . $matches[1];
}, $html);
// Response the parsed data
return $this->render('JityHomepageBundle:Editor:format.html.twig', array(
'content' => $html
......
......@@ -368,12 +368,13 @@ erreichen, oder über Google+.
->setNavigation($this->getReference('blog-navigation'))
->setAuthor($this->getReference('admin-user'))
->setIcon('icon-font')
->setCreatedAt(new \DateTime('15.10.2012'))
->addTag(new Tag('Doctrine'))
->addTag(new Tag('Entities'), Tag::MATCH_LOW)
->addTag(new Tag('Many-to-Many'), Tag::MATCH)
->addTag(new Tag('Mapping'), Tag::MATCH)
->addTag(new Tag('Sortierung'))
->addComment($comment)
// ->addComment($comment)
;
/*
......
<?php
namespace Jity\HomepageBundle\EventListener;
use Symfony\Component\HttpFoundation\Request,
Symfony\Component\HttpFoundation\RedirectResponse,
JMS\DiExtraBundle\Annotation as DI,
Presta\SitemapBundle\Service\SitemapListenerInterface,
Presta\SitemapBundle\Event\SitemapPopulateEvent,
Presta\SitemapBundle\Sitemap\Url\UrlConcrete;
/**
* SitemapListener
*
* @DI\Service("jity.listener.sitemap")
* @DI\Tag("presta.sitemap.listener")
*
* @version $id$
* @author Hermann Mayer <hermann.mayer92@gmail.com>
*/
class SitemapListener implements SitemapListenerInterface
{
private $router;
private $em;
private $sections = array(
'pages' => array(
'repository' => 'JityHomepageBundle:Page',
'route' => 'page'
),
'articles' => array(
'repository' => 'JityHomepageBundle:Article',
'route' => 'article'
),
);
/**
* __construct
*
* @DI\InjectParams({
* "em" = @DI\Inject("doctrine.orm.entity_manager"),
* "router" = @DI\Inject("router")
* })
*
* @param mixed $session
* @param mixed $router
*
* @access public
* @return void
*/
public function __construct($em, $router)
{
$this->em = $em;
$this->router = $router;
}
public function populateSitemap(SitemapPopulateEvent $event)
{
$section = $event->getSection();
if (is_null($section) || $section == 'default') {
// Get absolute root url
$url = $this->router->generate('page', array(), true);
// Add root url to the url-set named default
$event->getGenerator()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
1
),
'sitemap.default'
);
}
// We generate links for all sections
if (is_null($section)) {
$links = $this->generateLinksByRepositories($this->sections);
// We generate links for a specified section
} else {
$links = $this->generateLinksByRepositories(array(
$section => $this->sections[$section]
));
}
// We add all found links
foreach ($links as $section => $sections) {
foreach ($sections as $url) {
// Add root url to the url-set named default
$event->getGenerator()->addUrl(
new UrlConcrete(
$url,
new \DateTime(),
UrlConcrete::CHANGEFREQ_HOURLY,
1
),
'sitemap.' . $section
);
}
}
}
/**
* generateLinksByRepositories
*
* @param array $sections
*
* @access private
* @return void
*/
private function generateLinksByRepositories(array $sections)
{
$links = array();
foreach ($sections as $section => $config) {
$config = (object) $config;
// Use DQL because its more powerfull and only one query is needed
$q = $this->em->createQueryBuilder('u')
->select('r.slug')
->from($config->repository, 'r')
->getQuery()
;
// Generate the Urls
foreach ($q->getResult() as $match) {
$links[$section][] = $this->router->generate(
$config->route,
array(
'slug' => $match['slug']
),
true
);
}
}
return $links;
}
}
.collection {
min-height: 50px;
border-radius: 6px;
......
......@@ -48,18 +48,30 @@ $(document).ready(function() {
/*
* scrollTo
*
* @param el int|string (absolute position|css selector)
* @return void
* @param el int|string|jQuery Object (absolute position|css selector|jQuery Object)
* @return jQuery Object
*/
app.scrollTo = function (el)
{
if (typeof(el) == 'number' && parseInt(el) == el)
if (typeof(el) == 'number' && parseInt(el) == el) {
var position = el;
else {
var returnEl = $(el);
} else if (typeof el == 'string') {
var position = $(el).offset().top;
}
var returnEl = $(el);
} else if (el instanceof jQuery) {
var position = el.offset().top;
var returnEl = el;
}
$('html,body').animate({scrollTop: position}, 'fast');
return $(el);
}
/*
......@@ -125,7 +137,26 @@ $(document).ready(function() {
}
});
});
$('.blog-article-wrapper h1, '
+ '.blog-article-wrapper h2, '
+ '.blog-article-wrapper h3, '
+ '.blog-article-wrapper h4, '
+ '.blog-article-wrapper h5, '
+ '.blog-article-wrapper h6').hover(
function (e) {
$(this).append(
$('<span> <a title="Permalink zum Abschnitt" href="#'
+ $(e.target).prev('a').attr('name')
+ '">⁋</a></span>'
)
);
},
function () {
$(this).find("span:last").remove();
}
);
}();
});
......
......@@ -16,11 +16,14 @@
</div>
<div class="blog-navigation">
<div id="blog-navigation-top" class="blog-navigation-element">
<div id="blog-navigation-top" class="blog-navigation-element" title="Zum Seiten Anfang">
<img src="{{ asset('bundles/jityhomepage/img/glyphicons_218_circle_arrow_top.png') }}" alt="" title="Zum Seiten Anfang">
</div>
<div id="blog-navigation-comments" class="blog-navigation-element">
<img src="{{ asset('bundles/jityhomepage/img/glyphicons_039_notes.png') }}" alt="" title="Zu den Kommentaren">
<div id="blog-navigation-headlines" class="blog-navigation-element" title="Zum nächsten Abschnitt">
<img src="{{ asset('bundles/jityhomepage/img/glyphicons_222_share.png') }}" alt="" title="Zum nächsten Abschnitt">
</div>
<div id="blog-navigation-comments" class="blog-navigation-element" title="Zu den Kommentaren">
<img src="{{ asset('bundles/jityhomepage/img/glyphicons_309_comments.png') }}" alt="" title="Zu den Kommentaren">
</div>
</div>
......@@ -65,12 +68,12 @@
</a>
</div>
<div class="push"></div>
{% render 'JityHomepageBundle:Blog:deleteCommentForm' with {id: comment.id, renderForm: true, action: path('article_comment_delete', {id: comment.id}) } %}
{% endif %}
{% endif %}
<div class="blog-article-comments-section">
<h4>
{% if comment.author %}
......@@ -105,7 +108,7 @@
{% else %}
{% render 'JityHomepageBundle:Blog:createCommentForm' with {renderFormTag: false, form: form_edit} %}
{% endif %}
<div class="form-actions">
<button type="submit" class="btn btn-primary">
<i class="icon-pencil icon-white"></i>
......@@ -154,7 +157,7 @@
Schreiben
</button>
</div>
{% endif %}
</form>
......@@ -190,25 +193,47 @@ $(document).ready(function() {
app.scrollTo(0);
});
lastHeadline = $();
$('#blog-navigation-headlines').click(function (){
if (0 == lastHeadline.size()) {
lastHeadline = '.blog-article-wrapper h1, '
+ '.blog-article-wrapper h2, '
+ '.blog-article-wrapper h3, '
+ '.blog-article-wrapper h4, '
+ '.blog-article-wrapper h5, '
+ '.blog-article-wrapper h6';
}
var last = app.scrollTo(lastHeadline);
lastHeadline = last.not(':first');
});
$('#blog-navigation-comments').click(function (){
app.scrollTo('a[name="comments"]');
});
article = {
refreshNavigation: function (){
// Fetch current values
var position = $(window).scrollTop();
var navbarHeight = $('.navbar').height();
var helper = $('.blog-article > div > .pull-left');
var topHelper = $('#blog-navigation-top');
var page = $('.blog-article');
var pageTop = page.offset().top;
var maxTop = pageTop + page.height() - helper.height() - 40; // 20 = Margins
var position = $(window).scrollTop();
var positionBottom = position + $(window).height();
var navbarHeight = $('.navbar').height();
var helper = $('.blog-article > div > .pull-left');
var topHelper = $('#blog-navigation-top');
var commentsHelper = $('#blog-navigation-comments');
var page = $('.blog-article');
var pageTop = page.offset().top;
var maxTop = pageTop + page.height() - helper.height() - 40; // 20 = Margins
var comElement = $('.blog-article-comments');
var comElementTop = comElement.offset().top;
var comElementBottom = comElementTop + comElement.height();
if ((position > navbarHeight) && (position < maxTop)) {
// User cant see the top and isnt near to the bottom
var curTop = $('.row:first').position().top - navbarHeight;
......@@ -222,9 +247,21 @@ $(document).ready(function() {
// Show Top-Trigger
topHelper.slideDown();
// Comments are visible or not
if ((comElementBottom <= positionBottom) && (comElementTop >= position)) {
// We are at the outer scope, just hide comments helper
commentsHelper.slideUp();
} else {
// We are at usefull position to display comments helper
commentsHelper.slideDown();
}
} else {
// User can see the top and is near to the bottom
// Remove Style and Hide Top-Trigger
topHelper.slideUp();
......@@ -236,7 +273,7 @@ $(document).ready(function() {
$(window).scroll(article.refreshNavigation);
comments = {
init: function() {
article.refreshNavigation();
......@@ -260,11 +297,8 @@ $(document).ready(function() {
var commentContent = comment.find('.blog-article-comment-content');
var form = comment.find('form:last');
console.log(form);
form.slideToggle();
commentContent.slideToggle();
});
$('.blog-article-comments .controllpanel .btn-remove').click(function (e){
......@@ -312,7 +346,7 @@ $(document).ready(function() {
// Just trigger the prepared form
form.trigger('submit');
comment.slideUp(function() {
// At end of sliding remove element from dom
......
......@@ -2,6 +2,8 @@
{% block layout_content %}{% endblock %}
{% block title %}{{ page.title }} &bull; {% endblock %}
{% block sidebar %}
{% if page is defined and page.sidebar.sections is defined %}
{% for section in page.sidebar.sections %}
......
......@@ -42,7 +42,7 @@
{% if label %}
{% if required %}
{% set label = label ~ ' <b>*</b>' %}
{% set label = label ~ ' *' %}
{# ' <span class="badge badge-important"><i class="icon-white icon-asterisk"></i></span>' #}
{% endif %}
......
......@@ -2,3 +2,5 @@
# www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449
User-agent: *
Sitemap: http://hermann-mayer.net/sitemap.xml
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment