cforge-2.0.x-dev/modules/cforge_import/src/Plugin/CsvParser/Transactions.php
modules/cforge_import/src/Plugin/CsvParser/Transactions.php
<?php
namespace Drupal\cforge_import\Plugin\CsvParser;
use Drupal\mcapi\Entity\Transaction;
use Drupal\user\Entity\User;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
/**
* Import transactions from csv file.
*/
abstract class Transactions extends ImportBase {
private $allWallets = [];
protected $tempStore;
/**
* Constructor
*
* @param type $configuration
* @param type $plugin_id
* @param type $plugin_definition
* @param type $logger_channel
* @param PrivateTempStoreFactory $private_tempstore
*/
public function __construct($configuration, $plugin_id, $plugin_definition, $logger_channel, PrivateTempStoreFactory $private_tempstore) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $logger_channel);
$this->tempStore = $private_tempstore->get('saved');
}
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'),
$container->get('tempstore.private')
);
}
/**
* {@inheritdoc}
*/
public function columns() {
return [
'serial' => t('numeric identifer, not database key'),
'payer' => t('integer wallet id e.g. abcd1234 OR email of wallet owner'),
'payee' => t('integer wallet id e.g. abcd1234 OR email of wallet owner'),
'entries.quant' => t('Raw integer value of transaction (assumes only one currency)'),
'created' => t('Item created date in any strtotime format'),
'state' => t('is always 1 which translates to transaction state "done" in D8'),
'description' => t('plain text'),
'creator' => t('integer uid of the of the transaction creator'),
];
}
/**
* {@inheritdoc}
*/
public static function deleteAll() {
// Might run out of memory this way.
foreach (\Drupal::entityTypeManager()->getStorage('mcapi_transaction')->loadMultiple() as $entity) {
$entity->delete();
}
}
/**
* Preprocessing for csv field 'state'.
*/
protected function stateProcess($val, array $fields) {
if (is_numeric($val)) {
// State constants from drupal 7
switch ($val) {
case 1: $state = 'done';
break;
case 0: $state = 'erased';
break;
case -1: $state = 'pending';
break;
default:
throw new \Exception('Unknown transaction state: ' . $val);
}
}
elseif (is_string($val)) {
$state = $val;
}
$this->entity->state->target_id = 'done';
}
/**
* {@inheritdoc}
*/
public static function saveEntities(string $plugin_id, array $rows, bool $save, array &$sandbox= []) : void {
// Bypass the setting that sends transaction emails
\Drupal::State()->set('mcapi_mail_stop', 1);
$mcapi = \Drupal::configFactory()->getEditable('mcapi.settings');
$temp = $mcapi->get('mail_all');
$mcapi->set('mail_all', FALSE);
$plugin = \Drupal::service('cforge.csv_importer')->createInstance($plugin_id);
\Drupal::service('account_switcher')->switchTo(User::load(1));
$plugin->tempStore->delete('stash');
foreach ($rows as $rownum => $row) {
$plugin->buildEntity($row);
foreach ($plugin->entity->validate() as $violation) {
\Drupal::messenger()->addWarning($violation->getMessage());
}
if ($save) {
$plugin->stash($sandbox);
}
}
\Drupal::service('account_switcher')->switchBack();
$mcapi->set('mail_all', $temp)->save();
\Drupal::State()->delete('mcapi_mail_stop');
}
/**
* Stash a transaction in the tempStore.
*/
public function stash(&$sandbox) {
$tempstore = \Drupal::service('tempstore.private')->get('saved');
// Get the previous transaction if there is one, save it, and put the
// current transaction in the tempstore.
$previous_transaction = $this->tempStore->get('stash');
if ($previous_transaction instanceof Transaction) {
if ($this->entity->type->target_id == 'default') {
$previous_transaction->save();
\Drupal::service('logger.channel.cforge')->debug(
'Imported transaction @serial with @count children: @print',
[
'@serial' => $previous_transaction->serial->value,
'@count' => count($previous_transaction->children),
'@print' => print_r($previous_transaction->toArray(), 1)
]
);
$this->tempStore->set('stash', $this->entity);
}
elseif ($this->entity->type->target_id == 'auto') {
$previous_transaction->children[] = $this->entity;
$this->tempStore->set('stash', $previous_transaction);
\Drupal::service('logger.channel.cforge')->debug('Stashed transaction');
}
}
// First time we run this put the current transaction in the tempstore.
else {
$this->tempStore->set('stash', $this->entity);
}
}
/**
* {@inheritDoc}
*/
public function buildEntity(array $fields) {
if ($fields['creator'] == $fields['payee']) {
$fields['workflow'] = 'default_bill';
}
elseif ($fields['creator'] == $fields['payer']) {
$fields['workflow'] = 'default_credit';
}
else $fields['workflow'] = 'admin';
parent::buildEntity($fields);
$this->entity->assembled = TRUE;
}
/**
* Get the last transaction from the stash and save it.
*
* Used only at the end of the batch.
*/
public function saveLastTransaction($success, $results, $operations) {
// Trigger saving the last transaction
// ugly workaround because the sandbox appears not to be working.
$last = $this->tempStore->get('stash');
if ($last instanceof Transaction) {
$last->save();
}
else {
$this->messenger()->addStatus('problem saving last transaction: ' . gettype($last));
}
$this->tempStore->delete('stash');
}
/**
* {@inheritdoc}
*/
public function makeBatch($rows, $delete = FALSE, $test = TRUE) {
// @todo this should really be injected
$this->tempStore->delete('stash');
$batch = parent::makeBatch($rows, $delete, $test);
$batch['title'] = 'Importing transaction history';
if (!$test) {
$batch['finished'] = [$this, 'saveLastTransaction'];
}
return $batch;
}
/**
* {@inheritdoc}
*/
public function getDefaults() {
return ['type' => 'default'];
}
/**
* {@inheritDoc}
*/
public function ready(): bool {
return TRUE;
}
}
