public function mapValues(&$item, &$values, $ignoreNotExistingValues = false)
{
$setted = [];
$applyColumn = function ($name) use(&$item, &$values, &$setted, &$ignoreNotExistingValues) {
$fieldName = lcfirst($name);
$setted[] = $fieldName;
$fieldValue = @$values[$fieldName];
if (!isset($values[$fieldName]) && $ignoreNotExistingValues) {
return;
}
$fieldName = ucfirst($fieldName);
$set = 'set' . $fieldName;
$methodExist = method_exists($item, $set);
if ($methodExist) {
$item->{$set}($fieldValue);
}
};
$pluralizer = new StandardEnglishPluralizer();
$self = $this;
/**
* @param RelationDefinition $relation
*
* @throws ObjectNotFoundException
* @throws \Exception
*/
$applyRelation = function ($relation) use($self, $pluralizer, &$item, &$values, &$setted, &$ignoreNotExistingValues) {
$fieldName = lcfirst($relation->getName());
$fieldValue = isset($values[$fieldName]) ? $values[$fieldName] : null;
if (!isset($values[$fieldName]) && $ignoreNotExistingValues) {
return;
}
if ($relation->getType() == AbstractStorage::MANY_TO_MANY || $relation->getType() == AbstractStorage::ONE_TO_MANY) {
$name = $pluralizer->getPluralForm($pluralizer->getSingularForm(Tools::underscore2Camelcase($fieldName)));
$setItems = 'set' . $name;
$clearItems = 'clear' . $name;
if (is_array($fieldValue)) {
$foreignQuery = $self->getQueryClass($relation->getForeignObjectKey());
$foreignClass = $self->getPhpName($relation->getForeignObjectKey());
$foreignObjClass = $self->objects->getStorageController($relation->getForeignObjectKey());
if ($relation->getType() == AbstractStorage::ONE_TO_MANY) {
$coll = new ObjectCollection();
$coll->setModel(ucfirst($foreignClass));
if (!is_array($fieldValue)) {
throw new \LogicException(sprintf('Relation `%s` on object %s requires array value, not %s', $relation->getName(), $this->getObjectKey(), gettype($fieldValue)));
}
foreach ($fieldValue as $foreignItem) {
$pk = $self->objects->getObjectPk($relation->getForeignObjectKey(), $foreignItem);
$item2 = null;
if ($pk) {
$propelPk = $self->getPropelPk($pk, $relation->getForeignObjectKey());
$item2 = $foreignQuery->findPk($propelPk);
}
if (!$item2) {
$item2 = new $foreignClass();
}
$item2->fromArray($foreignItem, TableMap::TYPE_CAMELNAME);
$coll[] = $item2;
}
$item->{$setItems}($coll);
} else {
$primaryKeys = array();
if (is_array($fieldValue)) {
foreach ($fieldValue as $value) {
$primaryKeys[] = $foreignObjClass->normalizePrimaryKey($value);
}
}
$propelPks = array();
foreach ($primaryKeys as $primaryKey) {
$propelPks[] = $self->getPropelPk($primaryKey, $relation->getForeignObjectKey());
}
$collItems = $foreignQuery->findPks($propelPks);
$item->{$setItems}($collItems);
}
} elseif ($ignoreNotExistingValues) {
$item->{$clearItems}();
}
}
if ($relation->getType() == AbstractStorage::MANY_TO_ONE || $relation->getType() == AbstractStorage::ONE_TO_ONE) {
if (!$self->tableMap->hasRelation(ucfirst($fieldName))) {
throw new \Exception(sprintf('Relation %s not found in propel object %s (%s)', ucfirst($fieldName), $self->getObjectKey(), $self->getPhpName()));
}
//try to set the local column of the relation directly, when we get only primary keys
$propelRelation = $self->tableMap->getRelation(ucfirst($fieldName));
$localColumns = $propelRelation->getLocalColumns();
$firstColumn = current($localColumns);
$hasPrimaryKey = false;
if (is_array($fieldValue)) {
$foreignColumns = $propelRelation->getForeignColumns();
$firstForeignColumn = current($foreignColumns);
$key = lcfirst($firstForeignColumn->getPhpName());
if (isset($fieldValue[$key])) {
$fieldValue = $fieldValue[$key];
$hasPrimaryKey = true;
}
} else {
$hasPrimaryKey = true;
}
if ($hasPrimaryKey) {
//set local column of foreign key directly
$setter = 'set' . ucfirst($firstColumn->getPhpName());
$item->{$setter}($fieldValue);
} else {
//we got no primary key, so set values at the object directly
$getter = 'get' . ucfirst($relation->getName());
$relatedItem = $item->{$getter}();
if (!$relatedItem) {
$class = $propelRelation->getForeignTable()->getClassName();
$relatedItem = new $class();
$setter = 'set' . ucfirst($relation->getName());
$item->{$setter}($relatedItem);
}
foreach ($fieldValue as $k => $v) {
$relatedItem->{'set' . ucfirst($k)}($v);
}
}
}
};
foreach ($this->getDefinition()->getFields(true) as $field) {
if ($field->isPrimaryKey() && $field->isAutoIncrement()) {
continue;
}
foreach ($field->getFieldType()->getColumns() as $column) {
$applyColumn($column->getName());
}
}
foreach ($this->getDefinition()->getRelations() as $relation) {
$applyRelation($relation);
}
// /*
// * all virtual fields which are not present in the object.
// * Virtual fields are all methods in the model which have a setter.
// * Examples:
// *
// * setPassword => 'password'
// */
// foreach ($values as $fieldName => $fieldValue) {
// $fieldName = lcfirst($fieldName);
// if (in_array($fieldName, $setted)) {
// continue;
// }
//
// $fieldName = ucfirst($fieldName);
// $set = 'set' . $fieldName;
// $methodExist = method_exists($item, $set);
//
// if ($methodExist) {
// $item->$set($fieldValue);
// }
// }
}