You are here

abstract class ConverterBase in Drupal 7 to 8/9 Module Upgrader 8

Base class for converters.

Hierarchy

Expanded class hierarchy of ConverterBase

30 files declare their use of ConverterBase
Blocks.php in src/Plugin/DMU/Converter/Blocks.php
ContentRoute.php in src/Plugin/DMU/Routing/ContentRoute.php
EntityHooks.php in src/Plugin/DMU/Converter/EntityHooks.php
FunctionCallModifier.php in src/Plugin/DMU/Converter/Functions/FunctionCallModifier.php
Grep.php in src/Plugin/DMU/Converter/Grep.php

... See full list

File

src/ConverterBase.php, line 24

Namespace

Drupal\drupalmoduleupgrader
View source
abstract class ConverterBase extends PluginBase implements ConverterInterface {

  // Used by buildFixMe() to determine the comment style of the generated
  // FIXME notice.
  const LINE_COMMENT = '//';
  const DOC_COMMENT = '/**/';

  /**
   * {@inheritdoc}
   */
  public function isExecutable(TargetInterface $target) {

    // If the plugin applies to particular hook(s), only return TRUE if the
    // target module implements any of the hooks. Otherwise, return TRUE
    // unconditionally.
    if (isset($this->pluginDefinition['hook'])) {
      return (bool) array_filter((array) $this->pluginDefinition['hook'], [
        $target
          ->getIndexer('function'),
        'has',
      ]);
    }
    else {
      return TRUE;
    }
  }

  /**
   * Executes the target module's implementation of the specified hook, and
   * returns the result.
   *
   * @return mixed
   *
   * @throws \LogicException if the target module doesn't implement the
   * specified hook, or if the implementation contains logic.
   *
   * @deprecated
   */
  protected function executeHook(TargetInterface $target, $hook) {
    $indexer = $target
      ->getIndexer('function');
    if ($indexer
      ->has($hook)) {

      // Configure the ContainsLogicFilter so that certain "safe" functions
      // will pass it.
      $has_logic = new ContainsLogicFilter();
      $has_logic
        ->whitelist('t');
      $has_logic
        ->whitelist('drupal_get_path');
      $function = $indexer
        ->get($hook);
      if ($function
        ->is($has_logic)) {
        throw new \LogicException('{target}_{hook} cannot be executed because it contains logic.');
      }
      else {
        $function_name = $function
          ->getName()
          ->getText();
        if (!function_exists($function_name)) {
          eval($function
            ->getText());
        }
        return call_user_func($function_name);
      }
    }
    else {
      throw new \LogicException('{target} does not implement hook_{hook}.');
    }
  }

  /**
   * Creates an empty implementation of a hook.
   *
   * @param TargetInterface $target
   *   The target module.
   * @param string $hook
   *   The hook to implement, without the hook_ prefix.
   *
   * @return \Pharborist\Functions\FunctionDeclarationNode
   *   The hook implementation, appended to the main module file.
   */
  protected function implement(TargetInterface $target, $hook) {
    $function = FunctionDeclarationNode::create($target
      ->id() . '_' . $hook);
    $function
      ->setDocComment(DocCommentNode::create('Implements hook_' . $hook . '().'));
    $module_file = $target
      ->getPath('.module');
    $target
      ->open($module_file)
      ->append($function);
    WhitespaceNode::create("\n")
      ->insertBefore($function);
    WhitespaceNode::create("\n")
      ->insertAfter($function);
    return $function;
  }

  /**
   * Writes a file to the target module's directory.
   *
   * @param TargetInterface $target
   *   The target module.
   * @param string $path
   *   The path of the file to write, relative to the module root.
   * @param string $data
   *   The file contents.
   *
   * @return string
   *   The path of the file, including the target's base path.
   */
  public function write(TargetInterface $target, $path, $data) {
    static $fs;
    if (empty($fs)) {
      $fs = new Filesystem();
    }
    $destination_path = $target
      ->getPath($path);
    $fs
      ->dumpFile($destination_path, (string) $data);
    return $destination_path;
  }

  /**
   * Writes a class to the target module's PSR-4 root.
   *
   * @param TargetInterface $target
   *   The target module.
   * @param \Pharborist\Objects\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));
  }

  /**
   * Writes out arbitrary data in YAML format.
   *
   * @param TargetInterface $target
   *   The target module.
   * @param string $group
   *   The name of the YAML file. It will be prefixed with the module's machine
   *   name and suffixed with .yml. For example, a group value of 'routing'
   *   will write MODULE.routing.yml.
   * @param array $data
   *   The data to write.
   *
   * @todo This should be writeYAML, not writeInfo.
   */
  protected function writeInfo(TargetInterface $target, $group, array $data) {
    $destination = $target
      ->getPath('.' . $group . '.yml');
    file_put_contents($destination, Yaml::encode($data));
  }

  /**
   * Writes a service definition to the target module's services.yml file.
   *
   * @param TargetInterface $target
   *   The target module.
   * @param string $service_id
   *   The service ID. If an existing one with the same ID already exists,
   *   it will be overwritten.
   * @param array $service_definition
   */
  protected function writeService(TargetInterface $target, $service_id, array $service_definition) {
    $services = $target
      ->getServices();
    $services
      ->set($service_id, $service_definition);
    $this
      ->writeInfo($target, 'services', [
      'services' => $services
        ->toArray(),
    ]);
  }

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

  /**
   * Builds a FIXME notice using either the text in the plugin definition,
   * or passed-in text.
   *
   * @param string|null $text
   *   The FIXME notice's text, with variable placeholders and no translation.
   * @param array $variables
   *   Optional variables to use in translation. If empty, the FIXME will not
   *   be translated.
   * @param string|null $style
   *   The comment style. Returns a LineCommentBlockNode if this is set to
   *   self::LINE_COMMENT, a DocCommentNode if self::DOC_COMMENT, or the FIXME
   *   as a string if set to anything else.
   *
   * @return mixed
   */
  protected function buildFixMe($text = NULL, array $variables = [], $style = self::LINE_COMMENT) {
    $fixMe = "@FIXME\n" . ($text ?: $this->pluginDefinition['fixme']);
    if (isset($this->pluginDefinition['documentation'])) {
      $fixMe .= "\n";
      foreach ($this->pluginDefinition['documentation'] as $doc) {
        $fixMe .= "\n@see ";
        $fixMe .= isset($doc['url']) ? $doc['url'] : (string) $doc;
      }
    }
    if ($variables) {
      $fixMe = (new FormattableMarkup($fixMe, $variables))
        ->__toString();
    }
    switch ($style) {
      case self::LINE_COMMENT:
        return LineCommentBlockNode::create($fixMe);
      case self::DOC_COMMENT:
        return DocCommentNode::create($fixMe);
      default:
        return $fixMe;
    }
  }

  /**
   * Parametrically rewrites a function.
   *
   * @param \Drupal\drupalmoduleupgrader\RewriterInterface $rewriter
   *   A fully configured parametric rewriter.
   * @param \Pharborist\Functions\ParameterNode $parameter
   *   The parameter upon which to base the rewrite.
   * @param TargetInterface $target
   *   The target module.
   * @param bool $recursive
   *   If TRUE, rewriting will recurse into called functions which are passed
   *   the rewritten parameter as an argument.
   */
  protected function rewriteFunction(RewriterInterface $rewriter, ParameterNode $parameter, TargetInterface $target, $recursive = TRUE) {
    $rewriter
      ->rewrite($parameter);
    $target
      ->save($parameter);

    // Find function calls within the rewritten function which are called
    // with the rewritten parameter.
    $indexer = $target
      ->getIndexer('function');
    $next = $parameter
      ->getFunction()
      ->find(new FunctionCallArgumentFilter($parameter
      ->getName()))
      ->filter(function (FunctionCallNode $call) use ($indexer) {
      return $indexer
        ->has($call
        ->getName()
        ->getText());
    });

    /** @var \Pharborist\Functions\FunctionCallNode $call */
    foreach ($next as $call) {

      /** @var \Pharborist\Functions\FunctionDeclarationNode $function */
      $function = $indexer
        ->get($call
        ->getName()
        ->getText());
      foreach ($call
        ->getArguments() as $index => $argument) {
        if ($argument instanceof VariableNode && $argument
          ->getName() == $parameter
          ->getName()) {
          $this
            ->rewriteFunction($rewriter, $function
            ->getParameterAtIndex($index), $target, $recursive);
          break;
        }
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ConverterBase::buildFixMe protected function Builds a FIXME notice using either the text in the plugin definition, or passed-in text.
ConverterBase::DOC_COMMENT constant
ConverterBase::executeHook protected function Executes the target module's implementation of the specified hook, and returns the result.
ConverterBase::implement protected function Creates an empty implementation of a hook.
ConverterBase::isExecutable public function Returns if this conversion applies to the target module. If FALSE, the convert() method will not be called. Overrides ConverterInterface::isExecutable 4
ConverterBase::LINE_COMMENT constant
ConverterBase::parse protected function Parses a generated class into a syntax tree.
ConverterBase::rewriteFunction protected function Parametrically rewrites a function.
ConverterBase::write public function Writes a file to the target module's directory.
ConverterBase::writeClass public function Writes a class to the target module's PSR-4 root.
ConverterBase::writeInfo protected function Writes out arbitrary data in YAML format.
ConverterBase::writeService protected function Writes a service definition to the target module's services.yml file.
ConverterInterface::convert public function Performs required conversions. 30
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$log protected property
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::create public static function Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface::create 2
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
PluginBase::__construct public function Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides PluginBase::__construct 11
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.