Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

Commit

Permalink
Merge pull request #288 from symfony-cmf/depth_information_in_sitemap…
Browse files Browse the repository at this point in the history
…_1.3

Depth information in sitemap 1.3
  • Loading branch information
dbu committed Apr 22, 2016
2 parents 799d539 + 7dc16f2 commit 806cb9d
Show file tree
Hide file tree
Showing 10 changed files with 339 additions and 6 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
=========

1.3.0 (unreleased)
------------------

* **2016-04-12**: Build and register DepthGuesser for PHPCR to use depths information for structure sitemap

1.2.0
-----

Expand Down
2 changes: 1 addition & 1 deletion Doctrine/Phpcr/SitemapDocumentProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function load($sitemap)
{
// todo rewrite query when https://github.com/symfony-cmf/CoreBundle/issues/126 is ready
$documentsCollection = $this->manager->createQuery(
'SELECT * FROM [nt:unstructured] WHERE (visible_for_sitemap = true)',
'SELECT * FROM [nt:unstructured] WHERE (visible_for_sitemap = true) ORDER BY [jcr:path]',
QueryInterface::JCR_SQL2
)->execute();

Expand Down
22 changes: 22 additions & 0 deletions Model/UrlInformation.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ class UrlInformation
*/
private $alternateLocales;

/**
* @var int|null
*/
private $depth;

public function __construct()
{
$this->alternateLocales = array();
Expand Down Expand Up @@ -94,6 +99,7 @@ public function toArray()
'lastmod' => $this->lastModification,
'priority' => $this->priority,
'alternate_locales' => array(),
'depth' => $this->depth,
);
foreach ($result as $key => $value) {
if (null === $value) {
Expand Down Expand Up @@ -248,4 +254,20 @@ public function addAlternateLocale(AlternateLocale $alternateLocale)

return $this;
}

/**
* @return int
*/
public function getDepth()
{
return $this->depth;
}

/**
* @param int|null $depth
*/
public function setDepth($depth)
{
$this->depth = $depth;
}
}
6 changes: 6 additions & 0 deletions Resources/config/phpcr-sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,11 @@

<tag name="cmf_seo.sitemap.loader" priority="-2"/>
</service>
<service id="cmf_seo.sitemap.phpcr.depth_guesser" class="Symfony\Cmf\Bundle\SeoBundle\Sitemap\DepthGuesser">
<argument type="service" id="doctrine_phpcr"/>
<argument>%cmf_routing.dynamic.persistence.phpcr.content_basepath%</argument>

<tag name="cmf_seo.sitemap.guesser" position="-2"/>
</service>
</services>
</container>
2 changes: 1 addition & 1 deletion Resources/views/Sitemap/index.html.twig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<ul class="cmf-sitemap">
{% for url in urls %}
<li>
<li{% if url.depth is not null %} class="indent-{{ url.depth }}"{% endif %}>
<a href="{{ url.location }}" title="{{ url.label }}">{{ url.label }}</a>
</li>
{% endfor %}
Expand Down
68 changes: 68 additions & 0 deletions Sitemap/DepthGuesser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2016 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Cmf\Bundle\SeoBundle\Sitemap;

use Doctrine\Bundle\PHPCRBundle\ManagerRegistry;
use Doctrine\Common\Util\ClassUtils;
use Doctrine\ODM\PHPCR\DocumentManager;
use Symfony\Cmf\Bundle\SeoBundle\Model\UrlInformation;

/**
* This guesser will add the depth of a document persisted on a phpcr node.
*
* @author Maximilian Berghoff <Maximilian.Berghoff@mayflower.de>
*/
class DepthGuesser implements GuesserInterface
{
/**
* @var ManagerRegistry
*/
private $managerRegistry;

/**
* @var int The depth of the content base path as the depth offset.
*/
private $offset;

/**
* DepthGuesser constructor.
*
* @param ManagerRegistry $managerRegistry
* @param $contentBasePath
*/
public function __construct(ManagerRegistry $managerRegistry, $contentBasePath)
{
$this->managerRegistry = $managerRegistry;
$this->offset = ('/' === $contentBasePath) ? 1 : substr_count($contentBasePath, '/') + 1;
}

/**
* {@inheritdoc}
*/
public function guessValues(UrlInformation $urlInformation, $object, $sitemap)
{
if (null !== $urlInformation->getDepth()) {
return;
}

$manager = $this->managerRegistry->getManagerForClass(ClassUtils::getRealClass(get_class($object)));
if (!$manager instanceof DocumentManager) {
return;
}

$node = $manager->getNodeForDocument($object);
if (null === $node) {
return;
}
$urlInformation->setDepth($node->getDepth() - $this->offset);
}
}
57 changes: 57 additions & 0 deletions Tests/Functional/Doctrine/Phpcr/SitemapDocumentProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2016 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Cmf\Bundle\SeoBundle\Tests\Functional\Doctrine\Phpcr;

use Symfony\Cmf\Bundle\SeoBundle\Doctrine\Phpcr\SitemapDocumentProvider;
use Symfony\Cmf\Component\Testing\Functional\BaseTestCase;

/**
* @author Maximilian Berghoff <Maximilian.Berghoff@mayflower.de>
*/
class SitemapDocumentProviderTest extends BaseTestCase
{
/**
* @var SitemapDocumentProvider
*/
private $documentProvider;

public function setUp()
{
$this->db('PHPCR')->createTestNode();
$this->dm = $this->db('PHPCR')->getOm();
$this->base = $this->dm->find(null, '/test');
$this->db('PHPCR')->loadFixtures(array(
'Symfony\Cmf\Bundle\SeoBundle\Tests\Resources\DataFixtures\Phpcr\LoadSitemapData',
));

$this->documentProvider = new SitemapDocumentProvider($this->dm);
}

public function testDocumentOrder()
{
$documents = $this->documentProvider->load('default');

$paths = array();
foreach ($documents as $document) {
$paths[] = $document->getId();
}

$this->assertEquals(
array(
'/test/content/sitemap-aware',
'/test/content/sitemap-aware-non-publish',
'/test/content/sitemap-aware-publish',
),
$paths
);
}
}
175 changes: 175 additions & 0 deletions Tests/Unit/Sitemap/DepthGuesserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<?php

/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2016 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Cmf\Bundle\SeoBundle\Tests\Unit\Sitemap;

use Doctrine\Bundle\PHPCRBundle\ManagerRegistry;
use Doctrine\ODM\PHPCR\DocumentManager;
use PHPCR\NodeInterface;
use Symfony\Cmf\Bundle\SeoBundle\Model\UrlInformation;
use Symfony\Cmf\Bundle\SeoBundle\Sitemap\DepthGuesser;
use Symfony\Cmf\Bundle\SeoBundle\Sitemap\GuesserInterface;

/**
* @author Maximilian Berghoff <Maximilian.Berghoff@mayflower.de>
*/
class DepthGuesserTest extends GuesserTestCase
{
/**
* @var \stdClass
*/
protected $object;

/**
* @var ManagerRegistry
*/
protected $managerRegistry;

/**
* @var DocumentManager
*/
protected $documentManager;

/**
* @var DepthGuesser
*/
protected $guesser;

/**
* @var NodeInterface
*/
protected $node;

/**
* Create the guesser for this test.
*
* @return GuesserInterface
*/
protected function createGuesser()
{
$this->buildMocks();

$this->managerRegistry
->expects($this->any())
->method('getManagerForClass')
->with(get_class($this->object))
->will($this->returnValue($this->documentManager));
$this->documentManager
->expects($this->any())
->method('getNodeForDocument')
->with($this->object)
->willReturn($this->node);
$this->node
->expects($this->any())
->method('getDepth')
->will($this->returnValue(3));

return $this->guesser;
}

/**
* @return object
*/
protected function createData()
{
return $this->object;
}

/**
* Provide list of fields in UrlInformation covered by this guesser.
*
* @return array
*/
protected function getFields()
{
return array('depth');
}

/**
* Method to extract mock building.
*
* @param string $contentBasePath
*/
private function buildMocks($contentBasePath = '/cms/test')
{
$this->managerRegistry = $this->getMockBuilder('Doctrine\Bundle\PHPCRBundle\ManagerRegistry')
->disableOriginalConstructor()
->getMock();
$this->documentManager = $this->getMockBuilder('Doctrine\ODM\PHPCR\DocumentManager')
->disableOriginalConstructor()
->getMock();
$this->node = $this->getMock('PHPCR\NodeInterface');
$this->object = new \stdClass();
$this->guesser = new DepthGuesser($this->managerRegistry, $contentBasePath);
}

public function testNullOnNoManager()
{
$this->buildMocks();
$this->managerRegistry
->expects($this->any())
->method('getManagerForClass')
->with(get_class($this->object))
->will($this->returnValue(null));
$urlInformation = new UrlInformation();
$this->guesser->guessValues($urlInformation, $this->object, 'default');

$this->assertNull($urlInformation->getDepth());
}

public function testDepthOffsetCalculation()
{
$this->buildMocks();

$this->managerRegistry
->expects($this->any())
->method('getManagerForClass')
->with(get_class($this->object))
->will($this->returnValue($this->documentManager));
$this->documentManager
->expects($this->any())
->method('getNodeForDocument')
->with($this->object)
->willReturn($this->node);
$this->node
->expects($this->any())
->method('getDepth')
->will($this->returnValue(4));
$urlInformation = new UrlInformation();
$this->guesser->guessValues($urlInformation, $this->object, 'default');

$this->assertEquals(1, $urlInformation->getDepth());
}

public function testRootEdgeCase()
{
$this->buildMocks('/');

$this->managerRegistry
->expects($this->any())
->method('getManagerForClass')
->with(get_class($this->object))
->will($this->returnValue($this->documentManager));
$this->documentManager
->expects($this->any())
->method('getNodeForDocument')
->with($this->object)
->willReturn($this->node);
$this->node
->expects($this->any())
->method('getDepth')
->will($this->returnValue(4));
$urlInformation = new UrlInformation();
$this->guesser->guessValues($urlInformation, $this->object, 'default');

$this->assertEquals(3, $urlInformation->getDepth());
}
}
Loading

0 comments on commit 806cb9d

Please sign in to comment.