/**
  * {@inheritdoc}
  */
 public function getUsages($identifier)
 {
     $files = $this->getQuery(['file'])->distinct()->condition('id', $identifier)->execute()->fetchCol();
     $usages = new NodeCollection();
     foreach ($files as $file) {
         $this->target->open($file)->find(Filter::isInstanceOf('\\Pharborist\\Constants\\ConstantNode'))->filter(function (ConstantNode $node) use($identifier) {
             return $node->getConstantName() == $identifier;
         })->addTo($usages);
     }
     return $usages;
 }
 /**
  * Tests if a function contains logic: any branching operator, function
  * call, or object instantiation.
  *
  * @param \Pharborist\ParentNode $node
  *  The node to test.
  *
  * @return boolean
  */
 public function __invoke(ParentNode $node)
 {
     $function_calls = $node->find(Filter::isInstanceOf('\\Pharborist\\Functions\\FunctionCallNode'))->not(function (FunctionCallNode $call) {
         return in_array($call->getName()->getText(), $this->whitelist);
     });
     if ($function_calls->isEmpty()) {
         $filter = call_user_func_array('\\Pharborist\\Filter::isInstanceOf', static::$logic);
         return (bool) $node->find($filter)->count();
     } else {
         return TRUE;
     }
 }
Beispiel #3
0
 /**
  * Get the use declarations of this statement block.
  *
  * @return NodeCollection|UseDeclarationNode[]
  *   Use declarations.
  */
 public function getUseDeclarations()
 {
     $declarations = [];
     /** @var \Pharborist\Namespaces\UseDeclarationBlockNode[] $use_blocks */
     $use_blocks = $this->children(Filter::isInstanceOf('\\Pharborist\\Namespaces\\UseDeclarationBlockNode'));
     foreach ($use_blocks as $use_block) {
         foreach ($use_block->getDeclarationStatements() as $use_statement) {
             $declarations = array_merge($declarations, $use_statement->getDeclarations()->toArray());
         }
     }
     return new NodeCollection($declarations, FALSE);
 }
 /**
  * {@inheritdoc}
  */
 public function convert(TargetInterface $target)
 {
     $this->target = $target;
     $mapping = ['DrupalWebTestCase' => 'convertWeb', 'AJAXTestCase' => 'convertAjax'];
     foreach ($mapping as $parent_class => $convert_method) {
         $test_files = $target->getIndexer('class')->getQuery(['file'])->condition('parent', $parent_class)->execute()->fetchCol();
         foreach ($test_files as $test_file) {
             /** @var \Pharborist\Objects\Classnode[] $tests */
             $tests = $target->open($test_file)->find(Filter::isInstanceOf('\\Pharborist\\Objects\\SingleInheritanceNode'))->toArray();
             foreach ($tests as $test) {
                 if ((string) $test->getExtends() === $parent_class) {
                     $this->{$convert_method}($test);
                 }
             }
         }
     }
 }
 public function testStatic()
 {
     /** @var ClassNode $class_node */
     $class_node = Parser::parseSnippet('class Foo { public $bar; }');
     /** @var ClassMemberNode $a */
     $a = $class_node->getProperties()[0];
     $this->assertFalse($a->isStatic());
     $this->assertNull($a->getStatic());
     $a->setStatic(TRUE);
     $this->assertTrue($a->isStatic());
     $this->assertSame('public static $bar;', $a->closest(Filter::isInstanceOf('\\Pharborist\\Objects\\ClassMemberListNode'))->getText());
     $class_node = Parser::parseSnippet('class Bar { protected static $baz; }');
     /** @var ClassMemberNode $b */
     $b = $class_node->getProperties()[0];
     $this->assertTrue($b->isStatic());
     $this->assertInstanceOf('\\Pharborist\\TokenNode', $b->getStatic());
     $this->assertSame(T_STATIC, $b->getStatic()->getType());
     $b->setStatic(FALSE);
     $this->assertFalse($b->isStatic());
     $this->assertSame('protected $baz;', $b->closest(Filter::isInstanceOf('\\Pharborist\\Objects\\ClassMemberListNode'))->getText());
 }
    public function testGetTypes()
    {
        $source = <<<'EOF'
<?php
use MyNamespace\MyClass;
use MyNamespace\SomeClass as TestClass;

class Test {
  /**
   * A property using class.
   *
   * @var MyClass
   */
  private $a;

  /**
   * Property using class alias.
   *
   * @var TestClass
   */
  private $b;

  /**
   * An array property.
   *
   * @var array
   */
  private $data;

  /**
   * A callable property.
   *
   * @var callable
   */
  private $callback;

  /**
   * An integer property.
   *
   * @var int
   */
   private $num;

  /**
   * A generic property.
   */
  private $generic;
}
EOF;
        $tree = Parser::parseSource($source);
        /** @var ClassNode $class */
        $class = $tree->children(Filter::isInstanceOf('\\Pharborist\\Objects\\ClassNode'))[0];
        $properties = $class->getProperties();
        $this->assertEquals(['\\MyNamespace\\MyClass'], $properties[0]->getTypes());
        $this->assertEquals(['\\MyNamespace\\SomeClass'], $properties[1]->getTypes());
        $this->assertEquals(['array'], $properties[2]->getTypes());
        $this->assertEquals(['callable'], $properties[3]->getTypes());
        $this->assertEquals(['int'], $properties[4]->getTypes());
        $this->assertEquals(['mixed'], $properties[5]->getTypes());
    }
Beispiel #7
0
 /**
  * Resolve an unqualified name to fully qualified name.
  *
  * @param string $name
  *   The unqualified name to resolve.
  *
  * @return string
  *   Fully qualified name.
  */
 protected function resolveUnqualified($name)
 {
     if ($this->parent instanceof NamespaceNode) {
         return '\\' . $name;
     }
     if ($this->parent instanceof UseDeclarationNode) {
         return '\\' . $name;
     }
     $namespace = $this->getNamespace();
     $use_declarations = array();
     if ($namespace) {
         $use_declarations = $namespace->getBody()->getUseDeclarations();
     } else {
         /** @var \Pharborist\RootNode $root_node */
         $root_node = $this->closest(Filter::isInstanceOf('\\Pharborist\\RootNode'));
         if ($root_node) {
             $use_declarations = $root_node->getUseDeclarations();
         }
     }
     if ($this->parent instanceof FunctionCallNode) {
         /** @var UseDeclarationNode $use_declaration */
         foreach ($use_declarations as $use_declaration) {
             if ($use_declaration->isFunction() && $use_declaration->getBoundedName() === $name) {
                 return '\\' . $use_declaration->getName()->getPath();
             }
         }
         return $this->getParentPath() . $name;
     } elseif ($this->parent instanceof ConstantNode) {
         /** @var UseDeclarationNode $use_declaration */
         foreach ($use_declarations as $use_declaration) {
             if ($use_declaration->isConst() && $use_declaration->getBoundedName() === $name) {
                 return '\\' . $use_declaration->getName()->getPath();
             }
         }
         return $this->getParentPath() . $name;
     } else {
         // Name is a class reference.
         /** @var UseDeclarationNode $use_declaration */
         foreach ($use_declarations as $use_declaration) {
             if ($use_declaration->isClass() && $use_declaration->getBoundedName() === $name) {
                 return '\\' . $use_declaration->getName()->getPath();
             }
         }
         // No use declaration so class name refers to class in current namespace.
         return $this->getParentPath() . $name;
     }
 }
Beispiel #8
0
 /**
  * Returns if the array has a specific key.
  *
  * @param mixed $key
  *  Either a scalar value ('foo') or an ExpressionNode representing the key.
  *  If $key is an ExpressionNode, the key's string representation is compared
  *  with the string representations of the array keys. Otherwise, the actual
  *  value is compared.
  * @param boolean $recursive
  *  Whether or not to check every level of the array.
  *
  * @return boolean
  *
  * @throws \InvalidArgumentException
  */
 public function hasKey($key, $recursive = TRUE)
 {
     if (!$key instanceof ExpressionNode && !is_scalar($key)) {
         throw new \InvalidArgumentException();
     }
     $keys = $this->getKeys($recursive);
     if (is_scalar($key)) {
         return $keys->filter(Filter::isInstanceOf('\\Pharborist\\Types\\ScalarNode'))->is(function (ScalarNode $node) use($key) {
             return $node->toValue() === $key;
         });
     } else {
         return $keys->is(function (ExpressionNode $expr) use($key) {
             return $expr->getText() === $key->getText();
         });
     }
 }
Beispiel #9
0
 /**
  * Returns every namespace in this document.
  *
  * @return \Pharborist\NodeCollection
  */
 public function getNamespaces()
 {
     return $this->children(Filter::isInstanceOf('\\Pharborist\\Namespaces\\NamespaceNode'));
 }
 /**
  * Returns if the parameter is fully reassigned anywhere in the function.
  *
  * @param \Pharborist\Functions\ParameterNode $parameter
  *  The parameter to check.
  *
  * @return boolean
  */
 protected function isReassigned(ParameterNode $parameter)
 {
     return (bool) $parameter->getFunction()->find(Filter::isInstanceOf('\\Pharborist\\Variables\\VariableNode'))->filter(function (VariableNode $variable) use($parameter) {
         return $variable->getName() == $parameter->getName();
     })->filter($this->isAssigned)->count();
 }
 /**
  * Parses a generated class into a syntax tree.
  *
  * @param string|array $class
  *  The class to parse, either as a string of PHP code or a renderable array.
  *
  * @return \Pharborist\Objects\ClassNode
  */
 protected function parse($class)
 {
     if (is_array($class)) {
         $class = \Drupal::service('renderer')->renderPlain($class);
     }
     return Parser::parseSnippet($class)->find(Filter::isInstanceOf('Pharborist\\Objects\\ClassNode'))[0];
 }
    /**
     * Test template file.
     */
    public function testTemplate()
    {
        $source = <<<'EOF'
<p>This is a template file</p>
<p>Hello, <?=$name?>. Welcome to <?=$lego . 'world'?>!</p>
<?php
code();
?><h1>End of template</h1><?php more_code();
EOF;
        $tree = Parser::parseSource($source);
        $this->assertEquals($source, $tree->getText());
        /** @var TemplateNode[] $templates */
        $templates = $tree->find(Filter::isInstanceOf('\\Pharborist\\TemplateNode'));
        $template = $templates[0];
        $this->assertEquals(5, $template->childCount());
        /** @var EchoTagStatementNode $echo_tag */
        $echo_tag = $template->firstChild()->next();
        $this->assertInstanceOf('\\Pharborist\\EchoTagStatementNode', $echo_tag);
        $this->assertEquals('<?=$name?>', $echo_tag->getText());
        $expressions = $echo_tag->getExpressions();
        $this->assertEquals('$name', $expressions[0]->getText());
        $template = $templates[1];
        $this->assertEquals('?><h1>End of template</h1><?php ', $template->getText());
    }
Beispiel #13
0
 /**
  * @return NodeCollection
  */
 public function getOptionalParameters()
 {
     return $this->parameters->children(Filter::isInstanceOf('\\Pharborist\\ParameterNode'))->filter(function (ParameterNode $parameter) {
         $value = $parameter->getValue();
         return isset($value);
     });
 }
 /**
  * {@inheritdoc}
  */
 public function buildRoute(TargetInterface $target, Drupal7Route $route)
 {
     $definition = $this->buildRouteDefinition($target, $route);
     $map = $this->buildParameterMap($target, $route);
     $map->applyRoute($definition->unwrap());
     $indexer = $target->getIndexer('function');
     foreach ($map->toArray() as $function_name => $parameters) {
         if ($parameters && $indexer->has($function_name)) {
             /** @var \Pharborist\Functions\FunctionDeclarationNode $function */
             $function = $indexer->get($function_name);
             foreach ($parameters as $parameter_name => $info) {
                 $parameter = $function->getParameterByName($parameter_name)->setName($info['name'], TRUE);
                 if (isset($info['type'])) {
                     $plugin_id = '_rewriter:' . $info['type'];
                     if ($this->rewriters->hasDefinition($plugin_id)) {
                         $this->rewriters->createInstance($plugin_id)->rewrite($parameter);
                     }
                 }
             }
         }
     }
     $class_indexer = $target->getIndexer('class');
     if ($class_indexer->has('DefaultController')) {
         $controller = $class_indexer->get('DefaultController');
     } else {
         $controller = $this->getController($target, $route);
         $class_indexer->addFile($this->writeClass($target, $controller));
     }
     if ($indexer->has($route['title callback'])) {
         if (!$controller->hasMethod($route['title callback'])) {
             $indexer->get($route['title callback'])->cloneAsMethodOf($controller);
         }
     }
     if ($indexer->has($route['access callback'])) {
         $func = $indexer->get($route['access callback']);
         $returns = $func->find(Filter::isInstanceOf('\\Pharborist\\ReturnStatementNode'));
         foreach ($returns as $ret) {
             $call = ClassMethodCallNode::create('\\Drupal\\Core\\Access\\AccessResult', 'allowedIf')->appendArgument($ret->getExpression());
             $ret->replaceWith(ReturnStatementNode::create($call));
         }
         // The access callback always receives an $account parameter.
         if ($func->hasParameter('account')) {
             $func->getParameter('account')->setTypeHint('Drupal\\Core\\Session\\AccountInterface');
         } else {
             $account = ParameterNode::create('account')->setTypeHint('Drupal\\Core\\Session\\AccountInterface');
             $func->appendParameter($account);
         }
         if (!$controller->hasMethod($route['access callback'])) {
             $func->cloneAsMethodOf($controller);
         }
     }
     if ($indexer->has($route['page callback'])) {
         if (!$controller->hasMethod($route['page callback'])) {
             $indexer->get($route['page callback'])->cloneAsMethodOf($controller);
         }
     }
     $this->writeClass($target, $controller);
 }
Beispiel #15
0
 public function getRoot()
 {
     return $this->closest(Filter::isInstanceOf('\\Pharborist\\RootNode'));
 }
    /**
     * @requires PHP 5.6
     */
    public function testVariadic()
    {
        $source = <<<'EOF'
<?php
function foo($args) {
}
EOF;
        $tree = Parser::parseSource($source);
        /** @var \Pharborist\Functions\FunctionDeclarationNode $function */
        $function = $tree->children(Filter::isInstanceOf('\\Pharborist\\Functions\\FunctionDeclarationNode'))[0];
        $parameter = $function->getParameter(0);
        $this->assertFalse($parameter->isVariadic());
        $parameter->setVariadic(TRUE);
        $this->assertTrue($parameter->isVariadic());
        $this->assertEquals('...$args', $parameter->getText());
    }
 /**
  * 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();
 }
 /**
  * {@inheritdoc}
  */
 public function addFile($path)
 {
     $doc = Parser::parseFile($path);
     $doc->children(Filter::isInstanceOf('\\Pharborist\\Functions\\FunctionDeclarationNode'))->each([$this, 'add']);
     $doc->find(Filter::isInstanceOf('\\Pharborist\\Functions\\FunctionCallNode'))->each([$this, 'add']);
 }
Beispiel #19
0
 /**
  * @param SingleInheritanceNode|InterfaceNode $node
  */
 protected function endClassTraitOrInterface($node)
 {
     $nl = $this->config['nl'];
     $indent = str_repeat(' ', $this->config['indent']);
     $indent = str_repeat($indent, $this->indentLevel + 1);
     /** @var WhitespaceNode $ws_node */
     $whitespace = $node->getBody()->children(Filter::isInstanceOf('\\Pharborist\\WhitespaceNode'));
     foreach ($whitespace->slice(1, -1) as $ws_node) {
         // Blank line between methods and properties.
         $ws_node->setText(str_repeat($nl, 2) . $indent);
     }
     if ($whitespace->count() === 1) {
         return;
     }
     $blank_lines_around_class_body = $this->config['blank_lines_around_class_body'];
     $nl_count = $blank_lines_around_class_body + 1;
     /** @var WhitespaceNode $open_whitespace */
     $open_whitespace = $whitespace->get(0);
     $open_whitespace->setText(str_repeat($nl, $nl_count) . $indent);
     /** @var WhitespaceNode $close_whitespace */
     $close_whitespace = $whitespace->last()->get(0);
     $indent = str_repeat($indent, $this->indentLevel);
     $close_whitespace->setText(str_repeat($nl, $nl_count) . $indent);
 }
Beispiel #20
0
 /**
  * Sets the imported item's alias. If NULL is passed, the alias is removed.
  *
  * @param \Pharborist\TokenNode|string|NULL $alias
  *
  * @return $this
  */
 public function setAlias($alias)
 {
     if (is_string($alias)) {
         $alias = new TokenNode(T_STRING, $alias);
     }
     if ($alias instanceof TokenNode) {
         if ($this->hasAlias()) {
             $this->alias->replaceWith($alias);
         } else {
             $this->alias = $alias;
             $this->addChild(WhitespaceNode::create(' '));
             $this->addChild(Token::_as());
             $this->addChild(WhitespaceNode::create(' '));
             $this->addChild($alias, 'alias');
         }
     } elseif ($alias === NULL && $this->hasAlias()) {
         $this->alias->previousUntil(Filter::isInstanceOf('\\Pharborist\\Namespaces\\NameNode'))->remove();
         $this->alias->remove();
         $this->alias = NULL;
     } else {
         throw new \InvalidArgumentException();
     }
     return $this;
 }
Beispiel #21
0
 /**
  * @param ExpressionNode|NULL $node
  * @return $this
  */
 public function setValue($node)
 {
     if ($node === NULL) {
         if (isset($this->value)) {
             $this->value->previousUntil(Filter::isInstanceOf('\\Pharborist\\Variables\\VariableNode'))->remove();
             $this->value->remove();
         }
     } else {
         if (isset($this->value)) {
             /** @var Node $node */
             $this->value->replaceWith($node);
         } else {
             $this->append([Token::space(), Token::assign(), Token::space(), $node]);
         }
     }
     return $this;
 }
Beispiel #22
0
 /**
  * @return NodeCollection|ConstantDeclarationNode[]
  */
 public function getConstants()
 {
     $constants = [];
     /** @var ConstantDeclarationStatementNode $node */
     foreach ($this->statements->children(Filter::isInstanceOf('\\Pharborist\\Constants\\ConstantDeclarationStatementNode')) as $node) {
         $constants = array_merge($constants, $node->getDeclarations()->toArray());
     }
     return new NodeCollection($constants, FALSE);
 }
 /**
  * Add property to class.
  *
  * @param string|ClassMemberListNode $property
  * @return $this
  */
 public function appendProperty($property)
 {
     if (is_string($property)) {
         $property = ClassMemberListNode::create($property);
     }
     $properties = $this->statements->children(Filter::isInstanceOf('\\Pharborist\\ClassMemberListNode'));
     if ($properties->count() === 0) {
         $this->statements->firstChild()->after($property);
     } else {
         $properties->last()->after($property);
     }
     FormatterFactory::format($this);
     return $this;
 }
Beispiel #24
0
 /**
  * Gets the fully qualified name of the method, e.g. \My\Namespaced\Class::foo.
  *
  * @return string
  */
 public function getFullyQualifiedName()
 {
     /** @var ClassNode $class_node */
     $class_node = $this->closest(Filter::isInstanceOf('\\Pharborist\\Objects\\ClassNode'));
     return $class_node->getName()->getAbsolutePath() . '::' . $this->getName()->getText();
 }
 /**
  * Tests if the given node is on the left side of an assignment.
  *
  * @param \Pharborist\Node $node
  *  The node to test.
  *
  * @return boolean
  */
 public function __invoke(Node $node)
 {
     /** @var \Pharborist\Operators\AssignNode $assignment */
     $assignment = $node->closest(Filter::isInstanceOf('\\Pharborist\\Operators\\AssignNode'));
     return $assignment ? $assignment->getLeftOperand() === $node : FALSE;
 }
Beispiel #26
0
 /**
  * @return NodeCollection|InterfaceMethodNode[]
  */
 public function getMethods()
 {
     return $this->statements->children(Filter::isInstanceOf('\\Pharborist\\Objects\\InterfaceMethodNode'));
 }