<?php

/**
 * IsisImporterEntities: provides ISIS import methods for importing data
 * into model entities.
 */
class sfIsisImporterEntities {
  /**
   * Constructor.
   */ 
  public function __construct($isis) {
    $this->isis = $isis;
  }

  /**
   * Get the entity name from a subfield.
   *
   * @param  string $subfield Subfield name
   * @return string           Genre name
   */
  static function entityName($subfield)
  {
    return ucfirst($subfield);
  }  

  /**
   * Import a single field into a model.
   *
   * @param object $model    Model
   * @param array  $field    Field data from ISIS database schema
   * @param int    $row      Row number
   */
  public function addMain(&$model, $field, $row = 0)
  {
    $value = $this->isis->filterBrackets($this->isis->getMainItem($field, $row));

    if ($value != null)
    {
      $map   = $this->isis->getMap($field);
      $model->{$map}($value);
    }
  }

  /**
   * Import a single subfield into a model.
   *
   * @param object $model    Model
   * @param array  $field    Field data from ISIS database schema
   * @param string $subfield Subfield name
   * @param int    $row      Row number
   */
  public function addSubfield(&$model, $field, $subfield, $row = 0)
  {
    $value = $this->isis->filterBrackets($this->isis->getSubfield($field, $subfield, $row));

    if ($value != null)
    {
      $map   = $this->isis->getMap($field, $subfield);
      $model->{$map}($value);
    }
  }

  /**
   * Import all subfields from a field row into a model.
   *
   * @param object $model Model
   * @param array  $field Field data from ISIS database schema
   * @param int    $row   Row number
   */
  public function addSubfields(&$model, $field, $row = 0)
  {
    foreach ($this->isis->getSubfieldList($field) as $subfield)
    {
      $this->addSubfield($model, $field, $subfield, $row);
    }
  }

  /**
   * Import single values into the model.
   *
   * Currently undefined mappings for a field/subfield
   * are not saved as we would need to make sure a corresponding
   * field exists in the model. This prevents the map
   * configurations like $map = array('type' => 'value'); to work.
   *
   * As we are importing single values, here we don't care with
   * row numbers as we assume that just the first row should be
   * imported.
   *
   * @param object $model Model object
   * @param array  $field Field data
   */
  public function importValues(&$model, array $field)
  {
    if ($this->isis->fieldHasMap($field))
    {
      $this->addMain($model, $field);
    }

    foreach ($this->isis->getSubfieldList($field) as $subfield)
    {
      if ($this->isis->subfieldHasMap($field, $subfield))
      {
        $this->addSubfield($model, $field, $subfield);
      }
    }
  }

  /**
   * Get an existing entity.
   *
   * @param  string $entity Entity name
   * @param  string $value  Value to search for
   * @param  string $by     Field to search $value
   * @return mixed          Entity data or false
   */
  public function getEntity($entity, $value, $by = 'name')
  {
    $findby = 'findOneBy'. ucfirst($by);
    $data   = Doctrine_Core::getTable($entity)->{$findby}($value);

    if ($data)
    {
      return $data;
    }

    return false;
  }

  /**
   * Add a new entity into the database if needed, returning
   * the corresponding object.
   *
   * @param  string $entity Entity name
   * @param  string $name   Name value
   * @param  string $key    Value key
   * @return object         Entity data
   */
  public function addEntity($entity, $name, $key = 'name')
  {
    $name = $this->entityName($name);
    $data = $this->getEntity($entity, $name, $key);

    if (!$data)
    {
      $this->log("Adding new $entity $name.");
      $data = $this->newEntity($entity, $name, $key);
    }

    return $data;
  }

  /**
   * Add a new entity into the database.
   *
   * @param  string $entity Entity name
   * @param  string $name   Name value
   * @param  string $key    Value key
   * @return object         Entity data
   */
  public function newEntity($entity, $name, $key = 'name')
  {
    $data         = new $entity();
    $data->{$key} = $name;
    $data->save();

    return $data;
  }

  /**
   * Add an element into the database if needed, returning
   * the resulting object.
   *
   * @param  string $entity Entity name
   * @param  string $value  Entity value
   * @return object         Entity data
   */
  public function newOrExisting($entity, $value, $by = 'Name')
  {
    // Check for a null value.
    if ($value == null)
    {
      $this->log("Null element value for $entity.", 'debug');
      return;
    }

    // Get existing element.
    $name    = ($by == 'Name') ? $this->parseName($value) : $value;
    $element = call_user_func(array($entity, 'getBy'. $by), $name);

    // Create new element if needed.
    if (!$element)
    {
      $this->log("Adding new $entity $value.");
      $element = call_user_func(array($entity, 'addBy'. $by), $name);
    }

    return $element;
  }
}