cforge-2.0.x-dev/modules/cforge_import/src/Plugin/CsvParser/ImportBase.php

modules/cforge_import/src/Plugin/CsvParser/ImportBase.php
<?php

namespace Drupal\cforge_import\Plugin\CsvParser;

use Drupal\user\Entity\User;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Logger\LoggerChannel;
use Symfony\Component\DependencyInjection\ContainerInterface;

ini_set('max_execution_time', 150);

/**
 * Base class for importing entities from csv files.
 */
abstract class ImportBase extends PluginBase implements CsvParserInterface, ContainerFactoryPluginInterface {

  use MessengerTrait;
  protected $entity;
  protected $logger;
  protected array $fields;


  public function __construct($configuration, $plugin_id, $plugin_definition, LoggerChannel $logger_channel) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->logger = $logger_channel;
  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('logger.channel.cforge')
    );
  }

  /**
   * {@inheritDoc}
   *
   * The sandbox seems to be empty every time, unfortunately.
   */
  public static function saveEntities(string $plugin_id, array $rows, bool $save, array &$sandbox = []) : void {
    $plugin = \Drupal::service('cforge.csv_importer')->createInstance($plugin_id);
    $accountSwitcher = \Drupal::service('account_switcher');
    $accountSwitcher->switchTo(User::load(1));
    foreach ($rows as $row) {
      $plugin->saveEntity($row, $save);
    }
    $accountSwitcher->switchBack();
  }

  /**
   * {@inheritDoc}
   */
  function saveEntity($row, $save = FALSE) {
    $this->fields = $row;
    $this->buildEntity($row);
    foreach ($this->entity->validate() as $violation) {
      $this->logger->error(
        "Failed validation @parents: '@message' in <pre>@row</pre><br /><pre>@array</pre>",
        array(
          '@parents' => $violation->getPropertyPath(),
          '@message' => $violation->getMessage(),
          '@row' => print_r($row, 1),
          '@array' => print_r($this->entity->toArray(), 1),
        )
      );
    }
    if ($save) {
      $this->entity->save();
      if ($postCols = array_keys($this->columns())) {
        foreach ($postCols as $col) {
          $methodname = $col . 'PostProcess';
          if (isset($row[$col]) and method_exists($this, $methodname)) {
            $this->{$methodname}($row[$col], $row);
          }
        }
        $this->entity->save();
      }
    }
  }

  /**
   * {@inheritDoc}
   */
  public function buildEntity(array $fields) {
    $entity_type_manager = \Drupal::entityTypeManager();
    $defaults = $this->getDefaults();
    $def = $this->getPluginDefinition();
    $entity_type = $def['entity_type'];
    if (isset($def['bundle'])) {
      $bundle_key = $entity_type_manager->getDefinition($entity_type)->getKey('bundle');
      $defaults[$bundle_key] = $def['bundle'];
    }
    $entity_type = $this->getPluginDefinition()['entity_type'];
    $this->entity = $entity_type_manager->getStorage($entity_type)
      ->create($defaults);
    foreach ($fields as $fieldname => $value) {
      $error = '';
      // Fields with multiple columns.
      if (strpos($fieldname, '.')) {
        list($field, $col) = explode('.', $fieldname);
        $method = $field . '_' . $col . 'Process';
        if (method_exists($this, $method)) {
          $error = $this->{$method}($fields[$fieldname]);
        }
        elseif ($value) {
          $this->entity->{$field}->{$col} = $value;
        }
      }
      // Time fields.
      elseif (in_array($fieldname, ['created', 'changed', 'access'])) {
        $this->entity->{$fieldname}->setValue($this->toUnixtime($fields[$fieldname]));
      }
      else {// Normal fields
        $method = $fieldname . 'Process';
        if (method_exists($this, $method)) {
          $error = $this->{$method}($fields[$fieldname]);
        }
        elseif ($this->entity->hasField($fieldname) and $value !== "") {
          $this->entity->set($fieldname, $value);
        }
        else {
          // It must need postprocessing.
        }
      }
      if ($error) {
        \Drupal::messenger()->addWarning($error);
      }
    }
  }
  /**
   * {@inheritDoc}
   */
  protected function getDefaults() {
    return [];
  }

  /**
   * {@inheritDoc}
   */
  protected function toUnixtime($val) {
    if ($val) {
      if (!is_int($val)) {
        $val = strtotime($val);
      }
      return $val;
    }
  }

  /**
   * {@inheritDoc}
   */
  protected function langcodeProcess($val) {
    $this->entity->set('langcode', $val);
    $this->entity->set('preferred_langcode', $val);
  }

  /**
   * {@inheritDoc}
   */
  public function ready() :bool {
    return FALSE;
  }

  /**
   * {@inheritDoc}
   */
  function makeBatch($rows, $delete = FALSE, $save = FALSE) {
    // This could be overwritten.
    $batch = ['title' => 'Creating entities'];
    if ($delete) {
      $batch['operations'][] = [[get_class($this), 'deleteAll'], []];
    }
    foreach (array_chunk($rows, 25) as $chunk) {
      $batch['operations'][] = [[get_class($this), 'saveEntities'], [$this->getPluginId(), $chunk, $save]];
    }
    return $batch;
  }

  /**
   * {@inheritDoc}
   */
  public function getCsvRows(array $csv) {
    $headings = $csv[0];
    array_walk($csv, function(&$a) use ($headings) {
      if (count($headings) != count($a)) {
        throw new \Exception('Wrong number of columns in csv row. '. count($headings) .' header fields, '.count($a).' fields in row: '.implode(',', $a));
      }
      $a = array_combine($headings, $a);
    });

    // Remove first row.
    $headings = array_shift($csv);

    $output = [];
    foreach ($csv as $key => $row) {
      $fields = array_combine($headings, $row);

      foreach (array_keys($this->columns()) as $col_name) {
        if (isset($fields[$col_name])) {
          $output[$key][$col_name] = $fields[$col_name];
        }
        else $missing[] = $col_name;
      }
    }
    if (isset($missing)) {
      \Drupal::messenger()->addWarning('Missing fields: '.implode(', ', array_unique($missing)));
    }
    return $output;
  }

}

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

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