Skip to content

Commit

Permalink
Symfony 3 compatibility work
Browse files Browse the repository at this point in the history
  • Loading branch information
mbabker committed Feb 14, 2016
1 parent 84f51ed commit e596e79
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 43 deletions.
11 changes: 5 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ cache:
env:
global:
- PATH="$HOME/.composer/vendor/bin:$PATH"
- SYMFONY_DEPRECATIONS_HELPER=weak

matrix:
fast_finish: true
Expand All @@ -31,16 +30,16 @@ matrix:
env: SYMFONY_VERSION=2.3.*
- php: 5.6
env: SYMFONY_VERSION=2.7.*
- php: 5.6
env: SYMFONY_VERSION=2.8.*
- php: 5.5
env: SYMFONY_VERSION="3.0.*" ACL_VERSION="dev-master"
env: SYMFONY_VERSION=3.0.* ACL_VERSION="dev-master"
- php: 5.6
env: SYMFONY_VERSION="3.0.*" ACL_VERSION="dev-master"
env: SYMFONY_VERSION=3.0.* ACL_VERSION="dev-master"
- php: 7.0
env: SYMFONY_VERSION="3.0.*" ACL_VERSION="dev-master"
env: SYMFONY_VERSION=3.0.* ACL_VERSION="dev-master"

allow_failures:
- php: 7.0
env: SYMFONY_VERSION=3.0.* ACL_VERSION="dev-master"
- php: hhvm

before_script:
Expand Down
2 changes: 1 addition & 1 deletion CDN/CloudFront.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ private function getClient()
public function setClient($client)
{
if (!$client instanceof CloudFrontClient) {
trigger_error('The '.__METHOD__.' expects a CloudFrontClient as parameter.', E_USER_DEPRECATED);
@trigger_error('The '.__METHOD__.' expects a CloudFrontClient as parameter.', E_USER_DEPRECATED);
}

$this->client = $client;
Expand Down
44 changes: 44 additions & 0 deletions DependencyInjection/Compiler/SecurityContextCompilerPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\MediaBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
* SecurityContextCompilerPass.
*
* This compiler pass provides compatibility with Syfmony < 2.6 security.context service
* and 2.6+ security.authorization_checker service. This pass may be removed when support
* for Symfony < 2.6 is dropped.
*/
class SecurityContextCompilerPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
// Prefer the security.authorization_checker service
if ($container->hasDefinition('security.authorization_checker')) {
$security = $container->getDefinition('security.authorization_checker');
} else {
$security = $container->getDefinition('security.context');
}

$container->getDefinition('sonata.media.security.superadmin_strategy')
->replaceArgument(1, $security);

$container->getDefinition('sonata.media.security.connected_strategy')
->replaceArgument(1, $security);
}
}
20 changes: 16 additions & 4 deletions Model/Media.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

use Imagine\Image\Box;
use Sonata\ClassificationBundle\Model\CategoryInterface;
use Symfony\Component\Validator\ExecutionContextInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\ExecutionContextInterface as LegacyExecutionContextInterface;

abstract class Media implements MediaInterface
{
Expand Down Expand Up @@ -611,12 +612,23 @@ public function getPreviousProviderReference()
}

/**
* @param ExecutionContextInterface $context
* @param ExecutionContextInterface|LegacyExecutionContextInterface $context
*/
public function isStatusErroneous(ExecutionContextInterface $context)
public function isStatusErroneous($context)
{
if ($this->getBinaryContent() && $this->getProviderStatus() == self::STATUS_ERROR) {
$context->addViolationAt('binaryContent', 'invalid', array(), null);
// Interface compatibility, the new ExecutionContextInterface should be typehinted when support for Symfony <2.5 is dropped
if (!$context instanceof ExecutionContextInterface && !$context instanceof LegacyExecutionContextInterface) {
throw new \InvalidArgumentException('Argument 1 should be an instance of Symfony\Component\Validator\ExecutionContextInterface or Symfony\Component\Validator\Context\ExecutionContextInterface');
}

if ($context instanceof LegacyExecutionContextInterface) {
$context->addViolationAt('binaryContent', 'invalid', array(), null);
} else {
$context->buildViolation('invalid')
->atPath('binaryContent')
->addViolation();
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions Resources/config/security.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

<service id="sonata.media.security.superadmin_strategy" class="Sonata\MediaBundle\Security\RolesDownloadStrategy" >
<argument type="service" id="translator" />
<argument type="service" id="security.context" />
<argument /> <!-- Either security.context or security.authorization_checker -->
<argument type="collection">
<argument>ROLE_SUPER_ADMIN</argument>
<argument>ROLE_ADMIN</argument>
Expand All @@ -24,7 +24,7 @@

<service id="sonata.media.security.connected_strategy" class="Sonata\MediaBundle\Security\RolesDownloadStrategy" >
<argument type="service" id="translator" />
<argument type="service" id="security.context" />
<argument /> <!-- Either security.context or security.authorization_checker -->
<argument type="collection">
<argument>IS_AUTHENTICATED_FULLY</argument>
<argument>IS_AUTHENTICATED_REMEMBERED</argument>
Expand Down
23 changes: 17 additions & 6 deletions Security/RolesDownloadStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

use Sonata\MediaBundle\Model\MediaInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Translation\TranslatorInterface;

Expand All @@ -24,7 +26,7 @@ class RolesDownloadStrategy implements DownloadStrategyInterface
protected $roles;

/**
* @var SecurityContextInterface
* @var AuthorizationCheckerInterface|SecurityContextInterface
*/
protected $security;

Expand All @@ -34,12 +36,16 @@ class RolesDownloadStrategy implements DownloadStrategyInterface
protected $translator;

/**
* @param TranslatorInterface $translator
* @param SecurityContextInterface $security
* @param string[] $roles
* @param TranslatorInterface $translator
* @param AuthorizationCheckerInterface|SecurityContextInterface $security
* @param string[] $roles
*/
public function __construct(TranslatorInterface $translator, SecurityContextInterface $security, array $roles = array())
public function __construct(TranslatorInterface $translator, $security, array $roles = array())
{
if (!$security instanceof AuthorizationCheckerInterface && !$security instanceof SecurityContextInterface) {
throw new \InvalidArgumentException('Argument 2 should be an instance of Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface or Symfony\Component\Security\Core\SecurityContextInterface');
}

$this->roles = $roles;
$this->security = $security;
$this->translator = $translator;
Expand All @@ -50,7 +56,12 @@ public function __construct(TranslatorInterface $translator, SecurityContextInte
*/
public function isGranted(MediaInterface $media, Request $request)
{
return $this->security->getToken() && $this->security->isGranted($this->roles);
try {
return $this->security->isGranted($this->roles);
} catch (AuthenticationCredentialsNotFoundException $e) {
// The token is not set in an AuthorizationCheckerInterface object
return false;
}
}

/**
Expand Down
2 changes: 2 additions & 0 deletions SonataMediaBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Sonata\CoreBundle\Form\FormHelper;
use Sonata\MediaBundle\DependencyInjection\Compiler\AddProviderCompilerPass;
use Sonata\MediaBundle\DependencyInjection\Compiler\GlobalVariablesCompilerPass;
use Sonata\MediaBundle\DependencyInjection\Compiler\SecurityContextCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

Expand All @@ -26,6 +27,7 @@ public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new AddProviderCompilerPass());
$container->addCompilerPass(new GlobalVariablesCompilerPass());
$container->addCompilerPass(new SecurityContextCompilerPass());

$this->registerFormMapping();
}
Expand Down
10 changes: 8 additions & 2 deletions Tests/CDN/CloudFrontTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
*/
class CloudFrontTest extends \PHPUnit_Framework_TestCase
{
public function testCloudFront()
/**
* @group legacy
*/
public function testLegacyCloudFront()
{
$client = $this->getMock('CloudFrontClientSpy', array('createInvalidation'), array(), '', false);
$client->expects($this->exactly(3))->method('createInvalidation')->will($this->returnValue(new CloudFrontResultSpy()));
Expand All @@ -36,7 +39,10 @@ public function testCloudFront()
$cloudFront->flushPaths(array($path));
}

public function testException()
/**
* @group legacy
*/
public function testLegacyException()
{
$this->setExpectedException('\RuntimeException', 'Unable to flush : ');
$client = $this->getMock('CloudFrontClientSpy', array('createInvalidation'), array(), '', false);
Expand Down
25 changes: 13 additions & 12 deletions Tests/Security/RolesDownloadStrategyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@

class RolesDownloadStrategyTest extends \PHPUnit_Framework_TestCase
{
/**
* @group legacy
*/
public function testIsGrantedTrue()
{
$media = $this->getMock('Sonata\MediaBundle\Model\MediaInterface');
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
$security = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
$translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface');

// Prefer the Syfmony 2.6+ API if available
if (interface_exists('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')) {
$security = $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface');
} else {
$security = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
}

$security->expects($this->any())
->method('isGranted')
->will($this->returnCallback(function (array $roles) {
return in_array('ROLE_ADMIN', $roles);
}));
$security->expects($this->once())
->method('getToken')
->will(($this->returnValue(true)));

$strategy = new RolesDownloadStrategy($translator, $security, array('ROLE_ADMIN'));
$this->assertTrue($strategy->isGranted($media, $request));
Expand All @@ -44,18 +44,19 @@ public function testIsGrantedFalse()
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
$translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface');

$security = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
// Prefer the Syfmony 2.6+ API if available
if (interface_exists('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')) {
$security = $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface');
} else {
$security = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
}

$security->expects($this->any())
->method('isGranted')
->will($this->returnCallback(function (array $roles) {
return in_array('FOO', $roles);
}));

$security->expects($this->once())
->method('getToken')
->will(($this->returnValue(true)));

$strategy = new RolesDownloadStrategy($translator, $security, array('ROLE_ADMIN'));
$this->assertFalse($strategy->isGranted($media, $request));
}
Expand Down
21 changes: 16 additions & 5 deletions Tests/Validator/FormatValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@

class FormatValidatorTest extends \PHPUnit_Framework_TestCase
{
/**
* @group legacy
*/
public function testValidate()
{
$pool = new Pool('defaultContext');
Expand All @@ -29,7 +26,14 @@ public function testValidate()
$gallery->expects($this->once())->method('getDefaultFormat')->will($this->returnValue('format1'));
$gallery->expects($this->once())->method('getContext')->will($this->returnValue('test'));

$context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
// Prefer the Syfmony 2.5+ API if available
if (class_exists('Symfony\Component\Validator\Context\ExecutionContext')) {
$contextClass = 'Symfony\Component\Validator\Context\ExecutionContext';
} else {
$contextClass = 'Symfony\Component\Validator\ExecutionContext';
}

$context = $this->getMock($contextClass, array(), array(), '', false);
$context->expects($this->never())->method('addViolation');

$validator = new FormatValidator($pool);
Expand All @@ -47,7 +51,14 @@ public function testValidateWithValidContext()
$gallery->expects($this->once())->method('getDefaultFormat')->will($this->returnValue('format1'));
$gallery->expects($this->once())->method('getContext')->will($this->returnValue('test'));

$context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
// Prefer the Syfmony 2.5+ API if available
if (class_exists('Symfony\Component\Validator\Context\ExecutionContext')) {
$contextClass = 'Symfony\Component\Validator\Context\ExecutionContext';
} else {
$contextClass = 'Symfony\Component\Validator\ExecutionContext';
}

$context = $this->getMock($contextClass, array(), array(), '', false);
$context->expects($this->once())->method('addViolation');

$validator = new FormatValidator($pool);
Expand Down
10 changes: 9 additions & 1 deletion Validator/FormatValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Sonata\MediaBundle\Provider\Pool;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\ExecutionContextInterface as LegacyExecutionContextInterface;

class FormatValidator extends ConstraintValidator
{
Expand All @@ -39,7 +40,14 @@ public function validate($value, Constraint $constraint)
$formats = $this->pool->getFormatNamesByContext($value->getContext());

if (!$value instanceof GalleryInterface) {
$this->context->addViolationAtPath('defaultFormat', 'Invalid instance, expected GalleryInterface');
// Interface compatibility, support for LegacyExecutionContextInterface can be removed when support for Symfony <2.5 is dropped
if ($this->context instanceof LegacyExecutionContextInterface) {
$this->context->addViolationAt('defaultFormat', 'Invalid instance, expected GalleryInterface');
} else {
$this->context->buildViolation('Invalid instance, expected GalleryInterface')
->atPath('defaultFormat')
->addViolation();
}
}

if (!array_key_exists($value->getDefaultFormat(), $formats)) {
Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
],
"require": {
"symfony/framework-bundle": "~2.3|~3.0",
"sonata-project/core-bundle": "~2.3,>=2.3.10",
"sonata-project/core-bundle": "^2.3.10",
"sonata-project/notification-bundle": "~2.2",
"sonata-project/easy-extends-bundle": "~2.1",
"sonata-project/doctrine-extensions": "~1.0",
Expand All @@ -34,13 +34,14 @@
"sonata-project/admin-bundle": "~2.3",
"sonata-project/formatter-bundle": "~2.2",
"sonata-project/datagrid-bundle": "~2.2",
"sonata-project/seo-bundle": "~1.1.5|~2.0",
"sonata-project/seo-bundle": "^1.1.5|~2.0",
"sonata-project/block-bundle": "^2.3.7",
"aws/aws-sdk-php": "~2.7",
"doctrine/mongodb-odm": "~1.0",
"jackalope/jackalope-doctrine-dbal": "~1.1",
"symfony/phpunit-bridge": "~2.7|~3.0",
"friendsofsymfony/rest-bundle": "~1.1",
"nelmio/api-doc-bundle": "~2.4"
"friendsofsymfony/rest-bundle": "^1.7.4|~2.0",
"nelmio/api-doc-bundle": "~2.11"
},
"suggest": {
"sonata-project/doctrine-orm-admin-bundle": "~2.3",
Expand Down

0 comments on commit e596e79

Please sign in to comment.