Beispiel #1
0
 /**
  * @param $class                   Reflection_Class
  * @param $composite_class_name    string
  * @return Reflection_Property_Value[]
  */
 protected function getProperties(Reflection_Class $class, $composite_class_name = null)
 {
     $properties = [];
     if (isset($composite_class_name) && isA($class->name, Component::class)) {
         $composite_property = call_user_func([$class->name, 'getCompositeProperties'], $composite_class_name);
         $composite_property = reset($composite_property);
     } else {
         $composite_property = null;
     }
     if ($class->getAnnotation('link')->value) {
         $link_class = new Link_Class($class->name);
         $composite_link_property = $link_class->getCompositeProperty();
         foreach ($link_class->getProperties([T_EXTENDS, T_USE]) as $property) {
             if ((!$composite_property || $property->name !== $composite_property->name) && (!$composite_link_property || $property->name !== $composite_link_property->name) && !$property->isStatic() && !$property->getListAnnotation('user')->has(User_Annotation::INVISIBLE)) {
                 $properties[] = $property;
             }
         }
     } else {
         foreach ($class->getProperties([T_EXTENDS, T_USE]) as $property) {
             if ((empty($composite_property) || $property->name !== $composite_property->name) && !$property->isStatic() && !$property->getListAnnotation('user')->has(User_Annotation::INVISIBLE)) {
                 $properties[] = $property;
             }
         }
     }
     return $properties;
 }
Beispiel #2
0
 /**
  * To use this :
  * - Create your own writeSubClassNames() method
  * - Your method has no parameters
  * - Your method returns nothing
  * - Call return writeSub('sub_class_names', 'super_class_name') using your two properties names
  *
  * @param $sub   string sub property name ie 'sub_class_names'
  * @param $super string super property name ie 'super_class_name'
  */
 private function writeSub($sub, $super)
 {
     $written = [];
     // update $super_property into new $sub_properties
     foreach ($this->{$sub} as $sub) {
         if (!Dao::is($this, $sub->{$super})) {
             $sub->{$super} = $this;
             Dao::write($sub, [Dao::only($super)]);
         }
         $written[Dao::getObjectIdentifier($sub)] = true;
     }
     // empty $super_property from removed $sub_properties
     $subs = Dao::search([$super => $this], Link_Class::linkedClassNameOf($this));
     foreach ($subs as $sub) {
         if (!isset($written[Dao::getObjectIdentifier($sub)])) {
             $sub->{$super} = null;
             Dao::write($sub, [Dao::only($super)]);
         }
     }
 }
Beispiel #3
0
 /**
  * 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;
 }
Beispiel #4
0
 /**
  * Adds properties of the class name into $properties
  *
  * Please always call this instead of adding properties manually : it manages 'link'
  * class annotations.
  *
  * @param $path       string
  * @param $class_name string
  * @param $join_mode  string
  */
 private function addProperties($path, $class_name, $join_mode = null)
 {
     $class = new Link_Class($class_name);
     $this->properties[$class_name] = $class->getProperties([T_EXTENDS, T_USE]);
     $linked_class_name = $class->getAnnotation('link')->value;
     if ($linked_class_name) {
         $this->addLinkedClass($path, $class, $linked_class_name, $join_mode);
     }
 }
Beispiel #5
0
 /**
  * @param $class_name string
  * @param $search     array
  * @return array
  */
 private function createArrayReference($class_name, $search)
 {
     $array = isset($search) ? [Builder::fromArray($class_name, $search)] : null;
     $class = new Link_Class($class_name);
     $link_class = $class->getAnnotation('link')->value;
     if ($link_class) {
         $object = reset($array);
         $link_search = Builder::create($link_class);
         $composite_property_name = $class->getCompositeProperty()->name;
         foreach (array_keys($class->getLinkedProperties()) as $property_name) {
             if (isset($search[$property_name])) {
                 $link_search->{$property_name} = $search[$property_name];
             }
         }
         $object->{$composite_property_name} = Dao::searchOne($link_search) ?: $link_search;
     }
     return $array;
 }
Beispiel #6
0
 /**
  * @param $object   object
  * @param $property Reflection_Property
  * @param $map      object[]
  */
 private function writeMap($object, Reflection_Property $property, $map)
 {
     // old map
     $class = new Link_Class(get_class($object));
     $composite_property_name = $class->getAnnotation('link')->value ? $class->getCompositeProperty()->name : null;
     $old_object = Search_Object::create(Link_Class::linkedClassNameOf($object));
     $this->setObjectIdentifier($old_object, $this->getObjectIdentifier($object, $composite_property_name));
     $aop_getter_ignore = Getter::$ignore;
     Getter::$ignore = false;
     $old_map = $property->getValue($old_object);
     Getter::$ignore = $aop_getter_ignore;
     // map properties : write each of them
     $insert_builder = new Map_Insert($property);
     $id_set = [];
     foreach ($map as $element) {
         $id = $this->getObjectIdentifier($element) ?: $this->getObjectIdentifier($this->write($element));
         if (!isset($old_map[$id])) {
             $query = $insert_builder->buildQuery($object, $element);
             $this->connection->query($query);
         } else {
             $id_set[$id] = true;
         }
     }
     // remove old unused elements
     $delete_builder = new Map_Delete($property);
     foreach ($old_map as $old_element) {
         $id = $this->getObjectIdentifier($old_element);
         if (!isset($id_set[$id])) {
             $query = $delete_builder->buildQuery($object, $old_element);
             $this->connection->query($query);
         }
     }
 }
Beispiel #7
0
 /**
  * Build SQL WHERE section for an object
  *
  * @param $path        string Base property path pointing to the object
  * @param $object      object The value is an object, which will be used for search
  * @return string
  */
 private function buildObject($path, $object)
 {
     $class = new Link_Class(get_class($object));
     $id = $this->sql_link->getObjectIdentifier($object, $class->getAnnotation('link')->value ? $class->getCompositeProperty()->name : null);
     if ($id) {
         // object is linked to stored data : search with object identifier
         return $this->buildValue($path, $id, $path == 'id' ? '' : 'id_');
     }
     // object is a search object : each property is a search entry, and must join table
     $this->joins->add($path);
     $array = [];
     $class = new Reflection_Class(get_class($object));
     foreach ($class->accessProperties() as $property_name => $property) {
         if (isset($object->{$property_name})) {
             $sub_path = $property_name;
             $array[$sub_path] = $object->{$property_name};
         }
     }
     $sql = $this->buildArray($path, $array, 'AND');
     if (!$sql) {
         $sql = 'FALSE';
     }
     return $sql;
 }