Exemplo n.º 1
0
 /**
  * @return string
  */
 function masterColumn()
 {
     if (!isset($this->master_column)) {
         $this->master_column = 'id_' . Names::setToSingle($this->property->getAnnotation('foreign')->value);
     }
     return $this->master_column;
 }
Exemplo n.º 2
0
 /**
  * @return string[]
  */
 protected function getProperties()
 {
     // gets all properties from collection element class
     $class = new Reflection_Class($this->class_name);
     $properties = $class->getProperties([T_EXTENDS, T_USE]);
     // remove replaced properties
     /** @var $properties Reflection_Property[] */
     $properties = Replaces_Annotations::removeReplacedProperties($properties);
     // remove linked class properties
     $linked_class = $class->getAnnotation('link')->value;
     if ($linked_class) {
         foreach (array_keys((new Reflection_Class($linked_class))->getProperties([T_EXTENDS, T_USE])) as $property_name) {
             unset($properties[$property_name]);
         }
     }
     // remove composite property
     $property_name = $this->property->getAnnotation('foreign')->value;
     if (isset($properties[$property_name])) {
         unset($properties[$property_name]);
     }
     // remove static and user-invisible properties
     foreach ($properties as $property_name => $property) {
         if ($property->isStatic() || $property->getListAnnotation('user')->has(User_Annotation::INVISIBLE)) {
             unset($properties[$property_name]);
         }
     }
     // returns properties
     return $properties;
 }
Exemplo n.º 3
0
 /**
  * Returns the value with string format
  *
  * @param $value string
  * @return string
  */
 protected function formatString($value)
 {
     if ($this->property->getAnnotation('password')->value) {
         $value = strlen($value) ? str_repeat('*', strlen(Password::UNCHANGED)) : '';
     }
     return $value;
 }
Exemplo n.º 4
0
 /**
  * @param $property Reflection_Property
  * @param $value    mixed
  * @return Line[]
  */
 private static function checkProperty(Reflection_Property $property, $value)
 {
     $report_lines = [];
     if (is_null($value)) {
         if (!$property->getAnnotation('null')) {
             self::checkValue($report_lines, false, $property, new Null_Annotation(false, $property), $value);
         }
     } else {
         foreach ($property->getAnnotations() as $annotation_name => $annotation) {
             switch ($annotation_name) {
                 case 'min_length':
                     self::checkValue($report_lines, strlen($value) >= $annotation->value, $property, $annotation, $value);
                     break;
                 case 'max_length':
                     self::checkValue($report_lines, strlen($value) <= $annotation->value, $property, $annotation, $value);
                     break;
                 case 'min_value':
                     self::checkValue($report_lines, $value >= $annotation->value, $property, $annotation, $value);
                     break;
                 case 'max_value':
                     self::checkValue($report_lines, $value <= $annotation->value, $property, $annotation, $value);
                     break;
                     //case 'precision':
                     //case 'signed':
                 //case 'precision':
                 //case 'signed':
                 case 'var':
                     self::checkVar($report_lines, $property, $annotation, $value);
                     break;
             }
         }
     }
     return $report_lines;
 }
Exemplo n.º 5
0
 /**
  * @param $multiline boolean keep this value empty, it is not used because the @multiline
  *        annotation is automatically used
  * @param $values    string[] keep this value empty, it is not used because the @values annotation
  *        is automatically used
  * @return Element
  */
 protected function buildString($multiline = false, $values = null)
 {
     $values_captions = [];
     $values = $this->property->getListAnnotation('values')->values();
     foreach ($values as $value) {
         $values_captions[$value] = Names::propertyToDisplay($value);
     }
     if ($values_captions && !in_array($this->value, $values_captions)) {
         $values_captions[$this->value] = $this->value;
     }
     $element = parent::buildString($this->property->getAnnotation('multiline')->value, $values_captions);
     if ($this->property->getAnnotation('mandatory')->value) {
         $element->setAttribute('required', true);
     }
     if ($this->property->getAnnotation('password')->value) {
         $element->setAttribute('type', 'password');
         $element->setAttribute('value', strlen($this->value) ? Password::UNCHANGED : '');
     }
     return $element;
 }
Exemplo n.º 6
0
 /**
  * @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;
 }
Exemplo n.º 7
0
 /**
  * @param $class_name      string Main class name
  * @param $properties_path string[] $property_path = string[integer $column_number]
  * @return array [$property_link = string[string $property_path], $property_column = string[string $property_path]]
  */
 private static function getPropertiesLinkAndColumn($class_name, $properties_path)
 {
     $properties_link = ['' => Link_Annotation::OBJECT];
     $properties_column = [];
     foreach ($properties_path as $col_number => $property_path) {
         $property_path = str_replace('*', '', $property_path);
         $path = '';
         foreach (explode(DOT, $property_path) as $property_name) {
             $path .= ($path ? DOT : '') . $property_name;
             try {
                 $property = new Reflection_Property($class_name, $path);
                 $properties_link[$path] = $property->getAnnotation('link')->value;
             } catch (ReflectionException $exception) {
                 $properties_link[$path] = '';
             }
         }
         $i = strrpos($property_path, DOT);
         $property_name = substr($property_path, $i === false ? 0 : $i + 1);
         $property_path = substr($property_path, 0, $i);
         $properties_column[$property_path][$property_name] = $col_number;
     }
     foreach (array_keys($properties_column) as $property_path) {
         if ($property_path) {
             $path = '';
             foreach (explode(DOT, $property_path) as $property_name) {
                 if (!isset($properties_column[$path][$property_name])) {
                     $properties_column[$path][$property_name] = $path . ($path ? DOT : '') . $property_name;
                 }
                 $path .= ($path ? DOT : '') . $property_name;
             }
         }
     }
     return [$properties_link, $properties_column];
 }
Exemplo n.º 8
0
 /**
  * @param $description     string
  * @param $class_name      string
  * @param $property_name   string
  * @param $annotation_name string
  * @param $assumed_value   mixed
  */
 private function testAnnotation($description, $class_name, $property_name, $annotation_name, $assumed_value)
 {
     $property = new Reflection_Property($class_name, $property_name);
     $annotation = $property->getAnnotation($annotation_name);
     $this->assume($class_name . DOT . $property_name . AT . $annotation_name . SP . DQ . $assumed_value . DQ . SP . '(' . $description . ')', $annotation->value, $assumed_value);
 }
Exemplo n.º 9
0
 /**
  * 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);
         }
     }
 }
Exemplo n.º 10
0
 /**
  * @param $object        object
  * @param $property      Reflection_Property
  * @param $value         string
  * @param $null_if_empty boolean
  * @return boolean true if property value is null
  */
 private function buildProperty($object, Reflection_Property $property, $value, $null_if_empty)
 {
     $is_null = $null_if_empty;
     // use widget
     if ($this->from_form && ($builder = $property->getAnnotation('widget')->value) && is_a($builder, Property::class, true)) {
         $builder = Builder::create($builder, [$property, $value]);
         /** @var $builder Property */
         $value2 = $builder->buildValue($object, $null_if_empty);
         if ($value2 !== Property::DONT_BUILD_VALUE) {
             $value = $value2;
             $done = true;
         }
     }
     if (!isset($done)) {
         $type = $property->getType();
         if ($type->isBasic()) {
             // password
             if ($encryption = $property->getAnnotation('password')->value) {
                 if ($value == Password::UNCHANGED) {
                     return true;
                 }
                 $value = (new Password($value, $encryption))->encrypted();
             } else {
                 $value = $this->buildBasicValue($property, $value);
             }
         } elseif (is_array($value)) {
             $link = $property->getAnnotation('link')->value;
             // object
             if ($link == Link_Annotation::OBJECT) {
                 $class_name = $property->getType()->asString();
                 $value = $this->buildObjectValue($class_name, $value, $null_if_empty);
             } elseif ($link == Link_Annotation::COLLECTION) {
                 $class_name = $property->getType()->getElementTypeAsString();
                 $value = $this->buildCollection($class_name, $value, $null_if_empty, $object);
             } else {
                 $value = $this->buildMap($value, $property->getType()->getElementTypeAsString(), $link);
             }
         } elseif (isset($value) && $property->getAnnotation('output')->value == 'string') {
             /** @var $object_value Stringable */
             $object_value = Builder::create($property->getType()->asString());
             $object_value->fromString($value);
             $value = $object_value;
         }
     }
     // the property value is set only for official properties, if not default and not empty
     $property_name = $property->name;
     if ($value !== '' || !$property->getType()->isClass()) {
         $object->{$property_name} = $value;
     }
     if (!$property->isValueEmptyOrDefault($value)) {
         $is_null = false;
     }
     return $is_null;
 }
Exemplo n.º 11
0
 /**
  * Builds column name from a property
  *
  * If property data type is an object, the property name will be prefixed with 'id_'.
  * Array properties will return null as no column should be associated to them.
  *
  * @param $property Reflection_Property
  * @return string|null
  */
 public static function buildColumnName(Reflection_Property $property)
 {
     $type = $property->getType();
     return $type->isBasic() ? $property->getAnnotation('storage')->value : ($type->isMultiple() ? null : 'id_' . $property->getAnnotation('storage')->value);
 }
Exemplo n.º 12
0
 /**
  * Gets mysql expression for a property type
  *
  * @param $property Reflection_Property
  * @return string
  */
 private static function propertyTypeToMysql(Reflection_Property $property)
 {
     $property_type = $property->getType();
     if ($property_type->isBasic() || $property->getAnnotation('store')->value == 'string') {
         if ($property_type->hasSize()) {
             /** @var integer $max_length */
             $max_length = $property->getAnnotation('max_length')->value;
             $max_value = $property->getAnnotation('max_value')->value;
             $min_value = $property->getAnnotation('min_value')->value;
             $precision = $property->getAnnotation('precision')->value;
             $signed = $property->getAnnotation('signed')->value;
             $signed_length = $max_length + ($signed ? 1 : 0);
             if (!isset($max_length)) {
                 if ($property_type->isNumeric()) {
                     $max_length = 18;
                     $signed_length = 18;
                 } else {
                     $max_length = 255;
                 }
             }
             if ($property_type->isInteger()) {
                 if (!isset($signed) && $max_value < 0 || $min_value < 0) {
                     $signed = true;
                 }
                 return $max_length <= 3 && $min_value >= -128 && $max_value <= 127 && $signed ? 'tinyint(' . $signed_length . ')' : ($max_length <= 3 && $min_value >= 0 && $max_value <= 255 && !$signed ? 'tinyint(' . $max_length . ') unsigned' : ($max_length <= 5 && $min_value >= -32768 && $max_value <= 32767 ? 'smallint(' . $signed_length . ')' : ($max_length <= 5 && $min_value >= 0 && $max_value <= 65535 ? 'smallint(' . $max_length . ') unsigned' : ($max_length <= 7 && $min_value >= -8388608 && $max_value <= 8388607 ? 'mediumint(' . $signed_length . ')' : ($max_length <= 8 && $min_value >= 0 && $max_value <= 16777215 ? 'mediumint(' . $max_length . ') unsigned' : ($max_length <= 10 && $min_value >= -2147483648.0 && $max_value <= 2147483647 ? 'int(' . $signed_length . ')' : ($max_length <= 10 && $min_value >= 0 && $max_value <= 4294967295.0 ? 'int(' . $max_length . ') unsigned' : ($max_length <= 19 && $min_value >= -9.223372036854776E+18 && $max_value <= 9.223372036854776E+18 ? 'bigint(' . $signed_length . ')' : 'bigint(' . $max_length . ') unsigned'))))))));
             } elseif ($property_type->isFloat()) {
                 return $precision ? 'decimal(' . $signed_length . ', ' . $precision . ')' : 'double';
             } elseif ($property->getAnnotation('binary')->value) {
                 return $max_length <= 65535 ? 'blob' : ($max_length <= 16777215 ? 'mediumblob' : 'longblob');
             } else {
                 return $max_length <= 3 ? 'char(' . $max_length . ')' : ($max_length <= 255 ? 'varchar(' . $max_length . ')' : ($max_length <= 65535 ? 'text' : ($max_length <= 16777215 ? 'mediumtext' : 'longtext'))) . ' CHARACTER SET utf8 COLLATE utf8_general_ci';
             }
         }
         switch ($property_type->asString()) {
             case Type::_ARRAY:
                 return null;
             case Type::BOOLEAN:
                 return 'tinyint(1)';
             case Type::_CALLABLE:
                 return null;
             case Type::null:
             case Type::NULL:
                 return null;
             case Type::RESOURCE:
                 return null;
             case DateTime::class:
             case Date_Time::class:
                 return 'datetime';
             default:
                 return 'char(255)';
         }
     } elseif ($property_type->asString() === Type::STRING_ARRAY) {
         /** @var $values string[] */
         $values = [];
         foreach ($property->getListAnnotation('values')->values() as $key => $value) {
             $values[$key] = str_replace(Q, Q . Q, $value);
         }
         return $values ? ($property->getAnnotation('set')->value ? 'set' : 'enum') . "('" . join("','", $values) . "')" : 'text';
     } else {
         return 'bigint(18) unsigned';
     }
 }
Exemplo n.º 13
0
 /**
  * Generic getter for an object
  *
  * @param $stored     mixed actual value of the object, or identifier to an object, or null
  * @param $class_name string the object class name
  * @param $object     object the parent object
  * @param $property   string|Reflection_Property the parent property
  * @return object
  */
 public static function getObject(&$stored, $class_name, $object = null, $property = null)
 {
     if (!(self::$ignore || is_object($stored))) {
         if ($property instanceof Reflection_Property) {
             $property_name = $property->name;
         } elseif (is_string($property) && is_object($object)) {
             $property_name = $property;
             $property = new Reflection_Property(get_class($object), $property_name);
         }
         if (is_object($object) && isset($property_name)) {
             $id_property_name = 'id_' . $property_name;
             if (isset($object->{$id_property_name})) {
                 $stored = $object->{$id_property_name};
             }
         }
         if (isset($stored)) {
             if (isset($property) && $property->getAnnotation('store')->value == 'string') {
                 /** @var $stored_object Stringable */
                 $stored_object = Builder::create($property->getType()->asString());
                 $stored_object->fromString($stored);
                 $stored = $stored_object;
             } else {
                 $stored = isset($property) && ($dao = $property->getAnnotation('dao')->value) ? Dao::get($dao)->read($stored, $class_name) : Dao::read($stored, $class_name);
             }
         }
     }
     return $stored;
 }
Exemplo n.º 14
0
 /**
  * Test property @getter : setting annotation value
  */
 public function testGetterAnnotationSet()
 {
     $this->method('@getter : setting annotation value');
     $property = new Reflection_Property(self::class, 'property');
     // @getter methodName
     $this->assume('methodName', (new Getter_Annotation('testGetterAnnotation', $property))->value, __CLASS__ . '::testGetterAnnotation');
     // @getter Local_Class_Name::methodName
     $this->assume('Local_Class_Name::methodName', (new Getter_Annotation('User_Annotation::has', $property))->value, User_Annotation::class . '::has');
     // @getter Distant\Class\Full\Path::methodName
     $this->assume('Distant\\Class\\Full\\Path\\Class_Name::methodName', (new Getter_Annotation(Annoted::class . '::has', $property))->value, Annoted::class . '::has');
     // use Distant\Class\Full\Path\Class_Name
     // @getter Class_Name::methodName
     $this->assume('use Class_Name::methodName', (new Getter_Annotation('Annoted::has', $property))->value, Annoted::class . '::has');
     // default value for getter when there is a @link annotation
     $this->assume('default value when @link', $property->getAnnotation('getter')->value, Getter::class . '::getCollection');
 }
 /**
  * @param $property Reflection_Property
  * @return string
  */
 private static function propertyOnDeleteToMysql(Reflection_Property $property)
 {
     return $property->getAnnotation('composite')->value ? 'CASCADE' : 'RESTRICT';
 }