/** * If no property contains the charater '*' in import file, automatically detects which property * names are used to identify records using the @representative classes annotation * * @param $class_name string * @param $properties_path string[] $property_path = string[integer $column_number] * @return array $identified = boolean[string $property_path][integer $position] */ private static function autoIdentify($class_name, $properties_path) { foreach ($properties_path as $property_path) { if (strpos($property_path, '*') !== false) { return []; } } $auto_identify = []; foreach ($properties_path as $property_path) { $class = new Reflection_Class($class_name); $representative = $class->getListAnnotation('representative')->values(); foreach (explode(DOT, $property_path) as $pos => $property_name) { if (in_array($property_name, $representative)) { $auto_identify[$property_path][$pos] = true; } $property = $class->getProperty($property_name); if (isset($property)) { $type = $property->getType(); if ($type->isClass()) { $class = new Reflection_Class($type->getElementTypeAsString()); $representative = $class->getListAnnotation('representative')->values(); } } } } return $auto_identify; }
/** * @param $join Join * @param $master_path string * @param $master_property_name string * @param $foreign_path string * @return string the foreign class name */ private function addSimpleJoin(Join $join, $master_path, $master_property_name, $foreign_path) { $foreign_class_name = null; $master_property = $this->getProperty($master_path, $master_property_name); if ($master_property) { $foreign_type = $master_property->getType(); if ($foreign_type->isMultiple() && $foreign_type->getElementTypeAsString() == 'string') { // TODO : string[] can have multiple implementations, depending on database engine // linked strings table, mysql set.. should find a way to make this common without // knowing anything about the specific $foreign_class_name = $foreign_type->asString(); } elseif (!$foreign_type->isBasic()) { $join->mode = $master_property->getAnnotation('mandatory')->value ? Join::INNER : Join::LEFT; // force LEFT if any of the properties in the master property path is not mandatory if ($join->mode == Join::INNER && $master_path) { $root_class = new Reflection_Class($this->classes['']); $property_path = ''; foreach (explode(DOT, $master_path . DOT . $master_property_name) as $property_name) { $property_path .= ($property_path ? DOT : '') . $property_name; $property = $root_class->getProperty($property_path); if (!$property || !$property->getAnnotation('mandatory')->value) { $join->mode = Join::LEFT; break; } } } if ($foreign_type->isMultiple()) { $foreign_class_name = $foreign_type->getElementTypeAsString(); $foreign_property_name = $master_property->getAnnotation('foreign')->value; if (property_exists($foreign_class_name, $foreign_property_name) && $master_property->getAnnotation('link')->value != Link_Annotation::MAP) { $foreign_property = new Reflection_Property($foreign_class_name, $foreign_property_name); $join->foreign_column = 'id_' . $foreign_property->getAnnotation('storage')->value; $join->master_column = 'id'; } else { $this->addLinkedJoin($join, $master_path, $foreign_path, $foreign_class_name, $master_property); } } else { $foreign_class_name = $foreign_type->asString(); $join->master_column = 'id_' . $master_property->getAnnotation('storage')->value; $join->foreign_column = 'id'; } } } return $foreign_class_name; }
/** * @param $class Reflection_Class * @param $already string[] For recursion limits : already got classes * @return string[] */ private function classRepresentativeProperties($class, $already = []) { /** @var $property_names List_Annotation */ $property_names = $class->getListAnnotation('representative')->values(); foreach ($property_names as $key => $property_name) { $property_class = $class; $i = strpos($property_name, DOT); while ($i !== false) { $property = $property_class->getProperty(substr($property_name, 0, $i)); $property_class = new Reflection_Class($property->getType()->asString()); $property_name = substr($property_name, $i + 1); $i = strpos($property_name, DOT); } $property = $property_class->getProperty($property_name); $type = $property->getType(); $type_string = $type->asString(); if (!$type->isBasic()) { unset($property_names[$key]); if (!isset($already[$type_string])) { $sub_class = new Reflection_Class($type_string); $sub_already = $already; $sub_already[$type_string] = $type_string; foreach ($this->classRepresentativeProperties($sub_class, $sub_already) as $sub_property_name) { $property_names[] = $property_name . DOT . $sub_property_name; } } } } return $property_names; }