diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 40809fb7b4..852bd3af84 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -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('#^\s*(.*)\s*#s', '\\1', $code); $content = preg_split('#
#', $code); diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php index 3c031d2c5b..edbf7a878a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php @@ -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('#^\s*(.*)\s*#s', '\\1', $code); $content = preg_split('#
#', $code); diff --git a/src/Symfony/Component/ClassLoader/ClassLoader.php b/src/Symfony/Component/ClassLoader/ClassLoader.php index 1a359794ab..00de5b980b 100644 --- a/src/Symfony/Component/ClassLoader/ClassLoader.php +++ b/src/Symfony/Component/ClassLoader/ClassLoader.php @@ -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; diff --git a/src/Symfony/Component/Finder/Shell/Command.php b/src/Symfony/Component/Finder/Shell/Command.php index 9a02f7eafa..5fcfed803f 100644 --- a/src/Symfony/Component/Finder/Shell/Command.php +++ b/src/Symfony/Component/Finder/Shell/Command.php @@ -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]]; diff --git a/src/Symfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.php b/src/Symfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.php index 3bb0d68ffd..f4b9e5e212 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.php +++ b/src/Symfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.php @@ -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 * diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 8e18689ee4..6f345bc57f 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -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,73 +261,9 @@ 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->checkTimeout(); - } - - $this->updateStatus(); + $this->writePipes(false); + $this->updateStatus(false); + $this->checkTimeout(); } /** @@ -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->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(false); + if (null !== $callback) { + $this->callback = $this->buildCallback($callback); } - $this->updateStatus(); + while ($this->processInformation['running']) { + $this->updateStatus(true); + $this->checkTimeout(); + } + $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; + } + } + } + } } diff --git a/src/Symfony/Component/Process/Tests/AbstractProcessTest.php b/src/Symfony/Component/Process/Tests/AbstractProcessTest.php index 9c352d529e..53f79c5b55 100644 --- a/src/Symfony/Component/Process/Tests/AbstractProcessTest.php +++ b/src/Symfony/Component/Process/Tests/AbstractProcessTest.php @@ -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 diff --git a/src/Symfony/Component/Routing/Exception/RouteNotFoundException.php b/src/Symfony/Component/Routing/Exception/RouteNotFoundException.php index 4d5f288e7e..fd275bebe9 100644 --- a/src/Symfony/Component/Routing/Exception/RouteNotFoundException.php +++ b/src/Symfony/Component/Routing/Exception/RouteNotFoundException.php @@ -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é * diff --git a/src/Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.php b/src/Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.php index d8f4716002..c97d747d42 100644 --- a/src/Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.php +++ b/src/Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.php @@ -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 * diff --git a/src/Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.php b/src/Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.php index 3f3fc00df7..62a3dc2521 100644 --- a/src/Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.php +++ b/src/Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.php @@ -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')), diff --git a/src/Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.php b/src/Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.php index 3168a62289..8eb663637d 100644 --- a/src/Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.php +++ b/src/Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.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)); diff --git a/src/Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php index 673786752e..d8086b2b9c 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php @@ -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)); } diff --git a/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php index 6549bc8b99..1ce83e9159 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php @@ -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'); diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.php new file mode 100644 index 0000000000..3a1416cfc5 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.php @@ -0,0 +1,10 @@ +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()); } }