Chris@5: configuration += $this->defaultValues(); Chris@5: $this->logMessages = (bool) $this->configuration['log_messages']; Chris@5: $this->nonRoot = (bool) $this->configuration['non_root']; Chris@5: } Chris@5: Chris@5: /** Chris@5: * Supply default values of all optional parameters. Chris@5: * Chris@5: * @return array Chris@5: * An array with keys the optional parameters and values the corresponding Chris@5: * defaults. Chris@5: */ Chris@5: protected function defaultValues() { Chris@5: return [ Chris@5: 'non_root' => TRUE, Chris@5: 'log_messages' => TRUE, Chris@5: 'version' => '1.0', Chris@5: 'encoding' => 'UTF-8', Chris@5: ]; Chris@5: } Chris@5: Chris@5: /** Chris@5: * Converts a HTML string into a DOMDocument. Chris@5: * Chris@5: * It is not using \Drupal\Component\Utility\Html::load() because it ignores Chris@5: * all errors on import, and therefore incompatible with log_messages Chris@5: * option. Chris@5: * Chris@5: * @param mixed $value Chris@5: * The string to be imported. Chris@5: * @param \Drupal\migrate\MigrateExecutableInterface $migrate_executable Chris@5: * The migration in which this process is being executed. Chris@5: * @param \Drupal\migrate\Row $row Chris@5: * The row from the source to process. Normally, just transforming the value Chris@5: * is adequate but very rarely you might need to change two columns at the Chris@5: * same time or something like that. Chris@5: * @param string $destination_property Chris@5: * The destination property currently worked on. This is only used together Chris@5: * with the $row above. Chris@5: * Chris@5: * @return \DOMDocument Chris@5: * The document object based on the provided string. Chris@5: * Chris@5: * @throws \Drupal\migrate\MigrateException Chris@5: * When the received $value is not a string. Chris@5: */ Chris@5: public function import($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { Chris@5: if (!is_string($value)) { Chris@5: throw new MigrateException('Cannot import a non-string value.'); Chris@5: } Chris@5: Chris@5: if ($this->logMessages) { Chris@5: set_error_handler(function ($errno, $errstr) use ($migrate_executable) { Chris@5: $migrate_executable->saveMessage($errstr, MigrationInterface::MESSAGE_WARNING); Chris@5: }); Chris@5: } Chris@5: Chris@5: if ($this->nonRoot) { Chris@5: $html = $this->getNonRootHtml($value); Chris@5: } Chris@5: else { Chris@5: $html = $value; Chris@5: } Chris@5: Chris@5: $document = new \DOMDocument($this->configuration['version'], $this->configuration['encoding']); Chris@5: $document->loadHTML($html); Chris@5: Chris@5: if ($this->logMessages) { Chris@5: restore_error_handler(); Chris@5: } Chris@5: Chris@5: return $document; Chris@5: } Chris@5: Chris@5: /** Chris@5: * Converts a DOMDocument into a HTML string. Chris@5: * Chris@5: * @param mixed $value Chris@5: * The document to be exported. Chris@5: * @param \Drupal\migrate\MigrateExecutableInterface $migrate_executable Chris@5: * The migration in which this process is being executed. Chris@5: * @param \Drupal\migrate\Row $row Chris@5: * The row from the source to process. Normally, just transforming the value Chris@5: * is adequate but very rarely you might need to change two columns at the Chris@5: * same time or something like that. Chris@5: * @param string $destination_property Chris@5: * The destination property currently worked on. This is only used together Chris@5: * with the $row above. Chris@5: * Chris@5: * @return string Chris@5: * The HTML string corresponding to the provided document object. Chris@5: * Chris@5: * @throws \Drupal\migrate\MigrateException Chris@5: * When the received $value is not a \DOMDocument. Chris@5: */ Chris@5: public function export($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { Chris@5: if (!$value instanceof \DOMDocument) { Chris@5: $value_description = (gettype($value) == 'object') ? get_class($value) : gettype($value); Chris@5: throw new MigrateException(sprintf('Cannot export a "%s".', $value_description)); Chris@5: } Chris@5: Chris@5: if ($this->nonRoot) { Chris@5: return Html::serialize($value); Chris@5: } Chris@5: return $value->saveHTML(); Chris@5: } Chris@5: Chris@5: /** Chris@5: * Builds an full html string based on a partial. Chris@5: * Chris@5: * @param string $partial Chris@5: * A subset of a full html string. For instance the contents of the body Chris@5: * element. Chris@5: */ Chris@5: protected function getNonRootHtml($partial) { Chris@5: $replacements = [ Chris@5: "\n" => '', Chris@5: '!encoding' => strtolower($this->configuration['encoding']), Chris@5: '!value' => $partial, Chris@5: ]; Chris@5: // Prepend the html with a header using the configured source encoding. Chris@5: // By default, loadHTML() assumes ISO-8859-1. Chris@5: $html_template = << Chris@5: Chris@5: Chris@5: !value Chris@5: Chris@5: EOD; Chris@5: return strtr($html_template, $replacements); Chris@5: } Chris@5: Chris@5: }