/** * Write a component collection property value * * Ie when you write an order, it's implicitly needed to write it's lines * * @param $object object * @param $property Reflection_Property * @param $collection Component[] */ private function writeCollection($object, Reflection_Property $property, $collection) { // old collection $class_name = get_class($object); $old_object = Search_Object::create($class_name); $this->setObjectIdentifier($old_object, $this->getObjectIdentifier($object)); $aop_getter_ignore = Getter::$ignore; Getter::$ignore = false; $old_collection = $property->getValue($old_object); Getter::$ignore = $aop_getter_ignore; $element_class = $property->getType()->asReflectionClass(); /** @var $element_link Class_\Link_Annotation */ $element_link = $element_class->getAnnotation('link'); // collection properties : write each of them $id_set = []; if ($collection) { foreach ($collection as $key => $element) { if (!is_a($element, $element_class->getName())) { $collection[$key] = $element = Builder::createClone($element, $element_class->getName(), [$element_link->getLinkClass()->getCompositeProperty()->name => $element]); } $element->setComposite($object, $property->getAnnotation('foreign')->value); $id = $element_link->value ? $this->getLinkObjectIdentifier($element, $element_link) : $this->getObjectIdentifier($element); if (!empty($id)) { $id_set[$id] = true; } $this->write($element); } } // remove old unused elements foreach ($old_collection as $old_element) { $id = $element_link->value ? $this->getLinkObjectIdentifier($old_element, $element_link) : $this->getObjectIdentifier($old_element); if (!isset($id_set[$id])) { $this->delete($old_element); } } }
/** * Create a clone of the object, using a built class if needed * * @param $object object * @param $class_name string if set, the new object will use the matching built class * this class name must inherit from the object's class * @param $properties_values array some properties values for the cloned object * @param $same_identifier boolean * @return object */ public static function createClone($object, $class_name = null, $properties_values = [], $same_identifier = true) { $class_name = self::className($class_name); $source_class_name = get_class($object); if (!isset($class_name)) { $class_name = self::className($source_class_name); } if ($class_name !== $source_class_name) { // initialises cloned object $clone = self::create($class_name); $destination_class = new Link_Class($class_name); // deactivate AOP if (isset($clone->_)) { $save_aop = $clone->_; unset($clone->_); } // copy official properties values from the source object $properties = (new Reflection_Class($source_class_name))->accessProperties(); foreach ($properties as $property) { if (!isset($save_aop[$property->name])) { $property->setValue($clone, $property->getValue($object)); } } // copy unofficial properties values from the source object (ie AOP properties aliases) // clone collection objects using the destination collection property type $clone_collection = []; foreach (get_object_vars($object) as $property_name => $value) { if ($property_name !== '_' && !isset($properties[$property_name])) { $clone->{$property_name} = $value; if (isset($properties[rtrim($property_name, '_')])) { $property = $properties[rtrim($property_name, '_')]; if ($property->getAnnotation('link') == Link_Annotation::COLLECTION) { $element_class_from = $property->getType()->getElementTypeAsString(); $property = $destination_class->getProperty($property->name); $element_class_to = $property->getType()->getElementTypeAsString(); if ($element_class_to != $element_class_from) { $clone_collection[substr($property_name, 0, -1)] = $element_class_to; } } } } } // reactivate AOP if (isset($save_aop)) { $clone->_ = $save_aop; } foreach ($clone_collection as $property_name => $element_class_to) { $elements = []; foreach ($object->{$property_name} as $key => $element) { $elements[$key] = Builder::createClone($element, $element_class_to, [], $same_identifier); } $clone->{$property_name} = $elements; } // linked class object to link class object : store source object to linked object $destination_class = new Link_Class($class_name); if ($linked_class_name = $destination_class->getLinkedClassName()) { if ($linked_class_name == $source_class_name) { $destination_class->getLinkProperty()->setValue($clone, $object); } } // identify destination object = source object, or disconnect destination object if ($same_identifier) { Dao::replace($clone, $object, false); } else { Dao::disconnect($clone); } } else { $clone = clone $object; } // copy added properties values to the cloned object if ($properties_values) { $properties = (new Reflection_Class($class_name))->accessProperties(); foreach ($properties_values as $property_name => $value) { $properties[$property_name]->setValue($clone, $value); } } return $clone; }
/** * @param $array * @param $object * @return array */ private function initLinkObject(&$array, &$object) { /** @var $link Class_\Link_Annotation */ $link = $this->class->getAnnotation('link'); if ($link->value) { $id_property_value = null; $linked_class_name = null; $link_properties = $link->getLinkProperties(); $search = []; foreach ($link_properties as $property) { if ($property->getType()->isClass()) { $property_name = $property->getName(); $id_property_name = 'id_' . $property_name; if (isset($array[$id_property_name]) && $array[$id_property_name]) { $search[$property_name] = $array[$id_property_name]; } $property_class_name = $property->getType()->asString(); if (is_a($property_class_name, $link->value, true)) { $id_property_value = isset($array[$id_property_name]) ? $array[$id_property_name] : null; $linked_class_name = $property_class_name; if (!isset($array[$id_property_name]) && !isset($array[$property_name])) { $linked_array = $array; foreach (array_keys($link_properties) as $link_property_name) { unset($linked_array[$link_property_name]); } $builder = new Object_Builder_Array($property_class_name, $this->from_form); $array[$property_name] = $builder->build($linked_array); } } } } if (count($search) >= 2) { $object = Dao::searchOne($search, $this->class->name); } if ($id_property_value && !$object) { $object = Builder::createClone(Dao::read($id_property_value, $linked_class_name), $this->class->name); } return $search; } return null; }