Skip to content
This repository has been archived by the owner on Apr 4, 2019. It is now read-only.

Commit

Permalink
Merge pull request #9 from niels-nijens/fix-doctrine-proxy-upload
Browse files Browse the repository at this point in the history
Fix call stack when a Doctrine proxy subclass is active
  • Loading branch information
niels-nijens committed Feb 6, 2017
2 parents 15eaf18 + 5e6d14f commit 8d5a37e
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 5 deletions.
18 changes: 13 additions & 5 deletions Model/UploadTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ trait UploadTrait
*/
public function getFileUpload()
{
$propertyName = $this->getFileUploadPropertyName();
$propertyName = $this->getFileUploadPropertyName(__FUNCTION__);

if (isset($this->fileUploads[$propertyName])) {
return $this->fileUploads[$propertyName];
}
Expand All @@ -55,7 +56,8 @@ public function getFileUploads()
*/
public function setFileUpload(UploadedFile $file = null)
{
$propertyName = $this->getFileUploadPropertyName();
$propertyName = $this->getFileUploadPropertyName(__FUNCTION__);

unset($this->fileUploads[$propertyName]);
if ($file instanceof UploadedFile) {
$this->fileUploads[$propertyName] = $file;
Expand All @@ -77,8 +79,14 @@ public function setFileUploadPath($directory)
*
* @return string
*/
private function getFileUploadPropertyName()
private function getFileUploadPropertyName($realCallerMethod)
{
return lcfirst(substr(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)[1]['function'], 3, -6));
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
$callerMethodName = $backtrace[1]['function'];
if ($callerMethodName === $realCallerMethod) {
$callerMethodName = $backtrace[2]['function'];
}

return lcfirst(substr($callerMethodName, 3, -6));
}
}
}
100 changes: 100 additions & 0 deletions Tests/Model/UploadTraitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

namespace ConnectHolland\FileUploadBundle\Tests\Model;

use ConnectHolland\FileUploadBundle\Tests\UploadEntityMock;
use ConnectHolland\FileUploadBundle\Tests\UploadEntityProxyMock;
use PHPUnit_Framework_TestCase;
use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
* UploadTraitTest.
*
* @author Niels Nijens <niels@connectholland.nl>
*/
class UploadTraitTest extends PHPUnit_Framework_TestCase
{
/**
* Tests if the UploadEntityMock::setImageUpload (alias of UploadTrait::setFileUpload)
* sets the expected file uploads property.
*/
public function testSetFileUpload()
{
$uploadedFileMock = $this->getMockBuilder(UploadedFile::class)
->disableOriginalConstructor()
->getMock();

$entityMock = new UploadEntityMock();
$entityMock->setImageUpload($uploadedFileMock);

$this->assertAttributeSame(
array(
'image' => $uploadedFileMock,
),
'fileUploads',
$entityMock
);
}

/**
* Tests if the UploadEntityProxyMock::setImageUpload (alias of UploadTrait::setFileUpload)
* sets the expected file uploads property.
*
* This tests the scenario of a Doctrine entity being a parent class of
* a proxy class with all the method overloaded as this changes the
* PHP stack to determine the caller method.
*/
public function testSetFileUploadFromProxy()
{
$uploadedFileMock = $this->getMockBuilder(UploadedFile::class)
->disableOriginalConstructor()
->getMock();

$uploadEntityProxyMock = new UploadEntityProxyMock();
$uploadEntityProxyMock->setImageUpload($uploadedFileMock);

$this->assertAttributeSame(
array(
'image' => $uploadedFileMock,
),
'fileUploads',
$uploadEntityProxyMock
);
}

/**
* Tests if the UploadEntityMock::getImageUpload (alias of UploadTrait::getFileUpload)
* returns the expected file uploads property.
*/
public function testGetFileUpload()
{
$uploadedFileMock = $this->getMockBuilder(UploadedFile::class)
->disableOriginalConstructor()
->getMock();

$entityMock = new UploadEntityMock();
$entityMock->setImageUpload($uploadedFileMock);

$this->assertSame($uploadedFileMock, $entityMock->getImageUpload($uploadedFileMock));
}

/**
* Tests if the UploadEntityProxyMock::getImageUpload (alias of UploadTrait::getFileUpload)
* sets the expected file uploads property.
*
* This tests the scenario of a Doctrine entity being a parent class of
* a proxy class with all the method overloaded as this changes the
* PHP stack to determine the caller method.
*/
public function testGetFileUploadFromProxy()
{
$uploadedFileMock = $this->getMockBuilder(UploadedFile::class)
->disableOriginalConstructor()
->getMock();

$uploadEntityProxyMock = new UploadEntityProxyMock();
$uploadEntityProxyMock->setImageUpload($uploadedFileMock);

$this->assertSame($uploadedFileMock, $uploadEntityProxyMock->getImageUpload($uploadedFileMock));
}
}
18 changes: 18 additions & 0 deletions Tests/UploadEntityMock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace ConnectHolland\FileUploadBundle\Tests;

use ConnectHolland\FileUploadBundle\Model\UploadTrait;

/**
* Mock class for testing the UploadTrait.
*
* @author Niels Nijens <niels@connectholland.nl>
*/
class UploadEntityMock
{
use UploadTrait {
getFileUpload as getImageUpload;
setFileUpload as setImageUpload;
}
}
33 changes: 33 additions & 0 deletions Tests/UploadEntityProxyMock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace ConnectHolland\FileUploadBundle\Tests;

use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
* Mock class mimicking the behavior of a Doctrine proxy class.
*
* @author Niels Nijens <niels@connectholland.nl>
*/
class UploadEntityProxyMock extends UploadEntityMock
{
/**
* Overloaded trait method alias.
*
* @return UploadedFile
*/
public function getImageUpload()
{
return parent::getImageUpload();
}

/**
* Overloaded trait method alias.
*
* @param UploadedFile $file
*/
public function setImageUpload(UploadedFile $file = null)
{
parent::setImageUpload($file);
}
}

0 comments on commit 8d5a37e

Please sign in to comment.