/** * @param $field * @param $upState * @param int $index * @return mixed */ protected function generateObject($field, $upState, $index = 0) { $className = $field->dataType; $object = \QuickDataObject::create($className); $state = $upState->down($field, $object, $index); foreach ($field->fields as $objectField) { if ($objectField->ignore) { continue; } $values = $objectField->provider->generate($objectField, $state); if (!empty($values)) { $object->setField($objectField->fieldName, $values[0]); } } $writer = $this->writer; $hasOneIsAncestor = false; $afterHasOneExists = new \OnAfterExists(function () use($object, $field, $writer) { $writer->write($object, $field); }); foreach ($field->hasOne as $hasOneField) { if ($hasOneField->ignore) { continue; } $values = $hasOneField->provider->generate($hasOneField, $state); if (!empty($values[0])) { $value = $values[0]; $relation = $hasOneField->fieldName; $hasOneIsAncestor = $hasOneIsAncestor || $state->isAncestor($value); $afterHasOneExists->addCondition($values[0], function ($value) use($object, $relation) { $object->setField($relation, $value->getField('ID')); }); } } foreach ($field->manyMany as $manyManyField) { if ($manyManyField->ignore) { continue; } $values = $manyManyField->provider->generate($manyManyField, $state); if (!empty($values)) { $relation = $manyManyField->methodName; $afterExists = new \OnAfterExists(function () use($object, $relation, $values, $writer) { $writer->writeManyMany($object, $relation, $values); }); $afterExists->addCondition($object); $afterExists->addCondition($values); } } foreach ($field->hasMany as $hasManyField) { if ($hasManyField->ignore) { continue; } $values = $hasManyField->provider->generate($hasManyField, $state); if (!empty($values)) { $object->onAfterExistsCallback(function ($object) use($values, $writer, $hasManyField) { $relation = ''; foreach ($values[0]->has_one() as $fieldName => $className) { if ($object instanceof $className) { $relation = $fieldName . 'ID'; } } if ($relation) { $id = $object->getField('ID'); foreach ($values as $value) { // set has_many field to object ID $value->setField($relation, $id); $writer->write($value, $hasManyField); } } }); } } // only write object when it won't already be written when has_one fields are written // unless there is a dependency write loop, then write first // don't write has many fields since they will be written once their owner is written if ((!$afterHasOneExists->count() || $hasOneIsAncestor) && $field->fieldType !== Field::FT_HAS_MANY) { $this->writer->write($object, $field); } return $object; }
/** * */ public function testWriteManyMany_SetChildrenForParent_RelationWritten() { $parent = new Human(); $parent->Name = 'Bob'; $children = array(); for ($i = 0; $i < 5; $i++) { $child = new Child(); $child->Name = 'Soldier #' . $i; $children[] = $child; } $writer = new \BatchedWriter(); $afterExists = new \OnAfterExists(function () use($writer, $parent, $children) { $writer->writeManyMany($parent, 'Children', $children); }); $afterExists->addCondition($parent); $afterExists->addCondition($children); $writer->write(array($parent)); $writer->write($children); $writer->finish(); $parent = Human::get()->first(); $this->assertEquals(5, $parent->Children()->Count()); }
/** * */ public function testWriteManyMany_WriteManyManyObjects_ObjectsAccessibleFromManyMany() { $this->markTestIncomplete('Need silverstripe-batchwrite compatibility.'); $batchSizes = array(10, 30, 100, 300); foreach ($batchSizes as $batchSize) { $writer = new BatchedSeedWriter($batchSize); for ($i = 0; $i < 10; $i++) { $owner = new Human(); $owner->Name = 'Mr bean ' . $i; for ($j = 0; $j < 10; $j++) { $dog = new Dog(); $dog->Name = 'Walnut ' . $i; $afterExists = new \OnAfterExists(function () use($owner, $dog, $writer) { $writer->writeManyMany($owner, 'Pets', $dog); }); $afterExists->addCondition($owner); $afterExists->addCondition($dog); $writer->write($dog, $this->createField()); } $writer->write($owner, $this->createField()); } $writer->finish(); $owners = Human::get(); $dogs = Dog::get(); $this->assertEquals(10, $owners->Count()); $this->assertEquals(100, $dogs->Count()); foreach ($owners as $owner) { $this->assertEquals(10, $owner->Pets()->Count()); } $writer->delete($owners); $writer->delete($dogs); $writer->finish(); } }
/** * */ public function testOnAfterExists_ArrayCondition_CalledBack() { $parent = new Human(); $parent->Name = 'Bob'; $children = array(); for ($i = 0; $i < 5; $i++) { $child = new Child(); $child->Name = 'Soldier #' . $i; $children[] = $child; } $batch = new \Batch(); $afterExists = new \OnAfterExists(function () use($batch, $parent, $children) { $sets = array(); foreach ($children as $child) { $sets[] = array($parent, 'Children', $child); } $batch->writeManyMany($sets); }); $afterExists->addCondition($parent); $afterExists->addCondition($children); $batch->write(array($parent)); $batch->write($children); $parent = Human::get()->first(); $this->assertEquals(5, $parent->Children()->Count()); }