You are here

class ImporterService in Hierarchical Taxonomy Import 8

Class ImporterService.

Hierarchy

Expanded class hierarchy of ImporterService

1 file declares its use of ImporterService
TaxonomyImporterForm.php in src/Form/TaxonomyImporterForm.php
1 string reference to 'ImporterService'
hierarchical_taxonomy_importer.services.yml in ./hierarchical_taxonomy_importer.services.yml
hierarchical_taxonomy_importer.services.yml
1 service uses ImporterService
hierarchical_taxonomy_importer.importer in ./hierarchical_taxonomy_importer.services.yml
Drupal\hierarchical_taxonomy_importer\services\ImporterService

File

src/services/ImporterService.php, line 12

Namespace

Drupal\hierarchical_taxonomy_importer\services
View source
class ImporterService {
  const SAME_PARENT = 0;
  const DIFFERENT_PARENT = 1;
  const PREVIOUS_PARENT = -1;

  /**
   * Drupal\Core\Entity\EntityTypeManager definition.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  protected $entityTypeManager;
  protected $connection;

  /**
   * Constructs a new ImporterService object.
   */
  public function __construct(EntityTypeManager $entity_type_manager, Connection $connection) {
    $this->entityTypeManager = $entity_type_manager;
    $this->connection = $connection;
  }

  /**
   *
   * @param string $vid
   *   Vocabulary ID to import terms.
   * @param mixed $data
   *   Array structure with values to import as terms.
   * @param int $count
   *   Counter for total number of records checking to stop the execution.
   * @param int $row
   *   Current row number for CSV row.
   * @param int $pointer
   *   Current Column Pointer.
   * @param mixed $parent
   *   Parent TID for term being created.
   * @param mixed $tag
   *   This is a flag used for checking if there is a record on next level,
   *   same level or on top level.
   *
   * @return mixed
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function import($vid, $data, $count = 0, $row = 0, $pointer = 0, $parent = 0, $tag = 1) {

    // If all levels of a parents have been traversed and new parent has comeup for
    // import then reset the levels counter back to 0 for hierarhichal connect.
    if (!empty($data[$row][0])) {
      $pointer = 0;
      $parent = 0;
    }

    // If all rows have been traversed then exit.
    if ($count >= count($data)) {
      return;
    }

    // Returns the index of csv column has a value in a current record row.
    $pointer = $this
      ->getIndexOfNonNullValues($data[$row]);

    // If pointer is null then return null.
    if (is_null($pointer)) {
      return;
    }

    // Current Column value.
    $term_name = $data[$row][$pointer];

    // Searching for existing term.
    // It finds pointer for levels and breaks upon finding it.
    // If not empty columns value then asking it's index to the current pointer
    // and break.
    // Assigning current offset where a record resides.
    $parent_term_name = "";

    // Parent Row for the current record being read.
    $parent_row = $this
      ->getParentRow($data, $row, $pointer);

    // This checks for the parent row.
    if ($parent_row >= 0 && $pointer > 0) {
      $parent_term_name = $data[$parent_row][$pointer - 1];

      // This is the parent term name of currently processed taxonomy term.
      $csv_tree = $this
        ->getParentTree($data, $row, $pointer);

      // If parent_term is not empty then fetch the parent term's information.
      if (!empty($parent_term_name)) {

        // All terms with the same name as the parent in csv.
        $matching_parents = $this->entityTypeManager
          ->getStorage('taxonomy_term')
          ->loadByProperties([
          'vid' => $vid,
          'name' => $parent_term_name,
        ]);
        $parent_tree = [];

        // Get all parents with the same name as the supposed parent and construct a list of term names.
        foreach ($matching_parents as $mp) {
          $term_list = $this->entityTypeManager
            ->getStorage('taxonomy_term')
            ->loadAllParents($mp
            ->id());
          foreach ($term_list as $term) {
            $parent_tree[$mp
              ->id()][] = $term
              ->getName();
          }
        }
        foreach ($parent_tree as $parent_id => $children_list) {
          if ($parent_tree[$parent_id] == $csv_tree) {
            $parent = $parent_id;
          }
        }
      }
    }

    // This will be used when current term is being added or generated on same level.
    $original_parent = $parent;
    $parent = $this
      ->updateActualParent($vid, $term_name, $parent, $tag);

    // This works when system progress to the next level and finds values for that.
    if (!empty($data[$row + 1][$pointer + 1])) {
      return $this
        ->import($vid, $data, $count + 1, $row + 1, $pointer + 1, $parent, $this::DIFFERENT_PARENT);
    }

    // This works when system progress to the same level for current parent.
    if (!empty($data[$row + 1][$pointer])) {
      return $this
        ->import($vid, $data, $count + 1, $row + 1, $pointer, $original_parent, $this::SAME_PARENT);
    }

    // If none of the conditions matched above, then it traverses back by levelling backwards.
    return $this
      ->import($vid, $data, $count + 1, $row + 1, $pointer - 1, $parent, $this::PREVIOUS_PARENT);
  }

  /**
   * This method returns the index on non-null values in Array.
   *
   * @param mixed $data
   *
   * @return mixed
   */
  public function getIndexOfNonNullValues($data) {

    // This gives the index of column in CSV that would be created as a new
    // taxonomy term.
    if (!empty($data) && !is_null($data)) {

      // Return the column after removing null or blanks values from a row.
      $keys = array_keys(array_diff($data, [
        " ",
        "",
      ]));
      return !empty($data) ? array_shift($keys) : 0;
    }
    return 0;
  }

  /**
   * Returns all parents of current term.
   *
   * @param $data
   * @param $row
   * @param $pointer
   *
   * @return array
   */
  public function getParentTree($data, $row, $pointer) {
    $tree = [];
    $iterator = $row;
    $level = $pointer - 1;
    while ($level >= 0 && $iterator >= 0) {
      if (!empty($data[$iterator][$level])) {
        $tree[] = $data[$iterator][$level];
        $level -= 1;
      }
      $iterator -= 1;
    }
    return $tree;
  }

  /**
   * This method gives the index of parent row of a term being imported as a
   * taxonomy term.
   *
   * @param mixed $data
   *   CSV Data as an array.
   * @param numeric $parent_row
   *   Taxonomy term's parent offset.
   * @param numeric $pointer
   *   Imported term's offset.
   * @return numeric
   *   This returns the parent offset after calculations.
   */
  protected function getParentRow($data, $parent_row, $pointer) {

    // Fetching parent row.
    while (empty($data[$parent_row][$pointer - 1]) && $parent_row > 0) {
      $parent_row = $parent_row - 1;
    }
    return $parent_row;
  }

  /**
   * This method adds a new taxonomy term.
   *
   * @param string $vid
   *   Vocabulary ID.
   * @param string $term
   *   Term name
   * @param numeric $parent
   *   Parent Term ID.
   * @return numeric
   *   Newly create terms ID.
   */
  protected function createNewTerm($vid, $term, $parent) {
    try {

      // Adding a new term to the TAxonomy..
      $new_term = Term::create([
        'name' => $term,
        'parent' => $parent,
        'vid' => $vid,
      ]);
      $new_term
        ->save();
    } catch (\Exception $ex) {
      \Drupal::logger('hti')
        ->error($ex
        ->getMessage());
      return;
    }

    // Newly entered Term ID.
    return $new_term
      ->id();
  }

  /**
   * This method calculates upon CSV data and finds out actual parent.
   *
   * @param string $vid
   *   Vocabulary ID.
   * @param string $term_name
   *   current taxonomy term name.
   * @param numeric $parent
   *   Parent ID
   * @param numeric $tag
   *   This tells that if next term is to import is on same parent level, new parent
   *   level or on nested levels backward.
   * @return numeric
   *   Parent Term ID.
   */
  protected function updateActualParent($vid, $term_name, $parent, $tag) {
    $new_term_id = $this
      ->createNewTerm($vid, $term_name, $parent);

    // When importing sibling terms
    if ($tag !== $this::SAME_PARENT) {
      $parent = $new_term_id;
    }
    return $parent;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ImporterService::$connection protected property
ImporterService::$entityTypeManager protected property Drupal\Core\Entity\EntityTypeManager definition.
ImporterService::createNewTerm protected function This method adds a new taxonomy term.
ImporterService::DIFFERENT_PARENT constant
ImporterService::getIndexOfNonNullValues public function This method returns the index on non-null values in Array.
ImporterService::getParentRow protected function This method gives the index of parent row of a term being imported as a taxonomy term.
ImporterService::getParentTree public function Returns all parents of current term.
ImporterService::import public function
ImporterService::PREVIOUS_PARENT constant
ImporterService::SAME_PARENT constant
ImporterService::updateActualParent protected function This method calculates upon CSV data and finds out actual parent.
ImporterService::__construct public function Constructs a new ImporterService object.