drupalmoduleupgrader-8.x-1.5/src/Plugin/DMU/Converter/Tests.php

src/Plugin/DMU/Converter/Tests.php
<?php

namespace Drupal\drupalmoduleupgrader\Plugin\DMU\Converter;

use Drupal\drupalmoduleupgrader\ConverterBase;
use Drupal\drupalmoduleupgrader\TargetInterface;
use Drupal\drupalmoduleupgrader\Utility\Filter\ContainsLogicFilter;
use Pharborist\DocCommentNode;
use Pharborist\Filter;
use Pharborist\Objects\ClassMemberNode;
use Pharborist\Objects\ClassMethodCallNode;
use Pharborist\Objects\ClassNode;
use Pharborist\Parser;
use Pharborist\RootNode;
use Pharborist\Types\StringNode;
use Pharborist\WhitespaceNode;

/**
 * @Converter(
 *  id = "tests",
 *  description = @Translation("Modifies test classes.")
 * )
 */
class Tests extends ConverterBase {

  private $target;

  /**
   * {@inheritdoc}
   */
  public function isExecutable(TargetInterface $target) {
    foreach (['DrupalTestCase', 'DrupalWebTestCase'] as $parent_class) {
      if ($target->getIndexer('class')->getQuery()->condition('parent', $parent_class)->countQuery()->execute()) {
        return TRUE;
      }
    }
    return 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);
          }
        }
      }
    }
  }

  /**
   * Converts a single web test.
   *
   * @param \Pharborist\Objects\ClassNode $test
   */
  public function convertWeb(ClassNode $test) {
    $test->setExtends('\Drupal\simpletest\WebTestBase');
    $this->convertInfo($test);
    $this->setModules($test);
    $this->setProfile($test);
    $this->move($test);
  }

  /**
   * Converts the test's getInfo() method to an annotation.
   *
   * @param \Pharborist\Objects\ClassNode $test
   */
  private function convertInfo(ClassNode $test) {
    $info = $this->extractInfo($test);

    if ($info) {
      $comment = '';
      $comment .= $info['description'] . "\n\n";
      $comment .= '@group ' . $this->target->id();

      if (isset($info['dependencies'])) {
        $comment .= "\n";
        foreach ($info['dependencies'] as $module) {
          $comment .= '@requires module . ' . $module . "\n";
        }
      }

      $test->setDocComment(DocCommentNode::create($comment));
    }
    else {
      $this->log->error('Could not get info for test {class}.', [
        'class' => $test->getName(),
      ]);
    }
  }

  /**
   * Extracts the return value of the test's getInfo() method, if there's no
   * logic in the method.
   *
   * @param \Pharborist\Objects\ClassNode $test
   *
   * @return array|null
   */
  private function extractInfo(ClassNode $test) {
    if ($test->hasMethod('getInfo')) {
      $info = $test->getMethod('getInfo');

      if (!$info->is(new ContainsLogicFilter())) {
        return eval($info->getBody()->getText());
      }
    }
  }

  /**
   * Sets the test's $modules property.
   *
   * @param \Pharborist\Objects\ClassNode $test
   */
  private function setModules(ClassNode $test) {
    $modules = $this->extractModules($test);
    if ($modules) {
      // @todo Use ClassNode::createProperty() when #124 lands in Pharborist
      $property = Parser::parseSnippet('class Foo { public static $modules = ["' . implode('", "', $modules) . '"]; }')
        ->getBody()
        ->firstChild()
        ->remove();
      $test->appendProperty($property);
    }
  }

  /**
   * Extracts every module required by a web test by scanning its calls
   * to parent::setUp().
   *
   * @param \Pharborist\Objects\ClassNode $test
   *
   * @return string[]
   *   Array of modules set up by this module.
   */
  private function extractModules(ClassNode $test) {
    $modules = [];

    $test
      ->find(Filter::isClassMethodCall('parent', 'setUp'))
      ->filter(function (ClassMethodCallNode $call) {
        return (sizeof($call->getArguments()) > 0);
      })
      ->each(function (ClassMethodCallNode $call) use (&$modules) {
        foreach ($call->getArguments() as $argument) {
          if ($argument instanceof StringNode) {
            $modules[] = $argument->toValue();
          }
        }

        $call->clearArguments();
      });

    return array_unique($modules);
  }

  /**
   * Sets the test's $profile property.
   *
   * @param \Pharborist\Objects\ClassNode $test
   */
  private function setProfile(ClassNode $test) {
    if (!$test->hasProperty('profile')) {
      $test->appendProperty(ClassMemberNode::create('profile', StringNode::create("'standard'"), 'protected'));
    }
  }

  public function move(ClassNode $test) {
    $ns = 'Drupal\\' . $this->target->id() . '\\Tests';
    RootNode::create($ns)->getNamespace($ns)->append($test->remove());
    WhitespaceNode::create("\n\n")->insertBefore($test);

    $this->writeClass($this->target, $test);
  }

  /**
   * 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);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc