/** * @return \Pharborist\Objects\ClassNode */ public function render() { if (empty($this->controller)) { $render = ['#theme' => 'dmu_form', '#module' => $this->target->id(), '#form_id' => $this->formID, '#class' => $this->toTitleCase($this->formID), '#config' => $this->isConfig]; $source = \Drupal::service('renderer')->renderPlain($render); $this->controller = Parser::parseSource($source)->find(Filter::isClass($render['#class']))->get(0); } return $this->controller; }
/** * {@inheritdoc} */ public function getName(TargetInterface $target, RouteWrapper $route) { $name = $target->id() . '.' . $this->unPrefix($route['page arguments'][0], $target->id()); $arguments = array_filter(array_slice($route['page arguments'], 1), 'is_string'); if ($arguments) { $name .= '_' . implode('_', $arguments); } return $name; }
/** * Returns the collection of routes in the source. * * @return RouterInterface * The requested link collection. */ public function getSourceRoutes() { if (empty($this->sourceRoutes)) { $this->sourceRoutes = new Drupal7Router(); $items = call_user_func($this->target->id() . '_menu'); foreach ($items as $path => $item) { $this->sourceRoutes->addRoute(new Drupal7Route($path, $item)); } // Now that all routes have been loaded, tell them to resolve their // hierarchical relationships. $this->sourceRoutes->finalize(); } return $this->sourceRoutes; }
/** * {@inheritdoc} */ public function convert(TargetInterface $target) { $indexer = $target->getIndexer('function'); // @FIXME This is not working (returns empty result set)...don't know why. $alter_hooks = $indexer->getQuery()->condition(db_or()->condition('id', $target->id() . '_form_alter')->condition('id', db_like($target->id() . '_form_%_alter'), 'LIKE'))->execute(); foreach ($alter_hooks as $alter_hook) { /** @var \Pharborist\Functions\FunctionDeclarationNode $function */ $function = $indexer->get($alter_hook->id); $parameters = $function->getParameters(); if (sizeof($parameters) > 1) { $parameters[1]->setTypeHint('\\Drupal\\Core\\Form\\FormStateInterface'); $target->save($function); } } }
/** * 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; }
/** * Helper for subclasses' rewrite() methods. This checks if the call can * be rewritten at all and leaves a FIXME if it can't. If the variable's * key is not a string starting with MODULE_, the call will not be * considered rewritable. * * @return boolean */ protected function tryRewrite(FunctionCallNode $call, TargetInterface $target) { $statement = $call->getStatement(); $arguments = $call->getArguments(); if ($arguments[0] instanceof StringNode) { $key = $arguments[0]->toValue(); if (strPos($key, $target->id() . '_') === 0) { return TRUE; } else { $comment = <<<END This looks like another module's variable. You'll need to rewrite this call to ensure that it uses the correct configuration object. END; $this->buildFixMe($comment)->prependTo($statement); return FALSE; } } else { $comment = <<<END The correct configuration object could not be determined. You'll need to rewrite this call manually. END; $this->buildFixMe($comment)->prependTo($statement); return FALSE; } }
/** * {@inheritdoc} */ public function convert(TargetInterface $target) { $unit_tests = []; $test_files = $target->getIndexer('class')->getQuery(['file'])->condition('parent', 'DrupalUnitTestCase')->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() === 'DrupalUnitTestCase') { $unit_tests[] = $test; } } } /** @var \Pharborist\Objects\ClassNode $unit_test */ foreach ($unit_tests as $unit_test) { $unit_test->setExtends('\\Drupal\\Tests\\UnitTestCase'); $comment_text = <<<END @FIXME Unit tests are now written for the PHPUnit framework. You will need to refactor this test in order for it to work properly. END; $comment = DocCommentNode::create($comment_text); $unit_test->setDocComment($comment); $ns = 'Drupal\\Tests\\' . $target->id() . '\\Unit'; $doc = RootNode::create($ns)->getNamespace($ns)->append($unit_test->remove()); WhitespaceNode::create("\n\n")->insertBefore($unit_test); $this->write($target, 'tests/src/Unit/' . $unit_test->getName() . '.php', "<?php\n\n{$doc}"); } }
/** * {@inheritdoc} */ public function analyze(TargetInterface $target) { $violations = []; $indexer = $target->getIndexer('function'); if ($indexer->has('hook_form_alter')) { $violations[] = $indexer->get('hook_form_alter'); } $id = $target->id() . '_form_%_alter'; // Until kernel tests are run in PHPUnit, we need to check for // the existence of db_like(). if (function_exists('db_like')) { $id = db_like($id); } $alter_hooks = $target->getIndexer('function')->getQuery()->condition('id', $id, 'LIKE')->execute(); foreach ($alter_hooks as $alter_hook) { $violations[] = $target->open($alter_hook->file)->find(Filter::isFunction($alter_hook->id)); } $issues = []; if ($violations) { $issue = $this->buildIssue($target); array_walk($violations, function (FunctionDeclarationNode $function) use($issue) { $issue->addViolation($function, $this); }); $issues[] = $issue; } return $issues; }
/** * Creates a FormConverter for a specific form. * * @param TargetInterface $target * The module which defines the form. * @param string $form_id * The original form ID. * * @return FormConverter * * @throws \BadMethodCallException if the target module doesn't define * the given form. */ public function get(TargetInterface $target, $form_id) { $indexer = $target->getIndexer('function'); if ($indexer->has($form_id)) { return new FormConverter($target, $form_id, $this->rewriter); } else { $message = $this->t('@target does not define form @form_id.', ['@target' => $target->id(), '@form_id' => $form_id]); throw new \BadMethodCallException($message); } }
/** * {@inheritdoc} */ public function bind(TargetInterface $module) { $this->target = $module; $this->table = $module->id() . '__' . $this->getPluginId(); $schema = $this->db->schema(); if ($schema->tableExists($this->table)) { $this->clear(); } else { $schema->createTable($this->table, ['fields' => $this->getFields()]); } $this->build(); }
/** * {@inheritdoc} */ public function convert(TargetInterface $target) { $target->getIndexer('function')->get($this->pluginDefinition['hook'])->setDocComment($this->buildFixMe(NULL, [], self::DOC_COMMENT)); $render = ['#theme' => 'dmu_route_subscriber', '#module' => $target->id()]; $this->writeClass($target, $this->parse($render)); $alterable = ParameterNode::create('data'); $alterable->setTypeHint('array')->setReference(TRUE); $parameter = clone $alterable; $this->implement($target, 'menu_links_discovered_alter')->appendParameter($parameter->setName('links')); $parameter = clone $alterable; $this->implement($target, 'menu_local_tasks_alter')->appendParameter($parameter->setName('data'))->appendParameter(ParameterNode::create('route_name')); $parameter = clone $alterable; $this->implement($target, 'menu_local_actions_alter')->appendParameter($parameter->setName('local_actions')); $parameter = clone $alterable; $items = clone $alterable; $function = $this->implement($target, 'contextual_links_view_alter')->appendParameter($parameter->setName('element'))->appendParameter($items->setName('items')->setReference(FALSE)); $target->save($function); }
/** * {@inheritdoc} */ public function convert(TargetInterface $target) { $hook = $target->getIndexer('function')->get($this->pluginDefinition['hook'])->setName($target->id() . '_entity_bundle_create'); $target->save($hook); }
/** * Tests if the function call can be rewritten at all, which it will be * only if both arguments are strings, and the first argument is the machine * name of the target module. * * @param \Pharborist\Functions\FunctionCallNode $call * The function call to test. * @param \Drupal\drupalmoduleupgrader\TargetInterface $target * The target module. * * @return boolean */ public function canRewrite(FunctionCallNode $call, TargetInterface $target) { $arguments = $call->getArguments(); return $arguments[0] instanceof StringNode && $arguments[0]->toValue() == $target->id() && $arguments[1] instanceof StringNode; }
/** * {@inheritdoc} */ public function convert(TargetInterface $target) { // If the hook implementation contains logic, we cannot convert it and // that's that. So we'll leave a FIXME and bail out. /** @var \Pharborist\Functions\FunctionDeclarationNode $hook */ $hook = $target->getIndexer('function')->get('hook_menu'); if ($hook->is(new ContainsLogicFilter())) { $hook->setDocComment(DocCommentNode::create($this->pluginDefinition['fixme'])); $target->save($hook); return; } // Links are split out by group because there are separate config files // for each link type. $links = ['menu' => new LinkIndex(), 'task' => new LinkIndex(), 'action' => new LinkIndex(), 'contextual' => new LinkIndex()]; $hook_menu = new HookMenu($target, $this->routeConverters); foreach ($hook_menu->getSourceRoutes()->getAllLinks() as $path => $source) { /** @var LinkBinding $binding */ $binding = $this->linkBinding->create($source, $hook_menu->getDestinationRoute($path)); // Skip if the converter wasn't able to find a destination. $destination = $binding->getDestination(); if (empty($destination)) { continue; } if ($binding instanceof MenuLinkBinding) { $links['menu']->addBinding($binding); } elseif ($binding instanceof LocalTaskLinkBinding) { $links['task']->addBinding($binding); } elseif ($binding instanceof LocalActionLinkBinding) { $links['action']->addBinding($binding); } elseif ($source->isContextualLink()) { $links['contextual']->addBinding($binding); } } $links = array_map(function (LinkIndex $index) { return $index->build(); }, $links); foreach ($links['contextual'] as $link) { $link['group'] = $target->id(); } foreach ($links as $group => $data) { if ($data) { $this->writeInfo($target, 'links.' . $group, $data); } } }
protected function getController(TargetInterface $target, Drupal7Route $route) { $render = ['#theme' => 'dmu_controller', '#module' => $target->id()]; return $this->parse($render); }
/** * 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)); }