4 * This file is part of the Behat.
5 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
11 namespace Behat\Behat\Context\Snippet\Appender;
13 use Behat\Behat\Snippet\AggregateSnippet;
14 use Behat\Behat\Snippet\Appender\SnippetAppender;
15 use Behat\Testwork\Filesystem\FilesystemLogger;
19 * Appends context-related snippets to their context classes.
21 * @author Konstantin Kudryashov <ever.zet@gmail.com>
23 final class ContextSnippetAppender implements SnippetAppender
26 * @const PendingException class
28 const PENDING_EXCEPTION_CLASS = 'Behat\Behat\Tester\Exception\PendingException';
31 * @var FilesystemLogger
36 * Initializes appender.
38 * @param null|FilesystemLogger $logger
40 public function __construct(FilesystemLogger $logger = null)
42 $this->logger = $logger;
48 public function supportsSnippet(AggregateSnippet $snippet)
50 return 'context' === $snippet->getType();
56 public function appendSnippet(AggregateSnippet $snippet)
58 foreach ($snippet->getTargets() as $contextClass) {
59 $reflection = new ReflectionClass($contextClass);
60 $content = file_get_contents($reflection->getFileName());
62 foreach ($snippet->getUsedClasses() as $class) {
63 if (!$this->isClassImported($class, $content)) {
64 $content = $this->importClass($class, $content);
68 $generated = rtrim(strtr($snippet->getSnippet(), array('\\' => '\\\\', '$' => '\\$')));
69 $content = preg_replace('/}\s*$/', "\n" . $generated . "\n}\n", $content);
70 $path = $reflection->getFileName();
72 file_put_contents($path, $content);
74 $this->logSnippetAddition($snippet, $path);
79 * Checks if context file already has class in it.
81 * @param string $class
82 * @param string $contextFileContent
86 private function isClassImported($class, $contextFileContent)
88 $classImportRegex = sprintf(
90 preg_quote($class, '@')
93 return 1 === preg_match($classImportRegex, $contextFileContent);
97 * Adds use-block for class.
99 * @param string $class
100 * @param string $contextFileContent
104 private function importClass($class, $contextFileContent)
106 $replaceWith = "\$1" . 'use ' . $class . ";\n\$2;";
108 return preg_replace('@^(.*)(use\s+[^;]*);@m', $replaceWith, $contextFileContent, 1);
112 * Logs snippet addition to the provided path (if logger is given).
114 * @param AggregateSnippet $snippet
115 * @param string $path
117 private function logSnippetAddition(AggregateSnippet $snippet, $path)
119 if (!$this->logger) {
123 $steps = $snippet->getSteps();
124 $reason = sprintf("`<comment>%s</comment>` definition added", $steps[0]->getText());
126 $this->logger->fileUpdated($path, $reason);