/** * @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; }
/** * Build tabs containing class properties * * @param $class Reflection_Class * @return Tab[] Tabs will contain Reflection_Property[] as content */ public static function build(Reflection_Class $class) { /** @var $group_annotations Group_Annotation[] */ $group_annotations = $class->getAnnotations('group'); $properties = $class->getProperties([T_EXTENDS, T_USE]); return self::buildProperties($properties, $group_annotations); }
/** * 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 $class_name string * @param $properties_path string[]|Reverse[] */ public function __construct($class_name, $properties_path = []) { $this->class_name = $class_name; if ($properties_path) { $this->properties_path = $properties_path; } else { $class = new Reflection_Class($class_name); $this->properties_path = $class->getListAnnotation('sort')->values(); } }
/** * @param $property Reflection_Property * @param $map object[] */ public function __construct(Reflection_Property $property, $map) { $this->property = $property; $this->map = $map; $this->class_name = $this->property->getType()->getElementTypeAsString(); $class = new Reflection_Class($this->class_name); /** @var $representative Representative_Annotation */ $representative = $class->getListAnnotation('representative'); $this->properties = $representative->getProperties(); }
/** * Call onDuplicate methods defined by @duplicate class annotation * * @param $object object * @param $class Reflection_Class */ private function onDuplicate($object, Reflection_Class $class) { foreach ($class->getAnnotations('duplicate') as $on_duplicate) { $callback = explode('::', $on_duplicate->value); if ($callback[1] === true || is_numeric($callback[1])) { $callback[1] = 'onDuplicate'; } if (isA($object, $callback[0])) { call_user_func([$object, $callback[1]]); } else { call_user_func([$callback[0], $callback[1]], $object); } } }
/** * @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 $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 $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 the element's property value changed since previous value * and if it is not empty * * @param $element object * @param $property_name string * @param $default_value mixed * @return boolean */ protected function valueChanged($element, $property_name, $default_value) { $id_property_name = 'id_' . $property_name; if (!isset($element->{$property_name}) && empty($id_property_name)) { return false; } $element_value = $element->{$property_name}; if (is_object($element_value)) { $class = new Reflection_Class(get_class($element_value)); $defaults = $class->getDefaultProperties(); foreach ($class->getListAnnotation('representative')->values() as $property_name) { if (isset($defaults[$property_name]) && $this->valueChanged($element_value, $property_name, $defaults[$property_name])) { return true; } } return false; } else { return isset($element_value) && strval($element_value) != '' && strval($element_value) != strval($default_value); } }
/** * @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 $property Reflection_Property * @return Reflection_Class */ private function getForeignClass(Reflection_Property $property) { $type = $property->getType(); $foreign_class_name = Builder::className($type->getElementTypeAsString()); if ($property instanceof PHP\Reflection_Property) { $foreign_class = PHP\Reflection_Class::of($foreign_class_name); } else { $reflection_class = new Reflection\Reflection_Class(get_class($property->getDeclaringClass())); $foreign_class = $reflection_class->newInstance($foreign_class_name); } return $foreign_class; }
/** * @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; }
/** * 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 $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; }
/** * @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; }
/** * @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; }
/** * @param $base_class string The base name for the class, ie 'SAF\Framework\User' * @param $feature_name string The name of the feature, ie 'dataList' * @param $suffix string Class suffix, ie 'Controller', 'View' * @param $extension string File extension, ie 'php', 'html' * @param $class_form boolean true to use 'Feature_Class' naming instead of 'featureClass' * @return string[] [$class, $method] */ public static function get($base_class, $feature_name, $suffix, $extension, $class_form = true) { // ie : $feature_class = 'featureName' transformed into 'Feature_Name' $feature_class = Names::methodToClass($feature_name); // $feature_what is $feature_class or $feature_name depending on $class_name $feature_what = $class_form ? $feature_class : $feature_name; $_suffix = $suffix ? '_' . $suffix : ''; $class_name = $base_class; $ext = DOT . $extension; $method = 'run'; $application_classes = Application::current()->getClassesTree(); // $classes : the controller class name and its parents // ['Vendor\Application\Module\Class_Name' => '\Module\Class_Name'] $classes = []; do { $classes[$class_name] = substr($class_name, strpos($class_name, BS, strpos($class_name, BS) + 1) + 1); if (@class_exists($class_name)) { $reflection_class = new Reflection_Class(Builder::className($class_name)); foreach ($reflection_class->getTraits() as $trait) { $classes[$trait->name] = explode(BS, $trait->name, 3)[2]; } foreach ($reflection_class->getListAnnotation('extends')->values() as $extends) { $classes[$extends] = explode(BS, $extends, 3)[2]; } } $class_name = @get_parent_class($class_name); } while ($class_name); // Looking for specific controller for each application $application_class = reset($application_classes); do { $namespace = Namespaces::of($application_class); // for the controller class and its parents foreach ($classes as $short_class_name) { $class_name = $namespace . BS . $short_class_name; $path = strtolower(str_replace(BS, SL, $class_name)); if (isset($GLOBALS['D'])) { echo '- try A1 ' . $path . SL . $feature_what . $_suffix . $ext . BR; } if (file_exists($path . SL . $feature_what . $_suffix . $ext)) { $class = $class_name . BS . $feature_what . $_suffix; break 2; } if (isset($GLOBALS['D'])) { echo '- try A2 ' . $path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR; } if (file_exists($path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) { $class = $class_name . BS . $feature_class . BS . $feature_what . $_suffix; break 2; } if (isset($GLOBALS['D']) && $suffix) { echo '- try A3 ' . $path . SL . strtolower($feature_class) . SL . $suffix . $ext . BR; } if ($suffix && file_exists($path . SL . strtolower($feature_class) . SL . $suffix . $ext)) { $class = $class_name . BS . $feature_class . BS . $suffix; break 2; } if (isset($GLOBALS['D'])) { echo '- try A4 ' . Names::classToPath($class_name) . '_' . $feature_what . $_suffix . $ext . BR; } if (file_exists(Names::classToPath($class_name) . '_' . $feature_what . $_suffix . $ext)) { $class = $class_name . '_' . $feature_what . $_suffix; break 2; } if (isset($GLOBALS['D']) && $suffix) { echo '- try A5 ' . $path . SL . $suffix . $ext . BR; } if ($suffix && file_exists($path . SL . $suffix . $ext) && method_exists($class_name . BS . $suffix, 'run' . ucfirst($feature_name))) { $class = $class_name . BS . $suffix; $method = 'run' . ucfirst($feature_name); break 2; } } // next application is the parent one $application_class = next($application_classes); } while ($application_class); // Looking for default controller for each application if (empty($class)) { reset($application_classes); do { // looking for default controller $path = strtolower(str_replace(BS, SL, $namespace)); if (isset($GLOBALS['D']) && $suffix) { echo '- try B1 ' . $path . SL . strtolower($feature_class) . SL . $suffix . $ext . BR; } if ($suffix && file_exists($path . SL . strtolower($feature_class) . SL . $suffix . $ext)) { $class = $namespace . BS . $feature_class . BS . $suffix; break; } if (isset($GLOBALS['D'])) { echo '- try B2 ' . $path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR; } if (file_exists($path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) { $class = $namespace . BS . $feature_class . BS . $feature_what . $_suffix; break; } if (isset($GLOBALS['D']) && $suffix) { echo '- try B3 ' . $path . SL . 'widget' . SL . strtolower($feature_class) . SL . $suffix . $ext . BR; } if ($suffix && file_exists($path . SL . 'widget' . SL . strtolower($feature_class) . SL . $suffix . $ext)) { $class = $namespace . BS . 'Widget' . BS . $feature_class . BS . $suffix; break; } if (isset($GLOBALS['D'])) { echo '- try B4 ' . $path . SL . 'widget' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR; } if (file_exists($path . SL . 'widget' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) { $class = $namespace . BS . 'Widget' . BS . $feature_class . BS . $feature_what . $_suffix; break; } if (isset($GLOBALS['D']) && $suffix) { echo '- try B5 ' . $path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $suffix . $ext . BR; } if ($suffix && file_exists($path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $suffix . $ext)) { $class = $namespace . BS . 'Webservice' . BS . $feature_class . BS . $suffix; break; } if (isset($GLOBALS['D'])) { echo '- try B6 ' . $path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR; } if (file_exists($path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) { $class = $namespace . BS . 'Webservice' . BS . $feature_class . BS . $feature_what . $_suffix; break; } // next application is the parent one } while (next($application_classes)); // Looking for direct feature call, without using any controller static $last_controller_class = ''; static $last_controller_method = ''; if (empty($class) && (strpos($suffix, 'View') === false || $last_controller_class !== $base_class && $last_controller_method !== $feature_name)) { if (strpos($suffix, 'Controller') !== false) { $last_controller_class = $base_class; $last_controller_method = $feature_name; } if (@method_exists($base_class, $feature_name)) { $class = $base_class; $method = $feature_name; } } // Looking for default controller for each application if (empty($class) && $suffix) { reset($application_classes); // $suffix == 'Html_View' => $sub = 'View/Html', $suffix = 'View' if (strpos($suffix, '_')) { $elements = explode('_', $suffix); $sub = join(SL, array_reverse($elements)); $suffix = end($elements); } else { $sub = $suffix; } do { if (isset($GLOBALS['D'])) { echo '- try C2 ' . $path . SL . strtolower($sub) . '/Default_' . $suffix . $ext . BR; } if (file_exists($path . SL . strtolower($sub) . '/Default_' . $suffix . $ext)) { $class = $namespace . BS . str_replace(SL, BS, $sub) . BS . 'Default_' . $suffix; break; } } while (next($application_classes)); } } $result = [isset($class) ? $class : null, $method]; if (isset($GLOBALS['D'])) { echo '- FOUND ' . join('::', $result) . BR; } return $result; }
/** * 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); }
/** * The internal build method builds Table objects using a Php class definition * * It is the same than build(), but enables to add an additional field * (link field for @link classes) * * @param $class_name string * @param $more_field Column * @return Table[] */ private function buildInternal($class_name, $more_field) { $class = new Reflection_Class($class_name); $link = $class->getAnnotation('link')->value; $tables = $link ? $this->buildLinkTables($link, $class_name) : []; $tables[] = $this->buildClassTable($class, $more_field); return $tables; }
/** * 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; }
/** * Gets application parent classes names * Include extended parents using T_EXTENDS clause or @extends annotation * * @param $recursive boolean get all parents if true * @return string[] applications class names */ public static function getParentClasses($recursive = false) { $class_name = get_called_class(); $class = new Reflection_Class($class_name); $parent_class_name = get_parent_class($class_name); $extends_class_names = $class->getListAnnotation('extends')->values(); $parents = $parent_class_name ? array_merge([$parent_class_name], $extends_class_names) : $extends_class_names; if ($recursive) { foreach ($parents as $parent_class) { if ($parent_class) { $parents = array_merge($parents, call_user_func([$parent_class, 'getParentClasses'], true)); } } } return array_unique($parents); }
/** * 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 $class Reflection_Class * @return Reflection_Class */ private function getDeclaringTraitInternal(Reflection_Class $class) { $traits = $class->getTraits(); foreach ($traits as $trait) { $properties = $trait->getProperties(); if (isset($properties[$this->name])) { return $this->getDeclaringTraitInternal($trait) ?: $trait; } } return null; }