social_event_invite_flow-1.0.0-beta3/src/Form/EnrollInviteSendEmailsFromFileForm.php

src/Form/EnrollInviteSendEmailsFromFileForm.php
<?php

namespace Drupal\social_event_invite_flow\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\File\FileUrlGenerator;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\Utility\Token;
use Drupal\file\Entity\File;
use Drupal\node\NodeInterface;
use Drupal\social_event\Entity\Node\Event;
use Drupal\social_event\EventEnrollmentInterface;
use Drupal\social_event\Service\SocialEventEnrollServiceInterface;
use Drupal\social_event_max_enroll\Service\EventMaxEnrollService;
use Drupal\social_event_invite_flow\Service\EventInviteFlowService;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\social_event_invite_flow\Form\InviteFlowBaseForm;
use Drupal\Component\Utility\Environment;
use Drupal\Core\File\FileSystemInterface;

/**
 * Class EnrollInviteForm.
 */
class EnrollInviteSendEmailsFromFileForm extends InviteFlowBaseForm {

  /*
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The logger factory.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $loggerFactory;

  /**
   * The current group from route.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $group;  

  /**
   * The node storage for event enrollments.
   */
  protected EntityStorageInterface $entityStorage;

  /**
   * Drupal\Core\TempStore\PrivateTempStoreFactory definition.
   */
  protected PrivateTempStoreFactory $tempStoreFactory;

  /**
   * The token service.
   */
  protected Token $token;

  /**
   * The social event enroll.
   */
  protected SocialEventEnrollServiceInterface $eventEnrollService;

  /**
   * The module handler service.
   */
  protected ModuleHandlerInterface $moduleHandler;

  /**
   * The event maximum enroll service.
   */
  protected EventMaxEnrollService $eventMaxEnrollService;

  /**
   * File URL Generator services.
   *
   * @var \Drupal\Core\File\FileUrlGenerator
   */
  protected FileUrlGenerator $fileUrlGenerator;

  /**
   * The invite flow service.
   */
  protected EventInviteFlowService $eventInviteFlowService;

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'enroll_invite_upload_form';
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    $instance = parent::create($container);
    $instance->entityStorage = $instance->entityTypeManager->getStorage('event_enrollment');
    $instance->tempStoreFactory = $container->get('tempstore.private');
    $instance->token = $container->get('token');
    $instance->eventEnrollService = $container->get('social_event.enroll');
    $instance->moduleHandler = $container->get('module_handler');
    if ($instance->moduleHandler->moduleExists('social_event_max_enroll')) {
      $instance->eventMaxEnrollService = $container->get('social_event_max_enroll.service');
    }
    $instance->fileUrlGenerator = $container->get('file_url_generator');
    $instance->eventInviteFlowService = $container->get('social_event_invite_flow.invite_flow_service');

    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    $form = parent::buildForm($form, $form_state);

    $tempstore = $this->tempStoreFactory->get('social_event_invite_flow_enroll_invite_upload_form_values');
    $params = $tempstore->get('params'); 

    $email_column_default_value = $params['email_column'] ?? '';
    $delimiter_default_value = $params['delimiter'] ?? '';  


    $form['#attributes']['enctype'] = 'multipart/form-data';
    
    $form['#attributes']['class'][] = 'form--default';


    /** @var \Drupal\node\Entity\Node $node */
    $node = $this->routeMatch->getParameter('node');

    $params = [
      'user' => $this->currentUser(),
      'node' => $node,
    ];

    // Load event invite configuration.
    $invite_config = $this->config('social_event_invite.settings');


    $form['importdata'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Importdata'),      
    ];  

    $form['importdata']['csvfile'] = [
      '#title'            => $this->t('CSV file'),
      '#type'             => 'file',
      '#description'      => ($max_size = Environment::getUploadMaxSize()) ? $this->t('Due to server restrictions, the <strong>maximum upload file size is @max_size</strong>. Files that exceed this size will be disregarded.', ['@max_size' => format_size($max_size)]) : '',
      '#element_validate' => ['::validateFileupload'],
    ];    

    $form['importdata']['delimiter'] = array(
      '#title' => $this->t('CSV delimiter'),
      '#type' => 'select',
      '#options' => [';', ','], 
      '#default_value' => $delimiter_default_value     
    );      

    $form['importdata']['email_column'] = [
      '#title' => $this->t('Email column name'),
      '#type' => 'textfield',
      '#description' => $this->t('Enter the exact column name from which to import email addresses.'),
      '#required' => TRUE,
      '#default_value' => $email_column_default_value 
    ];   

    $form['invite_messages'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Invitee Messages'),
      '#collapsible' => FALSE,
      '#collapsed' => TRUE,
    ];

    /*
    $elements = $this->eventInviteFlowService->getEventInviteMessageFormElements();
    foreach ($elements as $key => $element) {
      $form['invite_messages'][$key] = [
        '#type' => $element['type'],
        '#title' => $element['title'],
        '#required' => $element['required'],
        '#default_value' => $element['default_value']
      ];
    }
    */
 

    $form['event'] = [
      '#type' => 'hidden',
      '#value' => $this->routeMatch->getRawParameter('node'),
    ];

    $form['actions']['#type'] = 'actions';

    $form['actions']['submit_cancel'] = [
      '#type' => 'submit',
      '#weight' => 999,
      '#value' => $this->t('Back to event'),
      '#submit' => [[$this, 'cancelForm']],
      '#limit_validation_errors' => [],
    ];

    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Send your invite(s) by email'),
      '#attributes' => [
        'class' => [
          'btn-primary',
          'btn-raised',
          'button--primary'
        ]
      ]
    ];    

    // We should prevent invite enrollments if social_event_max_enroll is
    // enabled and there are no left spots.
    if ($this->moduleHandler->moduleExists('social_event_max_enroll')) {
      if (
        $node instanceof NodeInterface &&
        $this->eventMaxEnrollService->isEnabled($node) &&
        $this->eventMaxEnrollService->getEnrollmentsLeft($node) === 0
      ) {
        $form['actions']['submit']['#attributes'] = [
          'disabled' => 'disabled',
          'title' => $this->t('There are no spots left'),
        ];
      }
    }

    return $form;
  }

  /**
   * Cancel form taking you back to an event.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function cancelForm(array &$form, FormStateInterface $form_state) {
    $form_state->setRedirect('view.event_manage_enrollments.page_manage_enrollments', [
      'node' => $this->routeMatch->getRawParameter('node'),
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {

    $delimiter = $form_state->getValue('delimiter');
    $csvfile = $form_state->getValue('csvfile');
    $email_column_name = $form_state->getValue('email_column');


    if (empty($csvfile)) {
      $form_state->setErrorByName('csvfile', $this->t('You have to provide a text or upload a file!'));    
    }
    else {

      if (!empty($csvfile) && !empty($email_column_name)) {

        if ($delimiter == '0') {
          $delimiter = ';';
        } else {
          $delimiter = ',';
        }
    
        if ($handle = fopen($csvfile, 'r')) {
          
          if ($headers = fgetcsv($handle, 4096, $delimiter)) {   
          
            if (!in_array($email_column_name,$headers)) {
              $form_state->setErrorByName('email_column', $this->t('No Email field available'));
            }  
    
          }
          fclose($handle);
        }
        else {
          $form_state->setErrorByName('csvfile', $this->t('Unable to read uploaded file @filepath', ['@filepath' => $csvupload]));
        }
  
      }


    }


    
    



  }

  /**
   * Validate the file upload.
   */
  public static function validateFileupload(&$element, FormStateInterface $form_state, &$complete_form) {

    $validators = [
      'file_validate_extensions' => ['csv'],
    ];

    // @TODO: File_save_upload will probably be deprecated soon as well.
    // @see https://www.drupal.org/node/2244513.
    if ($file = file_save_upload('csvfile', $validators, FALSE, 0, FileSystemInterface::EXISTS_REPLACE)) {

      // The file was saved using file_save_upload() and was added to the
      // files table as a temporary file. We'll make a copy and let the
      // garbage collector delete the original upload.
      $csv_dir = 'temporary://csvfile';
      $directory_exists = \Drupal::service('file_system')
        ->prepareDirectory($csv_dir, FileSystemInterface::CREATE_DIRECTORY);

      if ($directory_exists) {
        $destination = $csv_dir . '/' . $file->getFilename();
        if (\Drupal::service('file.repository')
              ->copy($file, $destination, FileSystemInterface::EXISTS_REPLACE)) {
          $form_state->setValue('csvfile', $destination);
        }
        else {
          $form_state->setErrorByName('enroll_invite_import', t('Unable to copy upload file to @dest', ['@dest' => $destination]));
        }
      }
    }
  }  

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {

    parent::submitForm($form, $form_state);

    $email_column = $form_state->getValue('email_column');
    $delimiter = $form_state->getValue('delimiter');
    $nid = $form_state->getValue('event');

    $params['email_column'] = $email_column;
    $params['delimiter'] = $delimiter;

    $tempstore = $this->tempStoreFactory->get('social_event_invite_flow_enroll_invite_upload_form_values');
    try {
      $tempstore->set('params', $params);
    }
    catch (\Exception $error) {
      $this->loggerFactory->get('event_invite_form_values')->alert(t('@err', ['@err' => $error]));
      $this->messenger->addWarning(t('Unable to proceed, please try again.'));
    }


    // BOM as a string for comparison.
    $bom = "\xef\xbb\xbf";

    $csvfile = $form_state->getValue('csvfile');
  
    $delimiter = $form_state->getValue('delimiter');

    if ($delimiter == '0') {
      $delimiter = ';';
    } else {
      $delimiter = ',';
    }

    // Prepare batch.
    $batch = [
      'title'            => $this->t('Prepare sending emails from CSV ...'),
      'operations'       => [],
      'init_message'     => $this->t('Prepare sending emails.'),
      'progress_message' => $this->t('Processed @current out of @total.'),
      'error_message'    => $this->t('An error occurred during processing'),
      'finished'         => '\Drupal\social_event_invite_flow\Service\SendEmails::csvUploadFinished'
    ];

    if ($handle = fopen($csvfile, 'r')) {

      // Progress file pointer and get first 3 characters to compare to the BOM string.
      if (fgets($handle, 4) !== $bom) {
        // BOM not found - rewind pointer to start of file.
        rewind($handle);
      }

      $batch['operations'][] = [
        '\Drupal\social_event_invite_flow\Service\SendEmails::csvUploadRememberFilename',
        [$csvfile]
      ];      

      $counter = 0;
    
      while ($line = fgetcsv($handle, 4096, $delimiter)) {    

        //\Drupal::logger('debug')->debug('count line numbers: <pre><code>' . print_r($counter, TRUE) . '</code></pre>');

        if ( $counter === 0 ) {
          $email_key = array_search($email_column, $line);
          //\Drupal::logger('debug')->debug('Line number: <pre><code>' . print_r($line, TRUE) . '</code></pre>');
        }
        else {
          $email = $line[$email_key];
          //\Drupal::logger('debug')->debug('LINE: <pre><code>' . print_r($line[$email_key], TRUE) . '</code></pre>');
          // Use base64_encode to ensure we don't overload the batch
          // processor by stuffing complex objects into it.                    
          $batch['operations'][] = [
            '\Drupal\social_event_invite_flow\Service\SendEmails::csvUploadLine',
            [$line,$email,$nid]
          ];          


        }        

        $counter++;

      }         

      fclose($handle);

    }   

    batch_set($batch);
  
  

  }

  /**
   * Returns access to the invite page.
   *
   * @param \Drupal\node\NodeInterface $node
   *   The node entity.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The currently logged in account.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access results.
   */
  public function inviteAccess(NodeInterface $node, AccountInterface $account) {
    // Anonymous users should not have the possibility to invite users.
    if ($account->isAnonymous()) {
      return AccessResult::forbidden();
    }

    // Allow for event managers/organizers.
    if (social_event_manager_or_organizer()) {
      return AccessResult::allowed();
    }

    // Disable access for non-enrolled users, invite by users was disabled in
    // the event invite settings, enrolment is disabled for this event or event
    // is visible only for group members.
    $event_invite_settings = $this->config('social_event_invite.settings');
    $enrollment = $this->entityTypeManager->getStorage('event_enrollment')
      ->loadByProperties([
        'status' => TRUE,
        'field_account' => $account->id(),
        'field_event' => $node->id(),
        'field_enrollment_status' => '1',
      ]);
    if (
      !$event_invite_settings->get('invite_by_users') ||
      !($node instanceof Event && $node->isEnrollmentEnabled()) ||
      empty($enrollment) ||
      $node->get('field_content_visibility')->getString() === 'group'
    ) {
      return AccessResult::forbidden();
    }

    // Allow sharing/invites for users only if allowed by the event manager.
    if (
      $node->hasField('field_event_send_invite_by_user') &&
      !$node->get('field_event_send_invite_by_user')->isEmpty() &&
      $node->get('field_event_send_invite_by_user')->getString() === '1'
    ) {
      return AccessResult::allowed();
    }

    return AccessResult::neutral();
  }

}

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

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