Skip to content

Commit

Permalink
Fix EZP-24053: Preview locks content object, and cause version edit c…
Browse files Browse the repository at this point in the history
…onflict

> https://jira.ez.no/browse/EZP-24053

This issue was due to an incomplete implementation of legacy website toolbar (handling preview was missing).
This PR ensures that:

* Content preview route is only used with Http GET (POST will be used by legacy to publish or go back to editing).
* One can easily check if preview is active and retrieve previewed content/location.

ContentPreviewHelper is now used to check if preview is active and to get previewed content/location
since as of Symfony 2.4, request attributes from the master request are not passed to sub-requests any more.
Furthermore, it's cleaner to be able to get this information through a dedicated service instead of request attributes.
  • Loading branch information
lolautruche committed Mar 30, 2015
1 parent 8371799 commit 7ebb250
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 15 deletions.
1 change: 1 addition & 0 deletions eZ/Bundle/EzPublishCoreBundle/Resources/config/papi.yml
Expand Up @@ -14,6 +14,7 @@ parameters:

ezpublish.api.content.class: eZ\Publish\Core\Repository\Values\Content\Content
ezpublish.api.location.class: eZ\Publish\Core\Repository\Values\Content\Location
ezpublish.api.version.class: eZ\Publish\Core\Repository\Values\Content\VersionInfo

services:
# API
Expand Down
Expand Up @@ -9,10 +9,12 @@ _ezpublishLocation:
_ezpublishPreviewContent:
path: /content/versionview/{contentId}/{versionNo}/{language}/site_access/{siteAccessName}
defaults: { _controller: ezpublish.controller.content.preview:previewContentAction }
methods: [GET]

_ezpublishPreviewContentDefaultSa:
path: /content/versionview/{contentId}/{versionNo}/{language}
defaults: { _controller: ezpublish.controller.content.preview:previewContentAction }
methods: [GET]

_ez_user_hash:
path: /_fos_user_context_hash
65 changes: 65 additions & 0 deletions eZ/Publish/Core/Helper/ContentPreviewHelper.php
Expand Up @@ -9,6 +9,8 @@

namespace eZ\Publish\Core\Helper;

use eZ\Publish\API\Repository\Values\Content\Content;
use eZ\Publish\API\Repository\Values\Content\Location;
use eZ\Publish\Core\MVC\Symfony\Event\ScopeChangeEvent;
use eZ\Publish\Core\MVC\Symfony\MVCEvents;
use eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessAware;
Expand All @@ -27,6 +29,21 @@ class ContentPreviewHelper implements SiteAccessAware
*/
protected $originalSiteAccess;

/**
* @var bool
*/
private $previewActive = false;

/**
* @var \eZ\Publish\API\Repository\Values\Content\Content
*/
private $previewedContent;

/**
* @var \eZ\Publish\API\Repository\Values\Content\Location
*/
private $previewedLocation;

public function __construct( EventDispatcherInterface $eventDispatcher )
{
$this->eventDispatcher = $eventDispatcher;
Expand Down Expand Up @@ -74,4 +91,52 @@ public function restoreConfigScope()

return $event->getSiteAccess();
}

/**
* @return boolean
*/
public function isPreviewActive()
{
return $this->previewActive;
}

/**
* @param boolean $previewActive
*/
public function setPreviewActive( $previewActive )
{
$this->previewActive = (bool)$previewActive;
}

/**
* @return \eZ\Publish\API\Repository\Values\Content\Content
*/
public function getPreviewedContent()
{
return $this->previewedContent;
}

/**
* @param \eZ\Publish\API\Repository\Values\Content\Content $previewedContent
*/
public function setPreviewedContent( Content $previewedContent)
{
$this->previewedContent = $previewedContent;
}

/**
* @return \eZ\Publish\API\Repository\Values\Content\Location
*/
public function getPreviewedLocation()
{
return $this->previewedLocation;
}

/**
* @param \eZ\Publish\API\Repository\Values\Content\Location $previewedLocation
*/
public function setPreviewedLocation( Location $previewedLocation )
{
$this->previewedLocation = $previewedLocation;
}
}
47 changes: 32 additions & 15 deletions eZ/Publish/Core/Helper/Tests/ContentPreviewHelperTest.php
Expand Up @@ -23,15 +23,15 @@ class ContentPreviewHelperTest extends PHPUnit_Framework_TestCase
private $eventDispatcher;

/**
* @var \PHPUnit_Framework_MockObject_MockObject
* @var \eZ\Publish\Core\Helper\ContentPreviewHelper
*/
private $configResolver;
private $previewHelper;

protected function setUp()
{
parent::setUp();
$this->eventDispatcher = $this->getMock( 'Symfony\Component\EventDispatcher\EventDispatcherInterface' );
$this->configResolver = $this->getMock( 'eZ\Publish\Core\MVC\ConfigResolverInterface' );
$this->previewHelper = new ContentPreviewHelper( $this->eventDispatcher );
}

public function testChangeConfigScope()
Expand All @@ -45,14 +45,10 @@ public function testChangeConfigScope()
->with( MVCEvents::CONFIG_SCOPE_CHANGE, $this->equalTo( $event ) );

$originalSiteAccess = new SiteAccess( 'foo', 'bar' );
$helper = new ContentPreviewHelper(
$this->eventDispatcher,
$this->configResolver
);
$helper->setSiteAccess( $originalSiteAccess );
$this->previewHelper->setSiteAccess( $originalSiteAccess );
$this->assertEquals(
$newSiteAccess,
$helper->changeConfigScope( $newSiteAccessName )
$this->previewHelper->changeConfigScope( $newSiteAccessName )
);
}

Expand All @@ -65,14 +61,35 @@ public function testRestoreConfigScope()
->method( 'dispatch' )
->with( MVCEvents::CONFIG_SCOPE_RESTORE, $this->equalTo( $event ) );

$helper = new ContentPreviewHelper(
$this->eventDispatcher,
$this->configResolver
);
$helper->setSiteAccess( $originalSiteAccess );
$this->previewHelper->setSiteAccess( $originalSiteAccess );
$this->assertEquals(
$originalSiteAccess,
$helper->restoreConfigScope()
$this->previewHelper->restoreConfigScope()
);
}

public function testPreviewActive()
{
$this->assertFalse( $this->previewHelper->isPreviewActive() );
$this->previewHelper->setPreviewActive( true );
$this->assertTrue( $this->previewHelper->isPreviewActive() );
$this->previewHelper->setPreviewActive( false );
$this->assertFalse( $this->previewHelper->isPreviewActive() );
}

public function testPreviewedContent()
{
$this->assertNull( $this->previewHelper->getPreviewedContent() );
$content = $this->getMock( '\eZ\Publish\API\Repository\Values\Content\Content' );
$this->previewHelper->setPreviewedContent( $content );
$this->assertSame( $content, $this->previewHelper->getPreviewedContent() );
}

public function testPreviewedLocation()
{
$this->assertNull( $this->previewHelper->getPreviewedLocation() );
$location = $this->getMock( '\eZ\Publish\API\Repository\Values\Content\Location' );
$this->previewHelper->setPreviewedLocation( $location );
$this->assertSame( $location, $this->previewHelper->getPreviewedLocation() );
}
}
Expand Up @@ -78,10 +78,14 @@ public function setRequest( Request $request = null )

public function previewContentAction( $contentId, $versionNo, $language, $siteAccessName = null )
{
$this->previewHelper->setPreviewActive( true );

try
{
$content = $this->contentService->loadContent( $contentId, array( $language ), $versionNo );
$location = $this->locationProvider->loadMainLocation( $contentId );
$this->previewHelper->setPreviewedContent( $content );
$this->previewHelper->setPreviewedLocation( $location );
}
catch ( UnauthorizedException $e )
{
Expand All @@ -108,6 +112,7 @@ public function previewContentAction( $contentId, $versionNo, $language, $siteAc
$response->headers->remove( 'expires' );

$this->previewHelper->restoreConfigScope();
$this->previewHelper->setPreviewActive( false );

return $response;
}
Expand Down
Expand Up @@ -165,6 +165,25 @@ public function testPreview()
$request = $this->getMock( 'Symfony\Component\HttpFoundation\Request', array( 'duplicate' ) );

// PreviewHelper expectations
$this->previewHelper
->expects( $this->exactly( 2 ) )
->method( 'setPreviewActive' )
->will(
$this->returnValueMap(
array(
array( true, null ),
array( false, null ),
)
)
);
$this->previewHelper
->expects( $this->once() )
->method( 'setPreviewedContent' )
->with( $content );
$this->previewHelper
->expects( $this->once() )
->method( 'setPreviewedLocation' )
->with( $location );
$this->previewHelper
->expects( $this->once() )
->method( 'getOriginalSiteAccess' )
Expand Down

0 comments on commit 7ebb250

Please sign in to comment.