/** * @param $object object */ public function createDuplicate($object) { if ($this->dao->getObjectIdentifier($object)) { // duplicate @link Collection and Map properties values $class_name = get_class($object); $class = new Reflection_Class($class_name); /** @var $link Link_Annotation */ $link = $class->getAnnotation('link'); $exclude_properties = $link->value ? array_keys((new Reflection_Class($link->value))->getProperties([T_EXTENDS, T_USE])) : []; foreach ($class->accessProperties() as $property) { if (!$property->isStatic() && !in_array($property->name, $exclude_properties)) { $property_link = $property->getAnnotation('link')->value; // @link Collection : must disconnect objects // @link Collection | Map : duplicate and remove reference to the parent id if (in_array($property_link, [Link_Annotation::COLLECTION, Link_Annotation::MAP])) { $elements = $property->getValue($object); if ($property_link == Link_Annotation::COLLECTION) { foreach ($elements as $element) { $this->createDuplicate($element); } } $this->removeCompositeFromComponents($elements, $class_name); } } } // duplicate object $this->dao->disconnect($object); // after duplicate $this->onDuplicate($object, $class); } }
/** * Builds a Table object using a Php class definition * * This takes care of excluded properties, so buildLinkTable() should be called * before buildClassTable(). * * @param $class Reflection_Class * @param $more_field Column * @return Table */ private function buildClassTable(Reflection_Class $class, $more_field) { $table_name = Dao::current()->storeNameOf($class->name); $table = new Table($table_name); if (!in_array('id', $this->excluded_properties)) { $table->addColumn(Column::buildId()); } if ($more_field) { $table->addColumn($more_field); } if ($class->isAbstract()) { $table->addColumn(new Column('class', 'varchar(255)')); } else { foreach ($class->accessProperties() as $property) { if (!in_array($property->name, $this->excluded_properties)) { $type = $property->getType(); if (($type->isMultipleString() || !$type->isMultiple()) && !$property->isStatic()) { $table->addColumn(Column::buildProperty($property)); if ($property->getAnnotation('link')->value == Link_Annotation::OBJECT && $property->getAnnotation('store')->value != 'string') { $class_name = $property->getType()->asString(); $this->dependencies_context[$class_name] = $class_name; $table->addForeignKey(Foreign_Key::buildProperty($table_name, $property)); $table->addIndex(Index::buildLink($property->getAnnotation('storage')->value)); } } } } } return $table; }
/** * @param $class_name string */ public function start($class_name = null) { if (isset($class_name)) { $this->setClass($class_name); } elseif ($this->started) { $this->stop(); } $this->built_objects = []; $this->properties = $this->class->accessProperties(); $this->started = true; }
/** * @param $file_name string The Excel file name to be read * @return Spreadsheet_File */ public static function createFromFile($file_name) { $source_object = PHPExcel_IOFactory::load($file_name); $destination_object = new Spreadsheet_File(); $source_class = new Reflection_Class(get_class($source_object)); $destination_class = new Reflection_Class(__CLASS__); $destination_properties = $destination_class->accessProperties(); foreach ($source_class->accessProperties() as $source_property) { if (!$source_property->isStatic()) { $destination_property = $destination_properties[$source_property->name]; $destination_property->setValue($destination_object, $source_property->getValue($source_object)); } } return $destination_object; }
/** * Returns true if the object properties values are all empty (or null or unset or equal to * default value) or empty objects. * * @param $object object * @return boolean */ public static function isEmpty($object) { $is_empty = true; $class = new Reflection_Class(get_class($object)); $default = get_class_vars($class->name); foreach ($class->accessProperties() as $property) { if (!$property->isStatic()) { $value = $property->getValue($object); if (!empty($value) && (!is_object($value) || !Empty_Object::isEmpty($value)) && (is_object($value) || $value !== $default[$property->name])) { $is_empty = false; break; } } } return $is_empty; }
public function testAccessPropertiesDone() { $test_order = new Order(date('Y-m-d'), 'CDE001'); $class = new Reflection_Class(Order::class); $class->accessProperties(); $properties = $class->getProperties([T_EXTENDS, T_USE]); $check = []; foreach ($properties as $property) { try { $check[$property->name] = $property->getValue($test_order); } catch (ReflectionException $e) { $check[$property->name] = null; } } $this->assume(__METHOD__, $check, ['date' => null, 'number' => null, 'client' => null, 'delivery_client' => null, 'lines' => null, 'salesmen' => null]); }
/** * Build tabs containing object properties * * This fills in properties 'display' and 'value' special properties, usefull ie for * Html_Template_Functions * * @param $object object * @param $filter_properties string[] * @return Tab[] tabs will contain Reflection_Property_Value[] as content */ public static function buildObject($object, $filter_properties = null) { $class = new Reflection_Class(get_class($object)); /** @var $group_annotations Group_Annotation[] */ $group_annotations = $class->getAnnotations('group'); self::mergeGroups($group_annotations); $properties = $class->accessProperties(); foreach ($properties as $property_name => $property) { if (!isset($filter_properties) || in_array($property_name, $filter_properties)) { $property = new Reflection_Property_Value($property->class, $property->name, $object, false, true); $property->final_class = $class->name; $properties[$property_name] = $property; } else { unset($properties[$property_name]); } } return parent::buildProperties($properties, $group_annotations); }
/** * @param $property Reflection_Property * @param $value boolean|integer|float|string|array */ public function beforeObjectBuilderArrayBuildBasicValue(Reflection_Property $property, &$value) { if (isset($value)) { if (is_array($value) && !empty($value)) { if ($property->getAnnotation('link')->value == Link_Annotation::COLLECTION) { $class = new Reflection_Class($property->getType()->getElementTypeAsString()); $properties = $class->accessProperties(); reset($value); if (!is_numeric(key($value))) { $value = arrayFormRevert($value); } foreach ($value as $key => $element) { foreach ($element as $property_name => $property_value) { if (isset($property_value) && isset($properties[$property_name])) { $value[$key][$property_name] = self::propertyToIso($properties[$property_name], $property_value); } } } } } else { $value = self::propertyToIso($property, $value); } } }
/** * Returns true if any property of $object is set and different than its default value * * @param $object * @return boolean */ public static function isObjectSet($object) { $result = false; $class = new Reflection_Class(get_class($object)); $defaults = $class->getDefaultProperties(); foreach ($class->accessProperties() as $property) { if (!$property->isStatic()) { $value = $property->getValue($object); if (isset($value)) { $default = isset($defaults[$property->name]) ? $defaults[$property->name] : $property->getType()->getDefaultValue(); if (is_object($value) && !self::isObjectSet($value)) { $value = null; } if ($value != $default) { $result = true; break; } } } } return $result; }
/** * Delete an object from current data link * * If object was originally read from data source, matching data will be overwritten. * If object was not originally read from data source, nothing is done and returns false. * * @param $object object object to delete from data source * @return boolean true if deleted * @see Data_Link::delete() */ public function delete($object) { $will_delete = true; foreach ((new Reflection_Class(get_class($object)))->getAnnotations('before_delete') as $before_delete) { /** @var $before_delete Method_Annotation */ if ($before_delete->call($object, [$this]) === false) { $will_delete = false; break; } } if ($will_delete) { $id = $this->getObjectIdentifier($object); if ($id) { $class_name = get_class($object); $class = new Reflection_Class($class_name); /** @var $link Class_\Link_Annotation */ $link = $class->getAnnotation('link'); $exclude_properties = $link->value ? array_keys((new Reflection_Class($link->value))->getProperties([T_EXTENDS, T_USE])) : []; foreach ($class->accessProperties() as $property) { if (!$property->isStatic() && !in_array($property->name, $exclude_properties)) { if ($property->getAnnotation('link')->value == Link_Annotation::COLLECTION) { if ($property->getType()->isMultiple()) { $this->deleteCollection($object, $property, $property->getValue($object)); } else { $this->delete($property->getValue($object)); trigger_error("Dead code into Mysql\\Link::delete() on {$property->name} is not so dead", E_USER_NOTICE); } } } } $this->setContext($class_name); if ($link->value) { $id = []; foreach ($link->getLinkProperties() as $link_property) { $property_name = $link_property->getName(); $column_name = ($link_property->getType()->isClass() ? 'id_' : '') . $link_property->getAnnotation('storage')->value; $id[$column_name] = $this->getObjectIdentifier($object, $property_name); } } $this->query(Sql\Builder::buildDelete($class_name, $id)); $this->disconnect($object); return true; } } return false; }
/** * @param $result mixed[] * @param $first boolean * @return array */ private function resultToRow($result, $first) { $row = []; for ($i = 0; $i < $this->column_count; $i++) { $j = $this->i_to_j[$i]; if (!isset($this->classes[$j])) { $row[$this->columns[$j]] = $result[$i]; } else { if (!isset($row[$this->columns[$j]])) { // TODO LOW try to get the object from object map to avoid multiple instances $row[$this->columns[$j]] = Builder::create($this->classes[$j]); if ($first && !isset($this->reflection_classes[$this->classes[$j]])) { $class = new Reflection_Class($this->classes[$j]); $class->accessProperties(); $this->reflection_classes[$this->classes[$j]] = $class; } } $property_name = $this->column_names[$i]; if ($property_name === 'id') { $this->link->setObjectIdentifier($row[$this->columns[$j]], $result[$i]); } else { $row[$this->columns[$j]]->{$property_name} = $result[$i]; } } } return $row; }
/** * 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; }
/** * @param $object object * @param $only_properties string[] property names if we want to check those properties only * @return boolean */ public function validate($object, $only_properties = []) { $this->valid = true; $only_properties = array_flip($only_properties); $class = new Reflection_Class($object); // properties value validation foreach ($class->accessProperties() as $property) { if (!$only_properties || isset($only_properties[$property->name])) { $property_validator = new Property_Validator($property); $validated_property = $property_validator->validate($object); if (is_null($validated_property)) { return $this->valid = null; } else { $this->report = array_merge($this->report, $property_validator->report); $this->valid = $this->valid && $validated_property; } } } // object validation foreach ($class->getAnnotations() as $annotation) { if ($annotation instanceof Template\Object_Validator) { $validated_annotation = $annotation->validate($object); if (is_null($validated_annotation)) { return $this->valid = null; } else { if (!$validated_annotation) { $this->report[] = $annotation; } $this->valid = $this->valid && $validated_annotation; } } } return $this->valid; }
/** * Returns object's properties, and their display and value * * @param $template Template * @return Reflection_Property_Value[] */ public function getProperties(Template $template) { $object = reset($template->objects); $properties_filter = $template->getParameter(Parameter::PROPERTIES_FILTER); $class = new Reflection_Class(get_class($object)); $result_properties = []; foreach ($class->accessProperties() as $property_name => $property) { if (!$property->isStatic() && !$property->getListAnnotation('user')->has(User_Annotation::INVISIBLE)) { if (!isset($properties_filter) || in_array($property_name, $properties_filter)) { $property = new Reflection_Property_Value($property->class, $property->name, $object, false, true); $property->final_class = $class->name; $result_properties[$property_name] = $property; } } } return Replaces_Annotations::removeReplacedProperties($result_properties); }