Merge branch '2.2' into 2.3
* 2.2: corrected English grammar (s/does not exists/does not exist) [Process] Add more precision to Process::stop timeout [Process] Avoid zombie process in case of unit tests failure [Process] Fix #8739 [Process] Add failing test for #8739 [Process] Fix CS Fixed documentation grammar for AuthenticationManagerInterface::authenticate() [Validator] fixed the wrong isAbstract() check against the class (fixed #8589) [TwigBridge] Prevent code extension to display warning Use strstr instead of strpos Conflicts: src/Symfony/Component/Finder/Shell/Command.php src/Symfony/Component/Process/Process.php
This commit is contained in:
commit
11018011dd
@ -137,7 +137,9 @@ class CodeExtension extends \Twig_Extension
|
||||
public function fileExcerpt($file, $line)
|
||||
{
|
||||
if (is_readable($file)) {
|
||||
$code = highlight_file($file, true);
|
||||
// highlight_file could throw warnings
|
||||
// see https://bugs.php.net/bug.php?id=25725
|
||||
$code = @highlight_file($file, true);
|
||||
// remove main code/span tags
|
||||
$code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
|
||||
$content = preg_split('#<br />#', $code);
|
||||
|
@ -131,7 +131,9 @@ class CodeHelper extends Helper
|
||||
}
|
||||
}
|
||||
|
||||
$code = highlight_file($file, true);
|
||||
// highlight_file could throw warnings
|
||||
// see https://bugs.php.net/bug.php?id=25725
|
||||
$code = @highlight_file($file, true);
|
||||
// remove main code/span tags
|
||||
$code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
|
||||
$content = preg_split('#<br />#', $code);
|
||||
|
@ -177,7 +177,7 @@ class ClassLoader
|
||||
$classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
|
||||
|
||||
foreach ($this->prefixes as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
if ($class === strstr($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
|
||||
return $dir.DIRECTORY_SEPARATOR.$classPath;
|
||||
|
@ -187,7 +187,7 @@ class Command
|
||||
public function get($label)
|
||||
{
|
||||
if (!isset($this->labels[$label])) {
|
||||
throw new \RuntimeException(sprintf('Label "%s" does not exists.', $label));
|
||||
throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
|
||||
}
|
||||
|
||||
return $this->bits[$this->labels[$label]];
|
||||
|
@ -35,7 +35,7 @@ interface ProfilerStorageInterface
|
||||
/**
|
||||
* Reads data associated with the given token.
|
||||
*
|
||||
* The method returns false if the token does not exists in the storage.
|
||||
* The method returns false if the token does not exist in the storage.
|
||||
*
|
||||
* @param string $token A token
|
||||
*
|
||||
|
@ -39,6 +39,7 @@ class Process
|
||||
// Timeout Precision in seconds.
|
||||
const TIMEOUT_PRECISION = 0.2;
|
||||
|
||||
private $callback;
|
||||
private $commandline;
|
||||
private $cwd;
|
||||
private $env;
|
||||
@ -166,6 +167,7 @@ class Process
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$this->callback = null;
|
||||
$this->exitcode = null;
|
||||
$this->fallbackExitcode = null;
|
||||
$this->processInformation = null;
|
||||
@ -201,7 +203,7 @@ class Process
|
||||
{
|
||||
$this->start($callback);
|
||||
|
||||
return $this->wait($callback);
|
||||
return $this->wait();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,7 +238,7 @@ class Process
|
||||
$this->stderr = '';
|
||||
$this->incrementalOutputOffset = 0;
|
||||
$this->incrementalErrorOutputOffset = 0;
|
||||
$callback = $this->buildCallback($callback);
|
||||
$this->callback = $this->buildCallback($callback);
|
||||
$descriptors = $this->getDescriptors();
|
||||
|
||||
$commandline = $this->commandline;
|
||||
@ -259,75 +261,11 @@ class Process
|
||||
stream_set_blocking($pipe, false);
|
||||
}
|
||||
|
||||
if ($this->tty) {
|
||||
$this->status = self::STATUS_TERMINATED;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (null === $this->stdin) {
|
||||
fclose($this->pipes[0]);
|
||||
unset($this->pipes[0]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$writePipes = array($this->pipes[0]);
|
||||
unset($this->pipes[0]);
|
||||
$stdinLen = strlen($this->stdin);
|
||||
$stdinOffset = 0;
|
||||
|
||||
while ($writePipes) {
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
$this->processFileHandles($callback);
|
||||
}
|
||||
|
||||
$r = $this->pipes;
|
||||
$w = $writePipes;
|
||||
$e = null;
|
||||
|
||||
if (false === $n = @stream_select($r, $w, $e, 0, ceil(static::TIMEOUT_PRECISION * 1E6))) {
|
||||
// if a system call has been interrupted, forget about it, let's try again
|
||||
if ($this->hasSystemCallBeenInterrupted()) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// nothing has changed, let's wait until the process is ready
|
||||
if (0 === $n) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($w) {
|
||||
$written = fwrite($writePipes[0], (binary) substr($this->stdin, $stdinOffset), 8192);
|
||||
if (false !== $written) {
|
||||
$stdinOffset += $written;
|
||||
}
|
||||
if ($stdinOffset >= $stdinLen) {
|
||||
fclose($writePipes[0]);
|
||||
$writePipes = null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($r as $pipe) {
|
||||
$type = array_search($pipe, $this->pipes);
|
||||
$data = fread($pipe, 8192);
|
||||
if (strlen($data) > 0) {
|
||||
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
|
||||
}
|
||||
if (false === $data || feof($pipe)) {
|
||||
fclose($pipe);
|
||||
unset($this->pipes[$type]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->writePipes(false);
|
||||
$this->updateStatus(false);
|
||||
$this->checkTimeout();
|
||||
}
|
||||
|
||||
$this->updateStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts the process.
|
||||
*
|
||||
@ -371,55 +309,15 @@ class Process
|
||||
*/
|
||||
public function wait($callback = null)
|
||||
{
|
||||
$this->updateStatus();
|
||||
$callback = $this->buildCallback($callback);
|
||||
while ($this->pipes || (defined('PHP_WINDOWS_VERSION_BUILD') && $this->fileHandles)) {
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->fileHandles) {
|
||||
$this->processFileHandles($callback, !$this->pipes);
|
||||
$this->updateStatus(false);
|
||||
if (null !== $callback) {
|
||||
$this->callback = $this->buildCallback($callback);
|
||||
}
|
||||
while ($this->processInformation['running']) {
|
||||
$this->updateStatus(true);
|
||||
$this->checkTimeout();
|
||||
|
||||
if ($this->pipes) {
|
||||
$r = $this->pipes;
|
||||
$w = null;
|
||||
$e = null;
|
||||
|
||||
// let's have a look if something changed in streams
|
||||
if (false === $n = @stream_select($r, $w, $e, 0, ceil(static::TIMEOUT_PRECISION * 1E6))) {
|
||||
// if a system call has been interrupted, forget about it, let's try again
|
||||
// otherwise, an error occured, let's reset pipes
|
||||
if (!$this->hasSystemCallBeenInterrupted()) {
|
||||
$this->pipes = array();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// nothing has changed
|
||||
if (0 === $n) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($r as $pipe) {
|
||||
$type = array_search($pipe, $this->pipes);
|
||||
$data = fread($pipe, 8192);
|
||||
|
||||
if (strlen($data) > 0) {
|
||||
// last exit code is output and caught to work around --enable-sigchild
|
||||
if (3 == $type) {
|
||||
$this->fallbackExitcode = (int) $data;
|
||||
} else {
|
||||
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
|
||||
}
|
||||
}
|
||||
if (false === $data || feof($pipe)) {
|
||||
fclose($pipe);
|
||||
unset($this->pipes[$type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->updateStatus();
|
||||
$this->updateStatus(false);
|
||||
if ($this->processInformation['signaled']) {
|
||||
if ($this->isSigchildEnabled()) {
|
||||
throw new RuntimeException('The process has been signaled.');
|
||||
@ -466,7 +364,7 @@ class Process
|
||||
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.');
|
||||
}
|
||||
|
||||
$this->updateStatus();
|
||||
$this->updateStatus(false);
|
||||
|
||||
return $this->isRunning() ? $this->processInformation['pid'] : null;
|
||||
}
|
||||
@ -507,7 +405,7 @@ class Process
|
||||
*/
|
||||
public function getOutput()
|
||||
{
|
||||
$this->updateOutput();
|
||||
$this->readPipes(false);
|
||||
|
||||
return $this->stdout;
|
||||
}
|
||||
@ -539,7 +437,7 @@ class Process
|
||||
*/
|
||||
public function getErrorOutput()
|
||||
{
|
||||
$this->updateErrorOutput();
|
||||
$this->readPipes(false);
|
||||
|
||||
return $this->stderr;
|
||||
}
|
||||
@ -578,7 +476,7 @@ class Process
|
||||
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method');
|
||||
}
|
||||
|
||||
$this->updateStatus();
|
||||
$this->updateStatus(false);
|
||||
|
||||
return $this->exitcode;
|
||||
}
|
||||
@ -630,7 +528,7 @@ class Process
|
||||
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
|
||||
}
|
||||
|
||||
$this->updateStatus();
|
||||
$this->updateStatus(false);
|
||||
|
||||
return $this->processInformation['signaled'];
|
||||
}
|
||||
@ -652,7 +550,7 @@ class Process
|
||||
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
|
||||
}
|
||||
|
||||
$this->updateStatus();
|
||||
$this->updateStatus(false);
|
||||
|
||||
return $this->processInformation['termsig'];
|
||||
}
|
||||
@ -668,7 +566,7 @@ class Process
|
||||
*/
|
||||
public function hasBeenStopped()
|
||||
{
|
||||
$this->updateStatus();
|
||||
$this->updateStatus(false);
|
||||
|
||||
return $this->processInformation['stopped'];
|
||||
}
|
||||
@ -684,7 +582,7 @@ class Process
|
||||
*/
|
||||
public function getStopSignal()
|
||||
{
|
||||
$this->updateStatus();
|
||||
$this->updateStatus(false);
|
||||
|
||||
return $this->processInformation['stopsig'];
|
||||
}
|
||||
@ -700,7 +598,7 @@ class Process
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->updateStatus();
|
||||
$this->updateStatus(false);
|
||||
|
||||
return $this->processInformation['running'];
|
||||
}
|
||||
@ -722,7 +620,7 @@ class Process
|
||||
*/
|
||||
public function isTerminated()
|
||||
{
|
||||
$this->updateStatus();
|
||||
$this->updateStatus(false);
|
||||
|
||||
return $this->status == self::STATUS_TERMINATED;
|
||||
}
|
||||
@ -736,7 +634,7 @@ class Process
|
||||
*/
|
||||
public function getStatus()
|
||||
{
|
||||
$this->updateStatus();
|
||||
$this->updateStatus(false);
|
||||
|
||||
return $this->status;
|
||||
}
|
||||
@ -753,12 +651,10 @@ class Process
|
||||
*/
|
||||
public function stop($timeout = 10, $signal = null)
|
||||
{
|
||||
$timeoutMicro = (int) $timeout*1E6;
|
||||
$timeoutMicro = microtime(true) + $timeout;
|
||||
if ($this->isRunning()) {
|
||||
proc_terminate($this->process);
|
||||
$time = 0;
|
||||
while (1 == $this->isRunning() && $time < $timeoutMicro) {
|
||||
$time += 1000;
|
||||
while ($this->isRunning() && microtime(true) < $timeoutMicro) {
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
@ -1161,14 +1057,18 @@ class Process
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the status of the process.
|
||||
* Updates the status of the process, reads pipes.
|
||||
*
|
||||
* @param Boolean $blocking Whether to use a clocking read call.
|
||||
*/
|
||||
protected function updateStatus()
|
||||
protected function updateStatus($blocking)
|
||||
{
|
||||
if (self::STATUS_STARTED !== $this->status) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->readPipes($blocking);
|
||||
|
||||
$this->processInformation = proc_get_status($this->process);
|
||||
if (!$this->processInformation['running']) {
|
||||
$this->status = self::STATUS_TERMINATED;
|
||||
@ -1178,29 +1078,6 @@ class Process
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current error output of the process (STDERR).
|
||||
*/
|
||||
protected function updateErrorOutput()
|
||||
{
|
||||
if (isset($this->pipes[self::STDERR]) && is_resource($this->pipes[self::STDERR])) {
|
||||
$this->addErrorOutput(stream_get_contents($this->pipes[self::STDERR]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current output of the process (STDOUT).
|
||||
*/
|
||||
protected function updateOutput()
|
||||
{
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD') && isset($this->fileHandles[self::STDOUT]) && is_resource($this->fileHandles[self::STDOUT])) {
|
||||
fseek($this->fileHandles[self::STDOUT], $this->readBytes[self::STDOUT]);
|
||||
$this->addOutput(stream_get_contents($this->fileHandles[self::STDOUT]));
|
||||
} elseif (isset($this->pipes[self::STDOUT]) && is_resource($this->pipes[self::STDOUT])) {
|
||||
$this->addOutput(stream_get_contents($this->pipes[self::STDOUT]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether PHP has been compiled with the '--enable-sigchild' option or not.
|
||||
*
|
||||
@ -1221,10 +1098,9 @@ class Process
|
||||
/**
|
||||
* Handles the windows file handles fallbacks.
|
||||
*
|
||||
* @param callable $callback A valid PHP callback
|
||||
* @param Boolean $closeEmptyHandles if true, handles that are empty will be assumed closed
|
||||
*/
|
||||
private function processFileHandles($callback, $closeEmptyHandles = false)
|
||||
private function processFileHandles($closeEmptyHandles = false)
|
||||
{
|
||||
$fh = $this->fileHandles;
|
||||
foreach ($fh as $type => $fileHandle) {
|
||||
@ -1232,7 +1108,7 @@ class Process
|
||||
$data = fread($fileHandle, 8192);
|
||||
if (strlen($data) > 0) {
|
||||
$this->readBytes[$type] += strlen($data);
|
||||
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
|
||||
call_user_func($this->callback, $type == 1 ? self::OUT : self::ERR, $data);
|
||||
}
|
||||
if (false === $data || ($closeEmptyHandles && '' === $data && feof($fileHandle))) {
|
||||
fclose($fileHandle);
|
||||
@ -1253,4 +1129,112 @@ class Process
|
||||
// stream_select returns false when the `select` system call is interrupted by an incoming signal
|
||||
return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads pipes, executes callback.
|
||||
*
|
||||
* @param Boolean $blocking Whether to use blocking calls or not.
|
||||
*/
|
||||
private function readPipes($blocking)
|
||||
{
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->fileHandles) {
|
||||
$this->processFileHandles(!$this->pipes);
|
||||
}
|
||||
|
||||
if ($this->pipes) {
|
||||
$r = $this->pipes;
|
||||
$w = null;
|
||||
$e = null;
|
||||
|
||||
// let's have a look if something changed in streams
|
||||
if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? ceil(self::TIMEOUT_PRECISION * 1E6) : 0)) {
|
||||
// if a system call has been interrupted, forget about it, let's try again
|
||||
// otherwise, an error occured, let's reset pipes
|
||||
if (!$this->hasSystemCallBeenInterrupted()) {
|
||||
$this->pipes = array();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// nothing has changed
|
||||
if (0 === $n) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($r as $pipe) {
|
||||
$type = array_search($pipe, $this->pipes);
|
||||
$data = fread($pipe, 8192);
|
||||
|
||||
if (strlen($data) > 0) {
|
||||
// last exit code is output and caught to work around --enable-sigchild
|
||||
if (3 == $type) {
|
||||
$this->fallbackExitcode = (int) $data;
|
||||
} else {
|
||||
call_user_func($this->callback, $type == 1 ? self::OUT : self::ERR, $data);
|
||||
}
|
||||
}
|
||||
if (false === $data || feof($pipe)) {
|
||||
fclose($pipe);
|
||||
unset($this->pipes[$type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data to pipes.
|
||||
*
|
||||
* @param Boolean $blocking Whether to use blocking calls or not.
|
||||
*/
|
||||
private function writePipes($blocking)
|
||||
{
|
||||
if ($this->tty) {
|
||||
$this->status = self::STATUS_TERMINATED;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (null === $this->stdin) {
|
||||
fclose($this->pipes[0]);
|
||||
unset($this->pipes[0]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$writePipes = array($this->pipes[0]);
|
||||
unset($this->pipes[0]);
|
||||
$stdinLen = strlen($this->stdin);
|
||||
$stdinOffset = 0;
|
||||
|
||||
while ($writePipes) {
|
||||
$r = array();
|
||||
$w = $writePipes;
|
||||
$e = null;
|
||||
|
||||
if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? ceil(static::TIMEOUT_PRECISION * 1E6) : 0)) {
|
||||
// if a system call has been interrupted, forget about it, let's try again
|
||||
if ($this->hasSystemCallBeenInterrupted()) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// nothing has changed, let's wait until the process is ready
|
||||
if (0 === $n) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($w) {
|
||||
$written = fwrite($writePipes[0], (binary) substr($this->stdin, $stdinOffset), 8192);
|
||||
if (false !== $written) {
|
||||
$stdinOffset += $written;
|
||||
}
|
||||
if ($stdinOffset >= $stdinLen) {
|
||||
fclose($writePipes[0]);
|
||||
$writePipes = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,23 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertLessThan(1.8, $duration);
|
||||
}
|
||||
|
||||
public function testCallbacksAreExecutedWithStart()
|
||||
{
|
||||
$data = '';
|
||||
|
||||
$process = $this->getProcess('echo "foo";sleep 1;echo "foo"');
|
||||
$process->start(function ($type, $buffer) use (&$data) {
|
||||
$data .= $buffer;
|
||||
});
|
||||
|
||||
$start = microtime(true);
|
||||
while ($process->isRunning()) {
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
$this->assertEquals("foo\nfoo\n", $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* tests results from sub processes
|
||||
*
|
||||
@ -254,7 +271,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testStop()
|
||||
{
|
||||
$process = $this->getProcess('php -r "while (true) {}"');
|
||||
$process = $this->getProcess('php -r "sleep(4);"');
|
||||
$process->start();
|
||||
$this->assertTrue($process->isRunning());
|
||||
$process->stop();
|
||||
@ -270,7 +287,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testIsNotSuccessful()
|
||||
{
|
||||
$process = $this->getProcess('php -r "while (true) {}"');
|
||||
$process = $this->getProcess('php -r "sleep(4);"');
|
||||
$process->start();
|
||||
$this->assertTrue($process->isRunning());
|
||||
$process->stop();
|
||||
@ -316,7 +333,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
||||
$this->markTestSkipped('Windows does not support POSIX signals');
|
||||
}
|
||||
|
||||
$process = $this->getProcess('php -r "while (true) {}"');
|
||||
$process = $this->getProcess('php -r "sleep(4);"');
|
||||
$process->start();
|
||||
$process->stop();
|
||||
$this->assertTrue($process->hasBeenSignaled());
|
||||
@ -331,7 +348,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
||||
// SIGTERM is only defined if pcntl extension is present
|
||||
$termSignal = defined('SIGTERM') ? SIGTERM : 15;
|
||||
|
||||
$process = $this->getProcess('php -r "while (true) {}"');
|
||||
$process = $this->getProcess('php -r "sleep(4);"');
|
||||
$process->start();
|
||||
$process->stop();
|
||||
|
||||
@ -382,7 +399,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
// Sleep doesn't work as it will allow the process to handle signals and close
|
||||
// file handles from the other end.
|
||||
$process = $this->getProcess('php -r "while (true) {}"');
|
||||
$process = $this->getProcess('php -r "sleep 4"');
|
||||
$process->start();
|
||||
|
||||
// PHP will deadlock when it tries to cleanup $process
|
||||
|
@ -12,7 +12,7 @@
|
||||
namespace Symfony\Component\Routing\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a route does not exists
|
||||
* Exception thrown when a route does not exist
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*
|
||||
|
@ -23,7 +23,7 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
interface AuthenticationManagerInterface
|
||||
{
|
||||
/**
|
||||
* Attempts to authenticates a TokenInterface object.
|
||||
* Attempts to authenticate a TokenInterface object.
|
||||
*
|
||||
* @param TokenInterface $token The TokenInterface instance to authenticate
|
||||
*
|
||||
|
@ -45,7 +45,7 @@ class ChainLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$loader = new ProjectTemplateLoader1(array($this->loader1, $this->loader2));
|
||||
$this->assertFalse($loader->load(new TemplateReference('bar', 'php')), '->load() returns false if the template is not found');
|
||||
$this->assertFalse($loader->load(new TemplateReference('foo', 'php')), '->load() returns false if the template does not exists for the given renderer');
|
||||
$this->assertFalse($loader->load(new TemplateReference('foo', 'php')), '->load() returns false if the template does not exist for the given renderer');
|
||||
$this->assertInstanceOf(
|
||||
'Symfony\Component\Templating\Storage\FileStorage',
|
||||
$loader->load(new TemplateReference('foo.php', 'php')),
|
||||
|
@ -61,7 +61,7 @@ class FilesystemLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$loader = new ProjectTemplateLoader2($pathPattern);
|
||||
$loader->setDebugger($debugger = new \Symfony\Component\Templating\Tests\Fixtures\ProjectTemplateDebugger());
|
||||
$this->assertFalse($loader->load(new TemplateReference('foo.xml', 'php')), '->load() returns false if the template does not exists for the given engine');
|
||||
$this->assertFalse($loader->load(new TemplateReference('foo.xml', 'php')), '->load() returns false if the template does not exist for the given engine');
|
||||
$this->assertTrue($debugger->hasMessage('Failed loading template'), '->load() logs a "Failed loading template" message if the template is not found');
|
||||
|
||||
$loader = new ProjectTemplateLoader2(array(self::$fixturesPath.'/null/%name%', $pathPattern));
|
||||
|
@ -31,9 +31,13 @@ class StaticMethodLoader implements LoaderInterface
|
||||
/** @var \ReflectionClass $reflClass */
|
||||
$reflClass = $metadata->getReflectionClass();
|
||||
|
||||
if (!$reflClass->isInterface() && !$reflClass->isAbstract() && $reflClass->hasMethod($this->methodName)) {
|
||||
if (!$reflClass->isInterface() && $reflClass->hasMethod($this->methodName)) {
|
||||
$reflMethod = $reflClass->getMethod($this->methodName);
|
||||
|
||||
if ($reflMethod->isAbstract()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$reflMethod->isStatic()) {
|
||||
throw new MappingException(sprintf('The method %s::%s should be static', $reflClass->name, $this->methodName));
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class GetterMetadataTest extends \PHPUnit_Framework_TestCase
|
||||
public function testGetPropertyValueFromPublicGetter()
|
||||
{
|
||||
// private getters don't work yet because ReflectionMethod::setAccessible()
|
||||
// does not exists yet in a stable PHP release
|
||||
// does not exist yet in a stable PHP release
|
||||
|
||||
$entity = new Entity('foobar');
|
||||
$metadata = new GetterMetadata(self::CLASSNAME, 'internal');
|
||||
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Validator\Tests\Mapping\Loader;
|
||||
|
||||
use Symfony\Component\Validator\Mapping\ClassMetadata;
|
||||
|
||||
abstract class AbstractMethodStaticLoader
|
||||
{
|
||||
abstract public static function loadMetadata(ClassMetadata $metadata);
|
||||
}
|
@ -66,13 +66,28 @@ class StaticMethodLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertCount(0, $metadata->getConstraints());
|
||||
}
|
||||
|
||||
public function testLoadClassMetadataIgnoresAbstractClasses()
|
||||
public function testLoadClassMetadataInAbstractClasses()
|
||||
{
|
||||
$loader = new StaticMethodLoader('loadMetadata');
|
||||
$metadata = new ClassMetadata(__NAMESPACE__.'\AbstractStaticLoader');
|
||||
|
||||
$loader->loadClassMetadata($metadata);
|
||||
|
||||
$this->assertCount(1, $metadata->getConstraints());
|
||||
}
|
||||
|
||||
public function testLoadClassMetadataIgnoresAbstractMethods()
|
||||
{
|
||||
$loader = new StaticMethodLoader('loadMetadata');
|
||||
try {
|
||||
include __DIR__ . '/AbstractMethodStaticLoader.php';
|
||||
$this->fail('AbstractMethodStaticLoader should produce a strict standard error.');
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
$metadata = new ClassMetadata(__NAMESPACE__.'\AbstractMethodStaticLoader');
|
||||
$loader->loadClassMetadata($metadata);
|
||||
|
||||
$this->assertCount(0, $metadata->getConstraints());
|
||||
}
|
||||
}
|
||||
@ -86,6 +101,7 @@ abstract class AbstractStaticLoader
|
||||
{
|
||||
public static function loadMetadata(ClassMetadata $metadata)
|
||||
{
|
||||
$metadata->addConstraint(new ConstraintA());
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user