/**
  * Utility method to PSR4-ify a class. It'll move the class into its own file
  * in the given module's namespace. The class is modified in-place, so you
  * should clone it before calling this function if you want to make a PSR-4
  * *copy* of it.
  *
  * @param \Drupal\drupalmoduleupgrader\TargetInterface $target
  *  The module which will own the class.
  * @param \Pharborist\ClassNode $class
  *  The class to modify.
  *
  * @return \Pharborist\ClassNode
  *  The modified class, returned for convenience.
  */
 public static function toPSR4(TargetInterface $target, ClassNode $class)
 {
     $ns = 'Drupal\\' . $target->id();
     RootNode::create($ns)->getNamespace($ns)->append($class->remove());
     WhitespaceNode::create("\n\n")->insertBefore($class);
     return $class;
 }
 public function execute()
 {
     $ns = $this->extractNS($this->configuration['class']);
     $class = $this->extractLocal($this->configuration['class']);
     $doc = RootNode::create($ns);
     $ns = $doc->getNamespace($ns);
     Token::newline()->insertBefore($ns);
     Token::newline()->appendTo($ns);
     $class = ClassNode::create($class);
     if ($parent = $this->configuration['parent']) {
         Parser::parseSnippet('use ' . ltrim($parent, '\\') . ';')->appendTo($ns)->after(Token::newline());
         $class->setExtends($this->extractLocal($parent));
     }
     $interfaces = (array) $this->configuration['interfaces'];
     foreach ($interfaces as $interface) {
         Parser::parseSnippet('use ' . ltrim($interface, '\\') . ';')->appendTo($ns)->after(Token::newline());
     }
     $class->setImplements(array_map([$this, 'extractLocal'], $interfaces));
     if (isset($this->configuration['doc'])) {
         $class->setDocComment(DocCommentNode::create($this->configuration['doc']));
     }
     $class->appendTo($ns)->before(Token::newline());
     $destination = $this->getUnaliasedPath($this->configuration['destination']);
     $dir = subStr($destination, 0, strrPos($destination, '/'));
     $this->fs->mkdir($dir);
     file_put_contents($destination, $doc->getText());
     // Need to store the class' local name as its index identifier because
     // \Pharborist\Filter::isClass() doesn't support lookup by qualified path.
     $this->target->getIndexer('class')->addFile($destination);
 }
    public function testUseDeclarations()
    {
        $snippet = <<<'EOF'
namespace Test {
  use const Other\MY_CONST;
  use function Other\my_func;
  use Other\MyClass;
  use Other\OtherClass as Bind;
  class TestClass {}
}
EOF;
        /** @var NamespaceNode $namespace */
        $namespace = Parser::parseSnippet($snippet);
        $declarations = $namespace->getUseDeclarations();
        $this->assertCount(4, $declarations);
        $aliases = $namespace->getClassAliases();
        $this->assertCount(2, $aliases);
        $this->assertArrayHasKey('MyClass', $aliases);
        $this->assertEquals('\\Other\\MyClass', $aliases['MyClass']);
        $this->assertArrayHasKey('Bind', $aliases);
        $this->assertEquals('\\Other\\OtherClass', $aliases['Bind']);
        $class_node = $namespace->find(Filter::isClass('TestClass'))[0];
        $this->assertTrue($namespace->owns($class_node));
        $class_node = ClassNode::create('Dummy');
        $this->assertFalse($namespace->owns($class_node));
    }
 public function test()
 {
     $class = ClassNode::create('Foobaz');
     $indexer = $this->getMock('\\Drupal\\drupalmoduleupgrader\\IndexerInterface');
     $indexer->method('get')->with('Foobaz')->willReturn(new NodeCollection([$class]));
     $this->container->get('plugin.manager.drupalmoduleupgrader.indexer')->method('createInstance')->with('class')->willReturn($indexer);
     $config = ['definition' => '\\Drupal\\Core\\Block\\BlockPluginInterface::blockForm', 'target' => 'Foobaz'];
     $plugin = new Implement($config, uniqID(), []);
     $plugin->setTarget($this->target);
     try {
         // We expect a CodeManagerIOException because we're implementing the
         // method on a class that is not officially part of the target's code.
         // That's OK, though.
         $plugin->execute();
     } catch (IOException $e) {
     }
     $this->assertTrue($class->hasMethod('blockForm'));
     $method = $class->getMethod('blockForm');
     $this->assertInstanceOf('\\Pharborist\\Objects\\ClassMethodNode', $method);
     $parameters = $method->getParameters();
     $this->assertCount(2, $parameters);
     $this->assertEquals($parameters[0]->getName(), 'form');
     $this->assertNull($parameters[0]->getTypeHint());
     $this->assertEquals($parameters[1]->getName(), 'form_state');
     $type = $parameters[1]->getTypeHint();
     $this->assertInstanceOf('\\Pharborist\\Namespaces\\NameNode', $type);
     $this->assertEquals('Drupal\\Core\\Form\\FormStateInterface', $type->getText());
 }
    public function testBuildClass()
    {
        $classNode = ClassNode::create('MyClass');
        $this->assertEquals('class MyClass {}', $classNode->getText());
        $classNode->setFinal(TRUE);
        $this->assertEquals('final class MyClass {}', $classNode->getText());
        $classNode->setFinal(FALSE);
        $this->assertEquals('class MyClass {}', $classNode->getText());
        $classNode->setName('MyTest');
        $this->assertEquals('class MyTest {}', $classNode->getText());
        $classNode->setExtends('MyClass');
        $this->assertEquals('class MyTest extends MyClass {}', $classNode->getText());
        $classNode->setExtends('BaseClass');
        $this->assertEquals('class MyTest extends BaseClass {}', $classNode->getText());
        $classNode->setExtends(NULL);
        $this->assertNull($classNode->getExtends());
        $this->assertEquals('class MyTest {}', $classNode->getText());
        $classNode->setImplements('MyInterface');
        $this->assertEquals('class MyTest implements MyInterface {}', $classNode->getText());
        $classNode->setImplements('Yai');
        $this->assertEquals('class MyTest implements Yai {}', $classNode->getText());
        $classNode->setImplements(NULL);
        $this->assertNull($classNode->getImplementList());
        $this->assertEquals('class MyTest {}', $classNode->getText());
        $classNode->appendProperty('someProperty');
        $classNode->appendMethod('someMethod');
        $expected = <<<'EOF'
class MyTest {

  private $someProperty;

  public function someMethod() {
  }

}
EOF;
        $this->assertEquals($expected, $classNode->getText());
        $property = $classNode->getProperty('someProperty');
        $property->getClassMemberListNode()->setDocComment(DocCommentNode::create('Some property.'));
        $method = $classNode->getMethod('someMethod');
        $method->setDocComment(DocCommentNode::create('Some method.'));
        $expected = <<<'EOF'
class MyTest {

  /**
   * Some property.
   */
  private $someProperty;

  /**
   * Some method.
   */
  public function someMethod() {
  }

}
EOF;
        $this->assertEquals($expected, $classNode->getText());
    }
 public function testChangeDocComment()
 {
     $node = ClassNode::create('Foo');
     $node->setDocComment(DocCommentNode::create('Ni!'));
     $node->setDocComment(DocCommentNode::create('Noo!'));
     $comment = $node->getDocComment();
     $this->assertInstanceOf('\\Pharborist\\DocCommentNode', $comment);
     $this->assertEquals('Noo!', $comment->getCommentText());
 }
 public function test()
 {
     $class = ClassNode::create('Wambooli');
     $indexer = $this->getMock('\\Drupal\\drupalmoduleupgrader\\IndexerInterface');
     $indexer->method('get')->with('Wambooli')->willReturn(new NodeCollection([$class]));
     $this->container->get('plugin.manager.drupalmoduleupgrader.indexer')->method('createInstance')->with('class')->willReturn($indexer);
     $config = ['source' => 'Wambooli', 'destination' => 'Drupal\\foo\\Wambooli'];
     $plugin = new PSR4($config, uniqID(), []);
     $plugin->setTarget($this->target);
     $plugin->execute();
     $url = $this->target->getPath('src/Wambooli.php');
     $this->assertFileExists($url);
 }
    public function testDocComment()
    {
        $class = ClassNode::create('Wambooli');
        $class->setDocComment(DocCommentNode::create('Double wambooli!'));
        $this->assertInstanceOf('\\Pharborist\\DocCommentNode', $class->getDocComment());
        $indexer = $this->getMock('\\Drupal\\drupalmoduleupgrader\\IndexerInterface');
        $indexer->method('get')->with('Wambooli')->willReturn(new NodeCollection([$class]));
        $this->container->get('plugin.manager.drupalmoduleupgrader.indexer')->method('createInstance')->with('class')->willReturn($indexer);
        $config = ['type' => 'class', 'id' => 'Wambooli', 'note' => 'You need to rewrite this thing because I said so!'];
        $plugin = new Notify($config, uniqID(), []);
        $plugin->setTarget($this->target);
        $plugin->execute();
        $comment = $class->getDocComment();
        $this->assertInstanceOf('\\Pharborist\\DocCommentNode', $comment);
        $expected = <<<END
Double wambooli!

You need to rewrite this thing because I said so!
END;
        $this->assertEquals($expected, $comment->getCommentText());
    }
 public function test()
 {
     $callback = Parser::parseSnippet('function foo_submit(&$form, &$form_state) {}');
     $function_indexer = $this->getMock('\\Drupal\\drupalmoduleupgrader\\IndexerInterface');
     $function_indexer->method('get')->with('foo_submit')->willReturn(new NodeCollection([$callback]));
     $class = ClassNode::create('FooForm');
     $class_indexer = $this->getMock('\\Drupal\\drupalmoduleupgrader\\IndexerInterface');
     $class_indexer->method('get')->with('FooForm')->willReturn(new NodeCollection([$class]));
     $this->container->get('plugin.manager.drupalmoduleupgrader.indexer')->method('createInstance')->willReturnCallback(function ($which) use($class_indexer, $function_indexer) {
         switch ($which) {
             case 'class':
                 return $class_indexer;
             case 'function':
                 return $function_indexer;
             default:
                 break;
         }
     });
     $config = ['callback' => 'foo_submit', 'destination' => 'FooForm::submitForm'];
     $plugin = new FormCallbackToMethod($config, uniqID(), []);
     $plugin->setTarget($this->target);
     try {
         // We expect a CodeManagerIOException because we're implementing the
         // method on a class that is not officially part of the target's code.
         // That's OK, though.
         $plugin->execute();
     } catch (IOException $e) {
     }
     $this->assertTrue($class->hasMethod('submitForm'));
     $parameters = $class->getMethod('submitForm')->getParameters();
     $this->assertCount(2, $parameters);
     $this->assertEquals('form', $parameters[0]->getName());
     $this->assertInstanceOf('\\Pharborist\\TokenNode', $parameters[0]->getTypeHint());
     $this->assertSame(T_ARRAY, $parameters[0]->getTypeHint()->getType());
     $this->assertInstanceOf('\\Pharborist\\TokenNode', $parameters[0]->getReference());
     $this->assertEquals('form_state', $parameters[1]->getName());
     $this->assertInstanceOf('\\Pharborist\\Namespaces\\NameNode', $parameters[1]->getTypeHint());
     $this->assertEquals('Drupal\\Core\\Form\\FormStateInterface', $parameters[1]->getTypeHint()->getText());
     $this->assertNull($parameters[1]->getReference());
 }
 /**
  * Converts a single Ajax test.
  *
  * @param \Pharborist\Objects\ClassNode $test
  */
 public function convertAjax(ClassNode $test)
 {
     $test->setExtends('\\Drupal\\system\\Tests\\Ajax\\AjaxTestBase');
     $this->setModules($test);
     $this->move($test);
 }
 /**
  * A helper function to ease exception catching in the __toString() method.
  *
  * @return string
  */
 protected function toString()
 {
     $doc = RootNode::create($this->getNamespace());
     $class = ClassNode::create($this->getName());
     $constructor = ClassMethodNode::create('__construct');
     $class->appendMethod($constructor);
     $constructorDocString = '';
     foreach ($this->getProperties() as $name => $info) {
         $class->createProperty($name, isset($info['default']) ? $info['default'] : NULL, 'protected');
         if (isset($info['description'])) {
             $propertyDocString = "@var {$info['type']} {$name}\n  {$info['description']}";
             $constructorDocString .= "@param {$info['type']} {$name}\n  {$info['description']}\n\n";
         } else {
             $propertyDocString = "@var {$info['type']} {$name}";
             $constructorDocString .= "@param {$info['type']} {$name}\n\n";
         }
         $class->getProperty($name)->closest(Filter::isInstanceOf('\\Pharborist\\Objects\\ClassMemberListNode'))->setDocComment(DocCommentNode::create($propertyDocString));
         $constructor->appendParameter(ParameterNode::create($name));
         $expression = Parser::parseSnippet("\$this->{$name} = \${$name};");
         $constructor->getBody()->lastChild()->before($expression);
         $getter = ClassMethodNode::create('get' . ucfirst($name));
         $class->appendMethod($getter);
         $class->getMethod('get' . ucfirst($name))->setDocComment(DocCommentNode::create("Gets the {$name} value."));
         $getter_expression = Parser::parseSnippet("return \$this->{$name};");
         $getter->getBody()->lastChild()->before($getter_expression);
     }
     $class->getMethod('__construct')->setDocComment(DocCommentNode::create($constructorDocString));
     $doc->getNamespace($this->getNamespace())->getBody()->append($class);
     /* @todo dispatch an event to allow subscribers to alter $doc */
     $formatter = FormatterFactory::getPsr2Formatter();
     $formatter->format($doc->getNamespace($this->getNamespace()));
     return $doc->getText();
 }
 /**
  * @return \Pharborist\Objects\ClassMethodNode
  */
 protected function addMethod(FunctionDeclarationNode $function, ClassNode $class, $alias = NULL)
 {
     $method = ClassMethodNode::fromFunction($function);
     if ($alias) {
         $method->setName($alias);
     }
     $class->appendMethod($method);
     // Add the parameters required for FormInterface conformance.
     $parameters = $method->getParameters()->toArray();
     if (empty($parameters)) {
         $parameters[0] = ParameterNode::create('$form');
         $method->appendParameter($parameters[0]);
     }
     if (sizeof($parameters) == 1) {
         $parameters[1] = ParameterNode::create('$form_state');
         $method->appendParameter($parameters[1]);
     }
     // The $form parameter must have the array type hint.
     $parameters[0]->setTypeHint('array');
     // The form state is never passed by reference.
     $parameters[1]->setReference(FALSE);
     // Additional parameters MUST have a default value of NULL in order to conform
     // to FormInterface.
     for ($i = 2; $i < sizeof($parameters); $i++) {
         $parameters[$i]->setValue(new TokenNode(T_STRING, 'NULL'));
     }
     $this->formStateRewriter->rewrite($parameters[1]);
     return $method;
 }
Beispiel #13
0
 /**
  * Creates a clone of this property list and adds it to a class.
  *
  * @param ClassNode $class
  *  The target class.
  *
  * @return static
  *  The cloned property list.
  */
 public function cloneInto(ClassNode $class)
 {
     $clone = clone $this;
     $class->appendProperty($this);
     return $clone;
 }
Beispiel #14
0
 /**
  * Determine if the node belongs to this namespace.
  *
  * @param ClassNode|InterfaceNode|TraitNode|FunctionDeclarationNode|ConstantDeclarationNode $node
  *   Node to test if owned by namespace.
  *
  * @return bool
  */
 public function owns($node)
 {
     return $this === $node->getName()->getNamespace();
 }
 /**
  * Writes a class to the target module's PSR-4 root.
  *
  * @param TargetInterface $target
  *  The target module.
  * @param ClassNode $class
  *  The class to write. The path will be determined from the class'
  *  fully qualified name.
  *
  * @return string
  *  The generated path to the class.
  */
 public function writeClass(TargetInterface $target, ClassNode $class)
 {
     $class_path = ltrim($class->getName()->getAbsolutePath(), '\\');
     $path = str_replace(['Drupal\\' . $target->id(), '\\'], ['src', '/'], $class_path) . '.php';
     return $this->write($target, $path, $class->parents()->get(0));
 }
 /**
  * Creates a class method from this function and add it to the given
  * class definition.
  *
  * @param \Pharborist\Objects\ClassNode $class
  *  The class to add the new method to.
  *
  * @return \Pharborist\Objects\ClassMethodNode
  *  The newly created method.
  */
 public function cloneAsMethodOf(ClassNode $class)
 {
     $clone = ClassMethodNode::fromFunction($this);
     $class->appendMethod($clone);
     return $clone;
 }