/** * Hydrate one entity and its associated data. * * @param array $data The data to hydrate. * @param array $include The associations to include. * @return \Cake\ORM\Entity * @see \Cake\ORM\Table::newEntity() */ public function one(array $data, array $include = []) { $propertyMap = $this->_buildPropertyMap($include); $schema = $this->_table->schema(); $tableName = $this->_table->alias(); $entityClass = $this->_table->entityClass(); $entity = new $entityClass(); $entity->source($this->_table->alias()); if (isset($data[$tableName])) { $data = $data[$tableName]; } $properties = []; foreach ($data as $key => $value) { $columnType = $schema->columnType($key); if (isset($propertyMap[$key])) { $assoc = $propertyMap[$key]['association']; $nested = $propertyMap[$key]['nested']; $value = $this->_marshalAssociation($assoc, $value, $nested); } elseif ($columnType) { $converter = Type::build($columnType); $value = $converter->marshal($value); } $properties[$key] = $value; } $entity->set($properties); return $entity; }
public function setUp() { parent::setUp(); $this->entityMap = ['Authors' => Author::class, 'Users' => User::class, 'Editors' => Editor::class, 'Readers' => Reader::class, 'Subscribers' => Reader::class, '' => User::class]; $this->table = TableRegistry::get('Users'); $this->table->entityClass(User::class); $authors = TableRegistry::get('Authors', ['table' => 'users']); $editors = TableRegistry::get('Editors', ['table' => 'users']); $readers = TableRegistry::get('Readers', ['table' => 'users']); $authors->addBehavior('Robotusers/TableInheritance.Sti'); $editors->addBehavior('Robotusers/TableInheritance.Sti'); $readers->addBehavior('Robotusers/TableInheritance.Sti'); $this->table->addBehavior('Robotusers/TableInheritance.StiParent', ['discriminatorMap' => ['Authors' => 'Authors', 'Editors' => 'Editors'], 'tableMap' => ['Readers' => ['Readers', 'Subscribers']]]); $authors->entityClass(Author::class); $editors->entityClass(Editor::class); $readers->entityClass(Reader::class); }
/** * Hydrate one entity and its associated data. * * ### Options: * * - validate: Set to false to disable validation. Can also be a string of the validator ruleset to be applied. * Defaults to true/default. * - associated: Associations listed here will be marshalled as well. Defaults to null. * - fieldList: A whitelist of fields to be assigned to the entity. If not present, * the accessible fields list in the entity will be used. Defaults to null. * - accessibleFields: A list of fields to allow or deny in entity accessible fields. Defaults to null * - forceNew: When enabled, belongsToMany associations will have 'new' entities created * when primary key values are set, and a record does not already exist. Normally primary key * on missing entities would be ignored. Defaults to false. * * The above options can be used in each nested `associated` array. In addition to the above * options you can also use the `onlyIds` option for HasMany and BelongsToMany associations. * When true this option restricts the request data to only be read from `_ids`. * * ``` * $result = $marshaller->one($data, [ * 'associated' => ['Tags' => ['onlyIds' => true]] * ]); * ``` * * @param array $data The data to hydrate. * @param array $options List of options * @return \Cake\ORM\Entity * @see \Cake\ORM\Table::newEntity() */ public function one(array $data, array $options = []) { list($data, $options) = $this->_prepareDataAndOptions($data, $options); $propertyMap = $this->_buildPropertyMap($options); $schema = $this->_table->schema(); $primaryKey = (array) $this->_table->primaryKey(); $entityClass = $this->_table->entityClass(); $entity = new $entityClass(); $entity->source($this->_table->registryAlias()); if (isset($options['accessibleFields'])) { foreach ((array) $options['accessibleFields'] as $key => $value) { $entity->accessible($key, $value); } } $marshallOptions = []; if (isset($options['forceNew'])) { $marshallOptions['forceNew'] = $options['forceNew']; } $errors = $this->_validate($data, $options, true); $properties = []; foreach ($data as $key => $value) { if (!empty($errors[$key])) { if ($entity instanceof InvalidPropertyInterface) { $entity->invalid($key, $value); } continue; } $columnType = $schema->columnType($key); if (isset($propertyMap[$key])) { $assoc = $propertyMap[$key]['association']; $value = $this->_marshalAssociation($assoc, $value, $propertyMap[$key] + $marshallOptions); } elseif ($value === '' && in_array($key, $primaryKey, true)) { // Skip marshalling '' for pk fields. continue; } elseif ($columnType) { $converter = Type::build($columnType); $value = $converter->marshal($value); } $properties[$key] = $value; } if (!isset($options['fieldList'])) { $entity->set($properties); $entity->errors($errors); return $entity; } foreach ((array) $options['fieldList'] as $field) { if (array_key_exists($field, $properties)) { $entity->set($field, $properties[$field]); } } $entity->errors($errors); return $entity; }
/** * Hydrate one entity and its associated data. * * ### Options: * * - validate: Set to false to disable validation. Can also be a string of the validator ruleset to be applied. * Defaults to true/default. * - associated: Associations listed here will be marshalled as well. Defaults to null. * - fieldList: A whitelist of fields to be assigned to the entity. If not present, * the accessible fields list in the entity will be used. Defaults to null. * - accessibleFields: A list of fields to allow or deny in entity accessible fields. Defaults to null * - forceNew: When enabled, belongsToMany associations will have 'new' entities created * when primary key values are set, and a record does not already exist. Normally primary key * on missing entities would be ignored. Defaults to false. * * The above options can be used in each nested `associated` array. In addition to the above * options you can also use the `onlyIds` option for HasMany and BelongsToMany associations. * When true this option restricts the request data to only be read from `_ids`. * * ``` * $result = $marshaller->one($data, [ * 'associated' => ['Tags' => ['onlyIds' => true]] * ]); * ``` * * @param array $data The data to hydrate. * @param array $options List of options * @return \Cake\ORM\Entity * @see \Cake\ORM\Table::newEntity() */ public function one(array $data, array $options = []) { list($data, $options) = $this->_prepareDataAndOptions($data, $options); $primaryKey = (array) $this->_table->primaryKey(); $entityClass = $this->_table->entityClass(); $entity = new $entityClass(); $entity->source($this->_table->registryAlias()); if (isset($options['accessibleFields'])) { foreach ((array) $options['accessibleFields'] as $key => $value) { $entity->accessible($key, $value); } } $errors = $this->_validate($data, $options, true); $options['isMerge'] = false; $propertyMap = $this->_buildPropertyMap($data, $options); $properties = []; foreach ($data as $key => $value) { if (!empty($errors[$key])) { if ($entity instanceof InvalidPropertyInterface) { $entity->invalid($key, $value); } continue; } if ($value === '' && in_array($key, $primaryKey, true)) { // Skip marshalling '' for pk fields. continue; } elseif (isset($propertyMap[$key])) { $properties[$key] = $propertyMap[$key]($value, $entity); } else { $properties[$key] = $value; } } if (!isset($options['fieldList'])) { $entity->set($properties); $entity->errors($errors); return $entity; } foreach ((array) $options['fieldList'] as $field) { if (array_key_exists($field, $properties)) { $entity->set($field, $properties[$field]); } } $entity->errors($errors); return $entity; }
/** * Modifies the results from a table find in order to merge full translation records * into each entity under the `_translations` key * * @param \Cake\Datasource\ResultSetInterface $results Results to modify. * @return \Cake\Collection\Collection */ public function groupTranslations($results) { return $results->map(function ($row) { $translations = (array) $row->get('_i18n'); $grouped = new Collection($translations); $result = []; foreach ($grouped->combine('field', 'content', 'locale') as $locale => $keys) { $entityClass = $this->_table->entityClass(); $translation = new $entityClass($keys + ['locale' => $locale], ['markNew' => false, 'useSetters' => false, 'markClean' => true]); $result[$locale] = $translation; } $options = ['setter' => false, 'guard' => false]; $row->set('_translations', $result, $options); unset($row['_i18n']); $row->clean(); return $row; }); }
/** * Hydrate one entity and its associated data. * * ### Options: * * * associated: Associations listed here will be marshalled as well. * * fieldList: A whitelist of fields to be assigned to the entity. If not present, * the accessible fields list in the entity will be used. * * accessibleFields: A list of fields to allow or deny in entity accessible fields. * * @param array $data The data to hydrate. * @param array $options List of options * @return \Cake\ORM\Entity * @see \Cake\ORM\Table::newEntity() */ public function one(array $data, array $options = []) { $propertyMap = $this->_buildPropertyMap($options); $schema = $this->_table->schema(); $tableName = $this->_table->alias(); $entityClass = $this->_table->entityClass(); $entity = new $entityClass(); $entity->source($this->_table->alias()); if (isset($data[$tableName])) { $data = $data[$tableName]; } if (isset($options['accessibleFields'])) { foreach ((array) $options['accessibleFields'] as $key => $value) { $entity->accessible($key, $value); } } $primaryKey = $schema->primaryKey(); $properties = []; foreach ($data as $key => $value) { $columnType = $schema->columnType($key); if (isset($propertyMap[$key])) { $assoc = $propertyMap[$key]['association']; $value = $this->_marshalAssociation($assoc, $value, $propertyMap[$key]); } elseif ($value === '' && in_array($key, $primaryKey, true)) { // Skip marshalling '' for pk fields. continue; } elseif ($columnType) { $converter = Type::build($columnType); $value = $converter->marshal($value); } $properties[$key] = $value; } if (!isset($options['fieldList'])) { $entity->set($properties); return $entity; } foreach ((array) $options['fieldList'] as $field) { if (isset($properties[$field])) { $entity->set($field, $properties[$field]); } } return $entity; }
/** * Modifies the results from a table find in order to merge full version records * into each entity under the `_versions` key * * @param \Cake\Datasource\ResultSetInterface $results Results to modify. * @return \Cake\Collection\Collection */ public function groupVersions($results) { $property = $this->versionAssociation()->property(); return $results->map(function ($row) use($property) { $versionField = $this->_config['versionField']; $versions = (array) $row->get($property); $grouped = new Collection($versions); $result = []; foreach ($grouped->combine('field', 'content', 'version_id') as $versionId => $keys) { $entityClass = $this->_table->entityClass(); $version = new $entityClass($keys + [$versionField => $versionId], ['markNew' => false, 'useSetters' => false, 'markClean' => true]); $result[$versionId] = $version; } $options = ['setter' => false, 'guard' => false]; $row->set('_versions', $result, $options); unset($row[$property]); $row->clean(); return $row; }); }
/** * Constructor hook method. * * Implement this method to avoid having to overwrite * the constructor and call parent. * * @param array $config The configuration array this behavior is using. * @return void */ public function initialize(array $config) { if ($this->_config['length'] === null) { $length = $this->_table->schema()->column($this->_config['field'])['length']; $this->_config['length'] = $length ?: 0; } $label = $this->_config['label'] = (array) $this->_config['label']; if ($this->_table->behaviors()->has('Translate')) { $this->_config['length'] = false; } if ($this->_config['length']) { foreach ($label as $field) { $alias = $this->_table->alias(); if (strpos($field, '.')) { list($alias, $field) = explode('.', $field); if (!$this->_table->{$alias}->hasField($field)) { throw new Exception('(SluggedBehavior::setup) model ' . $this->_table->{$alias}->name . ' is missing the field ' . $field . ' (specified in the setup for model ' . $this->_table->name . ') '); } } elseif (!$this->_table->hasField($field) && !method_exists($this->_table->entityClass(), '_get' . Inflector::classify($field))) { throw new Exception('(SluggedBehavior::setup) model ' . $this->_table->name . ' is missing the field ' . $field . ' specified in the setup.'); } } } }
/** * Tests setting a entity class object using the setter method * * @return void */ public function testSetEntityClass() { $table = new Table(); $class = '\\' . $this->getMockClass('\\Cake\\ORM\\Entity'); $table->entityClass($class); $this->assertEquals($class, $table->entityClass()); }