Sunday, November 6, 2016

Drupal 8: Validate a file while uploading via AJAX.

In Drupal 8 file uploading is done beautifully with its builtin AJAX support. Now visitor can upload many dump files into your server. This file uploading also gets entry into database with status 0 ;) Or may be you want to allow validated CSV file to be in server for further process.
Say, User is uploading test.csv file. You are checking the content of CSV file is as per required format and acceptable.
To do so you need to take help of hook function in your .module file. Like
function HOOK_file_validate(FileInterface $file) {
}
Here's the complete code :
use Drupal\file\FileInterface;

/**
 * hook function to check CSV file while uploading
 * $dataRow[0]->Name->string,  $dataRow[1]->Mobile->number
 * @param $file
 * @return array
 *
 */
function osu_studentdataupload_file_validate(FileInterface $file) {
  // Get Type of The Node so that this function validate only the specific.
  $node_type = getNodetypeFromUrl();
  if ($node_type == 'myNodeType') {
      //$file->id;
      // Getting Temp path :: we still don't have fully access to the file
      $filePath = $file->getFileUri();
      //$file->getFilename();
      $errors = [];
      foreach (getCsvFileRow($filePath) as $dataRow) {
        //if (!empty($dataRow[0]) && (1 === preg_match('~[0-9]~', $dataRow[0]))) {
        if (1 === preg_match('~[0-9]~', $dataRow[0])) {
          $errors[] = '"' . $dataRow[0] . '" - has number(s).';
        }
        if ((!empty($dataRow[1])) && (0 === preg_match('~[0-9]~', $dataRow[1]))) {
          $errors[] = '"' . $dataRow[1] . '" - has string.';
        }  
      }
      return $errors;
      }
  }
}

/**
 * Get NodeType from anywhere inside Drupal from Request url.
 *
 * @return string
 * The current node_type.
 *
 */
function getNodetypeFromUrl() {
  // While Creating
  $nodeTypeObj = \Drupal::request()->attributes->all()['node_type'];
  if (is_object($nodeTypeObj)) {
    $node_type = accessProtected($nodeTypeObj, 'type');
  }
  // While Editing
  $nodeObj = \Drupal::request()->attributes->all()['node'];
  if (is_object($nodeObj)) {
    $nodeObjToArray = (array) $nodeObj;
    $prefix = chr(0) . '*' . chr(0);
    $node_type = $nodeObjToArray[$prefix . 'values']['type']['x-default'];
  }
  return $node_type;
}

/**
 * Access protected property of Object by using ReflectionClass.
 *
 * @param Object
 * An Object containing public/restricted property.
 * @param string
 * The name of the property need in return.
 *
 * @return
 * Value of the required property.
 *
 */
function accessProtected($obj, $prop) {
  $reflection = new ReflectionClass($obj);
  $property = $reflection->getProperty($prop);
  $property->setAccessible(true);
  return $property->getValue($obj);
}

/**
 * CSV File format handler.
 *
 * @param file path
 * A CSV file path to read contents.
 *
 * @return array
 * Array of data of the current line.
 *
 */
function getCsvFileRow($bigDataFile) {
  $handler = fopen($bigDataFile, 'r');
  if ($handler === false) {
    throw new Exception();
  }
  while (feof($handler) === false) {
    yield fgetcsv($handler);
  }
  fclose($handler);
}

1 comment:

  1. Thanks for sharing your thoughts. I really appreciate your efforts and I will be waiting
    for your further post thank you once again.

    ReplyDelete