|
@@ -10,11 +10,14 @@ use Drupal\Core\Entity\EntityTypeManagerInterface;
|
|
|
use Drupal\Core\Session\AccountSwitcherInterface;
|
|
|
use Drupal\Core\Session\UserSession;
|
|
|
use Drupal\file\Entity\File;
|
|
|
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
|
|
use Symfony\Component\Serializer\Serializer;
|
|
|
use Symfony\Component\Yaml\Yaml;
|
|
|
|
|
|
|
|
|
* Class Dumper provides export for content entities.
|
|
|
+ *
|
|
|
+ * @see \Drupal\reinstall\DumperEvents
|
|
|
*/
|
|
|
class Dumper {
|
|
|
|
|
@@ -52,6 +55,13 @@ class Dumper {
|
|
|
*/
|
|
|
protected $entityTypeManager;
|
|
|
|
|
|
+
|
|
|
+ * The event_dispatcher service.
|
|
|
+ *
|
|
|
+ * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
|
|
+ */
|
|
|
+ protected $eventDispatcher;
|
|
|
+
|
|
|
|
|
|
* The actual path from which to perform imports.
|
|
|
*
|
|
@@ -88,6 +98,8 @@ class Dumper {
|
|
|
* The value of the app.root "parameter service".
|
|
|
* @param \Symfony\Component\Serializer\Serializer $serializer
|
|
|
* The serializer service.
|
|
|
+ * @param string $path
|
|
|
+ * The import path.
|
|
|
*/
|
|
|
public function __construct(
|
|
|
AccountSwitcherInterface $accountSwitcher,
|
|
@@ -95,15 +107,17 @@ class Dumper {
|
|
|
EntityTypeManagerInterface $entityTypeManager,
|
|
|
string $root,
|
|
|
Serializer $serializer,
|
|
|
- string $importPath
|
|
|
+ EventDispatcherInterface $eventDispatcher,
|
|
|
+ string $path
|
|
|
) {
|
|
|
$this->accountSwitcher = $accountSwitcher;
|
|
|
$this->entityTypeBundleInfo = $bundleInfo;
|
|
|
$this->entityTypeManager = $entityTypeManager;
|
|
|
$this->root = $root;
|
|
|
$this->serializer = $serializer;
|
|
|
+ $this->eventDispatcher = $eventDispatcher;
|
|
|
|
|
|
- $this->setPath($importPath);
|
|
|
+ $this->setPath($path);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -180,10 +194,15 @@ class Dumper {
|
|
|
: [$entityTypeName => $storage->loadMultiple()];
|
|
|
|
|
|
foreach ($entities as $bundleName => $bundleEntities) {
|
|
|
+
|
|
|
+ $eventPre = new DumperEvent($storage, $bundleName, $bundleEntities);
|
|
|
+ $this->eventDispatcher->dispatch(DumperEvents::PRE_DUMP, $eventPre);
|
|
|
+
|
|
|
$this->dumpEntities($bundleEntities, $entityTypeName, $bundleName);
|
|
|
- if ($entityTypeName === 'file') {
|
|
|
- $this->dumpFiles($bundleEntities, $bundleName);
|
|
|
- }
|
|
|
+
|
|
|
+
|
|
|
+ $eventPost = new DumperEvent($storage, $bundleName, $bundleEntities);
|
|
|
+ $this->eventDispatcher->dispatch(DumperEvents::POST_DUMP, $eventPost);
|
|
|
}
|
|
|
}
|
|
|
$this->accountSwitcher->switchBack();
|
|
@@ -194,99 +213,46 @@ class Dumper {
|
|
|
*
|
|
|
* @param array $entities
|
|
|
* The entities.
|
|
|
- * @param string $entity_type
|
|
|
+ * @param string $entityTypeName
|
|
|
* The entity type.
|
|
|
* @param string $bundle
|
|
|
* The bundle name.
|
|
|
*/
|
|
|
- public function dumpEntities(array $entities, string $entity_type, string $bundle = NULL) {
|
|
|
- if (!$bundle) {
|
|
|
- $bundle = $entity_type;
|
|
|
- }
|
|
|
-
|
|
|
- $json_options = [];
|
|
|
- $json = $this->serializer->serialize($entities, 'json', $json_options);
|
|
|
- $hash = json_decode($json, TRUE);
|
|
|
+ public function dumpEntities(array $entities, string $entityTypeName, string $specifiedBundle = NULL) {
|
|
|
+ $bundle = $specifiedBundle ?: $entityTypeName;
|
|
|
+ $array = $this->toArray($entities);
|
|
|
+ $path = $this->prepareDestination($entityTypeName, $bundle);
|
|
|
+ file_put_contents($path, Yaml::dump($array, static::INLINE_DEPTH, 2));
|
|
|
+ }
|
|
|
|
|
|
+
|
|
|
+ * Prepare the dump destination directory and return the file name within it.
|
|
|
+ *
|
|
|
+ * @param string $entityTypeName
|
|
|
+ * @param string $bundleName
|
|
|
+ *
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ protected function prepareDestination(string $entityTypeName, string $bundleName): string {
|
|
|
$importPath = $this->importPath;
|
|
|
- $dir = "$importPath/$entity_type";
|
|
|
+ $dir = "$importPath/$entityTypeName";
|
|
|
if (!file_exists($dir)) {
|
|
|
mkdir($dir, 0777, TRUE);
|
|
|
}
|
|
|
|
|
|
- $path = "${dir}/${bundle}.yml";
|
|
|
-
|
|
|
- file_put_contents($path, Yaml::dump($hash, static::INLINE_DEPTH, 2));
|
|
|
+ $path = "${dir}/${bundleName}.yml";
|
|
|
+ return $path;
|
|
|
}
|
|
|
|
|
|
- public function dumpFiles(array $files, string $bundle) {
|
|
|
- $importPath = $this->importPath;
|
|
|
- $dir = "$importPath/file";
|
|
|
- $usedNamespaces = array_keys(array_reduce($files, [$this, 'namespacesReducer'], []));
|
|
|
- $lists = [];
|
|
|
-
|
|
|
- foreach ($usedNamespaces as $ns) {
|
|
|
-
|
|
|
- $path = "$dir/$ns.list.txt";
|
|
|
-
|
|
|
- $nsDir = "$dir/$ns";
|
|
|
- if (!is_dir($nsDir)) {
|
|
|
- echo "Creating $nsDir\n";
|
|
|
- mkdir($nsDir, 0777, TRUE);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- $lists[$ns] = [
|
|
|
- 'dir' => $nsDir,
|
|
|
- 'handle' => fopen($path, 'w'),
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * @var int $fid
|
|
|
- * @var \Drupal\file\Entity\File $file
|
|
|
- */
|
|
|
- foreach ($files as $fid => $file) {
|
|
|
- $uri = $file->getFileUri();
|
|
|
- $target = file_uri_target($uri);
|
|
|
- fputs($lists[$ns]['handle'], $target . "\n");
|
|
|
- $dest = $lists[$ns]['dir'] . '/' . $target;
|
|
|
-
|
|
|
- $dir = dirname($dest);
|
|
|
- if (!is_dir($dir)) {
|
|
|
- mkdir($dir, 0777, TRUE);
|
|
|
- }
|
|
|
- file_unmanaged_copy($uri, $dest, FILE_EXISTS_REPLACE);
|
|
|
- }
|
|
|
-
|
|
|
- foreach ($lists as $list) {
|
|
|
- fclose($list['handle']);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
|
|
|
- * array_reduce() callback to collect namespaces from file entities.
|
|
|
- *
|
|
|
- * @param string[] $accu
|
|
|
- * @param \Drupal\file\Entity\File $fileItem
|
|
|
+ * Store the absolute path to the import directory.
|
|
|
*
|
|
|
- * @return string[]
|
|
|
+ * @param string $path
|
|
|
+ * The Drupal-root-relative import path.
|
|
|
*
|
|
|
- * @see \Drupal\reinstall\Dumper::dumpFiles()
|
|
|
+ * @throws \InvalidArgumentException
|
|
|
+ * If the directory does not exist.
|
|
|
*/
|
|
|
- protected function namespacesReducer(array $accu, File $fileItem) {
|
|
|
- $uri = $fileItem->getFileUri();
|
|
|
-
|
|
|
- if (FALSE === ($len = Unicode::strpos($uri, '://'))) {
|
|
|
- return $accu;
|
|
|
- };
|
|
|
-
|
|
|
- $namespace = Unicode::substr($uri, 0, $len);
|
|
|
- $accu[$namespace] = TRUE;
|
|
|
- return $accu;
|
|
|
- }
|
|
|
-
|
|
|
public function setPath(string $path) {
|
|
|
$completePath = $this->root . '/' . $path;
|
|
|
$real = realpath($completePath);
|
|
@@ -298,4 +264,19 @@ class Dumper {
|
|
|
|
|
|
$this->importPath = $real;
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ * Like NormalizerInterface::normalize(), but for an array.
|
|
|
+ *
|
|
|
+ * @param array $entities
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ protected function toArray(array $entities): array {
|
|
|
+ $json_options = [];
|
|
|
+ $json = $this->serializer->serialize($entities, 'json', $json_options);
|
|
|
+ $hash = json_decode($json, TRUE);
|
|
|
+
|
|
|
+ return $hash;
|
|
|
+ }
|
|
|
}
|